From bc31b7c06c0245708ff27b2b278edbfa0a526328 Mon Sep 17 00:00:00 2001
From: Alex <alex.tran1502@gmail.com>
Date: Sun, 18 Aug 2024 21:27:19 -0500
Subject: [PATCH] feat(mobile): memories lane with the new CarouselView
 (#11892)

* feat(mobile): memories lane with the new CarouselView

* tuning

* tuning
---
 mobile/lib/widgets/memories/memory_lane.dart | 157 ++++++++++---------
 1 file changed, 85 insertions(+), 72 deletions(-)

diff --git a/mobile/lib/widgets/memories/memory_lane.dart b/mobile/lib/widgets/memories/memory_lane.dart
index 4d4fa8c4e0..41e9cc628e 100644
--- a/mobile/lib/widgets/memories/memory_lane.dart
+++ b/mobile/lib/widgets/memories/memory_lane.dart
@@ -1,6 +1,8 @@
 import 'package:auto_route/auto_route.dart';
+import 'package:collection/collection.dart';
 import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/models/memories/memory.model.dart';
 import 'package:immich_mobile/widgets/asset_grid/thumbnail_placeholder.dart';
 import 'package:immich_mobile/providers/memory.provider.dart';
 import 'package:immich_mobile/routing/router.dart';
@@ -9,6 +11,7 @@ import 'package:immich_mobile/widgets/common/immich_image.dart';
 
 class MemoryLane extends HookConsumerWidget {
   const MemoryLane({super.key});
+
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     final memoryLaneFutureProvider = ref.watch(memoryFutureProvider);
@@ -16,82 +19,35 @@ class MemoryLane extends HookConsumerWidget {
     final memoryLane = memoryLaneFutureProvider
         .whenData(
           (memories) => memories != null
-              ? SizedBox(
-                  height: 200,
-                  child: ListView.builder(
-                    scrollDirection: Axis.horizontal,
-                    shrinkWrap: true,
-                    itemCount: memories.length,
-                    padding: const EdgeInsets.only(
-                      right: 8.0,
-                      bottom: 8,
-                      top: 10,
-                      left: 10,
+              ? ConstrainedBox(
+                  constraints: const BoxConstraints(
+                    maxHeight: 200,
+                  ),
+                  child: CarouselView(
+                    itemExtent: 145.0,
+                    shrinkExtent: 1.0,
+                    elevation: 2,
+                    backgroundColor: Colors.black,
+                    overlayColor: WidgetStateProperty.all(
+                      Colors.white.withOpacity(0.1),
                     ),
-                    itemBuilder: (context, index) {
-                      final memory = memories[index];
-
-                      return GestureDetector(
-                        onTap: () {
-                          ref
-                              .read(hapticFeedbackProvider.notifier)
-                              .heavyImpact();
-                          context.pushRoute(
-                            MemoryRoute(
-                              memories: memories,
-                              memoryIndex: index,
-                            ),
-                          );
-                        },
-                        child: Stack(
-                          children: [
-                            Card(
-                              elevation: 3,
-                              shape: RoundedRectangleBorder(
-                                borderRadius: BorderRadius.circular(13.0),
-                              ),
-                              clipBehavior: Clip.hardEdge,
-                              child: ColorFiltered(
-                                colorFilter: ColorFilter.mode(
-                                  Colors.black.withOpacity(0.2),
-                                  BlendMode.darken,
-                                ),
-                                child: Hero(
-                                  tag: 'memory-${memory.assets[0].id}',
-                                  child: ImmichImage(
-                                    memory.assets[0],
-                                    fit: BoxFit.cover,
-                                    width: 130,
-                                    height: 200,
-                                    placeholder: const ThumbnailPlaceholder(
-                                      width: 130,
-                                      height: 200,
-                                    ),
-                                  ),
-                                ),
-                              ),
-                            ),
-                            Positioned(
-                              bottom: 16,
-                              left: 16,
-                              child: ConstrainedBox(
-                                constraints: const BoxConstraints(
-                                  maxWidth: 114,
-                                ),
-                                child: Text(
-                                  memory.title,
-                                  style: const TextStyle(
-                                    fontWeight: FontWeight.w600,
-                                    color: Colors.white,
-                                    fontSize: 15,
-                                  ),
-                                ),
-                              ),
-                            ),
-                          ],
+                    onTap: (memoryIndex) {
+                      ref.read(hapticFeedbackProvider.notifier).heavyImpact();
+                      context.pushRoute(
+                        MemoryRoute(
+                          memories: memories,
+                          memoryIndex: memoryIndex,
                         ),
                       );
                     },
+                    children: memories
+                        .mapIndexed<Widget>(
+                          (index, memory) => MemoryCard(
+                            index: index,
+                            memory: memory,
+                          ),
+                        )
+                        .toList(),
                   ),
                 )
               : const SizedBox(),
@@ -101,3 +57,60 @@ class MemoryLane extends HookConsumerWidget {
     return memoryLane ?? const SizedBox();
   }
 }
+
+class MemoryCard extends ConsumerWidget {
+  const MemoryCard({
+    super.key,
+    required this.index,
+    required this.memory,
+  });
+
+  final int index;
+  final Memory memory;
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    return Center(
+      child: Stack(
+        children: [
+          ColorFiltered(
+            colorFilter: ColorFilter.mode(
+              Colors.black.withOpacity(0.2),
+              BlendMode.darken,
+            ),
+            child: Hero(
+              tag: 'memory-${memory.assets[0].id}',
+              child: ImmichImage(
+                memory.assets[0],
+                fit: BoxFit.cover,
+                width: 205,
+                height: 200,
+                placeholder: const ThumbnailPlaceholder(
+                  width: 105,
+                  height: 200,
+                ),
+              ),
+            ),
+          ),
+          Positioned(
+            bottom: 16,
+            left: 16,
+            child: ConstrainedBox(
+              constraints: const BoxConstraints(
+                maxWidth: 114,
+              ),
+              child: Text(
+                memory.title,
+                style: const TextStyle(
+                  fontWeight: FontWeight.w600,
+                  color: Colors.white,
+                  fontSize: 15,
+                ),
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}