feat(mobile): unify asset grid multiselect actions (#5407)
* feat(mobile): unify asset grid multiselect actions * add favorite & archive page * show edit date&place on main photos screen * Reposition exit button * Sort favorite with the same order as other view --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
committed by
GitHub
parent
b9a9a3956c
commit
c25556bb08
@@ -2,11 +2,13 @@ import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/album/services/album.service.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/models/store.dart';
|
||||
import 'package:immich_mobile/shared/models/user.dart';
|
||||
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/utils/renderlist_generator.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
class AlbumNotifier extends StateNotifier<List<Album>> {
|
||||
@@ -49,3 +51,24 @@ final albumProvider =
|
||||
ref.watch(dbProvider),
|
||||
);
|
||||
});
|
||||
|
||||
final albumWatcher =
|
||||
StreamProvider.autoDispose.family<Album, int>((ref, albumId) async* {
|
||||
final db = ref.watch(dbProvider);
|
||||
final a = await db.albums.get(albumId);
|
||||
if (a != null) yield a;
|
||||
await for (final a in db.albums.watchObject(albumId, fireImmediately: true)) {
|
||||
if (a != null) yield a;
|
||||
}
|
||||
});
|
||||
|
||||
final albumRenderlistProvider =
|
||||
StreamProvider.autoDispose.family<RenderList, int>((ref, albumId) {
|
||||
final album = ref.watch(albumWatcher(albumId)).value;
|
||||
if (album != null) {
|
||||
final query =
|
||||
album.assets.filter().isTrashedEqualTo(false).sortByFileCreatedAtDesc();
|
||||
return renderListGeneratorWithGroupBy(query, GroupAssetsBy.none);
|
||||
}
|
||||
return const Stream.empty();
|
||||
});
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/album/services/album.service.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/providers/user.provider.dart';
|
||||
|
||||
final albumDetailProvider =
|
||||
StreamProvider.family<Album, int>((ref, albumId) async* {
|
||||
final user = ref.watch(currentUserProvider);
|
||||
if (user == null) return;
|
||||
final AlbumService service = ref.watch(albumServiceProvider);
|
||||
|
||||
await for (final a in service.watchAlbum(albumId)) {
|
||||
if (a == null) {
|
||||
throw Exception("Album with ID=$albumId does not exist anymore!");
|
||||
}
|
||||
await for (final _ in a.watchRenderList(GroupAssetsBy.none)) {
|
||||
yield a;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
|
||||
final currentAlbumProvider = StateProvider<Album?>((ref) {
|
||||
return null;
|
||||
});
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/services/album.service.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
@@ -11,7 +10,7 @@ import 'package:immich_mobile/shared/providers/db.provider.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
class SharedAlbumNotifier extends StateNotifier<List<Album>> {
|
||||
SharedAlbumNotifier(this._albumService, Isar db, this._ref) : super([]) {
|
||||
SharedAlbumNotifier(this._albumService, Isar db) : super([]) {
|
||||
final query = db.albums.filter().sharedEqualTo(true).sortByCreatedAtDesc();
|
||||
query.findAll().then((value) => state = value);
|
||||
_streamSub = query.watch().listen((data) => state = data);
|
||||
@@ -19,7 +18,6 @@ class SharedAlbumNotifier extends StateNotifier<List<Album>> {
|
||||
|
||||
final AlbumService _albumService;
|
||||
late final StreamSubscription<List<Album>> _streamSub;
|
||||
final Ref _ref;
|
||||
|
||||
Future<Album?> createSharedAlbum(
|
||||
String albumName,
|
||||
@@ -68,15 +66,8 @@ class SharedAlbumNotifier extends StateNotifier<List<Album>> {
|
||||
return result;
|
||||
}
|
||||
|
||||
Future<bool> setActivityEnabled(Album album, bool activityEnabled) async {
|
||||
final result =
|
||||
await _albumService.setActivityEnabled(album, activityEnabled);
|
||||
|
||||
if (result) {
|
||||
_ref.invalidate(albumDetailProvider(album.id));
|
||||
}
|
||||
|
||||
return result;
|
||||
Future<bool> setActivityEnabled(Album album, bool activityEnabled) {
|
||||
return _albumService.setActivityEnabled(album, activityEnabled);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -91,6 +82,5 @@ final sharedAlbumProvider =
|
||||
return SharedAlbumNotifier(
|
||||
ref.watch(albumServiceProvider),
|
||||
ref.watch(dbProvider),
|
||||
ref,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -219,11 +219,6 @@ class AlbumService {
|
||||
);
|
||||
}
|
||||
|
||||
Stream<Album?> watchAlbum(int albumId) async* {
|
||||
yield await _db.albums.get(albumId);
|
||||
yield* _db.albums.watchObject(albumId);
|
||||
}
|
||||
|
||||
Future<AddAssetsResponse?> addAdditionalAssetToAlbum(
|
||||
Iterable<Asset> assets,
|
||||
Album album,
|
||||
@@ -248,8 +243,12 @@ class AlbumService {
|
||||
}
|
||||
}
|
||||
|
||||
album.assets.addAll(successAssets);
|
||||
await _db.writeTxn(() => album.assets.save());
|
||||
await _db.writeTxn(() async {
|
||||
await album.assets.update(link: successAssets);
|
||||
final a = await _db.albums.get(album.id);
|
||||
// trigger watcher
|
||||
await _db.albums.put(a!);
|
||||
});
|
||||
|
||||
return AddAssetsResponse(
|
||||
alreadyInAlbum: duplicatedAssets,
|
||||
@@ -359,8 +358,12 @@ class AlbumService {
|
||||
ids: assets.map((asset) => asset.remoteId!).toList(),
|
||||
),
|
||||
);
|
||||
album.assets.removeAll(assets);
|
||||
await _db.writeTxn(() => album.assets.update(unlink: assets));
|
||||
await _db.writeTxn(() async {
|
||||
await album.assets.update(unlink: assets);
|
||||
final a = await _db.albums.get(album.id);
|
||||
// trigger watcher
|
||||
await _db.albums.put(a!);
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
@@ -380,7 +383,12 @@ class AlbumService {
|
||||
);
|
||||
|
||||
album.sharedUsers.remove(user);
|
||||
await _db.writeTxn(() => album.sharedUsers.update(unlink: [user]));
|
||||
await _db.writeTxn(() async {
|
||||
await album.sharedUsers.update(unlink: [user]);
|
||||
final a = await _db.albums.get(album.id);
|
||||
// trigger watcher
|
||||
await _db.albums.put(a!);
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.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/album/ui/add_to_album_sliverlist.dart';
|
||||
@@ -63,8 +62,6 @@ class AddToAlbumBottomSheet extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
context.pop();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/activities/providers/activity.provider.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/album_viewer.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/share_dialog.dart';
|
||||
import 'package:immich_mobile/shared/services/share.service.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
|
||||
@@ -22,8 +18,6 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
Key? key,
|
||||
required this.album,
|
||||
required this.userId,
|
||||
required this.selected,
|
||||
required this.selectionDisabled,
|
||||
required this.titleFocusNode,
|
||||
this.onAddPhotos,
|
||||
this.onAddUsers,
|
||||
@@ -32,8 +26,6 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
|
||||
final Album album;
|
||||
final String userId;
|
||||
final Set<Asset> selected;
|
||||
final void Function() selectionDisabled;
|
||||
final FocusNode titleFocusNode;
|
||||
final Function(Album album)? onAddPhotos;
|
||||
final Function(Album album)? onAddUsers;
|
||||
@@ -144,109 +136,27 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void onRemoveFromAlbumPressed() async {
|
||||
isProcessing.value = true;
|
||||
|
||||
bool isSuccess =
|
||||
await ref.watch(sharedAlbumProvider.notifier).removeAssetFromAlbum(
|
||||
album,
|
||||
selected,
|
||||
);
|
||||
|
||||
if (isSuccess) {
|
||||
context.pop();
|
||||
selectionDisabled();
|
||||
ref.watch(albumProvider.notifier).getAllAlbums();
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
} else {
|
||||
context.pop();
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_remove".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
}
|
||||
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
void handleShareAssets(
|
||||
WidgetRef ref,
|
||||
BuildContext context,
|
||||
Set<Asset> selection,
|
||||
) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext buildContext) {
|
||||
ref.watch(shareServiceProvider).shareAssets(selection.toList()).then(
|
||||
(bool status) {
|
||||
if (!status) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: 'image_viewer_page_state_provider_share_error'.tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
}
|
||||
buildContext.pop();
|
||||
},
|
||||
);
|
||||
return const ShareDialog();
|
||||
},
|
||||
barrierDismissible: false,
|
||||
);
|
||||
}
|
||||
|
||||
void onShareAssetsTo() async {
|
||||
isProcessing.value = true;
|
||||
handleShareAssets(ref, context, selected);
|
||||
isProcessing.value = false;
|
||||
}
|
||||
|
||||
buildBottomSheetActions() {
|
||||
if (selected.isNotEmpty) {
|
||||
return [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.ios_share_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_to',
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onShareAssetsTo(),
|
||||
),
|
||||
album.ownerId == userId
|
||||
? ListTile(
|
||||
leading: const Icon(Icons.delete_sweep_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_remove',
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onRemoveFromAlbumPressed(),
|
||||
)
|
||||
: const SizedBox(),
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
album.ownerId == userId
|
||||
? ListTile(
|
||||
leading: const Icon(Icons.delete_forever_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_delete',
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onDeleteAlbumPressed(),
|
||||
)
|
||||
: ListTile(
|
||||
leading: const Icon(Icons.person_remove_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_leave',
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onLeaveAlbumPressed(),
|
||||
),
|
||||
];
|
||||
}
|
||||
return [
|
||||
album.ownerId == userId
|
||||
? ListTile(
|
||||
leading: const Icon(Icons.delete_forever_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_delete',
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onDeleteAlbumPressed(),
|
||||
)
|
||||
: ListTile(
|
||||
leading: const Icon(Icons.person_remove_rounded),
|
||||
title: const Text(
|
||||
'album_viewer_appbar_share_leave',
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
).tr(),
|
||||
onTap: () => onLeaveAlbumPressed(),
|
||||
),
|
||||
];
|
||||
// }
|
||||
}
|
||||
|
||||
void buildBottomSheet() {
|
||||
@@ -308,10 +218,8 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...buildBottomSheetActions(),
|
||||
if (selected.isEmpty && onAddPhotos != null) ...commonActions,
|
||||
if (selected.isEmpty &&
|
||||
onAddPhotos != null &&
|
||||
userId == album.ownerId)
|
||||
if (onAddPhotos != null) ...commonActions,
|
||||
if (onAddPhotos != null && userId == album.ownerId)
|
||||
...ownerActions,
|
||||
],
|
||||
),
|
||||
@@ -349,13 +257,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
}
|
||||
|
||||
buildLeadingButton() {
|
||||
if (selected.isNotEmpty) {
|
||||
return IconButton(
|
||||
onPressed: selectionDisabled,
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
splashRadius: 25,
|
||||
);
|
||||
} else if (isEditAlbum) {
|
||||
if (isEditAlbum) {
|
||||
return IconButton(
|
||||
onPressed: () async {
|
||||
bool isSuccess = await ref
|
||||
@@ -388,7 +290,6 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
||||
return AppBar(
|
||||
elevation: 0,
|
||||
leading: buildLeadingButton(),
|
||||
title: selected.isNotEmpty ? Text('${selected.length}') : null,
|
||||
centerTitle: false,
|
||||
actions: [
|
||||
if (album.shared && (album.activityEnabled || comments != 0))
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
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/extensions/asyncvalue_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||
import 'package:immich_mobile/modules/album/models/asset_selection_page_result.model.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/album_detail.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/album.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/providers/current_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/ui/album_action_outlined_button.dart';
|
||||
import 'package:immich_mobile/modules/album/ui/album_viewer_editable_title.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
|
||||
import 'package:immich_mobile/modules/home/providers/multiselect.provider.dart';
|
||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
|
||||
import 'package:immich_mobile/modules/album/ui/album_viewer_appbar.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/shared/models/album.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||
import 'package:immich_mobile/shared/ui/asset_grid/multiselect_grid.dart';
|
||||
import 'package:immich_mobile/shared/ui/immich_toast.dart';
|
||||
import 'package:immich_mobile/shared/ui/user_circle_avatar.dart';
|
||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||
|
||||
@@ -29,39 +32,30 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
FocusNode titleFocusNode = useFocusNode();
|
||||
final album = ref.watch(albumDetailProvider(albumId));
|
||||
final album = ref.watch(albumWatcher(albumId));
|
||||
album.whenData(
|
||||
(value) =>
|
||||
Future((() => ref.read(currentAlbumProvider.notifier).state = value)),
|
||||
);
|
||||
final userId = ref.watch(authenticationProvider).userId;
|
||||
final selection = useState<Set<Asset>>({});
|
||||
final multiSelectEnabled = useState(false);
|
||||
final isProcessing = useProcessingOverlay();
|
||||
|
||||
useEffect(
|
||||
() {
|
||||
// Fetch album updates, e.g., cover image
|
||||
ref.invalidate(albumDetailProvider(albumId));
|
||||
return null;
|
||||
},
|
||||
[],
|
||||
);
|
||||
Future<bool> onRemoveFromAlbumPressed(Iterable<Asset> assets) async {
|
||||
final a = album.valueOrNull;
|
||||
final bool isSuccess = a != null &&
|
||||
await ref
|
||||
.read(sharedAlbumProvider.notifier)
|
||||
.removeAssetFromAlbum(a, assets);
|
||||
|
||||
Future<bool> onWillPop() async {
|
||||
if (multiSelectEnabled.value) {
|
||||
selection.value = {};
|
||||
multiSelectEnabled.value = false;
|
||||
return false;
|
||||
if (!isSuccess) {
|
||||
ImmichToast.show(
|
||||
context: context,
|
||||
msg: "album_viewer_appbar_share_err_remove".tr(),
|
||||
toastType: ToastType.error,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void selectionListener(bool active, Set<Asset> selected) {
|
||||
selection.value = selected;
|
||||
multiSelectEnabled.value = selected.isNotEmpty;
|
||||
}
|
||||
|
||||
void disableSelection() {
|
||||
selection.value = {};
|
||||
multiSelectEnabled.value = false;
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
/// Find out if the assets in album exist on the device
|
||||
@@ -80,15 +74,10 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
// Check if there is new assets add
|
||||
isProcessing.value = true;
|
||||
|
||||
var addAssetsResult =
|
||||
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
|
||||
returnPayload.selectedAssets,
|
||||
albumInfo,
|
||||
);
|
||||
|
||||
if (addAssetsResult != null && addAssetsResult.successfullyAdded > 0) {
|
||||
ref.invalidate(albumDetailProvider(albumId));
|
||||
}
|
||||
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
|
||||
returnPayload.selectedAssets,
|
||||
albumInfo,
|
||||
);
|
||||
|
||||
isProcessing.value = false;
|
||||
}
|
||||
@@ -102,14 +91,10 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
if (sharedUserIds != null) {
|
||||
isProcessing.value = true;
|
||||
|
||||
var isSuccess = await ref
|
||||
await ref
|
||||
.watch(albumServiceProvider)
|
||||
.addAdditionalUserToAlbum(sharedUserIds, album);
|
||||
|
||||
if (isSuccess) {
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
}
|
||||
|
||||
isProcessing.value = false;
|
||||
}
|
||||
}
|
||||
@@ -193,10 +178,7 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
|
||||
Widget buildSharedUserIconsRow(Album album) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
await context.autoPush(AlbumOptionsRoute(album: album));
|
||||
ref.invalidate(albumDetailProvider(album.id));
|
||||
},
|
||||
onTap: () => context.autoPush(AlbumOptionsRoute(album: album)),
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: ListView.builder(
|
||||
@@ -244,42 +226,32 @@ class AlbumViewerPage extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: album.when(
|
||||
data: (data) => AlbumViewerAppbar(
|
||||
titleFocusNode: titleFocusNode,
|
||||
album: data,
|
||||
userId: userId,
|
||||
selected: selection.value,
|
||||
selectionDisabled: disableSelection,
|
||||
onAddPhotos: onAddPhotosPressed,
|
||||
onAddUsers: onAddUsersPressed,
|
||||
onActivities: onActivitiesPressed,
|
||||
),
|
||||
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
||||
loading: () => AppBar(),
|
||||
),
|
||||
body: album.widgetWhen(
|
||||
onData: (data) => WillPopScope(
|
||||
onWillPop: onWillPop,
|
||||
child: GestureDetector(
|
||||
onTap: () => titleFocusNode.unfocus(),
|
||||
child: ImmichAssetGrid(
|
||||
renderList: data.renderList,
|
||||
listener: selectionListener,
|
||||
selectionActive: multiSelectEnabled.value,
|
||||
showMultiSelectIndicator: false,
|
||||
topWidget: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildHeader(data),
|
||||
if (data.isRemote) buildControlButton(data),
|
||||
],
|
||||
appBar: ref.watch(multiselectProvider)
|
||||
? null
|
||||
: album.when(
|
||||
data: (data) => AlbumViewerAppbar(
|
||||
titleFocusNode: titleFocusNode,
|
||||
album: data,
|
||||
userId: userId,
|
||||
onAddPhotos: onAddPhotosPressed,
|
||||
onAddUsers: onAddUsersPressed,
|
||||
onActivities: onActivitiesPressed,
|
||||
),
|
||||
isOwner: userId == data.ownerId,
|
||||
sharedAlbumId:
|
||||
data.shared && data.activityEnabled ? data.remoteId : null,
|
||||
error: (error, stackTrace) => AppBar(title: const Text("Error")),
|
||||
loading: () => AppBar(),
|
||||
),
|
||||
body: album.widgetWhen(
|
||||
onData: (data) => MultiselectGrid(
|
||||
renderListProvider: albumRenderlistProvider(albumId),
|
||||
topWidget: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildHeader(data),
|
||||
if (data.isRemote) buildControlButton(data),
|
||||
],
|
||||
),
|
||||
onRemoveFromAlbum: onRemoveFromAlbumPressed,
|
||||
editEnabled: data.ownerId == userId,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user