diff --git a/packages/neon/neon/lib/neon.dart b/packages/neon/neon/lib/neon.dart index 048c8f32..ccf4aab4 100644 --- a/packages/neon/neon/lib/neon.dart +++ b/packages/neon/neon/lib/neon.dart @@ -91,9 +91,7 @@ part 'src/utils/validators.dart'; part 'src/widgets/account_settings_tile.dart'; part 'src/widgets/account_tile.dart'; part 'src/widgets/app_implementation_icon.dart'; -part 'src/widgets/cached_api_image.dart'; part 'src/widgets/cached_image.dart'; -part 'src/widgets/cached_url_image.dart'; part 'src/widgets/dialog.dart'; part 'src/widgets/exception.dart'; part 'src/widgets/image_wrapper.dart'; diff --git a/packages/neon/neon/lib/src/widgets/cached_api_image.dart b/packages/neon/neon/lib/src/widgets/cached_api_image.dart deleted file mode 100644 index 307d48dc..00000000 --- a/packages/neon/neon/lib/src/widgets/cached_api_image.dart +++ /dev/null @@ -1,32 +0,0 @@ -part of '../../neon.dart'; - -typedef APIImageDownloader = Future Function(); - -class NeonCachedApiImage extends NeonCachedImage { - NeonCachedApiImage({ - required final Account account, - required final String cacheKey, - required final APIImageDownloader download, - final String? etag, - super.size, - super.fit, - super.svgColor, - super.iconColor, - super.key, - }) : super( - getImageFile: () async { - final realKey = '${account.id}-$cacheKey'; - final cacheFile = await _cacheManager.getFileFromCache(realKey); - if (cacheFile != null && cacheFile.validTill.isAfter(DateTime.now())) { - return cacheFile.file; - } - - return _cacheManager.putFile( - realKey, - await download(), - maxAge: const Duration(days: 7), - eTag: etag, - ); - }, - ); -} diff --git a/packages/neon/neon/lib/src/widgets/cached_image.dart b/packages/neon/neon/lib/src/widgets/cached_image.dart index 3e1fe9b6..affa4a89 100644 --- a/packages/neon/neon/lib/src/widgets/cached_image.dart +++ b/packages/neon/neon/lib/src/widgets/cached_image.dart @@ -2,8 +2,10 @@ part of '../../neon.dart'; final _cacheManager = DefaultCacheManager(); -abstract class NeonCachedImage extends StatefulWidget { - const NeonCachedImage({ +typedef APIImageDownloader = Future Function(); + +class NeonCachedImage extends StatefulWidget { + const NeonCachedImage._({ required this.getImageFile, this.isSvgHint = false, this.size, @@ -13,6 +15,58 @@ abstract class NeonCachedImage extends StatefulWidget { super.key, }); + factory NeonCachedImage.url({ + required final String url, + final Size? size, + final BoxFit? fit, + final Color? svgColor, + final Color? iconColor, + final Key? key, + }) => + NeonCachedImage._( + getImageFile: () async => _cacheManager.getSingleFile(url), + isSvgHint: Uri.parse(url).path.endsWith('.svg'), + size: size, + fit: fit, + svgColor: svgColor, + iconColor: iconColor, + key: key, + ); + + factory NeonCachedImage.api({ + required final Account account, + required final String cacheKey, + required final APIImageDownloader download, + final String? etag, + final Size? size, + final BoxFit? fit, + final Color? svgColor, + final Color? iconColor, + final Key? key, + }) => + NeonCachedImage._( + getImageFile: () async { + final realKey = '${account.id}-$cacheKey'; + final cacheFile = await _cacheManager.getFileFromCache(realKey); + if (cacheFile != null && cacheFile.validTill.isAfter(DateTime.now())) { + return cacheFile.file; + } + + // TODO: don't await the image being written to disk + return _cacheManager.putFile( + realKey, + await download(), + maxAge: const Duration(days: 7), + eTag: etag, + ); + }, + size: size, + fit: fit, + svgColor: svgColor, + iconColor: iconColor, + key: key, + ); + final Future Function() getImageFile; final bool isSvgHint; diff --git a/packages/neon/neon/lib/src/widgets/cached_url_image.dart b/packages/neon/neon/lib/src/widgets/cached_url_image.dart deleted file mode 100644 index 6e66e6ee..00000000 --- a/packages/neon/neon/lib/src/widgets/cached_url_image.dart +++ /dev/null @@ -1,15 +0,0 @@ -part of '../../neon.dart'; - -class NeonCachedUrlImage extends NeonCachedImage { - NeonCachedUrlImage({ - required final String url, - super.size, - super.fit, - super.svgColor, - super.iconColor, - super.key, - }) : super( - getImageFile: () => _cacheManager.getSingleFile(url), - isSvgHint: Uri.parse(url).path.endsWith('.svg'), - ); -} diff --git a/packages/neon/neon/lib/src/widgets/drawer.dart b/packages/neon/neon/lib/src/widgets/drawer.dart index 2cf034b4..033e036a 100644 --- a/packages/neon/neon/lib/src/widgets/drawer.dart +++ b/packages/neon/neon/lib/src/widgets/drawer.dart @@ -187,7 +187,7 @@ class NeonDrawerHeader extends StatelessWidget { ], if (capabilities.requireData.capabilities.theming?.logo != null) ...[ Flexible( - child: NeonCachedUrlImage( + child: NeonCachedImage.url( url: capabilities.requireData.capabilities.theming!.logo!, ), ), diff --git a/packages/neon/neon/lib/src/widgets/user_avatar.dart b/packages/neon/neon/lib/src/widgets/user_avatar.dart index 4909dd9d..32e23c89 100644 --- a/packages/neon/neon/lib/src/widgets/user_avatar.dart +++ b/packages/neon/neon/lib/src/widgets/user_avatar.dart @@ -53,7 +53,7 @@ class _UserAvatarState extends State { radius: size / 2, backgroundColor: widget.backgroundColor, child: ClipOval( - child: NeonCachedApiImage( + child: NeonCachedImage.api( account: widget.account, cacheKey: 'avatar-${widget.username}-${isDark ? 'dark' : 'light'}$pixelSize', download: () async { diff --git a/packages/neon/neon_files/lib/widgets/file_preview.dart b/packages/neon/neon_files/lib/widgets/file_preview.dart index 9de089af..657a87d9 100644 --- a/packages/neon/neon_files/lib/widgets/file_preview.dart +++ b/packages/neon/neon_files/lib/widgets/file_preview.dart @@ -34,7 +34,7 @@ class FilePreview extends StatelessWidget { builder: (final context, final showPreviewsSnapshot) { if ((showPreviewsSnapshot.data ?? false) && (details.hasPreview ?? false)) { final account = Provider.of(context, listen: false).activeAccount.value!; - final child = NeonCachedApiImage( + final child = NeonCachedImage.api( account: account, cacheKey: 'preview-${details.path.join('/')}-$width-$height', etag: details.etag, diff --git a/packages/neon/neon_news/lib/widgets/articles_view.dart b/packages/neon/neon_news/lib/widgets/articles_view.dart index cc846e32..53592444 100644 --- a/packages/neon/neon_news/lib/widgets/articles_view.dart +++ b/packages/neon/neon_news/lib/widgets/articles_view.dart @@ -116,7 +116,7 @@ class _NewsArticlesViewState extends State { ), ), if (article.mediaThumbnail != null) ...[ - NeonCachedUrlImage( + NeonCachedImage.url( url: article.mediaThumbnail!, size: const Size(100, 50), fit: BoxFit.cover, diff --git a/packages/neon/neon_news/lib/widgets/feed_icon.dart b/packages/neon/neon_news/lib/widgets/feed_icon.dart index 1c9b7bb0..28dc64bd 100644 --- a/packages/neon/neon_news/lib/widgets/feed_icon.dart +++ b/packages/neon/neon_news/lib/widgets/feed_icon.dart @@ -21,7 +21,7 @@ class NewsFeedIcon extends StatelessWidget { size: Size.square(size), borderRadius: borderRadius, child: faviconLink != null && faviconLink.isNotEmpty - ? NeonCachedUrlImage( + ? NeonCachedImage.url( url: faviconLink, size: Size.square(size), iconColor: Theme.of(context).colorScheme.primary, diff --git a/packages/neon/neon_notifications/lib/pages/main.dart b/packages/neon/neon_notifications/lib/pages/main.dart index 18c76e3b..948b0d5b 100644 --- a/packages/neon/neon_notifications/lib/pages/main.dart +++ b/packages/neon/neon_notifications/lib/pages/main.dart @@ -78,7 +78,7 @@ class _NotificationsMainPageState extends State { ) : SizedBox.fromSize( size: const Size.square(40), - child: NeonCachedUrlImage( + child: NeonCachedImage.url( url: notification.icon!, size: const Size.square(40), svgColor: Theme.of(context).colorScheme.primary,