Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart';
Expand All @@ -16,22 +18,74 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_act
import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';

class RemoteAlbumBottomSheet extends ConsumerWidget {
class RemoteAlbumBottomSheet extends ConsumerStatefulWidget {
final RemoteAlbum album;
const RemoteAlbumBottomSheet({super.key, required this.album});

@override
Widget build(BuildContext context, WidgetRef ref) {
ConsumerState<RemoteAlbumBottomSheet> createState() => _RemoteAlbumBottomSheetState();
}

class _RemoteAlbumBottomSheetState extends ConsumerState<RemoteAlbumBottomSheet> {
late DraggableScrollableController sheetController;

@override
void initState() {
super.initState();
sheetController = DraggableScrollableController();
}

@override
void dispose() {
sheetController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final multiselect = ref.watch(multiSelectProvider);
final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));

Future<void> addAssetsToAlbum(RemoteAlbum album) async {
final selectedAssets = multiselect.selectedAssets;
if (selectedAssets.isEmpty) {
return;
}

final addedCount = await ref
.read(remoteAlbumProvider.notifier)
.addAssets(album.id, selectedAssets.map((e) => (e as RemoteAsset).id).toList());

if (addedCount != selectedAssets.length) {
ImmichToast.show(
context: context,
msg: 'add_to_album_bottom_sheet_already_exists'.t(context: context, args: {"album": album.name}),
);
} else {
ImmichToast.show(
context: context,
msg: 'add_to_album_bottom_sheet_added'.t(context: context, args: {"album": album.name}),
);
}

ref.read(multiSelectProvider.notifier).reset();
}

Future<void> onKeyboardExpand() {
return sheetController.animateTo(0.85, duration: const Duration(milliseconds: 200), curve: Curves.easeInOut);
}

return BaseBottomSheet(
initialChildSize: 0.25,
maxChildSize: 0.4,
controller: sheetController,
initialChildSize: 0.45,
maxChildSize: 0.85,
shouldCloseOnMinExtent: false,
actions: [
const ShareActionButton(source: ActionSource.timeline),
Expand All @@ -52,7 +106,11 @@ class RemoteAlbumBottomSheet extends ConsumerWidget {
const DeleteLocalActionButton(source: ActionSource.timeline),
const UploadActionButton(source: ActionSource.timeline),
],
RemoveFromAlbumActionButton(source: ActionSource.timeline, albumId: album.id),
RemoveFromAlbumActionButton(source: ActionSource.timeline, albumId: widget.album.id),
],
slivers: [
const AddToAlbumHeader(),
AlbumSelector(onAlbumSelected: addAssetsToAlbum, onKeyboardExpanded: onKeyboardExpand),
],
);
}
Expand Down
25 changes: 25 additions & 0 deletions mobile/lib/widgets/asset_grid/control_bottom_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/providers/album/album.provider.dart';
import 'package:immich_mobile/providers/routes.provider.dart';
import 'package:immich_mobile/widgets/album/add_to_album_sliverlist.dart';
import 'package:immich_mobile/widgets/album/add_to_album_bottom_sheet.dart';
import 'package:immich_mobile/models/asset_selection_state.dart';
import 'package:immich_mobile/widgets/asset_grid/delete_dialog.dart';
import 'package:immich_mobile/widgets/asset_grid/upload_dialog.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/widgets/common/drag_sheet.dart';
import 'package:immich_mobile/entities/album.entity.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/utils/draggable_scroll_controller.dart';

final controlBottomAppBarNotifier = ControlBottomAppBarNotifier();
Expand Down Expand Up @@ -45,6 +47,7 @@ class ControlBottomAppBar extends HookConsumerWidget {
final bool unfavorite;
final bool unarchive;
final AssetSelectionState selectionAssetState;
final List<Asset> selectedAssets;

const ControlBottomAppBar({
super.key,
Expand All @@ -64,6 +67,7 @@ class ControlBottomAppBar extends HookConsumerWidget {
this.onRemoveFromAlbum,
this.onToggleLocked,
this.selectionAssetState = const AssetSelectionState(),
this.selectedAssets = const [],
this.enabled = true,
this.unarchive = false,
this.unfavorite = false,
Expand Down Expand Up @@ -100,6 +104,18 @@ class ControlBottomAppBar extends HookConsumerWidget {
);
}

/// Show existing AddToAlbumBottomSheet
void showAddToAlbumBottomSheet() {
showModalBottomSheet(
elevation: 0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15.0))),
context: context,
builder: (BuildContext _) {
return AddToAlbumBottomSheet(assets: selectedAssets);
},
);
}

void handleRemoteDelete(bool force, Function(bool) deleteCb, {String? alertMsg}) {
if (!force) {
deleteCb(force);
Expand All @@ -121,6 +137,15 @@ class ControlBottomAppBar extends HookConsumerWidget {
label: "share_link".tr(),
onPressed: enabled ? () => onShare(false) : null,
),
if (!isInLockedView && hasRemote && albums.isNotEmpty)
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 100),
child: ControlBoxButton(
iconData: Icons.photo_album,
label: "add_to_album".tr(),
onPressed: enabled ? showAddToAlbumBottomSheet : null,
),
),
if (hasRemote && onArchive != null)
ControlBoxButton(
iconData: unarchive ? Icons.unarchive_outlined : Icons.archive_outlined,
Expand Down
1 change: 1 addition & 0 deletions mobile/lib/widgets/asset_grid/multiselect_grid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ class MultiselectGrid extends HookConsumerWidget {
onUpload: onUpload,
enabled: !processing.value,
selectionAssetState: selectionAssetState.value,
selectedAssets: selection.value.toList(),
onStack: stackEnabled ? onStack : null,
onEditTime: editEnabled ? onEditTime : null,
onEditLocation: editEnabled ? onEditLocation : null,
Expand Down