diff --git a/mobile/lib/modules/asset_viewer/providers/asset_stack.provider.dart b/mobile/lib/modules/asset_viewer/providers/asset_stack.provider.dart index 8f8e9bbe02..893e347d7c 100644 --- a/mobile/lib/modules/asset_viewer/providers/asset_stack.provider.dart +++ b/mobile/lib/modules/asset_viewer/providers/asset_stack.provider.dart @@ -46,5 +46,6 @@ final assetStackProvider = .isArchivedEqualTo(false) .isTrashedEqualTo(false) .stackParentIdEqualTo(asset.remoteId) + .sortByFileCreatedAtDesc() .findAll(); }); diff --git a/mobile/lib/modules/home/models/selection_state.dart b/mobile/lib/modules/home/models/selection_state.dart index 291b590689..e5a7b60a3c 100644 --- a/mobile/lib/modules/home/models/selection_state.dart +++ b/mobile/lib/modules/home/models/selection_state.dart @@ -4,33 +4,38 @@ class SelectionAssetState { final bool hasRemote; final bool hasLocal; final bool hasMerged; + final int selectedCount; const SelectionAssetState({ this.hasRemote = false, this.hasLocal = false, this.hasMerged = false, + this.selectedCount = 0, }); SelectionAssetState copyWith({ bool? hasRemote, bool? hasLocal, bool? hasMerged, + int? selectedCount, }) { return SelectionAssetState( hasRemote: hasRemote ?? this.hasRemote, hasLocal: hasLocal ?? this.hasLocal, hasMerged: hasMerged ?? this.hasMerged, + selectedCount: selectedCount ?? this.selectedCount, ); } SelectionAssetState.fromSelection(Set selection) : hasLocal = selection.any((e) => e.storage == AssetState.local), hasMerged = selection.any((e) => e.storage == AssetState.merged), - hasRemote = selection.any((e) => e.storage == AssetState.remote); + hasRemote = selection.any((e) => e.storage == AssetState.remote), + selectedCount = selection.length; @override String toString() => - 'SelectionAssetState(hasRemote: $hasRemote, hasMerged: $hasMerged, hasMerged: $hasMerged)'; + 'SelectionAssetState(hasRemote: $hasRemote, hasMerged: $hasMerged, hasMerged: $hasMerged, selectedCount: $selectedCount)'; @override bool operator ==(covariant SelectionAssetState other) { @@ -38,10 +43,14 @@ class SelectionAssetState { return other.hasRemote == hasRemote && other.hasLocal == hasLocal && - other.hasMerged == hasMerged; + other.hasMerged == hasMerged && + other.selectedCount == selectedCount; } @override int get hashCode => - hasRemote.hashCode ^ hasLocal.hashCode ^ hasMerged.hashCode; + hasRemote.hashCode ^ + hasLocal.hashCode ^ + hasMerged.hashCode ^ + selectedCount.hashCode; } diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart index 2c7f6ad632..ec44aaef15 100644 --- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart +++ b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart @@ -94,7 +94,7 @@ class ControlBottomAppBar extends ConsumerWidget { } : null, ), - if (!hasLocal) + if (!hasLocal && selectionAssetState.selectedCount > 1) ControlBoxButton( iconData: Icons.filter_none_rounded, label: "control_bottom_app_bar_stack".tr(), diff --git a/mobile/lib/modules/home/views/home_page.dart b/mobile/lib/modules/home/views/home_page.dart index 35670a93cf..d84fc153c5 100644 --- a/mobile/lib/modules/home/views/home_page.dart +++ b/mobile/lib/modules/home/views/home_page.dart @@ -7,12 +7,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart'; import 'package:immich_mobile/modules/album/providers/album.provider.dart'; import 'package:immich_mobile/modules/album/providers/album_detail.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/asset_viewer/providers/asset_stack.provider.dart'; import 'package:immich_mobile/modules/asset_viewer/services/asset_stack.service.dart'; import 'package:immich_mobile/modules/backup/providers/manual_upload.provider.dart'; import 'package:immich_mobile/modules/home/models/selection_state.dart'; @@ -259,46 +257,15 @@ class HomePage extends HookConsumerWidget { void onStack() async { try { processing.value = true; - if (!selectionEnabledHook.value) { + if (!selectionEnabledHook.value || selection.value.length < 2) { return; } - - final selectedAsset = selection.value.elementAt(0); - - if (selection.value.length == 1) { - final stackChildren = - (await ref.read(assetStackProvider(selectedAsset).future)) - .toSet(); - AssetSelectionPageResult? returnPayload = - await AutoRouter.of(context).push( - AssetSelectionRoute( - existingAssets: stackChildren, - canDeselect: true, - query: getAssetStackSelectionQuery(ref, selectedAsset), - ), - ); - - if (returnPayload != null) { - Set selectedAssets = returnPayload.selectedAssets; - // Do not add itself as its stack child - selectedAssets.remove(selectedAsset); - final removedChildren = stackChildren.difference(selectedAssets); - final addedChildren = selectedAssets.difference(stackChildren); - await ref.read(assetStackServiceProvider).updateStack( - selectedAsset, - childrenToAdd: addedChildren.toList(), - childrenToRemove: removedChildren.toList(), - ); - } - } else { - // Merge assets - selection.value.remove(selectedAsset); - final selectedAssets = selection.value; - await ref.read(assetStackServiceProvider).updateStack( - selectedAsset, - childrenToAdd: selectedAssets.toList(), - ); - } + final parent = selection.value.elementAt(0); + selection.value.remove(parent); + await ref.read(assetStackServiceProvider).updateStack( + parent, + childrenToAdd: selection.value.toList(), + ); } finally { processing.value = false; selectionEnabledHook.value = false; diff --git a/mobile/lib/shared/providers/asset.provider.dart b/mobile/lib/shared/providers/asset.provider.dart index bc36f65b98..8e6f8c12eb 100644 --- a/mobile/lib/shared/providers/asset.provider.dart +++ b/mobile/lib/shared/providers/asset.provider.dart @@ -245,31 +245,3 @@ QueryBuilder? getRemoteAssetQuery(WidgetRef ref) { .stackParentIdIsNull() .sortByFileCreatedAtDesc(); } - -QueryBuilder? getAssetStackSelectionQuery( - WidgetRef ref, - Asset parentAsset, -) { - final userId = ref.watch(currentUserProvider)?.isarId; - if (userId == null || !parentAsset.isRemote) { - return null; - } - return ref - .watch(dbProvider) - .assets - .where() - .remoteIdIsNotNull() - .filter() - .isArchivedEqualTo(false) - .ownerIdEqualTo(userId) - .not() - .remoteIdEqualTo(parentAsset.remoteId) - // Show existing stack children in selection page - .group( - (q) => q - .stackParentIdIsNull() - .or() - .stackParentIdEqualTo(parentAsset.remoteId), - ) - .sortByFileCreatedAtDesc(); -}