80 lines
1.9 KiB
Dart
80 lines
1.9 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:rra_app/pages/map/tiles/hive_tile_cache.dart';
|
|
|
|
class HiveTileImage extends StatefulWidget {
|
|
const HiveTileImage({required this.url, this.onLoaded, super.key});
|
|
|
|
final String url;
|
|
final ValueChanged<String>? onLoaded;
|
|
|
|
@override
|
|
State<HiveTileImage> createState() => _HiveTileImageState();
|
|
}
|
|
|
|
class _HiveTileImageState extends State<HiveTileImage> {
|
|
Uint8List? _bytes;
|
|
String? _loadingUrl;
|
|
bool _reportedLoaded = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_bytes = HiveTileCache.peek(widget.url);
|
|
if (_bytes != null && _bytes!.isNotEmpty) {
|
|
_reportLoaded();
|
|
} else {
|
|
_load(widget.url);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant HiveTileImage oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (oldWidget.url != widget.url) {
|
|
_reportedLoaded = false;
|
|
_bytes = HiveTileCache.peek(widget.url);
|
|
if (_bytes != null && _bytes!.isNotEmpty) {
|
|
_reportLoaded();
|
|
} else {
|
|
_load(widget.url);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> _load(String url) async {
|
|
_loadingUrl = url;
|
|
final bytes = await HiveTileCache.getOrFetch(url);
|
|
if (!mounted || _loadingUrl != url) return;
|
|
if (bytes != null && bytes.isNotEmpty) {
|
|
setState(() {
|
|
_bytes = bytes;
|
|
});
|
|
_reportLoaded();
|
|
}
|
|
}
|
|
|
|
void _reportLoaded() {
|
|
if (_reportedLoaded) return;
|
|
_reportedLoaded = true;
|
|
widget.onLoaded?.call(widget.url);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final bytes = _bytes;
|
|
if (bytes == null || bytes.isEmpty) {
|
|
return const ColoredBox(color: Colors.transparent);
|
|
}
|
|
_reportLoaded();
|
|
return Image.memory(
|
|
bytes,
|
|
scale: widget.url.contains('@2x') ? 2.0 : 1.0,
|
|
fit: BoxFit.cover,
|
|
gaplessPlayback: true,
|
|
filterQuality: FilterQuality.medium,
|
|
);
|
|
}
|
|
}
|