mirror of
https://github.com/immich-app/immich.git
synced 2025-07-09 03:04:16 -04:00
feat(mobile): remove from album action
This commit is contained in:
parent
ca78bc91b6
commit
83c5b167de
@ -1498,6 +1498,7 @@
|
|||||||
"remove_custom_date_range": "Remove custom date range",
|
"remove_custom_date_range": "Remove custom date range",
|
||||||
"remove_deleted_assets": "Remove Deleted Assets",
|
"remove_deleted_assets": "Remove Deleted Assets",
|
||||||
"remove_from_album": "Remove from album",
|
"remove_from_album": "Remove from album",
|
||||||
|
"remove_from_album_action_prompt": "{count} removed from the album",
|
||||||
"remove_from_favorites": "Remove from favorites",
|
"remove_from_favorites": "Remove from favorites",
|
||||||
"remove_from_lock_folder_action_prompt": "{count} removed from the locked folder",
|
"remove_from_lock_folder_action_prompt": "{count} removed from the locked folder",
|
||||||
"remove_from_locked_folder": "Remove from locked folder",
|
"remove_from_locked_folder": "Remove from locked folder",
|
||||||
|
@ -39,6 +39,20 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
|||||||
query.orderBy(orderings);
|
query.orderBy(orderings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> removeFromAlbum(List<String> ids, String albumId) {
|
||||||
|
return _db.batch((batch) {
|
||||||
|
for (final assetId in ids) {
|
||||||
|
batch.delete(
|
||||||
|
_db.remoteAlbumAssetEntity,
|
||||||
|
RemoteAlbumAssetEntityCompanion(
|
||||||
|
albumId: Value(albumId),
|
||||||
|
assetId: Value(assetId),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return query
|
return query
|
||||||
.map(
|
.map(
|
||||||
(row) => row.readTable(_db.remoteAlbumEntity).toDto(
|
(row) => row.readTable(_db.remoteAlbumEntity).toDto(
|
||||||
|
@ -1,16 +1,51 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
|
||||||
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
|
|
||||||
class RemoveFromAlbumActionButton extends ConsumerWidget {
|
class RemoveFromAlbumActionButton extends ConsumerWidget {
|
||||||
const RemoveFromAlbumActionButton({super.key});
|
final ActionSource source;
|
||||||
|
const RemoveFromAlbumActionButton({super.key, required this.source});
|
||||||
|
|
||||||
|
void _onTap(BuildContext context, WidgetRef ref) async {
|
||||||
|
if (!context.mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final result =
|
||||||
|
await ref.read(actionProvider.notifier).removeFromAlbum(source);
|
||||||
|
await ref.read(timelineServiceProvider).reloadBucket();
|
||||||
|
ref.read(multiSelectProvider.notifier).reset();
|
||||||
|
|
||||||
|
final successMessage = 'remove_from_album_action_prompt'.t(
|
||||||
|
context: context,
|
||||||
|
args: {'count': result.count.toString()},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
ImmichToast.show(
|
||||||
|
context: context,
|
||||||
|
msg: result.success
|
||||||
|
? successMessage
|
||||||
|
: 'scaffold_body_error_occurred'.t(context: context),
|
||||||
|
gravity: ToastGravity.BOTTOM,
|
||||||
|
toastType: result.success ? ToastType.success : ToastType.error,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return BaseActionButton(
|
return BaseActionButton(
|
||||||
iconData: Icons.remove_circle_outline,
|
iconData: Icons.remove_circle_outline,
|
||||||
label: "remove_from_album".t(context: context),
|
label: "remove_from_album".t(context: context),
|
||||||
|
onPressed: () => _onTap(context, ref);
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,21 @@ class ActionNotifier extends Notifier<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<ActionResult> removeFromAlbum(ActionSource source) async {
|
||||||
|
final ids = _getOwnedRemoteForSource(source);
|
||||||
|
try {
|
||||||
|
await _service.removeFromAlbum(ids);
|
||||||
|
return ActionResult(count: ids.length, success: true);
|
||||||
|
} catch (error, stack) {
|
||||||
|
_logger.severe('Failed to remove assets from album', error, stack);
|
||||||
|
return ActionResult(
|
||||||
|
count: ids.length,
|
||||||
|
success: false,
|
||||||
|
error: error.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<ActionResult?> editLocation(
|
Future<ActionResult?> editLocation(
|
||||||
ActionSource source,
|
ActionSource source,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
@ -66,6 +66,15 @@ class AssetApiRepository extends ApiRepository {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> removeFromAlbum(
|
||||||
|
List<String> ids,
|
||||||
|
String albumId
|
||||||
|
) async {
|
||||||
|
return _api.updateAlbum(
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> updateLocation(
|
Future<void> updateLocation(
|
||||||
List<String> ids,
|
List<String> ids,
|
||||||
LatLng location,
|
LatLng location,
|
||||||
|
@ -5,6 +5,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|||||||
import 'package:immich_mobile/infrastructure/repositories/exif.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/exif.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/remote_asset.repository.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
import 'package:immich_mobile/repositories/asset_api.repository.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
@ -17,6 +18,7 @@ final actionServiceProvider = Provider<ActionService>(
|
|||||||
ref.watch(assetApiRepositoryProvider),
|
ref.watch(assetApiRepositoryProvider),
|
||||||
ref.watch(remoteAssetRepository),
|
ref.watch(remoteAssetRepository),
|
||||||
ref.watch(remoteExifRepository),
|
ref.watch(remoteExifRepository),
|
||||||
|
ref.watch(remoteAlbumRepository),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -24,11 +26,13 @@ class ActionService {
|
|||||||
final AssetApiRepository _assetApiRepository;
|
final AssetApiRepository _assetApiRepository;
|
||||||
final DriftRemoteAssetRepository _remoteAssetRepository;
|
final DriftRemoteAssetRepository _remoteAssetRepository;
|
||||||
final DriftRemoteExifRepository _remoteExifRepository;
|
final DriftRemoteExifRepository _remoteExifRepository;
|
||||||
|
final DriftRemoteAlbumRepository _remoteAlbumRepository;
|
||||||
|
|
||||||
const ActionService(
|
const ActionService(
|
||||||
this._assetApiRepository,
|
this._assetApiRepository,
|
||||||
this._remoteAssetRepository,
|
this._remoteAssetRepository,
|
||||||
this._remoteExifRepository,
|
this._remoteExifRepository,
|
||||||
|
this._remoteAlbumRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> shareLink(List<String> remoteIds, BuildContext context) async {
|
Future<void> shareLink(List<String> remoteIds, BuildContext context) async {
|
||||||
@ -93,6 +97,11 @@ class ActionService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> removeFromAlbum(List<String> remoteIds, String albumId) async {
|
||||||
|
await _assetApiRepository.removeFromAlbum(remoteIds, albumId);
|
||||||
|
await _remoteAlbumRepository.removeFromAlbum(remoteIds, albumId);
|
||||||
|
}
|
||||||
|
|
||||||
Future<bool> editLocation(
|
Future<bool> editLocation(
|
||||||
List<String> remoteIds,
|
List<String> remoteIds,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user