Просмотр исходного кода

feat(mobile): Scroll to top when tapping photos while already on photo page (#1784)

* adds scroll to top when tapping photos while already on photo page

* unused import
martyfuhry 2 лет назад
Родитель
Сommit
6e9749d6c4

+ 9 - 0
mobile/lib/modules/asset_viewer/providers/scroll_notifier.provider.dart

@@ -0,0 +1,9 @@
+import 'package:flutter/material.dart';
+
+final scrollToTopNotifierProvider = ScrollNotifier();
+
+class ScrollNotifier with ChangeNotifier {
+  void scrollToTop() {
+    notifyListeners();
+  }
+}

+ 25 - 0
mobile/lib/modules/home/ui/asset_grid/immich_asset_grid.dart

@@ -3,6 +3,7 @@ import 'dart:collection';
 import 'package:collection/collection.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:immich_mobile/modules/asset_viewer/providers/scroll_notifier.provider.dart';
 import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart';
 import 'package:immich_mobile/shared/models/asset.dart';
 import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
@@ -234,6 +235,30 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
     return true;
   }
 
+  @override
+  void initState() {
+    super.initState();
+    scrollToTopNotifierProvider.addListener(_scrollToTop);
+  }
+
+  @override
+  void dispose() {
+    scrollToTopNotifierProvider.removeListener(_scrollToTop);
+    super.dispose();
+  }
+
+  void _scrollToTop() {
+    // for some reason, this is necessary as well in order 
+    // to correctly reposition the drag thumb scroll bar
+    _itemScrollController.jumpTo(
+      index: 0,
+    );
+    _itemScrollController.scrollTo(
+      index: 0,
+      duration: const Duration(milliseconds: 200),
+    );
+  }
+
   @override
   Widget build(BuildContext context) {
     return WillPopScope(

+ 11 - 42
mobile/lib/shared/views/tab_controller_page.dart

@@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/modules/asset_viewer/providers/scroll_notifier.provider.dart';
 import 'package:immich_mobile/modules/home/providers/multiselect.provider.dart';
 import 'package:immich_mobile/routing/router.dart';
 
@@ -16,6 +17,11 @@ class TabControllerPage extends ConsumerWidget {
         labelType: NavigationRailLabelType.all,
         selectedIndex: tabsRouter.activeIndex,
         onDestinationSelected: (index) {
+          // Selected Photos while it is active
+          if (tabsRouter.activeIndex == 0 && index == 0) {
+            // Scroll to top
+            scrollToTopNotifierProvider.scrollToTop();
+          }
           HapticFeedback.selectionClick();
           tabsRouter.setActiveIndex(index);
         },
@@ -60,51 +66,14 @@ class TabControllerPage extends ConsumerWidget {
       );
     }
 
-    // ignore: unused_element
     bottomNavigationBar(TabsRouter tabsRouter) {
-      return BottomNavigationBar(
-        selectedLabelStyle: const TextStyle(
-          fontSize: 13,
-          fontWeight: FontWeight.w600,
-        ),
-        unselectedLabelStyle: const TextStyle(
-          fontSize: 13,
-          fontWeight: FontWeight.w600,
-        ),
-        currentIndex: tabsRouter.activeIndex,
-        onTap: (index) {
-          HapticFeedback.selectionClick();
-          tabsRouter.setActiveIndex(index);
-        },
-        items: [
-          BottomNavigationBarItem(
-            label: 'tab_controller_nav_photos'.tr(),
-            icon: const Icon(Icons.photo_outlined),
-            activeIcon: const Icon(Icons.photo),
-          ),
-          BottomNavigationBarItem(
-            label: 'tab_controller_nav_search'.tr(),
-            icon: const Icon(Icons.search_rounded),
-            activeIcon: const Icon(Icons.search),
-          ),
-          BottomNavigationBarItem(
-            label: 'tab_controller_nav_sharing'.tr(),
-            icon: const Icon(Icons.group_outlined),
-            activeIcon: const Icon(Icons.group),
-          ),
-          BottomNavigationBarItem(
-            label: 'tab_controller_nav_library'.tr(),
-            icon: const Icon(Icons.photo_album_outlined),
-            activeIcon: const Icon(Icons.photo_album_rounded),
-          )
-        ],
-      );
-    }
-
-    experimentalNavigationBar(TabsRouter tabsRouter) {
       return NavigationBar(
         selectedIndex: tabsRouter.activeIndex,
         onDestinationSelected: (index) {
+          if (tabsRouter.activeIndex == 0 && index == 0) {
+            // Scroll to top
+            scrollToTopNotifierProvider.scrollToTop();
+          }
           HapticFeedback.selectionClick();
           tabsRouter.setActiveIndex(index);
         },
@@ -179,7 +148,7 @@ class TabControllerPage extends ConsumerWidget {
               final Widget body;
               if (constraints.maxWidth < medium) {
                 // Normal phone width
-                bottom = experimentalNavigationBar(tabsRouter);
+                bottom = bottomNavigationBar(tabsRouter);
                 body = FadeTransition(
                   opacity: animation,
                   child: child,