Browse Source

Improve scrolling performance in albums and search

Matthias Rupp 2 years ago
parent
commit
8440d9890c

+ 14 - 51
mobile/lib/modules/album/views/album_viewer_page.dart

@@ -1,9 +1,12 @@
+import 'dart:math';
+
 import 'package:auto_route/auto_route.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/ui/draggable_scrollbar.dart';
+import 'package:immich_mobile/modules/home/ui/asset_list_v2/asset_grid_data_structure.dart';
+import 'package:immich_mobile/modules/home/ui/asset_list_v2/immich_asset_grid.dart';
 import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
 import 'package:immich_mobile/modules/album/providers/asset_selection.provider.dart';
@@ -12,12 +15,10 @@ import 'package:immich_mobile/modules/album/services/album.service.dart';
 import 'package:immich_mobile/modules/album/ui/album_action_outlined_button.dart';
 import 'package:immich_mobile/modules/album/ui/album_viewer_appbar.dart';
 import 'package:immich_mobile/modules/album/ui/album_viewer_editable_title.dart';
-import 'package:immich_mobile/modules/album/ui/album_viewer_thumbnail.dart';
 import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
 import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 import 'package:immich_mobile/routing/router.dart';
 import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
-import 'package:immich_mobile/shared/ui/immich_sliver_persistent_app_bar_delegate.dart';
 import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
 import 'package:openapi/api.dart';
 
@@ -28,6 +29,7 @@ class AlbumViewerPage extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final appSettingService = ref.watch(appSettingsServiceProvider);
     FocusNode titleFocusNode = useFocusNode();
     ScrollController scrollController = useScrollController();
     var albumInfo = ref.watch(sharedAlbumDetailProvider(albumId));
@@ -188,34 +190,17 @@ class AlbumViewerPage extends HookConsumerWidget {
     }
 
     Widget _buildImageGrid(AlbumResponseDto albumInfo) {
-      final appSettingService = ref.watch(appSettingsServiceProvider);
+      final assetsPerRow =
+          appSettingService.getSetting(AppSettingsEnum.tilesPerRow);
       final bool showStorageIndicator =
           appSettingService.getSetting(AppSettingsEnum.storageIndicator);
+      final renderList = assetsToRenderList(albumInfo.assets, assetsPerRow);
 
-      if (albumInfo.assets.isNotEmpty) {
-        return SliverPadding(
-          padding: const EdgeInsets.only(top: 10.0),
-          sliver: SliverGrid(
-            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-              crossAxisCount:
-                  appSettingService.getSetting(AppSettingsEnum.tilesPerRow),
-              crossAxisSpacing: 5.0,
-              mainAxisSpacing: 5,
-            ),
-            delegate: SliverChildBuilderDelegate(
-              (BuildContext context, int index) {
-                return AlbumViewerThumbnail(
-                  asset: albumInfo.assets[index],
-                  assetList: albumInfo.assets,
-                  showStorageIndicator: showStorageIndicator,
-                );
-              },
-              childCount: albumInfo.assetCount,
-            ),
-          ),
-        );
-      }
-      return const SliverToBoxAdapter();
+      return ImmichAssetGrid(
+        assetsPerRow: assetsPerRow,
+        renderList: renderList,
+        showStorageIndicator: showStorageIndicator,
+      );
     }
 
     Widget _buildControlButton(AlbumResponseDto albumInfo) {
@@ -248,29 +233,7 @@ class AlbumViewerPage extends HookConsumerWidget {
         onTap: () {
           titleFocusNode.unfocus();
         },
-        child: DraggableScrollbar.semicircle(
-          backgroundColor: Theme.of(context).hintColor,
-          controller: scrollController,
-          heightScrollThumb: 48.0,
-          child: CustomScrollView(
-            controller: scrollController,
-            slivers: [
-              _buildHeader(albumInfo),
-              SliverPersistentHeader(
-                pinned: true,
-                delegate: ImmichSliverPersistentAppBarDelegate(
-                  minHeight: 50,
-                  maxHeight: 50,
-                  child: Container(
-                    color: Theme.of(context).scaffoldBackgroundColor,
-                    child: _buildControlButton(albumInfo),
-                  ),
-                ),
-              ),
-              _buildImageGrid(albumInfo)
-            ],
-          ),
-        ),
+        child: _buildImageGrid(albumInfo),
       );
     }
 

+ 1 - 29
mobile/lib/modules/home/providers/home_page_render_list_provider.dart

@@ -1,38 +1,10 @@
 import 'dart:math';
 
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/modules/home/ui/asset_list_v2/asset_grid_data_structure.dart';
 import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
 import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
 import 'package:immich_mobile/shared/providers/asset.provider.dart';
-import 'package:openapi/api.dart';
-
-enum RenderAssetGridElementType {
-  assetRow,
-  dayTitle,
-  monthTitle;
-}
-
-class RenderAssetGridRow {
-  final List<AssetResponseDto> assets;
-
-  RenderAssetGridRow(this.assets);
-}
-
-class RenderAssetGridElement {
-  final RenderAssetGridElementType type;
-  final RenderAssetGridRow? assetRow;
-  final String? title;
-  final DateTime date;
-  final List<AssetResponseDto>? relatedAssetList;
-
-  RenderAssetGridElement(
-    this.type, {
-    this.assetRow,
-    this.title,
-    required this.date,
-    this.relatedAssetList,
-  });
-}
 
 final renderListProvider = StateProvider((ref) {
   var assetGroups = ref.watch(assetGroupByDateTimeProvider);

+ 55 - 0
mobile/lib/modules/home/ui/asset_list_v2/asset_grid_data_structure.dart

@@ -0,0 +1,55 @@
+import 'dart:math';
+
+import 'package:openapi/api.dart';
+
+enum RenderAssetGridElementType {
+  assetRow,
+  dayTitle,
+  monthTitle;
+}
+
+class RenderAssetGridRow {
+  final List<AssetResponseDto> assets;
+
+  RenderAssetGridRow(this.assets);
+}
+
+class RenderAssetGridElement {
+  final RenderAssetGridElementType type;
+  final RenderAssetGridRow? assetRow;
+  final String? title;
+  final DateTime date;
+  final List<AssetResponseDto>? relatedAssetList;
+
+  RenderAssetGridElement(
+    this.type, {
+    this.assetRow,
+    this.title,
+    required this.date,
+    this.relatedAssetList,
+  });
+}
+
+List<RenderAssetGridElement> assetsToRenderList(
+    List<AssetResponseDto> assets, int assetsPerRow) {
+  List<RenderAssetGridElement> elements = [];
+
+  int cursor = 0;
+  while (cursor < assets.length) {
+    int rowElements = min(assets.length - cursor, assetsPerRow);
+    final date = DateTime.parse(assets[cursor].createdAt);
+
+    final rowElement = RenderAssetGridElement(
+      RenderAssetGridElementType.assetRow,
+      date: date,
+      assetRow: RenderAssetGridRow(
+        assets.sublist(cursor, cursor + rowElements),
+      ),
+    );
+
+    elements.add(rowElement);
+    cursor += rowElements;
+  }
+
+  return elements;
+}

+ 1 - 1
mobile/lib/modules/home/ui/asset_list_v2/immich_asset_grid.dart

@@ -7,13 +7,13 @@ import 'package:flutter/material.dart';
 import 'package:flutter/src/widgets/framework.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_render_list_provider.dart';
 import 'package:immich_mobile/modules/home/ui/asset_list_v2/daily_title_text.dart';
 import 'package:immich_mobile/modules/home/ui/asset_list_v2/draggable_scrollbar_custom.dart';
 import 'package:openapi/api.dart';
 import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
 
 import '../thumbnail_image.dart';
+import 'asset_grid_data_structure.dart';
 
 class ImmichAssetGrid extends HookConsumerWidget {
   final ItemScrollController _itemScrollController = ItemScrollController();