mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-30 10:12:33 -04:00 
			
		
		
		
	refactor(mobile): Uses blurhash for memory card instead of blurred thumbnail (#7469)
* Uses blurhash for memory card instead of blurred thumbnail New blurred backdrop widget Comments * Fixes video placeholder image placement * unused import
This commit is contained in:
		
							parent
							
								
									908104299d
								
							
						
					
					
						commit
						b15eec7ca7
					
				| @ -40,7 +40,7 @@ class VideoViewerPage extends HookWidget { | |||||||
|       controlsSafeAreaMinimum: const EdgeInsets.only( |       controlsSafeAreaMinimum: const EdgeInsets.only( | ||||||
|         bottom: 100, |         bottom: 100, | ||||||
|       ), |       ), | ||||||
|       placeholder: placeholder, |       placeholder: SizedBox.expand(child: placeholder), | ||||||
|       showControls: showControls && !isMotionVideo, |       showControls: showControls && !isMotionVideo, | ||||||
|       hideControlsTimer: hideControlsTimer, |       hideControlsTimer: hideControlsTimer, | ||||||
|       customControls: const VideoPlayerControls(), |       customControls: const VideoPlayerControls(), | ||||||
| @ -58,7 +58,7 @@ class VideoViewerPage extends HookWidget { | |||||||
|             if (controller == null) { |             if (controller == null) { | ||||||
|               return Stack( |               return Stack( | ||||||
|                 children: [ |                 children: [ | ||||||
|                   if (placeholder != null) placeholder!, |                   if (placeholder != null) SizedBox.expand(child: placeholder!), | ||||||
|                   const DelayedLoadingIndicator( |                   const DelayedLoadingIndicator( | ||||||
|                     fadeInDuration: Duration(milliseconds: 500), |                     fadeInDuration: Duration(milliseconds: 500), | ||||||
|                   ), |                   ), | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| import 'dart:ui'; | import 'dart:ui'; | ||||||
| 
 | 
 | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  | import 'package:flutter_hooks/flutter_hooks.dart'; | ||||||
| import 'package:immich_mobile/extensions/build_context_extensions.dart'; | import 'package:immich_mobile/extensions/build_context_extensions.dart'; | ||||||
| import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart'; | import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart'; | ||||||
| import 'package:immich_mobile/shared/models/asset.dart'; | import 'package:immich_mobile/shared/models/asset.dart'; | ||||||
| import 'package:immich_mobile/shared/models/store.dart'; | import 'package:immich_mobile/shared/ui/hooks/blurhash_hook.dart'; | ||||||
| import 'package:immich_mobile/shared/ui/immich_image.dart'; | import 'package:immich_mobile/shared/ui/immich_image.dart'; | ||||||
| import 'package:immich_mobile/shared/ui/immich_thumbnail.dart'; |  | ||||||
| 
 | 
 | ||||||
| class MemoryCard extends StatelessWidget { | class MemoryCard extends StatelessWidget { | ||||||
|   final Asset asset; |   final Asset asset; | ||||||
| @ -22,8 +22,6 @@ class MemoryCard extends StatelessWidget { | |||||||
|     super.key, |     super.key, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   String get accessToken => Store.get(StoreKey.accessToken); |  | ||||||
| 
 |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Card( |     return Card( | ||||||
| @ -38,19 +36,8 @@ class MemoryCard extends StatelessWidget { | |||||||
|       clipBehavior: Clip.hardEdge, |       clipBehavior: Clip.hardEdge, | ||||||
|       child: Stack( |       child: Stack( | ||||||
|         children: [ |         children: [ | ||||||
|           ImageFiltered( |           SizedBox.expand( | ||||||
|             imageFilter: ImageFilter.blur(sigmaX: 30, sigmaY: 30), |             child: _BlurredBackdrop(asset: asset), | ||||||
|             child: Container( |  | ||||||
|               decoration: BoxDecoration( |  | ||||||
|                 image: DecorationImage( |  | ||||||
|                   image: ImmichThumbnail.imageProvider( |  | ||||||
|                     asset: asset, |  | ||||||
|                   ), |  | ||||||
|                   fit: BoxFit.cover, |  | ||||||
|                 ), |  | ||||||
|               ), |  | ||||||
|               child: Container(color: Colors.black.withOpacity(0.2)), |  | ||||||
|             ), |  | ||||||
|           ), |           ), | ||||||
|           LayoutBuilder( |           LayoutBuilder( | ||||||
|             builder: (context, constraints) { |             builder: (context, constraints) { | ||||||
| @ -113,3 +100,50 @@ class MemoryCard extends StatelessWidget { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | class _BlurredBackdrop extends HookWidget { | ||||||
|  |   final Asset asset; | ||||||
|  | 
 | ||||||
|  |   const _BlurredBackdrop({required this.asset}); | ||||||
|  | 
 | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     final blurhash = useBlurHashRef(asset).value; | ||||||
|  |     if (blurhash != null) { | ||||||
|  |       // Use a nice cheap blur hash image decoration | ||||||
|  |       return Container( | ||||||
|  |         decoration: BoxDecoration( | ||||||
|  |           image: DecorationImage( | ||||||
|  |             image: MemoryImage( | ||||||
|  |               blurhash, | ||||||
|  |             ), | ||||||
|  |             fit: BoxFit.cover, | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |         child: Container( | ||||||
|  |           color: Colors.black.withOpacity(0.2), | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  |     } else { | ||||||
|  |       // Fall back to using a more expensive image filtered | ||||||
|  |       // Since the ImmichImage is already precached, we can | ||||||
|  |       // safely use that as the image provider | ||||||
|  |       return ImageFiltered( | ||||||
|  |         imageFilter: ImageFilter.blur(sigmaX: 30, sigmaY: 30), | ||||||
|  |         child: Container( | ||||||
|  |           decoration: BoxDecoration( | ||||||
|  |             image: DecorationImage( | ||||||
|  |               image: ImmichImage.imageProvider( | ||||||
|  |                 asset: asset, | ||||||
|  |               ), | ||||||
|  |               fit: BoxFit.cover, | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |           child: Container( | ||||||
|  |             color: Colors.black.withOpacity(0.2), | ||||||
|  |           ), | ||||||
|  |         ), | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -10,7 +10,6 @@ import 'package:immich_mobile/modules/memories/ui/memory_epilogue.dart'; | |||||||
| import 'package:immich_mobile/modules/memories/ui/memory_progress_indicator.dart'; | import 'package:immich_mobile/modules/memories/ui/memory_progress_indicator.dart'; | ||||||
| import 'package:immich_mobile/shared/models/asset.dart'; | import 'package:immich_mobile/shared/models/asset.dart'; | ||||||
| import 'package:immich_mobile/shared/ui/immich_image.dart'; | import 'package:immich_mobile/shared/ui/immich_image.dart'; | ||||||
| import 'package:immich_mobile/shared/ui/immich_thumbnail.dart'; |  | ||||||
| 
 | 
 | ||||||
| @RoutePage() | @RoutePage() | ||||||
| class MemoryPage extends HookConsumerWidget { | class MemoryPage extends HookConsumerWidget { | ||||||
| @ -110,24 +109,13 @@ class MemoryPage extends HookConsumerWidget { | |||||||
|         asset = memories[nextMemoryIndex].assets.first; |         asset = memories[nextMemoryIndex].assets.first; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       // Gets the thumbnail url and precaches it |       // Precache the asset | ||||||
|       final precaches = <Future<dynamic>>[]; |       await precacheImage( | ||||||
| 
 |  | ||||||
|       precaches.addAll([ |  | ||||||
|         precacheImage( |  | ||||||
|         ImmichImage.imageProvider( |         ImmichImage.imageProvider( | ||||||
|           asset: asset, |           asset: asset, | ||||||
|         ), |         ), | ||||||
|         context, |         context, | ||||||
|         ), |       ); | ||||||
|         precacheImage( |  | ||||||
|           ImmichThumbnail.imageProvider( |  | ||||||
|             asset: asset, |  | ||||||
|           ), |  | ||||||
|           context, |  | ||||||
|         ), |  | ||||||
|       ]); |  | ||||||
|       await Future.wait(precaches); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Precache the next page right away if we are on the first page |     // Precache the next page right away if we are on the first page | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user