💄 Improve the image don't animated the opacity if cached

This commit is contained in:
2026-01-10 23:02:31 +08:00
parent 1b2620e957
commit 2fd93246c7
2 changed files with 76 additions and 43 deletions

View File

@@ -7,8 +7,7 @@ import 'package:island/models/chat.dart';
import 'package:island/widgets/chat/message_item.dart'; import 'package:island/widgets/chat/message_item.dart';
// Provider to track animated messages to prevent replay // Provider to track animated messages to prevent replay
final animatedMessagesProvider = final animatedMessagesProvider = NotifierProvider.autoDispose(
NotifierProvider<AnimatedMessagesNotifier, Set<String>>(
AnimatedMessagesNotifier.new, AnimatedMessagesNotifier.new,
); );

View File

@@ -1,6 +1,7 @@
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_blurhash/flutter_blurhash.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
@@ -29,8 +30,16 @@ class UniversalImage extends HookWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final loaded = useState(false); final loaded = useState(false);
final isCached = useState<bool?>(null);
final isSvgImage = isSvg || uri.toLowerCase().endsWith('.svg'); final isSvgImage = isSvg || uri.toLowerCase().endsWith('.svg');
useEffect(() {
DefaultCacheManager().getFileFromCache(uri).then((fileInfo) {
isCached.value = fileInfo != null;
});
return null;
}, [uri]);
if (isSvgImage) { if (isSvgImage) {
return SvgPicture.network( return SvgPicture.network(
uri, uri,
@@ -59,6 +68,31 @@ class UniversalImage extends HookWidget {
fit: StackFit.expand, fit: StackFit.expand,
children: [ children: [
if (blurHash != null) BlurHash(hash: blurHash!), if (blurHash != null) BlurHash(hash: blurHash!),
if (isCached.value == null)
Center(child: CircularProgressIndicator())
else if (isCached.value!)
CachedNetworkImage(
imageUrl: uri,
fit: fit,
width: width,
height: height,
memCacheHeight: cacheHeight,
memCacheWidth: cacheWidth,
imageBuilder: (context, imageProvider) => Image(
image: imageProvider,
fit: fit,
width: width,
height: height,
),
errorWidget: (context, url, error) => useFallbackImage
? Image.asset(
'assets/images/media-offline.jpg',
fit: BoxFit.cover,
key: Key('image-broke-$uri'),
)
: SizedBox.shrink(),
)
else
CachedNetworkImage( CachedNetworkImage(
imageUrl: uri, imageUrl: uri,
fit: fit, fit: fit,
@@ -76,7 +110,7 @@ class UniversalImage extends HookWidget {
}, },
imageBuilder: (context, imageProvider) { imageBuilder: (context, imageProvider) {
Future(() { Future(() {
if (context.mounted) return loaded.value = true; if (context.mounted) loaded.value = true;
}); });
return AnimatedOpacity( return AnimatedOpacity(
opacity: loaded.value ? 1.0 : 0.0, opacity: loaded.value ? 1.0 : 0.0,