浏览代码

Get rid of home page state provider

Matthias Rupp 2 年之前
父节点
当前提交
6b84534632

+ 0 - 47
mobile/lib/modules/home/models/home_page_state.model.dart

@@ -1,47 +0,0 @@
-import 'package:collection/collection.dart';
-
-import 'package:openapi/api.dart';
-
-class HomePageState {
-  final bool isMultiSelectEnable;
-  final Set<AssetResponseDto> selectedItems;
-  final Set<String> selectedDateGroup;
-  HomePageState({
-    required this.isMultiSelectEnable,
-    required this.selectedItems,
-    required this.selectedDateGroup,
-  });
-
-  HomePageState copyWith({
-    bool? isMultiSelectEnable,
-    Set<AssetResponseDto>? selectedItems,
-    Set<String>? selectedDateGroup,
-  }) {
-    return HomePageState(
-      isMultiSelectEnable: isMultiSelectEnable ?? this.isMultiSelectEnable,
-      selectedItems: selectedItems ?? this.selectedItems,
-      selectedDateGroup: selectedDateGroup ?? this.selectedDateGroup,
-    );
-  }
-
-  @override
-  String toString() =>
-      'HomePageState(isMultiSelectEnable: $isMultiSelectEnable, selectedItems: $selectedItems, selectedDateGroup: $selectedDateGroup)';
-
-  @override
-  bool operator ==(Object other) {
-    if (identical(this, other)) return true;
-    final setEquals = const DeepCollectionEquality().equals;
-
-    return other is HomePageState &&
-        other.isMultiSelectEnable == isMultiSelectEnable &&
-        setEquals(other.selectedItems, selectedItems) &&
-        setEquals(other.selectedDateGroup, selectedDateGroup);
-  }
-
-  @override
-  int get hashCode =>
-      isMultiSelectEnable.hashCode ^
-      selectedItems.hashCode ^
-      selectedDateGroup.hashCode;
-}

+ 0 - 91
mobile/lib/modules/home/providers/home_page_state.provider.dart

@@ -1,91 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/models/home_page_state.model.dart';
-import 'package:immich_mobile/shared/services/share.service.dart';
-import 'package:immich_mobile/shared/ui/share_dialog.dart';
-import 'package:openapi/api.dart';
-
-class HomePageStateNotifier extends StateNotifier<HomePageState> {
-
-  final ShareService _shareService;
-
-  HomePageStateNotifier(this._shareService)
-      : super(
-          HomePageState(
-            isMultiSelectEnable: false,
-            selectedItems: {},
-            selectedDateGroup: {},
-          ),
-        );
-
-  void addSelectedDateGroup(String dateGroupTitle) {
-    state = state.copyWith(
-      selectedDateGroup: {...state.selectedDateGroup, dateGroupTitle},
-    );
-  }
-
-  void removeSelectedDateGroup(String dateGroupTitle) {
-    var currentDateGroup = state.selectedDateGroup;
-
-    currentDateGroup.removeWhere((e) => e == dateGroupTitle);
-
-    state = state.copyWith(selectedDateGroup: currentDateGroup);
-  }
-
-  void enableMultiSelect(Set<AssetResponseDto> selectedItems) {
-    state =
-        state.copyWith(isMultiSelectEnable: true, selectedItems: selectedItems);
-  }
-
-  void disableMultiSelect() {
-    state = state.copyWith(
-      isMultiSelectEnable: false,
-      selectedItems: {},
-      selectedDateGroup: {},
-    );
-  }
-
-  void addSingleSelectedItem(AssetResponseDto asset) {
-    state = state.copyWith(selectedItems: {...state.selectedItems, asset});
-  }
-
-  void addMultipleSelectedItems(List<AssetResponseDto> assets) {
-    state = state.copyWith(selectedItems: {...state.selectedItems, ...assets});
-  }
-
-  void removeSingleSelectedItem(AssetResponseDto asset) {
-    Set<AssetResponseDto> currentList = state.selectedItems;
-
-    currentList.removeWhere((e) => e.id == asset.id);
-
-    state = state.copyWith(selectedItems: currentList);
-  }
-
-  void removeMultipleSelectedItem(List<AssetResponseDto> assets) {
-    Set<AssetResponseDto> currentList = state.selectedItems;
-
-    for (AssetResponseDto asset in assets) {
-      currentList.removeWhere((e) => e.id == asset.id);
-    }
-
-    state = state.copyWith(selectedItems: currentList);
-  }
-
-  void shareAssets(List<AssetResponseDto> assets, BuildContext context) {
-    showDialog(
-      context: context,
-      builder: (BuildContext buildContext) {
-        _shareService
-            .shareAssets(assets)
-            .then((_) => Navigator.of(buildContext).pop());
-        return const ShareDialog();
-      },
-      barrierDismissible: false,
-    );
-  }
-}
-
-final homePageStateProvider =
-    StateNotifierProvider<HomePageStateNotifier, HomePageState>(
-  ((ref) => HomePageStateNotifier(ref.watch(shareServiceProvider))),
-);

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

@@ -1,8 +1,6 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
-import 'package:openapi/api.dart';
 
 class DailyTitleText extends ConsumerWidget {
   const DailyTitleText({

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

@@ -14,12 +14,13 @@ import 'daily_title_text.dart';
 import 'disable_multi_select_button.dart';
 import 'draggable_scrollbar_custom.dart';
 
-typedef ImmichAssetGridSelectionListener = void Function(bool);
+typedef ImmichAssetGridSelectionListener = void Function(
+    bool, Set<AssetResponseDto>);
 
 class ImmichAssetGridState extends State<ImmichAssetGrid> {
   final ItemScrollController _itemScrollController = ItemScrollController();
   final ItemPositionsListener _itemPositionsListener =
-  ItemPositionsListener.create();
+      ItemPositionsListener.create();
 
   bool _scrolling = false;
   bool _multiselect = false;
@@ -37,18 +38,26 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
         .flattened
         .toList();
   }
-  
-  void _selectAssets(List<AssetResponseDto> assets) {
-    setState(() {
 
-      if (!_multiselect) {
-        _multiselect = true;
-        widget.listener?.call(true);
-      }
+  Set<AssetResponseDto> _getSelectedAssets() {
+    return _selectedAssets
+        .map((e) => _assets.firstWhereOrNull((a) => a.id == e))
+        .whereNotNull()
+        .toSet();
+  }
 
+  void _callSelectionListener() {
+    widget.listener?.call(_multiselect, _getSelectedAssets());
+  }
+
+  void _selectAssets(List<AssetResponseDto> assets) {
+    setState(() {
       for (var e in assets) {
         _selectedAssets.add(e.id);
       }
+
+      _multiselect = true;
+      _callSelectionListener();
     });
   }
 
@@ -60,8 +69,9 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
 
       if (_selectedAssets.isEmpty) {
         _multiselect = false;
-        widget.listener?.call(false);
       }
+
+      _callSelectionListener();
     });
   }
 
@@ -70,11 +80,13 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
       _multiselect = false;
       _selectedAssets.clear();
     });
-    widget.listener?.call(false);
+
+    _callSelectionListener();
   }
 
   bool _allAssetsSelected(List<AssetResponseDto> assets) {
-    return _multiselect && assets.firstWhereOrNull((e) => !_selectedAssets.contains(e.id)) == null;
+    return _multiselect &&
+        assets.firstWhereOrNull((e) => !_selectedAssets.contains(e.id)) == null;
   }
 
   double _getItemSize(BuildContext context) {
@@ -113,7 +125,8 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
           key: Key("asset-${asset.id}"),
           width: size,
           height: size,
-          margin: EdgeInsets.only(top: widget.margin, right: last ? 0.0 : widget.margin),
+          margin: EdgeInsets.only(
+              top: widget.margin, right: last ? 0.0 : widget.margin),
           child: _buildThumbnailOrPlaceholder(asset, scrolling),
         );
       }).toList(),
@@ -165,7 +178,8 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> {
 
   Text _labelBuilder(int pos) {
     final date = widget.renderList[pos].date;
-    return Text(DateFormat.yMMMd().format(date),
+    return Text(
+      DateFormat.yMMMd().format(date),
       style: const TextStyle(
         color: Colors.white,
         fontWeight: FontWeight.bold,
@@ -231,7 +245,6 @@ class ImmichAssetGrid extends StatefulWidget {
   final bool showStorageIndicator;
   final ImmichAssetGridSelectionListener? listener;
 
-
   ImmichAssetGrid({
     super.key,
     required this.renderList,
@@ -245,4 +258,4 @@ class ImmichAssetGrid extends StatefulWidget {
   State<StatefulWidget> createState() {
     return ImmichAssetGridState();
   }
-}
+}

+ 0 - 0
mobile/lib/modules/home/ui/monthly_title_text.dart → mobile/lib/modules/home/ui/asset_grid/monthly_title_text.dart


+ 0 - 2
mobile/lib/modules/home/ui/asset_grid/thumbnail_image.dart

@@ -1,12 +1,10 @@
 import 'package:auto_route/auto_route.dart';
 import 'package:cached_network_image/cached_network_image.dart';
-import 'package:collection/collection.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:hive_flutter/hive_flutter.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:immich_mobile/constants/hive_box.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 import 'package:immich_mobile/routing/router.dart';
 import 'package:immich_mobile/utils/image_url_builder.dart';

+ 10 - 11
mobile/lib/modules/home/ui/control_bottom_app_bar.dart

@@ -1,11 +1,15 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart';
 
 class ControlBottomAppBar extends ConsumerWidget {
-  const ControlBottomAppBar({Key? key}) : super(key: key);
+  final Function onShare;
+  final Function onDelete;
+
+  const ControlBottomAppBar(
+      {Key? key, required this.onShare, required this.onDelete})
+      : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
@@ -36,7 +40,9 @@ class ControlBottomAppBar extends ConsumerWidget {
                       showDialog(
                         context: context,
                         builder: (BuildContext context) {
-                          return const DeleteDialog();
+                          return DeleteDialog(
+                            onDelete: onDelete,
+                          );
                         },
                       );
                     },
@@ -45,14 +51,7 @@ class ControlBottomAppBar extends ConsumerWidget {
                     iconData: Icons.share,
                     label: "control_bottom_app_bar_share".tr(),
                     onPressed: () {
-                      final homePageState = ref.watch(homePageStateProvider);
-                      ref.watch(homePageStateProvider.notifier).shareAssets(
-                            homePageState.selectedItems.toList(),
-                            context,
-                          );
-                      ref
-                          .watch(homePageStateProvider.notifier)
-                          .disableMultiSelect();
+                      onShare();
                     },
                   ),
                 ],

+ 0 - 109
mobile/lib/modules/home/ui/daily_title_text.dart

@@ -1,109 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
-import 'package:openapi/api.dart';
-
-class DailyTitleText extends ConsumerWidget {
-  const DailyTitleText({
-    Key? key,
-    required this.isoDate,
-    required this.assetGroup,
-  }) : super(key: key);
-
-  final String isoDate;
-  final List<AssetResponseDto> assetGroup;
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    var currentYear = DateTime.now().year;
-    var groupYear = DateTime.parse(isoDate).year;
-    var formatDateTemplate = currentYear == groupYear
-        ? "daily_title_text_date".tr()
-        : "daily_title_text_date_year".tr();
-    var dateText = DateFormat(formatDateTemplate)
-        .format(DateTime.parse(isoDate).toLocal());
-    var isMultiSelectEnable =
-        ref.watch(homePageStateProvider).isMultiSelectEnable;
-    var selectedDateGroup = ref.watch(homePageStateProvider).selectedDateGroup;
-    var selectedItems = ref.watch(homePageStateProvider).selectedItems;
-
-    void _handleTitleIconClick() {
-      if (isMultiSelectEnable &&
-          selectedDateGroup.contains(dateText) &&
-          selectedDateGroup.length == 1 &&
-          selectedItems.length <= assetGroup.length) {
-        // Multi select is active - click again on the icon while it is the only active group -> disable multi select
-        ref.watch(homePageStateProvider.notifier).disableMultiSelect();
-      } else if (isMultiSelectEnable &&
-          selectedDateGroup.contains(dateText) &&
-          selectedItems.length != assetGroup.length) {
-        // Multi select is active - click again on the icon while it is not the only active group -> remove that group from selected group/items
-        ref
-            .watch(homePageStateProvider.notifier)
-            .removeSelectedDateGroup(dateText);
-        ref
-            .watch(homePageStateProvider.notifier)
-            .removeMultipleSelectedItem(assetGroup);
-      } else if (isMultiSelectEnable &&
-          selectedDateGroup.contains(dateText) &&
-          selectedDateGroup.length > 1) {
-        ref
-            .watch(homePageStateProvider.notifier)
-            .removeSelectedDateGroup(dateText);
-        ref
-            .watch(homePageStateProvider.notifier)
-            .removeMultipleSelectedItem(assetGroup);
-      } else if (isMultiSelectEnable && !selectedDateGroup.contains(dateText)) {
-        ref
-            .watch(homePageStateProvider.notifier)
-            .addSelectedDateGroup(dateText);
-        ref
-            .watch(homePageStateProvider.notifier)
-            .addMultipleSelectedItems(assetGroup);
-      } else {
-        ref
-            .watch(homePageStateProvider.notifier)
-            .enableMultiSelect(assetGroup.toSet());
-        ref
-            .watch(homePageStateProvider.notifier)
-            .addSelectedDateGroup(dateText);
-      }
-    }
-
-    return SliverToBoxAdapter(
-      child: Padding(
-        padding: const EdgeInsets.only(
-          top: 29.0,
-          bottom: 29.0,
-          left: 12.0,
-          right: 12.0,
-        ),
-        child: Row(
-          children: [
-            Text(
-              dateText,
-              style: const TextStyle(
-                fontSize: 14,
-                fontWeight: FontWeight.bold,
-              ),
-            ),
-            const Spacer(),
-            GestureDetector(
-              onTap: _handleTitleIconClick,
-              child: isMultiSelectEnable && selectedDateGroup.contains(dateText)
-                  ? Icon(
-                      Icons.check_circle_rounded,
-                      color: Theme.of(context).primaryColor,
-                    )
-                  : const Icon(
-                      Icons.check_circle_outline_rounded,
-                      color: Colors.grey,
-                    ),
-            )
-          ],
-        ),
-      ),
-    );
-  }
-}

+ 4 - 9
mobile/lib/modules/home/ui/delete_diaglog.dart

@@ -1,15 +1,14 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/shared/providers/asset.provider.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 
 class DeleteDialog extends ConsumerWidget {
-  const DeleteDialog({Key? key}) : super(key: key);
+  final Function onDelete;
+
+  const DeleteDialog({Key? key, required this.onDelete}) : super(key: key);
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final homePageState = ref.watch(homePageStateProvider);
 
     return AlertDialog(
       backgroundColor: Colors.grey[200],
@@ -28,11 +27,7 @@ class DeleteDialog extends ConsumerWidget {
         ),
         TextButton(
           onPressed: () {
-            ref
-                .watch(assetProvider.notifier)
-                .deleteAssets(homePageState.selectedItems);
-            ref.watch(homePageStateProvider.notifier).disableMultiSelect();
-
+            onDelete();
             Navigator.of(context).pop();
           },
           child: Text(

+ 0 - 47
mobile/lib/modules/home/ui/image_grid.dart

@@ -1,47 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:hooks_riverpod/hooks_riverpod.dart';
-import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart';
-import 'package:openapi/api.dart';
-
-// ignore: must_be_immutable
-class ImageGrid extends ConsumerWidget {
-  final List<AssetResponseDto> assetGroup;
-  final List<AssetResponseDto> sortedAssetGroup;
-  final int tilesPerRow;
-  final bool showStorageIndicator;
-
-  ImageGrid({
-    Key? key,
-    required this.assetGroup,
-    required this.sortedAssetGroup,
-    this.tilesPerRow = 4,
-    this.showStorageIndicator = true,
-  }) : super(key: key);
-
-  List<AssetResponseDto> imageSortedList = [];
-
-  @override
-  Widget build(BuildContext context, WidgetRef ref) {
-    return SliverGrid(
-      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-        crossAxisCount: tilesPerRow,
-        crossAxisSpacing: 5.0,
-        mainAxisSpacing: 5,
-      ),
-      delegate: SliverChildBuilderDelegate(
-        (BuildContext context, int index) {
-          var assetType = assetGroup[index].type;
-          return GestureDetector(
-            onTap: () {},
-            child: ThumbnailImage(
-              asset: assetGroup[index],
-              assetList: sortedAssetGroup,
-              showStorageIndicator: showStorageIndicator,
-            ),
-          );
-        },
-        childCount: assetGroup.length,
-      ),
-    );
-  }
-}

+ 27 - 16
mobile/lib/modules/home/views/home_page.dart

@@ -2,7 +2,6 @@ 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/providers/home_page_render_list_provider.dart';
-import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
 import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
 import 'package:immich_mobile/modules/home/ui/control_bottom_app_bar.dart';
 import 'package:immich_mobile/modules/home/ui/immich_sliver_appbar.dart';
@@ -12,6 +11,8 @@ import 'package:immich_mobile/modules/settings/services/app_settings.service.dar
 import 'package:immich_mobile/shared/providers/asset.provider.dart';
 import 'package:immich_mobile/shared/providers/server_info.provider.dart';
 import 'package:immich_mobile/shared/providers/websocket.provider.dart';
+import 'package:immich_mobile/shared/services/share.service.dart';
+import 'package:openapi/api.dart';
 
 class HomePage extends HookConsumerWidget {
   const HomePage({Key? key}) : super(key: key);
@@ -22,6 +23,7 @@ class HomePage extends HookConsumerWidget {
     var renderList = ref.watch(renderListProvider);
 
     final multiselectEnabled = useState(false);
+    final selection = useState(<AssetResponseDto>{});
 
     useEffect(
       () {
@@ -38,21 +40,18 @@ class HomePage extends HookConsumerWidget {
     }
 
     Widget buildBody() {
-      buildSliverAppBar() {
-        return multiselectEnabled.value
-            ? const SliverToBoxAdapter(
-                child: SizedBox(
-                  height: 70,
-                  child: null,
-                ),
-              )
-            : ImmichSliverAppBar(
-                onPopBack: reloadAllAsset,
-              );
+      void selectionListener(
+          bool multiselect, Set<AssetResponseDto> selectedAssets) {
+        multiselectEnabled.value = multiselect;
+        selection.value = selectedAssets;
       }
 
-      void selectionListener(bool multiselect) {
-        multiselectEnabled.value = multiselect;
+      void onShareAssets() {
+        ref.watch(shareServiceProvider).shareAssets(selection.value.toList());
+      }
+
+      void onDelete() {
+        ref.watch(assetProvider.notifier).deleteAssets(selection.value);
       }
 
       return SafeArea(
@@ -62,7 +61,16 @@ class HomePage extends HookConsumerWidget {
           children: [
             CustomScrollView(
               slivers: [
-                buildSliverAppBar(),
+                multiselectEnabled.value
+                    ? const SliverToBoxAdapter(
+                        child: SizedBox(
+                          height: 70,
+                          child: null,
+                        ),
+                      )
+                    : ImmichSliverAppBar(
+                        onPopBack: reloadAllAsset,
+                      ),
               ],
             ),
             Padding(
@@ -77,7 +85,10 @@ class HomePage extends HookConsumerWidget {
               ),
             ),
             if (multiselectEnabled.value) ...[
-              const ControlBottomAppBar(),
+              ControlBottomAppBar(
+                onShare: onShareAssets,
+                onDelete: onDelete,
+              ),
             ],
           ],
         ),

+ 2 - 4
mobile/lib/shared/views/tab_controller_page.dart

@@ -1,8 +1,8 @@
 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/providers/home_page_state.provider.dart';
 import 'package:immich_mobile/routing/router.dart';
 
 class TabControllerPage extends ConsumerWidget {
@@ -10,8 +10,6 @@ class TabControllerPage extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    var isMultiSelectEnable =
-        ref.watch(homePageStateProvider).isMultiSelectEnable;
 
     return AutoTabsRouter(
       routes: [
@@ -32,7 +30,7 @@ class TabControllerPage extends ConsumerWidget {
               opacity: animation,
               child: child,
             ),
-            bottomNavigationBar: isMultiSelectEnable
+            bottomNavigationBar: false
                 ? null
                 : BottomNavigationBar(
                     selectedLabelStyle: const TextStyle(