mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:29:32 -05: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(
 | 
				
			||||||
 | 
					        ImmichImage.imageProvider(
 | 
				
			||||||
      precaches.addAll([
 | 
					          asset: asset,
 | 
				
			||||||
        precacheImage(
 | 
					 | 
				
			||||||
          ImmichImage.imageProvider(
 | 
					 | 
				
			||||||
            asset: asset,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          context,
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        precacheImage(
 | 
					        context,
 | 
				
			||||||
          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