mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-01 19:17:12 -04:00 
			
		
		
		
	feat(mobile): Precaches next image in memories (#3365)
* Precaches images in memories * Fixes jumps and precaches images * refactors to move precacheAsset over to ImmichImage to keep logic in same place --------- Co-authored-by: Alex Tran <Alex.Tran@conductix.com>
This commit is contained in:
		
							parent
							
								
									ace755f264
								
							
						
					
					
						commit
						7f35583c2c
					
				| @ -5,7 +5,10 @@ import 'package:flutter_hooks/flutter_hooks.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:immich_mobile/modules/memories/models/memory.dart'; | ||||
| import 'package:immich_mobile/modules/memories/ui/memory_card.dart'; | ||||
| import 'package:immich_mobile/shared/models/asset.dart'; | ||||
| import 'package:immich_mobile/shared/ui/immich_image.dart'; | ||||
| import 'package:intl/intl.dart'; | ||||
| import 'package:openapi/api.dart' as api; | ||||
| 
 | ||||
| class MemoryPage extends HookConsumerWidget { | ||||
|   final List<Memory> memories; | ||||
| @ -37,11 +40,16 @@ class MemoryPage extends HookConsumerWidget { | ||||
|     } | ||||
| 
 | ||||
|     toNextAsset(int currentAssetIndex) { | ||||
|       (currentAssetIndex + 1 < currentMemory.value.assets.length) | ||||
|           ? memoryAssetPageController.jumpToPage( | ||||
|               (currentAssetIndex + 1), | ||||
|             ) | ||||
|           : toNextMemory(); | ||||
|       if (currentAssetIndex + 1 < currentMemory.value.assets.length) { | ||||
|         // Go to the next asset | ||||
|         memoryAssetPageController.nextPage( | ||||
|           curve: Curves.easeInOut, | ||||
|           duration: const Duration(milliseconds: 500), | ||||
|         ); | ||||
|       } else { | ||||
|         // Go to the next memory since we are at the end of our assets | ||||
|         toNextMemory(); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     updateProgressText() { | ||||
| @ -49,9 +57,67 @@ class MemoryPage extends HookConsumerWidget { | ||||
|           "${currentAssetPage.value + 1}|${currentMemory.value.assets.length}"; | ||||
|     } | ||||
| 
 | ||||
|     /// Downloads and caches the image for the asset at this [currentMemory]'s index | ||||
|     precacheAsset(int index) async { | ||||
|       // Guard index out of range | ||||
|       if (index < 0) { | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       late Asset asset; | ||||
|       if (index < currentMemory.value.assets.length) { | ||||
|         // Uses the next asset in this current memory | ||||
|         asset = currentMemory.value.assets[index]; | ||||
|       } else { | ||||
|         // Precache the first asset in the next memory if available | ||||
|         final currentMemoryIndex = memories.indexOf(currentMemory.value); | ||||
| 
 | ||||
|         // Guard no memory found | ||||
|         if (currentMemoryIndex == -1) { | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         final nextMemoryIndex = currentMemoryIndex + 1; | ||||
|         // Guard no next memory | ||||
|         if (nextMemoryIndex >= memories.length) { | ||||
|           return; | ||||
|         } | ||||
| 
 | ||||
|         // Get the first asset from the next memory | ||||
|         asset = memories[nextMemoryIndex].assets.first; | ||||
|       } | ||||
| 
 | ||||
|       // Gets the thumbnail url and precaches it | ||||
|       final precaches = <Future<dynamic>>[]; | ||||
| 
 | ||||
|       precaches.add( | ||||
|         ImmichImage.precacheAsset( | ||||
|           asset, | ||||
|           context, | ||||
|           type: api.ThumbnailFormat.WEBP, | ||||
|         ), | ||||
|       ); | ||||
|       precaches.add( | ||||
|         ImmichImage.precacheAsset( | ||||
|           asset, | ||||
|           context, | ||||
|           type: api.ThumbnailFormat.JPEG, | ||||
|         ), | ||||
|       ); | ||||
| 
 | ||||
|       await Future.wait(precaches); | ||||
|     } | ||||
| 
 | ||||
|     // Precache the next page right away if we are on the first page | ||||
|     if (currentAssetPage.value == 0) { | ||||
|       Future.delayed(const Duration(milliseconds: 200)) | ||||
|           .then((_) => precacheAsset(1)); | ||||
|     } | ||||
| 
 | ||||
|     onAssetChanged(int otherIndex) { | ||||
|       HapticFeedback.selectionClick(); | ||||
|       currentAssetPage.value = otherIndex; | ||||
|       precacheAsset(otherIndex + 1); | ||||
|       updateProgressText(); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -147,4 +147,46 @@ class ImmichImage extends StatelessWidget { | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   /// Precaches this asset for instant load the next time it is shown | ||||
|   static Future<void> precacheAsset( | ||||
|     Asset asset, | ||||
|     BuildContext context, { | ||||
|     type = api.ThumbnailFormat.WEBP, | ||||
|   }) { | ||||
|     final authToken = 'Bearer ${Store.get(StoreKey.accessToken)}'; | ||||
| 
 | ||||
|     if (type == api.ThumbnailFormat.WEBP) { | ||||
|       final thumbnailUrl = getThumbnailUrl(asset); | ||||
|       final thumbnailCacheKey = getThumbnailCacheKey(asset); | ||||
|       final thumbnailProvider = CachedNetworkImageProvider( | ||||
|         thumbnailUrl, | ||||
|         cacheKey: thumbnailCacheKey, | ||||
|         headers: {"Authorization": authToken}, | ||||
|       ); | ||||
|       return precacheImage(thumbnailProvider, context); | ||||
|     } | ||||
|     // Precache the local image | ||||
|     if (!asset.isRemote && | ||||
|         (asset.isLocal || !Store.get(StoreKey.preferRemoteImage, false))) { | ||||
|       final provider = AssetEntityImageProvider( | ||||
|         asset.local!, | ||||
|         isOriginal: false, | ||||
|         thumbnailSize: const ThumbnailSize.square(250), // like server thumbs | ||||
|       ); | ||||
|       return precacheImage(provider, context); | ||||
|     } else { | ||||
|       // Precache the remote image since we are not using local images | ||||
|       final url = getThumbnailUrl(asset, type: api.ThumbnailFormat.JPEG); | ||||
|       final cacheKey = | ||||
|           getThumbnailCacheKey(asset, type: api.ThumbnailFormat.JPEG); | ||||
|       final provider = CachedNetworkImageProvider( | ||||
|         url, | ||||
|         cacheKey: cacheKey, | ||||
|         headers: {"Authorization": authToken}, | ||||
|       ); | ||||
| 
 | ||||
|       return precacheImage(provider, context); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user