فهرست منبع

feat(mobile): Home screen customization options (#1563)

* Try staggered layout for home page

* Introduce setting for dynamic layout

* Fix some provider related bugs

* Make asset grouping configurable

* Add translation keys, refactor group title

* Rename enum values

* Fix enum names

* Reformat long if statement

* Fix timezone related bug

* Minor clean up

* Fix unit test

* Add second assets check back to home screen
Matthias Rupp 2 سال پیش
والد
کامیت
fd13265131

+ 5 - 1
mobile/assets/i18n/en-US.json

@@ -12,6 +12,10 @@
   "album_viewer_appbar_share_leave": "Leave album",
   "album_viewer_appbar_share_remove": "Remove from album",
   "album_viewer_page_share_add_users": "Add users",
+  "asset_list_layout_settings_dynamic_layout_title": "Dynamic layout",
+  "asset_list_layout_settings_group_by": "Group assets by",
+  "asset_list_layout_settings_group_by_month_day": "Month + day",
+  "asset_list_layout_settings_group_by_month": "Month",
   "asset_list_settings_subtitle": "Photo grid layout settings",
   "asset_list_settings_title": "Photo Grid",
   "backup_album_selection_page_albums_device": "Albums on device ({})",
@@ -199,4 +203,4 @@
   "version_announcement_overlay_text_2": "please take your time to visit the ",
   "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.",
   "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89"
-}
+}

+ 98 - 41
mobile/lib/modules/home/ui/asset_grid/asset_grid_data_structure.dart

@@ -1,5 +1,6 @@
 import 'dart:math';
 
+import 'package:collection/collection.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/foundation.dart';
 import 'package:immich_mobile/shared/models/asset.dart';
@@ -9,14 +10,15 @@ final log = Logger('AssetGridDataStructure');
 
 enum RenderAssetGridElementType {
   assetRow,
-  dayTitle,
+  groupDividerTitle,
   monthTitle;
 }
 
 class RenderAssetGridRow {
   final List<Asset> assets;
+  final List<double> widthDistribution;
 
-  RenderAssetGridRow(this.assets);
+  RenderAssetGridRow(this.assets, this.widthDistribution);
 }
 
 class RenderAssetGridElement {
@@ -35,19 +37,36 @@ class RenderAssetGridElement {
   });
 }
 
+enum GroupAssetsBy {
+  day,
+  month;
+}
+
+class AssetGridLayoutParameters {
+  final int perRow;
+  final bool dynamicLayout;
+  final GroupAssetsBy groupBy;
+
+  AssetGridLayoutParameters(
+    this.perRow,
+    this.dynamicLayout,
+    this.groupBy,
+  );
+}
+
 class _AssetGroupsToRenderListComputeParameters {
   final String monthFormat;
   final String dayFormat;
   final String dayFormatYear;
-  final Map<String, List<Asset>> groups;
-  final int perRow;
+  final List<Asset> assets;
+  final AssetGridLayoutParameters layout;
 
   _AssetGroupsToRenderListComputeParameters(
     this.monthFormat,
     this.dayFormat,
     this.dayFormatYear,
-    this.groups,
-    this.perRow,
+    this.assets,
+    this.layout,
   );
 }
 
@@ -56,62 +75,75 @@ class RenderList {
 
   RenderList(this.elements);
 
+  static Map<String, List<Asset>> _groupAssets(
+    List<Asset> assets,
+    GroupAssetsBy groupBy,
+  ) {
+    assets.sortByCompare<DateTime>(
+      (e) => e.createdAt,
+      (a, b) => b.compareTo(a),
+    );
+
+    if (groupBy == GroupAssetsBy.day) {
+      return assets.groupListsBy(
+        (element) => DateFormat('y-MM-dd').format(element.createdAt.toLocal()),
+      );
+    } else if (groupBy == GroupAssetsBy.month) {
+      return assets.groupListsBy(
+        (element) => DateFormat('y-MM').format(element.createdAt.toLocal()),
+      );
+    }
+
+    return {};
+  }
+
   static Future<RenderList> _processAssetGroupData(
     _AssetGroupsToRenderListComputeParameters data,
   ) async {
     final monthFormat = DateFormat(data.monthFormat);
     final dayFormatSameYear = DateFormat(data.dayFormat);
     final dayFormatOtherYear = DateFormat(data.dayFormatYear);
-    final groups = data.groups;
-    final perRow = data.perRow;
+    final allAssets = data.assets;
+    final perRow = data.layout.perRow;
+    final dynamicLayout = data.layout.dynamicLayout;
+    final groupBy = data.layout.groupBy;
 
     List<RenderAssetGridElement> elements = [];
     DateTime? lastDate;
 
+    final groups = _groupAssets(allAssets, groupBy);
+
     groups.forEach((groupName, assets) {
       try {
-        final date = DateTime.parse(groupName);
-
-        if (lastDate == null || lastDate!.month != date.month) {
-          // Month title
-
-          var monthTitleText = groupName;
-
-          var groupDate = DateTime.tryParse(groupName);
-          if (groupDate != null) {
-            monthTitleText = monthFormat.format(groupDate);
-          } else {
-            log.severe("Failed to format date for day title: $groupName");
-          }
+        final date = assets.first.createdAt.toLocal();
 
+        // Month title
+        if (groupBy == GroupAssetsBy.day &&
+            (lastDate == null || lastDate!.month != date.month)) {
           elements.add(
             RenderAssetGridElement(
               RenderAssetGridElementType.monthTitle,
-              title: monthTitleText,
+              title: monthFormat.format(date),
               date: date,
             ),
           );
         }
 
-        // Add group title
-        var currentYear = DateTime.now().year;
-        var groupYear = DateTime.parse(groupName).year;
-        var formatDate =
-            currentYear == groupYear ? dayFormatSameYear : dayFormatOtherYear;
+        // Group divider title (day or month)
+        var formatDate = dayFormatOtherYear;
 
-        var dateText = groupName;
+        if (DateTime.now().year == date.year) {
+          formatDate = dayFormatSameYear;
+        }
 
-        var groupDate = DateTime.tryParse(groupName);
-        if (groupDate != null) {
-          dateText = formatDate.format(groupDate);
-        } else {
-          log.severe("Failed to format date for day title: $groupName");
+        if (groupBy == GroupAssetsBy.month) {
+          formatDate = monthFormat;
         }
 
         elements.add(
           RenderAssetGridElement(
-            RenderAssetGridElementType.dayTitle,
-            title: dateText,
+            RenderAssetGridElementType.groupDividerTitle,
+            title: formatDate.format(date),
             date: date,
             relatedAssetList: assets,
           ),
@@ -121,12 +153,37 @@ class RenderList {
         int cursor = 0;
         while (cursor < assets.length) {
           int rowElements = min(assets.length - cursor, perRow);
+          final rowAssets = assets.sublist(cursor, cursor + rowElements);
+
+          // Default: All assets have the same width
+          var widthDistribution = List.filled(rowElements, 1.0);
+
+          if (dynamicLayout) {
+            final aspectRatios =
+                rowAssets.map((e) => (e.width ?? 1) / (e.height ?? 1)).toList();
+            final meanAspectRatio = aspectRatios.sum / rowElements;
+
+            // 1: mean width
+            // 0.5: width < mean - threshold
+            // 1.5: width > mean + threshold
+            final arConfiguration = aspectRatios.map((e) {
+              if (e - meanAspectRatio > 0.3) return 1.5;
+              if (e - meanAspectRatio < -0.3) return 0.5;
+              return 1.0;
+            });
+
+            // Normalize:
+            final sum = arConfiguration.sum;
+            widthDistribution =
+                arConfiguration.map((e) => (e * rowElements) / sum).toList();
+          }
 
           final rowElement = RenderAssetGridElement(
             RenderAssetGridElementType.assetRow,
             date: date,
             assetRow: RenderAssetGridRow(
-              assets.sublist(cursor, cursor + rowElements),
+              rowAssets,
+              widthDistribution,
             ),
           );
 
@@ -143,9 +200,9 @@ class RenderList {
     return RenderList(elements);
   }
 
-  static Future<RenderList> fromAssetGroups(
-    Map<String, List<Asset>> assetGroups,
-    int assetsPerRow,
+  static Future<RenderList> fromAssets(
+    List<Asset> assets,
+    AssetGridLayoutParameters layout,
   ) async {
     // Compute only allows for one parameter. Therefore we pass all parameters in a map
     return compute(
@@ -154,8 +211,8 @@ class RenderList {
         "monthly_title_text_date_format".tr(),
         "daily_title_text_date".tr(),
         "daily_title_text_date_year".tr(),
-        assetGroups,
-        assetsPerRow,
+        assets,
+        layout,
       ),
     );
   }

+ 2 - 2
mobile/lib/modules/home/ui/asset_grid/daily_title_text.dart → mobile/lib/modules/home/ui/asset_grid/group_divider_title.dart

@@ -1,8 +1,8 @@
 import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 
-class DailyTitleText extends ConsumerWidget {
-  const DailyTitleText({
+class GroupDividerTitle extends ConsumerWidget {
+  const GroupDividerTitle({
     Key? key,
     required this.text,
     required this.multiselectEnabled,

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

@@ -7,7 +7,7 @@ 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';
 import 'asset_grid_data_structure.dart';
-import 'daily_title_text.dart';
+import 'group_divider_title.dart';
 import 'disable_multi_select_button.dart';
 import 'draggable_scrollbar_custom.dart';
 
@@ -99,12 +99,12 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
           widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow;
         return Row(
           key: Key("asset-row-${row.assets.first.id}"),
-          children: row.assets.map((Asset asset) {
+          children: row.assets.mapIndexed((int index, Asset asset) {
             bool last = asset.id == row.assets.last.id;
 
             return Container(
               key: Key("asset-${asset.id}"),
-              width: size,
+              width: size * row.widthDistribution[index],
               height: size,
               margin: EdgeInsets.only(
                 top: widget.margin,
@@ -123,7 +123,7 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
     String title,
     List<Asset> assets,
   ) {
-    return DailyTitleText(
+    return GroupDividerTitle(
       text: title,
       multiselectEnabled: widget.selectionActive,
       onSelect: () => _selectAssets(assets),
@@ -150,7 +150,7 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
   Widget _itemBuilder(BuildContext c, int position) {
     final item = widget.renderList.elements[position];
 
-    if (item.type == RenderAssetGridElementType.dayTitle) {
+    if (item.type == RenderAssetGridElementType.groupDividerTitle) {
       return _buildTitle(c, item.title!, item.relatedAssetList!);
     } else if (item.type == RenderAssetGridElementType.monthTitle) {
       return _buildMonthTitle(c, item.title!);

+ 2 - 2
mobile/lib/modules/home/views/home_page.dart

@@ -220,8 +220,8 @@ class HomePage extends HookConsumerWidget {
         top: true,
         child: Stack(
           children: [
-            ref.watch(assetProvider).renderList == null ||
-                    ref.watch(assetProvider).allAssets.isEmpty
+            ref.watch(assetProvider).renderList == null
+                || ref.watch(assetProvider).allAssets.isEmpty
                 ? buildLoadingIndicator()
                 : ImmichAssetGrid(
                     renderList: ref.watch(assetProvider).renderList!,

+ 9 - 18
mobile/lib/modules/search/providers/search_result_page.provider.dart

@@ -1,4 +1,3 @@
-import 'package:collection/collection.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
 import 'package:immich_mobile/modules/search/models/search_result_page_state.model.dart';
@@ -7,7 +6,6 @@ import 'package:immich_mobile/modules/search/services/search.service.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/models/asset.dart';
-import 'package:intl/intl.dart';
 
 class SearchResultPageNotifier extends StateNotifier<SearchResultPageState> {
   SearchResultPageNotifier(this._searchService)
@@ -56,23 +54,16 @@ final searchResultPageProvider =
   return SearchResultPageNotifier(ref.watch(searchServiceProvider));
 });
 
-final searchResultGroupByDateTimeProvider = StateProvider((ref) {
-  var assets = ref.watch(searchResultPageProvider).searchResult;
-
-  assets.sortByCompare<DateTime>(
-    (e) => e.createdAt,
-    (a, b) => b.compareTo(a),
-  );
-  return assets.groupListsBy(
-    (element) => DateFormat('y-MM-dd').format(element.createdAt.toLocal()),
-  );
-});
-
 final searchRenderListProvider = FutureProvider((ref) {
-  var assetGroups = ref.watch(searchResultGroupByDateTimeProvider);
-
   var settings = ref.watch(appSettingsServiceProvider);
-  final assetsPerRow = settings.getSetting(AppSettingsEnum.tilesPerRow);
 
-  return RenderList.fromAssetGroups(assetGroups, assetsPerRow);
+  final assets = ref.watch(searchResultPageProvider).searchResult;
+
+  final layout = AssetGridLayoutParameters(
+    settings.getSetting(AppSettingsEnum.tilesPerRow),
+    settings.getSetting(AppSettingsEnum.dynamicLayout),
+    GroupAssetsBy.values[settings.getSetting(AppSettingsEnum.groupAssetsBy)],
+  );
+
+  return RenderList.fromAssets(assets, layout);
 });

+ 2 - 0
mobile/lib/modules/settings/services/app_settings.service.dart

@@ -6,6 +6,8 @@ enum AppSettingsEnum<T> {
   loadOriginal<bool>("loadOriginal", false),
   themeMode<String>("themeMode", "system"), // "light","dark","system"
   tilesPerRow<int>("tilesPerRow", 4),
+  dynamicLayout<bool>("dynamicLayout", false),
+  groupAssetsBy<int>("groupBy", 0),
   uploadErrorNotificationGracePeriod<int>(
     "uploadErrorNotificationGracePeriod",
     2,

+ 99 - 0
mobile/lib/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart

@@ -0,0 +1,99 @@
+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/asset_grid/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';
+
+class LayoutSettings extends HookConsumerWidget {
+  const LayoutSettings({
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final appSettingService = ref.watch(appSettingsServiceProvider);
+
+    final useDynamicLayout = useState(true);
+    final groupBy = useState(GroupAssetsBy.day);
+
+    void switchChanged(bool value) {
+      appSettingService.setSetting(AppSettingsEnum.dynamicLayout, value);
+      useDynamicLayout.value = value;
+      ref.watch(assetProvider.notifier).rebuildAssetGridDataStructure();
+    }
+
+    void changeGroupValue(GroupAssetsBy? value) {
+      if (value != null) {
+        appSettingService.setSetting(AppSettingsEnum.groupAssetsBy, value.index);
+        groupBy.value = value;
+        ref.watch(assetProvider.notifier).rebuildAssetGridDataStructure();
+      }
+    }
+
+    useEffect(
+      () {
+        useDynamicLayout.value =
+            appSettingService.getSetting<bool>(AppSettingsEnum.dynamicLayout);
+        groupBy.value =
+            GroupAssetsBy.values[appSettingService.getSetting<int>(AppSettingsEnum.groupAssetsBy)];
+
+        return null;
+      },
+      [],
+    );
+
+    return Column(
+      children: [
+        SwitchListTile.adaptive(
+          activeColor: Theme.of(context).primaryColor,
+          title: const Text(
+            "asset_list_layout_settings_dynamic_layout_title",
+            style: TextStyle(
+              fontSize: 12,
+            ),
+          ).tr(),
+          onChanged: switchChanged,
+          value: useDynamicLayout.value,
+        ),
+        ListTile(
+          title: const Text(
+            "asset_list_layout_settings_group_by",
+            style: TextStyle(
+              fontSize: 12,
+              fontWeight: FontWeight.bold,
+            ),
+          ).tr(),
+        ),
+        RadioListTile(
+          activeColor: Theme.of(context).primaryColor,
+          title: const Text(
+            "asset_list_layout_settings_group_by_month_day",
+            style: TextStyle(
+              fontSize: 12,
+            ),
+          ).tr(),
+          value: GroupAssetsBy.day,
+          groupValue: groupBy.value,
+          onChanged: changeGroupValue,
+          controlAffinity: ListTileControlAffinity.trailing,
+        ),
+        RadioListTile(
+          activeColor: Theme.of(context).primaryColor,
+          title: const Text(
+            "asset_list_layout_settings_group_by_month",
+            style: TextStyle(
+              fontSize: 12,
+            ),
+          ).tr(),
+          value: GroupAssetsBy.month,
+          groupValue: groupBy.value,
+          onChanged: changeGroupValue,
+          controlAffinity: ListTileControlAffinity.trailing,
+        ),
+      ],
+    );
+  }
+}

+ 2 - 0
mobile/lib/modules/settings/ui/asset_list_settings/asset_list_settings.dart

@@ -1,5 +1,6 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_layout_settings.dart';
 import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart';
 import 'asset_list_tiles_per_row.dart';
 
@@ -27,6 +28,7 @@ class AssetListSettings extends StatelessWidget {
       children: const [
         TilesPerRow(),
         StorageIndicator(),
+        LayoutSettings(),
       ],
     );
   }

+ 1 - 2
mobile/lib/modules/settings/ui/asset_list_settings/asset_list_storage_indicator.dart

@@ -20,8 +20,7 @@ class StorageIndicator extends HookConsumerWidget {
     void switchChanged(bool value) {
       appSettingService.setSetting(AppSettingsEnum.storageIndicator, value);
       showStorageIndicator.value = value;
-
-      ref.invalidate(assetProvider);
+      ref.watch(assetProvider.notifier).rebuildAssetGridDataStructure();
     }
 
     useEffect(

+ 1 - 2
mobile/lib/modules/settings/ui/asset_list_settings/asset_list_tiles_per_row.dart

@@ -23,8 +23,7 @@ class TilesPerRow extends HookConsumerWidget {
     }
 
     void sliderChangedEnd(double _) {
-      ref.invalidate(assetProvider);
-      ref.watch(assetProvider.notifier).getAllAsset();
+      ref.watch(assetProvider.notifier).rebuildAssetGridDataStructure();
     }
 
     useEffect(

+ 18 - 19
mobile/lib/shared/providers/asset.provider.dart

@@ -25,11 +25,15 @@ class AssetsState {
 
   AssetsState(this.allAssets, {this.renderList});
 
-  Future<AssetsState> withRenderDataStructure(int groupSize) async {
+  Future<AssetsState> withRenderDataStructure(
+    AssetGridLayoutParameters layout,
+  ) async {
     return AssetsState(
       allAssets,
-      renderList:
-          await RenderList.fromAssetGroups(await _groupByDate(), groupSize),
+      renderList: await RenderList.fromAssets(
+        allAssets,
+        layout,
+      ),
     );
   }
 
@@ -37,20 +41,6 @@ class AssetsState {
     return AssetsState([...allAssets, ...toAdd]);
   }
 
-  Future<Map<String, List<Asset>>> _groupByDate() async {
-    sortCompare(List<Asset> assets) {
-      assets.sortByCompare<DateTime>(
-        (e) => e.createdAt,
-        (a, b) => b.compareTo(a),
-      );
-      return assets.groupListsBy(
-        (element) => DateFormat('y-MM-dd').format(element.createdAt.toLocal()),
-      );
-    }
-
-    return await compute(sortCompare, allAssets.toList());
-  }
-
   static AssetsState fromAssetList(List<Asset> assets) {
     return AssetsState(assets);
   }
@@ -91,10 +81,19 @@ class AssetNotifier extends StateNotifier<AssetsState> {
       _assetCacheService.put(newAssetList);
     }
 
-    state =
-        await AssetsState.fromAssetList(newAssetList).withRenderDataStructure(
+    final layout = AssetGridLayoutParameters(
       _settingsService.getSetting(AppSettingsEnum.tilesPerRow),
+      _settingsService.getSetting(AppSettingsEnum.dynamicLayout),
+      GroupAssetsBy.values[_settingsService.getSetting(AppSettingsEnum.groupAssetsBy)],
     );
+
+    state = await AssetsState.fromAssetList(newAssetList)
+        .withRenderDataStructure(layout);
+  }
+
+  // Just a little helper to trigger a rebuild of the state object
+  Future<void> rebuildAssetGridDataStructure() async {
+    await _updateAssetsState(state.allAssets, cache: false);
   }
 
   getAllAsset() async {

+ 50 - 29
mobile/test/asset_grid_data_structure_test.dart

@@ -25,46 +25,61 @@ void main() {
     );
   }
 
-  final Map<String, List<Asset>> groups = {
-    '2022-01-05': testAssets.sublist(0, 5).map((e) {
+  final List<Asset> assets = [];
+
+  assets.addAll(
+    testAssets.sublist(0, 5).map((e) {
       e.createdAt = DateTime(2022, 1, 5);
       return e;
     }).toList(),
-    '2022-01-10': testAssets.sublist(5, 10).map((e) {
+  );
+  assets.addAll(
+    testAssets.sublist(5, 10).map((e) {
       e.createdAt = DateTime(2022, 1, 10);
       return e;
     }).toList(),
-    '2022-02-17': testAssets.sublist(10, 15).map((e) {
+  );
+  assets.addAll(
+    testAssets.sublist(10, 15).map((e) {
       e.createdAt = DateTime(2022, 2, 17);
       return e;
     }).toList(),
-    '2022-10-15': testAssets.sublist(15, 30).map((e) {
+  );
+  assets.addAll(
+    testAssets.sublist(15, 30).map((e) {
       e.createdAt = DateTime(2022, 10, 15);
       return e;
-    }).toList()
-  };
+    }).toList(),
+  );
 
   group('Test grouped', () {
     test('test grouped check months', () async {
-      final renderList = await RenderList.fromAssetGroups(groups, 3);
+      final renderList = await RenderList.fromAssets(
+        assets,
+        AssetGridLayoutParameters(
+          3,
+          false,
+          GroupAssetsBy.day,
+        ),
+      );
 
-      // Jan
+      // Oct
+      // Day 1
+      // 15 Assets => 5 Rows
+      // Feb
       // Day 1
       // 5 Assets => 2 Rows
+      // Jan
       // Day 2
       // 5 Assets => 2 Rows
-      // Feb
       // Day 1
       // 5 Assets => 2 Rows
-      // Oct
-      // Day 1
-      // 15 Assets => 5 Rows
       expect(renderList.elements.length, 18);
       expect(
         renderList.elements[0].type,
         RenderAssetGridElementType.monthTitle,
       );
-      expect(renderList.elements[0].date.month, 1);
+      expect(renderList.elements[0].date.month, 10);
       expect(
         renderList.elements[7].type,
         RenderAssetGridElementType.monthTitle,
@@ -74,38 +89,44 @@ void main() {
         renderList.elements[11].type,
         RenderAssetGridElementType.monthTitle,
       );
-      expect(renderList.elements[11].date.month, 10);
+      expect(renderList.elements[11].date.month, 1);
     });
 
     test('test grouped check types', () async {
-      final renderList = await RenderList.fromAssetGroups(groups, 5);
+      final renderList = await RenderList.fromAssets(
+        assets,
+        AssetGridLayoutParameters(
+          5,
+          false,
+          GroupAssetsBy.day,
+        ),
+      );
 
-      // Jan
+      // Oct
       // Day 1
-      // 5 Assets
-      // Day 2
-      // 5 Assets
+      // 15 Assets => 3 Rows
       // Feb
       // Day 1
-      // 5 Assets
-      // Oct
+      // 5 Assets => 1 Row
+      // Jan
+      // Day 2
+      // 5 Assets => 1 Row
       // Day 1
-      // 15 Assets => 3 Rows
-
+      // 5 Assets => 1 Row
       final types = [
         RenderAssetGridElementType.monthTitle,
-        RenderAssetGridElementType.dayTitle,
+        RenderAssetGridElementType.groupDividerTitle,
+        RenderAssetGridElementType.assetRow,
         RenderAssetGridElementType.assetRow,
-        RenderAssetGridElementType.dayTitle,
         RenderAssetGridElementType.assetRow,
         RenderAssetGridElementType.monthTitle,
-        RenderAssetGridElementType.dayTitle,
+        RenderAssetGridElementType.groupDividerTitle,
         RenderAssetGridElementType.assetRow,
         RenderAssetGridElementType.monthTitle,
-        RenderAssetGridElementType.dayTitle,
+        RenderAssetGridElementType.groupDividerTitle,
         RenderAssetGridElementType.assetRow,
+        RenderAssetGridElementType.groupDividerTitle,
         RenderAssetGridElementType.assetRow,
-        RenderAssetGridElementType.assetRow
       ];
 
       expect(renderList.elements.length, types.length);