93 lines
2.0 KiB
Dart
93 lines
2.0 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../../core/services/svg_cache.dart';
|
|
|
|
class CachedSvg extends StatefulWidget {
|
|
final String url;
|
|
final double? width;
|
|
final double? height;
|
|
final BoxFit fit;
|
|
|
|
const CachedSvg({
|
|
required this.url,
|
|
this.width,
|
|
this.height,
|
|
this.fit = BoxFit.contain,
|
|
super.key,
|
|
});
|
|
|
|
@override
|
|
State<CachedSvg> createState() => _CachedSvgState();
|
|
}
|
|
|
|
class _CachedSvgState extends State<CachedSvg> {
|
|
String? _svgData;
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadSvg();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant CachedSvg oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (oldWidget.url != widget.url) {
|
|
_isLoading = true;
|
|
_svgData = null;
|
|
_loadSvg();
|
|
}
|
|
}
|
|
|
|
Future<void> _loadSvg() async {
|
|
try {
|
|
final cache = SvgCache();
|
|
String? cachedPath = await cache.getCachedPath(widget.url);
|
|
cachedPath ??= await cache.cacheSvg(widget.url);
|
|
if (kIsWeb && cachedPath.startsWith('web_cache_')) {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final fileName = cachedPath.replaceFirst('web_cache_', '');
|
|
_svgData = prefs.getString('svg_cache_$fileName');
|
|
} else {
|
|
_svgData = await File(cachedPath).readAsString();
|
|
}
|
|
|
|
if (mounted) {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
if (mounted) {
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_isLoading) {
|
|
return const SizedBox();
|
|
}
|
|
|
|
if (_svgData == null) {
|
|
return const Icon(Icons.error);
|
|
}
|
|
|
|
return SvgPicture.string(
|
|
_svgData!,
|
|
width: widget.width,
|
|
height: widget.height,
|
|
fit: widget.fit,
|
|
);
|
|
}
|
|
}
|