mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -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),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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 =
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@ import 'package:immich_mobile/shared/models/album.dart';
 | 
			
		||||
 | 
			
		||||
class ControlBottomAppBar extends ConsumerWidget {
 | 
			
		||||
  final Function onShare;
 | 
			
		||||
  final Function onFavorite;
 | 
			
		||||
  final Function onDelete;
 | 
			
		||||
  final Function(Album album) onAddToAlbum;
 | 
			
		||||
  final void Function() onCreateNewAlbum;
 | 
			
		||||
@ -18,6 +19,7 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
			
		||||
  const ControlBottomAppBar({
 | 
			
		||||
    Key? key,
 | 
			
		||||
    required this.onShare,
 | 
			
		||||
    required this.onFavorite,
 | 
			
		||||
    required this.onDelete,
 | 
			
		||||
    required this.sharedAlbums,
 | 
			
		||||
    required this.albums,
 | 
			
		||||
@ -37,6 +39,13 @@ class ControlBottomAppBar extends ConsumerWidget {
 | 
			
		||||
              onShare();
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          ControlBoxButton(
 | 
			
		||||
            iconData: Icons.star_rounded,
 | 
			
		||||
            label: "Favorite",
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              onFavorite();
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          ControlBoxButton(
 | 
			
		||||
            iconData: Icons.delete_outline_rounded,
 | 
			
		||||
            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/shared_album.provider.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/ui/asset_grid/immich_asset_grid.dart';
 | 
			
		||||
import 'package:immich_mobile/modules/home/ui/control_bottom_app_bar.dart';
 | 
			
		||||
@ -83,27 +84,39 @@ class HomePage extends HookConsumerWidget {
 | 
			
		||||
        selectionEnabledHook.value = false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      void onDelete() {
 | 
			
		||||
        ref.watch(assetProvider.notifier).deleteAssets(selection.value);
 | 
			
		||||
        selectionEnabledHook.value = false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Iterable<Asset> remoteOnlySelection() {
 | 
			
		||||
      Iterable<Asset> remoteOnlySelection({String? localErrorMessage}) {
 | 
			
		||||
        final Set<Asset> assets = selection.value;
 | 
			
		||||
        final bool onlyRemote = assets.every((e) => e.isRemote);
 | 
			
		||||
        if (!onlyRemote) {
 | 
			
		||||
          if (localErrorMessage != null && localErrorMessage.isNotEmpty) {
 | 
			
		||||
            ImmichToast.show(
 | 
			
		||||
              context: context,
 | 
			
		||||
            msg: "Can not add local assets to albums yet, skipping",
 | 
			
		||||
              msg: localErrorMessage,
 | 
			
		||||
              gravity: ToastGravity.BOTTOM,
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          return assets.where((a) => a.isRemote);
 | 
			
		||||
        }
 | 
			
		||||
        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 {
 | 
			
		||||
        final Iterable<Asset> assets = remoteOnlySelection();
 | 
			
		||||
        final Iterable<Asset> assets = remoteOnlySelection(
 | 
			
		||||
          localErrorMessage: "Can not add local assets to albums yet, skipping",
 | 
			
		||||
        );
 | 
			
		||||
        if (assets.isEmpty) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
@ -142,7 +155,9 @@ class HomePage extends HookConsumerWidget {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      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) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
@ -221,6 +236,7 @@ class HomePage extends HookConsumerWidget {
 | 
			
		||||
            if (selectionEnabledHook.value)
 | 
			
		||||
              ControlBottomAppBar(
 | 
			
		||||
                onShare: onShareAssets,
 | 
			
		||||
                onFavorite: onFavoriteAssets,
 | 
			
		||||
                onDelete: onDelete,
 | 
			
		||||
                onAddToAlbum: onAddToAlbum,
 | 
			
		||||
                albums: albums,
 | 
			
		||||
 | 
			
		||||
@ -277,14 +277,12 @@ class AssetNotifier extends StateNotifier<AssetsState> {
 | 
			
		||||
      return asset.isFavorite;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await _updateAssetsState(
 | 
			
		||||
      state.allAssets.map((a) {
 | 
			
		||||
        if (asset.id == a.id) {
 | 
			
		||||
          return Asset.remote(newAsset);
 | 
			
		||||
    final index = state.allAssets.indexWhere((a) => asset.id == a.id);
 | 
			
		||||
    if (index > 0) {
 | 
			
		||||
      state.allAssets.removeAt(index);
 | 
			
		||||
      state.allAssets.insert(index, Asset.remote(newAsset));
 | 
			
		||||
      _updateAssetsState(state.allAssets);
 | 
			
		||||
    }
 | 
			
		||||
        return a;
 | 
			
		||||
      }).toList(),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return newAsset.isFavorite;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user