From a81e934fbe5226f07803ad12ef879121bbe444a9 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Mon, 7 Jun 2021 16:11:54 +0900 Subject: [PATCH] reviewed thumbnail requests & cached thumbnail usage --- lib/model/entry_cache.dart | 13 ++++- lib/model/entry_images.dart | 11 ++-- lib/widgets/collection/collection_grid.dart | 14 +++-- lib/widgets/collection/thumbnail/raster.dart | 6 +- .../viewer/{ => debug}/debug_page.dart | 57 +++++++++---------- lib/widgets/viewer/entry_action_delegate.dart | 2 +- .../viewer/visual/entry_page_view.dart | 8 +-- lib/widgets/viewer/visual/raster.dart | 2 +- 8 files changed, 64 insertions(+), 49 deletions(-) rename lib/widgets/viewer/{ => debug}/debug_page.dart (85%) diff --git a/lib/model/entry_cache.dart b/lib/model/entry_cache.dart index 25f121154..a70fd6d63 100644 --- a/lib/model/entry_cache.dart +++ b/lib/model/entry_cache.dart @@ -4,7 +4,16 @@ import 'package:aves/image_providers/thumbnail_provider.dart'; import 'package:aves/image_providers/uri_image_provider.dart'; class EntryCache { - static final requestExtents = {}; + // ordered descending + static final thumbnailRequestExtents = []; + + static void markThumbnailExtent(double extent) { + if (!thumbnailRequestExtents.contains(extent)) { + thumbnailRequestExtents + ..add(extent) + ..sort((a, b) => b.compareTo(a)); + } + } static Future evict( String uri, @@ -36,7 +45,7 @@ class EntryCache { )).evict(); await Future.forEach( - requestExtents, + thumbnailRequestExtents, (extent) => ThumbnailProvider(ThumbnailProviderKey( uri: uri, mimeType: mimeType, diff --git a/lib/model/entry_images.dart b/lib/model/entry_images.dart index 7103c69a6..d62dfabd7 100644 --- a/lib/model/entry_images.dart +++ b/lib/model/entry_images.dart @@ -6,6 +6,7 @@ import 'package:aves/image_providers/thumbnail_provider.dart'; import 'package:aves/image_providers/uri_image_provider.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/entry_cache.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart'; extension ExtraAvesEntry on AvesEntry { @@ -14,7 +15,7 @@ extension ExtraAvesEntry on AvesEntry { } ThumbnailProviderKey _getThumbnailProviderKey(double extent) { - EntryCache.requestExtents.add(extent); + EntryCache.markThumbnailExtent(extent); return ThumbnailProviderKey( uri: uri, mimeType: mimeType, @@ -54,10 +55,10 @@ extension ExtraAvesEntry on AvesEntry { bool _isReady(Object providerKey) => imageCache!.statusForKey(providerKey).keepAlive; - ImageProvider getBestThumbnail(double extent) { - final sizedThumbnailKey = _getThumbnailProviderKey(extent); - if (_isReady(sizedThumbnailKey)) return ThumbnailProvider(sizedThumbnailKey); + List get cachedThumbnails => EntryCache.thumbnailRequestExtents.map(_getThumbnailProviderKey).where(_isReady).map((key) => ThumbnailProvider(key)).toList(); - return getThumbnail(); + ThumbnailProvider get bestCachedThumbnail { + final sizedThumbnailKey = EntryCache.thumbnailRequestExtents.map(_getThumbnailProviderKey).firstWhereOrNull(_isReady); + return sizedThumbnailKey != null ? ThumbnailProvider(sizedThumbnailKey) : getThumbnail(); } } diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 94fb901bc..743c1188a 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -204,11 +204,15 @@ class _CollectionScaler extends StatelessWidget { ), scaledBuilder: (entry, extent) => ThumbnailTheme( extent: extent, - child: DecoratedThumbnail( - entry: entry, - tileExtent: extent, - selectable: false, - highlightable: false, + child: Container( + width: extent, + height: extent, + child: DecoratedThumbnail( + entry: entry, + tileExtent: context.read().effectiveExtentMax, + selectable: false, + highlightable: false, + ), ), ), getScaledItemTileRect: (context, entry) { diff --git a/lib/widgets/collection/thumbnail/raster.dart b/lib/widgets/collection/thumbnail/raster.dart index a089a0a8e..d5e3bf64c 100644 --- a/lib/widgets/collection/thumbnail/raster.dart +++ b/lib/widgets/collection/thumbnail/raster.dart @@ -13,6 +13,7 @@ import 'package:flutter/material.dart'; class RasterImageThumbnail extends StatefulWidget { final AvesEntry entry; final double extent; + final BoxFit fit; final ValueNotifier? cancellableNotifier; final Object? heroTag; @@ -20,6 +21,7 @@ class RasterImageThumbnail extends StatefulWidget { Key? key, required this.entry, required this.extent, + this.fit = BoxFit.cover, this.cancellableNotifier, this.heroTag, }) : super(key: key); @@ -182,7 +184,7 @@ class _RasterImageThumbnailState extends State { width: extent, height: extent, scale: imageInfo.scale, - fit: BoxFit.cover, + fit: widget.fit, ); return widget.heroTag != null @@ -190,7 +192,7 @@ class _RasterImageThumbnailState extends State { tag: widget.heroTag!, flightShuttleBuilder: (flight, animation, direction, fromHero, toHero) { return TransitionImage( - image: entry.getBestThumbnail(extent), + image: entry.bestCachedThumbnail, animation: animation, ); }, diff --git a/lib/widgets/viewer/debug_page.dart b/lib/widgets/viewer/debug/debug_page.dart similarity index 85% rename from lib/widgets/viewer/debug_page.dart rename to lib/widgets/viewer/debug/debug_page.dart index 8eb2877ef..af8cd13c2 100644 --- a/lib/widgets/viewer/debug_page.dart +++ b/lib/widgets/viewer/debug/debug_page.dart @@ -117,37 +117,36 @@ class ViewerDebugPage extends StatelessWidget { } Widget _buildThumbnailsTabView() { - const extent = 128.0; + final children = []; + if (entry.isSvg) { + const extent = 128.0; + children.addAll([ + Text('SVG ($extent)'), + SvgPicture( + UriPicture( + uri: entry.uri, + mimeType: entry.mimeType, + ), + width: extent, + height: extent, + ) + ]); + } else { + children.addAll( + entry.cachedThumbnails.expand((provider) => [ + Text('Raster (${provider.key.extent})'), + Center( + child: Image( + image: provider, + ), + ), + SizedBox(height: 16), + ]), + ); + } return ListView( padding: EdgeInsets.all(16), - children: [ - if (entry.isSvg) ...[ - Text('SVG ($extent)'), - SvgPicture( - UriPicture( - uri: entry.uri, - mimeType: entry.mimeType, - ), - width: extent, - height: extent, - ) - ], - if (!entry.isSvg) ...[ - Text('Raster (fast)'), - Center( - child: Image( - image: entry.getThumbnail(), - ), - ), - SizedBox(height: 16), - Text('Raster ($extent)'), - Center( - child: Image( - image: entry.getThumbnail(extent: extent), - ), - ), - ], - ], + children: children, ); } } diff --git a/lib/widgets/viewer/entry_action_delegate.dart b/lib/widgets/viewer/entry_action_delegate.dart index a756bba08..53d449358 100644 --- a/lib/widgets/viewer/entry_action_delegate.dart +++ b/lib/widgets/viewer/entry_action_delegate.dart @@ -16,7 +16,7 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/rename_entry_dialog.dart'; import 'package:aves/widgets/filter_grids/album_pick.dart'; -import 'package:aves/widgets/viewer/debug_page.dart'; +import 'package:aves/widgets/viewer/debug/debug_page.dart'; import 'package:aves/widgets/viewer/info/notifications.dart'; import 'package:aves/widgets/viewer/printer.dart'; import 'package:aves/widgets/viewer/source_viewer_page.dart'; diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart index 1bfaf9176..f07795634 100644 --- a/lib/widgets/viewer/visual/entry_page_view.dart +++ b/lib/widgets/viewer/visual/entry_page_view.dart @@ -2,12 +2,11 @@ import 'dart:async'; import 'package:aves/image_providers/uri_picture_provider.dart'; import 'package:aves/model/entry.dart'; -import 'package:aves/model/entry_images.dart'; import 'package:aves/model/settings/entry_background.dart'; import 'package:aves/model/settings/enums.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/theme/durations.dart'; -import 'package:aves/widgets/collection/collection_page.dart'; +import 'package:aves/widgets/collection/thumbnail/raster.dart'; import 'package:aves/widgets/common/magnifier/controller/controller.dart'; import 'package:aves/widgets/common/magnifier/controller/state.dart'; import 'package:aves/widgets/common/magnifier/magnifier.dart'; @@ -213,8 +212,9 @@ class _EntryPageViewState extends State { duration: Durations.viewerVideoPlayerTransition, child: GestureDetector( onTap: _onTap, - child: Image( - image: entry.getBestThumbnail(settings.getTileExtent(CollectionPage.routeName)), + child: RasterImageThumbnail( + entry: entry, + extent: context.select((mq) => mq.size.shortestSide), fit: BoxFit.contain, ), ), diff --git a/lib/widgets/viewer/visual/raster.dart b/lib/widgets/viewer/visual/raster.dart index e1b7bb90a..72135831a 100644 --- a/lib/widgets/viewer/visual/raster.dart +++ b/lib/widgets/viewer/visual/raster.dart @@ -48,7 +48,7 @@ class _RasterImageViewState extends State { ViewState get viewState => viewStateNotifier.value; - ImageProvider get thumbnailProvider => entry.getBestThumbnail(settings.getTileExtent(CollectionPage.routeName)); + ImageProvider get thumbnailProvider => entry.bestCachedThumbnail; ImageProvider get fullImageProvider { if (entry.useTiles) {