From b8345e2ca6d9ceef2136cb6ccaf4f8384801936b Mon Sep 17 00:00:00 2001 From: krille-chan Date: Thu, 18 Jul 2024 17:41:45 +0200 Subject: [PATCH] chore: Follow up avatars --- lib/widgets/avatar.dart | 3 +- lib/widgets/mxc_image.dart | 108 +++++++++++++++++++++++++------------ pubspec.lock | 32 ----------- pubspec.yaml | 1 - 4 files changed, 77 insertions(+), 67 deletions(-) diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 96aed191..28524d91 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -75,7 +75,8 @@ class Avatar extends StatelessWidget { child: noPic ? textWidget : MxcImage( - key: Key(mxContent.toString()), + key: ValueKey(mxContent.toString()), + cacheKey: '${mxContent}_$size', uri: mxContent, fit: BoxFit.cover, width: size, diff --git a/lib/widgets/mxc_image.dart b/lib/widgets/mxc_image.dart index b12c9fc9..34c53cb5 100644 --- a/lib/widgets/mxc_image.dart +++ b/lib/widgets/mxc_image.dart @@ -2,7 +2,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:cached_network_image/cached_network_image.dart'; +import 'package:http/http.dart' as http; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/themes.dart'; @@ -18,8 +18,11 @@ class MxcImage extends StatefulWidget { final bool isThumbnail; final bool animated; final Duration retryDuration; + final Duration animationDuration; + final Curve animationCurve; final ThumbnailMethod thumbnailMethod; final Widget Function(BuildContext context)? placeholder; + final String? cacheKey; const MxcImage({ this.uri, @@ -30,8 +33,11 @@ class MxcImage extends StatefulWidget { this.placeholder, this.isThumbnail = true, this.animated = false, + this.animationDuration = FluffyThemes.animationDuration, this.retryDuration = const Duration(seconds: 2), + this.animationCurve = FluffyThemes.animationCurve, this.thumbnailMethod = ThumbnailMethod.scale, + this.cacheKey, super.key, }); @@ -40,11 +46,76 @@ class MxcImage extends StatefulWidget { } class _MxcImageState extends State { - Uint8List? _imageData; + static final Map _imageDataCache = {}; + Uint8List? _imageDataNoCache; + + Uint8List? get _imageData => widget.cacheKey == null + ? _imageDataNoCache + : _imageDataCache[widget.cacheKey]; + + set _imageData(Uint8List? data) { + if (data == null) return; + final cacheKey = widget.cacheKey; + cacheKey == null + ? _imageDataNoCache = data + : _imageDataCache[cacheKey] = data; + } + + bool? _isCached; Future _load() async { + final client = Matrix.of(context).client; + final uri = widget.uri; final event = widget.event; + if (uri != null) { + final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; + final width = widget.width; + final realWidth = width == null ? null : width * devicePixelRatio; + final height = widget.height; + final realHeight = height == null ? null : height * devicePixelRatio; + + final httpUri = widget.isThumbnail + ? uri.getThumbnail( + client, + width: realWidth, + height: realHeight, + animated: widget.animated, + method: widget.thumbnailMethod, + ) + : uri.getDownloadLink(client); + + final storeKey = widget.isThumbnail ? httpUri : uri; + + if (_isCached == null) { + final cachedData = await client.database?.getFile(storeKey); + if (cachedData != null) { + if (!mounted) return; + setState(() { + _imageData = cachedData; + _isCached = true; + }); + return; + } + _isCached = false; + } + + final response = await http.get(httpUri); + if (response.statusCode != 200) { + if (response.statusCode == 404) { + return; + } + throw Exception(); + } + final remoteData = response.bodyBytes; + + if (!mounted) return; + setState(() { + _imageData = remoteData; + }); + await client.database?.storeFile(storeKey, remoteData, 0); + } + if (event != null) { final data = await event.downloadAndDecryptAttachment( getThumbnail: widget.isThumbnail, @@ -60,7 +131,7 @@ class _MxcImageState extends State { } void _tryLoad(_) async { - if (_imageData != null || widget.event == null) { + if (_imageData != null) { return; } try { @@ -89,36 +160,6 @@ class _MxcImageState extends State { @override Widget build(BuildContext context) { - final uri = widget.uri; - - if (uri != null) { - final client = Matrix.of(context).client; - final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; - final width = widget.width; - final realWidth = width == null ? null : width * devicePixelRatio; - final height = widget.height; - final realHeight = height == null ? null : height * devicePixelRatio; - - final httpUri = widget.isThumbnail - ? uri.getThumbnail( - client, - width: realWidth, - height: realHeight, - animated: widget.animated, - method: widget.thumbnailMethod, - ) - : uri.getDownloadLink(client); - - return CachedNetworkImage( - imageUrl: httpUri.toString(), - width: width, - height: height, - fit: widget.fit, - placeholder: (context, _) => placeholder(context), - errorWidget: (context, _, __) => placeholder(context), - ); - } - final data = _imageData; final hasData = data != null && data.isNotEmpty; @@ -136,6 +177,7 @@ class _MxcImageState extends State { filterQuality: widget.isThumbnail ? FilterQuality.low : FilterQuality.medium, errorBuilder: (context, __, ___) { + _isCached = false; _imageData = null; WidgetsBinding.instance.addPostFrameCallback(_tryLoad); return placeholder(context); diff --git a/pubspec.lock b/pubspec.lock index afec622d..7e3909e5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,30 +129,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - cached_network_image: - dependency: "direct main" - description: - name: cached_network_image - sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" - url: "https://pub.dev" - source: hosted - version: "3.3.1" - cached_network_image_platform_interface: - dependency: transitive - description: - name: cached_network_image_platform_interface - sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - cached_network_image_web: - dependency: transitive - description: - name: cached_network_image_web - sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7" - url: "https://pub.dev" - source: hosted - version: "1.2.0" callkeep: dependency: "direct main" description: @@ -1294,14 +1270,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" - octo_image: - dependency: transitive - description: - name: octo_image - sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" - url: "https://pub.dev" - source: hosted - version: "2.0.0" olm: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d89ef7d8..a013aeea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,6 @@ dependencies: async: ^2.11.0 badges: ^3.1.2 blurhash_dart: ^1.2.1 - cached_network_image: ^3.3.1 callkeep: ^0.3.2 chewie: ^1.8.1 collection: ^1.18.0