mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:29:32 -05:00 
			
		
		
		
	feat(mobile): Multiselect add to favorite from the timeline (#1558)
* multiselect add to favorites
This commit is contained in:
		
							parent
							
								
									2139853dd9
								
							
						
					
					
						commit
						b8d2f5b373
					
				@ -34,6 +34,18 @@ class FavoriteSelectionNotifier extends StateNotifier<Set<String>> {
 | 
				
			|||||||
      state.contains(asset.id),
 | 
					      state.contains(asset.id),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> addToFavorites(Iterable<Asset> assets) {
 | 
				
			||||||
 | 
					    state = state.union(assets.map((a) => a.id).toSet());
 | 
				
			||||||
 | 
					    final futures = assets.map((a) => 
 | 
				
			||||||
 | 
					        ref.watch(assetProvider.notifier).toggleFavorite(
 | 
				
			||||||
 | 
					          a,
 | 
				
			||||||
 | 
					          true,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Future.wait(futures);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
final favoriteProvider =
 | 
					final favoriteProvider =
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ import 'package:immich_mobile/shared/models/album.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ControlBottomAppBar extends ConsumerWidget {
 | 
					class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			||||||
  final Function onShare;
 | 
					  final Function onShare;
 | 
				
			||||||
 | 
					  final Function onFavorite;
 | 
				
			||||||
  final Function onDelete;
 | 
					  final Function onDelete;
 | 
				
			||||||
  final Function(Album album) onAddToAlbum;
 | 
					  final Function(Album album) onAddToAlbum;
 | 
				
			||||||
  final void Function() onCreateNewAlbum;
 | 
					  final void Function() onCreateNewAlbum;
 | 
				
			||||||
@ -18,6 +19,7 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
  const ControlBottomAppBar({
 | 
					  const ControlBottomAppBar({
 | 
				
			||||||
    Key? key,
 | 
					    Key? key,
 | 
				
			||||||
    required this.onShare,
 | 
					    required this.onShare,
 | 
				
			||||||
 | 
					    required this.onFavorite,
 | 
				
			||||||
    required this.onDelete,
 | 
					    required this.onDelete,
 | 
				
			||||||
    required this.sharedAlbums,
 | 
					    required this.sharedAlbums,
 | 
				
			||||||
    required this.albums,
 | 
					    required this.albums,
 | 
				
			||||||
@ -37,6 +39,13 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
              onShare();
 | 
					              onShare();
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
 | 
					          ControlBoxButton(
 | 
				
			||||||
 | 
					            iconData: Icons.star_rounded,
 | 
				
			||||||
 | 
					            label: "Favorite",
 | 
				
			||||||
 | 
					            onPressed: () {
 | 
				
			||||||
 | 
					              onFavorite();
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
          ControlBoxButton(
 | 
					          ControlBoxButton(
 | 
				
			||||||
            iconData: Icons.delete_outline_rounded,
 | 
					            iconData: Icons.delete_outline_rounded,
 | 
				
			||||||
            label: "control_bottom_app_bar_delete".tr(),
 | 
					            label: "control_bottom_app_bar_delete".tr(),
 | 
				
			||||||
@ -51,6 +60,7 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
				
			|||||||
              );
 | 
					              );
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			|||||||
import 'package:immich_mobile/modules/album/providers/album.provider.dart';
 | 
					import 'package:immich_mobile/modules/album/providers/album.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
 | 
					import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/album/services/album.service.dart';
 | 
					import 'package:immich_mobile/modules/album/services/album.service.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/home/providers/multiselect.provider.dart';
 | 
					import 'package:immich_mobile/modules/home/providers/multiselect.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.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/control_bottom_app_bar.dart';
 | 
				
			||||||
@ -83,27 +84,39 @@ class HomePage extends HookConsumerWidget {
 | 
				
			|||||||
        selectionEnabledHook.value = false;
 | 
					        selectionEnabledHook.value = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      void onDelete() {
 | 
					      Iterable<Asset> remoteOnlySelection({String? localErrorMessage}) {
 | 
				
			||||||
        ref.watch(assetProvider.notifier).deleteAssets(selection.value);
 | 
					 | 
				
			||||||
        selectionEnabledHook.value = false;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Iterable<Asset> remoteOnlySelection() {
 | 
					 | 
				
			||||||
        final Set<Asset> assets = selection.value;
 | 
					        final Set<Asset> assets = selection.value;
 | 
				
			||||||
        final bool onlyRemote = assets.every((e) => e.isRemote);
 | 
					        final bool onlyRemote = assets.every((e) => e.isRemote);
 | 
				
			||||||
        if (!onlyRemote) {
 | 
					        if (!onlyRemote) {
 | 
				
			||||||
 | 
					          if (localErrorMessage != null && localErrorMessage.isNotEmpty) {
 | 
				
			||||||
            ImmichToast.show(
 | 
					            ImmichToast.show(
 | 
				
			||||||
              context: context,
 | 
					              context: context,
 | 
				
			||||||
            msg: "Can not add local assets to albums yet, skipping",
 | 
					              msg: localErrorMessage,
 | 
				
			||||||
              gravity: ToastGravity.BOTTOM,
 | 
					              gravity: ToastGravity.BOTTOM,
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
          return assets.where((a) => a.isRemote);
 | 
					          return assets.where((a) => a.isRemote);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return assets;
 | 
					        return assets;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      void onFavoriteAssets() {
 | 
				
			||||||
 | 
					        final remoteAssests = remoteOnlySelection(
 | 
				
			||||||
 | 
					          localErrorMessage: 'Can not favorite local assets yet, skipping',
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        ref.watch(favoriteProvider.notifier).addToFavorites(remoteAssests);
 | 
				
			||||||
 | 
					        selectionEnabledHook.value = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      void onDelete() {
 | 
				
			||||||
 | 
					        ref.watch(assetProvider.notifier).deleteAssets(selection.value);
 | 
				
			||||||
 | 
					        selectionEnabledHook.value = false;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      void onAddToAlbum(Album album) async {
 | 
					      void onAddToAlbum(Album album) async {
 | 
				
			||||||
        final Iterable<Asset> assets = remoteOnlySelection();
 | 
					        final Iterable<Asset> assets = remoteOnlySelection(
 | 
				
			||||||
 | 
					          localErrorMessage: "Can not add local assets to albums yet, skipping",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
        if (assets.isEmpty) {
 | 
					        if (assets.isEmpty) {
 | 
				
			||||||
          return;
 | 
					          return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -142,7 +155,9 @@ class HomePage extends HookConsumerWidget {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      void onCreateNewAlbum() async {
 | 
					      void onCreateNewAlbum() async {
 | 
				
			||||||
        final Iterable<Asset> assets = remoteOnlySelection();
 | 
					        final Iterable<Asset> assets = remoteOnlySelection(
 | 
				
			||||||
 | 
					          localErrorMessage: "Can not add local assets to albums yet, skipping",
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
        if (assets.isEmpty) {
 | 
					        if (assets.isEmpty) {
 | 
				
			||||||
          return;
 | 
					          return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -221,6 +236,7 @@ class HomePage extends HookConsumerWidget {
 | 
				
			|||||||
            if (selectionEnabledHook.value)
 | 
					            if (selectionEnabledHook.value)
 | 
				
			||||||
              ControlBottomAppBar(
 | 
					              ControlBottomAppBar(
 | 
				
			||||||
                onShare: onShareAssets,
 | 
					                onShare: onShareAssets,
 | 
				
			||||||
 | 
					                onFavorite: onFavoriteAssets,
 | 
				
			||||||
                onDelete: onDelete,
 | 
					                onDelete: onDelete,
 | 
				
			||||||
                onAddToAlbum: onAddToAlbum,
 | 
					                onAddToAlbum: onAddToAlbum,
 | 
				
			||||||
                albums: albums,
 | 
					                albums: albums,
 | 
				
			||||||
 | 
				
			|||||||
@ -277,14 +277,12 @@ class AssetNotifier extends StateNotifier<AssetsState> {
 | 
				
			|||||||
      return asset.isFavorite;
 | 
					      return asset.isFavorite;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await _updateAssetsState(
 | 
					    final index = state.allAssets.indexWhere((a) => asset.id == a.id);
 | 
				
			||||||
      state.allAssets.map((a) {
 | 
					    if (index > 0) {
 | 
				
			||||||
        if (asset.id == a.id) {
 | 
					      state.allAssets.removeAt(index);
 | 
				
			||||||
          return Asset.remote(newAsset);
 | 
					      state.allAssets.insert(index, Asset.remote(newAsset));
 | 
				
			||||||
 | 
					      _updateAssetsState(state.allAssets);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        return a;
 | 
					 | 
				
			||||||
      }).toList(),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return newAsset.isFavorite;
 | 
					    return newAsset.isFavorite;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user