mirror of
https://github.com/immich-app/immich.git
synced 2026-07-04 03:45:59 -07:00
f29f86542c
* feat: partner actions # Conflicts: # i18n/en.json * cleanup * fix tests * ci fix --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
126 lines
4.0 KiB
Dart
126 lines
4.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
|
import 'package:immich_mobile/generated/translations.g.dart';
|
|
import 'package:immich_mobile/presentation/actions/action.dart';
|
|
import 'package:immich_mobile/presentation/widgets/people/partner_user_avatar.widget.dart';
|
|
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
|
import 'package:immich_mobile/providers/user.provider.dart';
|
|
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
|
|
|
|
class PartnerAddAction extends BaseAction {
|
|
const PartnerAddAction();
|
|
|
|
@override
|
|
IconData get icon => Icons.person_add_rounded;
|
|
|
|
@override
|
|
String label(ActionScope scope) => scope.context.t.add_partner;
|
|
|
|
@override
|
|
Future<void> onAction(ActionScope scope) async {
|
|
final ActionScope(:context, :ref, :authUser) = scope;
|
|
final selected = await showDialog<User>(context: context, builder: (_) => const PartnerSelectionDialog());
|
|
if (selected == null) {
|
|
return;
|
|
}
|
|
|
|
await ref.read(partnerServiceProvider).create(sharedById: authUser.id, sharedWithId: selected.id);
|
|
}
|
|
}
|
|
|
|
class PartnerRemoveAction extends BaseAction {
|
|
const PartnerRemoveAction({required this.sharedWithId, required this.partnerName});
|
|
|
|
final String sharedWithId;
|
|
final String partnerName;
|
|
|
|
@override
|
|
IconData get icon => Icons.person_remove_rounded;
|
|
|
|
@override
|
|
String label(ActionScope scope) => scope.context.t.remove;
|
|
|
|
@override
|
|
Future<void> onAction(ActionScope scope) async {
|
|
final ActionScope(:context, :ref, :authUser) = scope;
|
|
|
|
final confirmed = await showDialog<bool>(
|
|
context: context,
|
|
builder: (_) => ConfirmDialog(
|
|
title: context.t.stop_photo_sharing,
|
|
content: context.t.partner_page_stop_sharing_content(partner: partnerName),
|
|
),
|
|
);
|
|
if (confirmed != true) {
|
|
return;
|
|
}
|
|
|
|
await ref.read(partnerServiceProvider).delete(sharedById: authUser.id, sharedWithId: sharedWithId);
|
|
}
|
|
}
|
|
|
|
@visibleForTesting
|
|
final candidatesStateProvider = StreamProvider.autoDispose<Iterable<User>>((ref) {
|
|
final currentUser = ref.watch(currentUserProvider);
|
|
// TODO: Refactor with a route guard to avoid this check in every provider
|
|
if (currentUser == null) {
|
|
return const Stream.empty();
|
|
}
|
|
return ref.watch(partnerServiceProvider).getCandidates(currentUser.id);
|
|
});
|
|
|
|
@visibleForTesting
|
|
class PartnerSelectionDialog extends ConsumerWidget {
|
|
const PartnerSelectionDialog({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final candidatesAsync = ref.watch(candidatesStateProvider);
|
|
|
|
return SimpleDialog(
|
|
title: Text(context.t.partner_page_select_partner),
|
|
children: candidatesAsync.when(
|
|
data: (candidates) {
|
|
final users = candidates.toList();
|
|
if (users.isEmpty) {
|
|
return [
|
|
Padding(
|
|
padding: const .symmetric(horizontal: 24, vertical: 8),
|
|
child: Text(context.t.partner_page_no_more_users),
|
|
),
|
|
];
|
|
}
|
|
return [
|
|
for (final candidate in users)
|
|
SimpleDialogOption(
|
|
onPressed: () => Navigator.of(context).pop(candidate),
|
|
child: Row(
|
|
children: [
|
|
Padding(
|
|
padding: const .only(right: 8),
|
|
child: PartnerUserAvatar(userId: candidate.id, name: candidate.name),
|
|
),
|
|
Text(candidate.name),
|
|
],
|
|
),
|
|
),
|
|
];
|
|
},
|
|
loading: () => const [
|
|
Padding(
|
|
padding: .all(24),
|
|
child: Center(child: CircularProgressIndicator()),
|
|
),
|
|
],
|
|
error: (error, _) => [
|
|
Padding(
|
|
padding: const .symmetric(horizontal: 24, vertical: 8),
|
|
child: Text(context.t.error_loading_partners(error: error)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|