From b1a896ba612a90320168541c2c289dc73aa6edbb Mon Sep 17 00:00:00 2001 From: martyfuhry Date: Wed, 28 Feb 2024 17:13:15 -0500 Subject: [PATCH] feat(mobile): Adds better precaching for assets in gallery view and memory lane (#7486) Adds better precaching for assets in gallery view and memory lane --- .../asset_viewer/views/gallery_viewer.dart | 30 +++++++++++++++---- .../modules/memories/views/memory_page.dart | 7 +++-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart index e296483cc2..dfdfb32844 100644 --- a/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart +++ b/mobile/lib/modules/asset_viewer/views/gallery_viewer.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'dart:math'; import 'dart:ui' as ui; @@ -132,7 +133,7 @@ class GalleryViewerPage extends HookConsumerWidget { void toggleFavorite(Asset asset) => ref.read(assetProvider.notifier).toggleFavorite([asset]); - void precacheNextImage(int index) { + Future precacheNextImage(int index) async { void onError(Object exception, StackTrace? stackTrace) { // swallow error silently debugPrint('Error precaching next image: $exception, $stackTrace'); @@ -140,7 +141,7 @@ class GalleryViewerPage extends HookConsumerWidget { if (index < totalAssets && index >= 0) { final asset = loadAsset(index); - precacheImage( + await precacheImage( ImmichImage.imageProvider(asset: asset), context, onError: onError, @@ -711,6 +712,21 @@ class GalleryViewerPage extends HookConsumerWidget { [], ); + useEffect( + () { + // No need to await this + unawaited( + // Delay this a bit so we can finish loading the page + Future.delayed(const Duration(milliseconds: 400)).then( + // Precache the next image + (_) => precacheNextImage(currentIndex.value + 1), + ), + ); + return null; + }, + [], + ); + ref.listen(showControlsProvider, (_, show) { if (show) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); @@ -761,12 +777,16 @@ class GalleryViewerPage extends HookConsumerWidget { ), itemCount: totalAssets, scrollDirection: Axis.horizontal, - onPageChanged: (value) { + onPageChanged: (value) async { final next = currentIndex.value < value ? value + 1 : value - 1; - precacheNextImage(next); + HapticFeedback.selectionClick(); currentIndex.value = value; stackIndex.value = -1; - HapticFeedback.selectionClick(); + + // Wait for page change animation to finish + await Future.delayed(const Duration(milliseconds: 400)); + // Then precache the next image + unawaited(precacheNextImage(next)); }, builder: (context, index) { final a = diff --git a/mobile/lib/modules/memories/views/memory_page.dart b/mobile/lib/modules/memories/views/memory_page.dart index 9308e812dc..d06bb959ee 100644 --- a/mobile/lib/modules/memories/views/memory_page.dart +++ b/mobile/lib/modules/memories/views/memory_page.dart @@ -124,11 +124,14 @@ class MemoryPage extends HookConsumerWidget { .then((_) => precacheAsset(1)); } - onAssetChanged(int otherIndex) { + Future onAssetChanged(int otherIndex) async { HapticFeedback.selectionClick(); currentAssetPage.value = otherIndex; - precacheAsset(otherIndex + 1); updateProgressText(); + // Wait for page change animation to finish + await Future.delayed(const Duration(milliseconds: 400)); + // And then precache the next asset + await precacheAsset(otherIndex + 1); } /* Notification listener is used instead of OnPageChanged callback since OnPageChanged is called