2026-06-26 02:25:06 +05:30
|
|
|
import 'package:flutter/material.dart';
|
2026-07-31 02:32:14 +05:30
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
|
import 'package:immich_mobile/constants/enums.dart';
|
2026-06-26 02:25:06 +05:30
|
|
|
import 'package:immich_mobile/generated/translations.g.dart';
|
|
|
|
|
import 'package:immich_mobile/presentation/actions/action.dart';
|
|
|
|
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
2026-07-31 02:32:14 +05:30
|
|
|
import 'package:immich_mobile/providers/infrastructure/toast.provider.dart';
|
|
|
|
|
import 'package:immich_mobile/utils/error_handler.dart';
|
2026-06-26 02:25:06 +05:30
|
|
|
|
2026-07-31 02:32:14 +05:30
|
|
|
typedef _State = ({bool shouldFavorite, List<String> assetIds});
|
2026-06-26 02:25:06 +05:30
|
|
|
|
2026-07-31 02:32:14 +05:30
|
|
|
final _stateProvider = Provider.family.autoDispose<_State?, ActionSource>((ref, source) {
|
|
|
|
|
final assets = ref.watch(ownedAssetsActionProvider(source));
|
|
|
|
|
if (assets.isEmpty) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2026-06-26 02:25:06 +05:30
|
|
|
|
2026-07-31 02:32:14 +05:30
|
|
|
final shouldFavorite = assets.favorite(isFavorite: false).isNotEmpty;
|
|
|
|
|
final assetIds = assets.favorite(isFavorite: !shouldFavorite).map((asset) => asset.id).toList(growable: false);
|
|
|
|
|
return (shouldFavorite: shouldFavorite, assetIds: assetIds);
|
2026-08-03 19:53:12 +05:30
|
|
|
}, dependencies: [ownedAssetsActionProvider]);
|
2026-06-26 02:25:06 +05:30
|
|
|
|
2026-07-31 02:32:14 +05:30
|
|
|
class FavoriteAction extends AssetActionBuilder {
|
|
|
|
|
const FavoriteAction({required super.source});
|
2026-06-26 02:25:06 +05:30
|
|
|
|
|
|
|
|
@override
|
2026-07-31 02:32:14 +05:30
|
|
|
ActionItem? create(BuildContext context, WidgetRef ref) {
|
|
|
|
|
final shouldFavorite = ref.watch(_stateProvider(source).select((state) => state?.shouldFavorite));
|
|
|
|
|
if (shouldFavorite == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return .new(
|
|
|
|
|
icon: shouldFavorite ? Icons.favorite_border_rounded : Icons.favorite_rounded,
|
|
|
|
|
label: shouldFavorite ? context.t.favorite : context.t.unfavorite,
|
|
|
|
|
onAction: () => _favorite(context, ref),
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-06-26 02:25:06 +05:30
|
|
|
|
2026-07-31 02:32:14 +05:30
|
|
|
Future<void> _favorite(BuildContext context, WidgetRef ref) async {
|
|
|
|
|
final state = ref.read(_stateProvider(source));
|
|
|
|
|
if (state == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-01 08:06:40 +05:30
|
|
|
final (:shouldFavorite, :assetIds) = state;
|
2026-07-31 02:32:14 +05:30
|
|
|
final message = shouldFavorite
|
|
|
|
|
? context.t.favorite_action_prompt(count: assetIds.length)
|
|
|
|
|
: context.t.unfavorite_action_prompt(count: assetIds.length);
|
2026-08-01 08:06:40 +05:30
|
|
|
final assetService = ref.read(assetServiceProvider);
|
2026-07-31 02:32:14 +05:30
|
|
|
final toastService = ref.read(toastServiceProvider);
|
|
|
|
|
final clearSelection = ref.read(clearSelectionProvider(source));
|
|
|
|
|
|
|
|
|
|
try {
|
2026-08-01 08:06:40 +05:30
|
|
|
await assetService.update(assetIds, isFavorite: .some(shouldFavorite));
|
2026-07-31 02:32:14 +05:30
|
|
|
toastService.success(message);
|
|
|
|
|
clearSelection();
|
|
|
|
|
} catch (error, stack) {
|
|
|
|
|
handleError(error, stack: stack, description: "Failed to update favorite status for assets");
|
|
|
|
|
}
|
2026-06-26 02:25:06 +05:30
|
|
|
}
|
|
|
|
|
}
|