cleanup
parent
4e27647233
commit
f746993a6d
|
|
@ -332,6 +332,16 @@ class Partner extends User {
|
|||
this.inTimeline = false,
|
||||
});
|
||||
|
||||
Partner.fromUser(User user, {this.inTimeline = false})
|
||||
: super(
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
email: user.email,
|
||||
profileChangedAt: user.profileChangedAt,
|
||||
hasProfileImage: user.hasProfileImage,
|
||||
avatarColor: user.avatarColor,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Partner(user: ${super.toString()}, inTimeline: $inTimeline)';
|
||||
|
|
|
|||
|
|
@ -25,18 +25,18 @@ class PartnerService {
|
|||
Stream<Iterable<Partner>> search(String userId, PartnerDirection direction) =>
|
||||
_partnerRepository.search(userId, direction);
|
||||
|
||||
Future<void> update(String partnerId, String userId, {required bool inTimeline}) async {
|
||||
await _partnerApiRepository.update(partnerId, inTimeline: inTimeline);
|
||||
await _partnerRepository.update(partnerId, userId, inTimeline: inTimeline);
|
||||
Future<void> update({required String sharedById, required String sharedWithId, required bool inTimeline}) async {
|
||||
await _partnerApiRepository.update(sharedById, inTimeline: inTimeline);
|
||||
await _partnerRepository.update(sharedById: sharedById, sharedWithId: sharedWithId, inTimeline: inTimeline);
|
||||
}
|
||||
|
||||
Future<void> create(String partnerId, String userId) async {
|
||||
await _partnerApiRepository.create(partnerId);
|
||||
await _partnerRepository.create(partnerId, userId);
|
||||
Future<void> create({required String sharedById, required String sharedWithId, bool inTimeline = false}) async {
|
||||
await _partnerApiRepository.create(sharedWithId);
|
||||
await _partnerRepository.create(sharedById: sharedById, sharedWithId: sharedWithId, inTimeline: inTimeline);
|
||||
}
|
||||
|
||||
Future<void> delete(String partnerId, String userId) async {
|
||||
await _partnerApiRepository.delete(partnerId);
|
||||
await _partnerRepository.delete(partnerId, userId);
|
||||
Future<void> delete({required String sharedById, required String sharedWithId}) async {
|
||||
await _partnerApiRepository.delete(sharedWithId);
|
||||
await _partnerRepository.delete(sharedById: sharedById, sharedWithId: sharedWithId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||
|
||||
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_partner_shared_with_id ON partner_entity (shared_with_id)')
|
||||
|
|
@ -17,14 +14,4 @@ class PartnerEntity extends Table with DriftDefaultsMixin {
|
|||
|
||||
@override
|
||||
Set<Column> get primaryKey => {sharedById, sharedWithId};
|
||||
|
||||
static Partner rowToPartner(UserEntityData user, PartnerEntityData partner) => Partner(
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
profileChangedAt: user.profileChangedAt,
|
||||
hasProfileImage: user.hasProfileImage,
|
||||
avatarColor: user.avatarColor,
|
||||
inTimeline: partner.inTimeline,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:drift/drift.dart' hide Index;
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||
|
||||
class UserEntity extends Table with DriftDefaultsMixin {
|
||||
|
|
@ -17,13 +16,4 @@ class UserEntity extends Table with DriftDefaultsMixin {
|
|||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
|
||||
static User rowToUser(UserEntityData row) => User(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
email: row.email,
|
||||
profileChangedAt: row.profileChangedAt,
|
||||
hasProfileImage: row.hasProfileImage,
|
||||
avatarColor: row.avatarColor,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
|
||||
|
||||
User mapToUser(UserEntityData data) => User(
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
hasProfileImage: data.hasProfileImage,
|
||||
profileChangedAt: data.profileChangedAt,
|
||||
avatarColor: data.avatarColor,
|
||||
);
|
||||
|
||||
Partner mapToPartner(UserEntityData user, PartnerEntityData partner) =>
|
||||
Partner.fromUser(mapToUser(user), inTimeline: partner.inTimeline);
|
||||
|
|
@ -1,24 +1,20 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/mapper.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
|
||||
class PartnerRepository {
|
||||
final Drift _db;
|
||||
const PartnerRepository(this._db);
|
||||
|
||||
Partner _resultToPartner(TypedResult result) {
|
||||
final user = result.readTable(_db.userEntity);
|
||||
final partner = result.readTable(_db.partnerEntity);
|
||||
return PartnerEntity.rowToPartner(user, partner);
|
||||
}
|
||||
|
||||
Future<Partner> get(String partnerId, String userId) =>
|
||||
Future<Partner> get({required String sharedById, required String sharedWithId}) =>
|
||||
(_db.select(_db.partnerEntity).join([
|
||||
innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)),
|
||||
])..where(_db.partnerEntity.sharedById.equals(partnerId) & _db.partnerEntity.sharedWithId.equals(userId)))
|
||||
])..where(
|
||||
_db.partnerEntity.sharedById.equals(sharedById) & _db.partnerEntity.sharedWithId.equals(sharedWithId),
|
||||
))
|
||||
.map(_resultToPartner)
|
||||
.getSingle();
|
||||
|
||||
|
|
@ -41,15 +37,26 @@ class PartnerRepository {
|
|||
.map(_resultToPartner)
|
||||
.watch();
|
||||
|
||||
Future<void> create(String partnerId, String userId) => _db.partnerEntity.insertOnConflictUpdate(
|
||||
PartnerEntityCompanion(sharedById: Value(userId), sharedWithId: Value(partnerId), inTimeline: const Value(false)),
|
||||
);
|
||||
|
||||
Future<void> update(String partnerId, String userId, {required bool inTimeline}) =>
|
||||
(_db.partnerEntity.update()..where((t) => t.sharedById.equals(partnerId) & t.sharedWithId.equals(userId))).write(
|
||||
PartnerEntityCompanion(inTimeline: Value(inTimeline)),
|
||||
Future<void> create({required String sharedById, required String sharedWithId, bool inTimeline = false}) =>
|
||||
_db.partnerEntity.insertOnConflictUpdate(
|
||||
PartnerEntityCompanion(
|
||||
sharedById: Value(sharedById),
|
||||
sharedWithId: Value(sharedWithId),
|
||||
inTimeline: Value(inTimeline),
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> delete(String partnerId, String userId) =>
|
||||
(_db.partnerEntity.delete()..where((t) => t.sharedById.equals(userId) & t.sharedWithId.equals(partnerId))).go();
|
||||
Future<void> update({required String sharedById, required String sharedWithId, required bool inTimeline}) =>
|
||||
(_db.partnerEntity.update()..where((t) => t.sharedById.equals(sharedById) & t.sharedWithId.equals(sharedWithId)))
|
||||
.write(PartnerEntityCompanion(inTimeline: Value(inTimeline)));
|
||||
|
||||
Future<void> delete({required String sharedById, required String sharedWithId}) =>
|
||||
(_db.partnerEntity.delete()..where((t) => t.sharedById.equals(sharedById) & t.sharedWithId.equals(sharedWithId)))
|
||||
.go();
|
||||
|
||||
Partner _resultToPartner(TypedResult result) {
|
||||
final user = result.readTable(_db.userEntity);
|
||||
final partner = result.readTable(_db.partnerEntity);
|
||||
return mapToPartner(user, partner);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:drift/drift.dart';
|
|||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/mapper.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart';
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ class UserRepository {
|
|||
final Drift _db;
|
||||
const UserRepository(this._db);
|
||||
|
||||
Stream<Iterable<User>> getAll() => _db.select(_db.userEntity).map(UserEntity.rowToUser).watch();
|
||||
Stream<Iterable<User>> getAll() => _db.select(_db.userEntity).map(mapToUser).watch();
|
||||
}
|
||||
|
||||
class DriftAuthUserRepository extends DriftDatabaseRepository {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:immich_mobile/providers/user.provider.dart';
|
|||
import 'package:immich_mobile/widgets/common/confirm_dialog.dart';
|
||||
|
||||
@visibleForTesting
|
||||
final candidatesProvider = StreamProvider.autoDispose<Iterable<User>>((ref) {
|
||||
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) {
|
||||
|
|
@ -20,7 +20,7 @@ final candidatesProvider = StreamProvider.autoDispose<Iterable<User>>((ref) {
|
|||
});
|
||||
|
||||
@visibleForTesting
|
||||
final partnersProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref) {
|
||||
final partnersStateProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref) {
|
||||
final currentUser = ref.watch(currentUserProvider);
|
||||
// TODO: Refactor with a route guard to avoid this check in every provider
|
||||
if (currentUser == null) {
|
||||
|
|
@ -30,35 +30,35 @@ final partnersProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref) {
|
|||
return ref.watch(partnerServiceProvider).search(currentUser.id, .sharedBy);
|
||||
});
|
||||
|
||||
@RoutePage()
|
||||
class DriftPartnerPage extends ConsumerWidget {
|
||||
const DriftPartnerPage({super.key});
|
||||
|
||||
Future<void> _addPartner(BuildContext context, WidgetRef ref) async {
|
||||
final selected = await showDialog<User>(context: context, builder: (_) => const PartnerSelectionDialog());
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (selected != null && currentUser != null) {
|
||||
await ref.read(partnerServiceProvider).create(selected.id, currentUser.id);
|
||||
}
|
||||
Future<void> _addPartner(BuildContext context, WidgetRef ref) async {
|
||||
final selected = await showDialog<User>(context: context, builder: (_) => const PartnerSelectionDialog());
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (selected != null && currentUser != null) {
|
||||
await ref.read(partnerServiceProvider).create(sharedById: currentUser.id, sharedWithId: selected.id);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _removePartner(BuildContext context, WidgetRef ref, Partner partner) => showDialog(
|
||||
context: context,
|
||||
builder: (_) => ConfirmDialog(
|
||||
title: "stop_photo_sharing",
|
||||
content: context.t.partner_page_stop_sharing_content(partner: partner.name),
|
||||
onOk: () {
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (currentUser != null) {
|
||||
ref.read(partnerServiceProvider).delete(partner.id, currentUser.id);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
Future<void> _removePartner(BuildContext context, WidgetRef ref, Partner partner) => showDialog(
|
||||
context: context,
|
||||
builder: (_) => ConfirmDialog(
|
||||
title: "stop_photo_sharing",
|
||||
content: context.t.partner_page_stop_sharing_content(partner: partner.name),
|
||||
onOk: () {
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (currentUser != null) {
|
||||
ref.read(partnerServiceProvider).delete(sharedById: currentUser.id, sharedWithId: partner.id);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@RoutePage()
|
||||
class PartnerPage extends ConsumerWidget {
|
||||
const PartnerPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final sharedByAsync = ref.watch(partnersProvider);
|
||||
final sharedByAsync = ref.watch(partnersStateProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -76,8 +76,8 @@ class DriftPartnerPage extends ConsumerWidget {
|
|||
body: sharedByAsync.when(
|
||||
data: (partners) => PartnerSharedByList(
|
||||
partners: partners.toList(growable: false),
|
||||
onAddPartner: () => _addPartner(context, ref),
|
||||
onRemovePartner: (partner) => _removePartner(context, ref, partner),
|
||||
onAdd: () => _addPartner(context, ref),
|
||||
onRemove: (partner) => _removePartner(context, ref, partner),
|
||||
),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => Center(child: Text(context.t.error_loading_partners(error: error))),
|
||||
|
|
@ -86,42 +86,48 @@ class DriftPartnerPage extends ConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class _EmptyPartners extends StatelessWidget {
|
||||
const _EmptyPartners({required this.onAdd});
|
||||
|
||||
final VoidCallback onAdd;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const .symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: .start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const .symmetric(vertical: 8),
|
||||
child: Text(context.t.partner_page_empty_message, style: const TextStyle(fontSize: 14)),
|
||||
),
|
||||
Align(
|
||||
alignment: .center,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: onAdd,
|
||||
icon: const Icon(Icons.person_add),
|
||||
label: Text(context.t.add_partner),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
class PartnerSharedByList extends StatelessWidget {
|
||||
const PartnerSharedByList({
|
||||
super.key,
|
||||
required this.partners,
|
||||
required this.onAddPartner,
|
||||
required this.onRemovePartner,
|
||||
});
|
||||
const PartnerSharedByList({super.key, required this.partners, required this.onAdd, required this.onRemove});
|
||||
|
||||
final List<Partner> partners;
|
||||
final VoidCallback onAddPartner;
|
||||
final ValueChanged<Partner> onRemovePartner;
|
||||
final VoidCallback onAdd;
|
||||
final ValueChanged<Partner> onRemove;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (partners.isEmpty) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(context.t.partner_page_empty_message, style: const TextStyle(fontSize: 14)),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: onAddPartner,
|
||||
icon: const Icon(Icons.person_add),
|
||||
label: Text(context.t.add_partner),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return _EmptyPartners(onAdd: onAdd);
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
|
|
@ -132,7 +138,7 @@ class PartnerSharedByList extends StatelessWidget {
|
|||
leading: PartnerUserAvatar(userId: partner.id, name: partner.name),
|
||||
title: Text(partner.name),
|
||||
subtitle: Text(partner.email),
|
||||
trailing: IconButton(icon: const Icon(Icons.person_remove), onPressed: () => onRemovePartner(partner)),
|
||||
trailing: IconButton(icon: const Icon(Icons.person_remove), onPressed: () => onRemove(partner)),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -145,7 +151,7 @@ class PartnerSelectionDialog extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final candidatesAsync = ref.watch(candidatesProvider);
|
||||
final candidatesAsync = ref.watch(candidatesStateProvider);
|
||||
|
||||
return SimpleDialog(
|
||||
title: const Text("partner_page_select_partner").tr(),
|
||||
|
|
@ -155,7 +161,7 @@ class PartnerSelectionDialog extends ConsumerWidget {
|
|||
if (users.isEmpty) {
|
||||
return [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
||||
padding: const .symmetric(horizontal: 24, vertical: 8),
|
||||
child: const Text("partner_page_no_more_users").tr(),
|
||||
),
|
||||
];
|
||||
|
|
@ -167,7 +173,7 @@ class PartnerSelectionDialog extends ConsumerWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
padding: const .only(right: 8),
|
||||
child: PartnerUserAvatar(userId: candidate.id, name: candidate.name),
|
||||
),
|
||||
Text(candidate.name),
|
||||
|
|
@ -178,14 +184,14 @@ class PartnerSelectionDialog extends ConsumerWidget {
|
|||
},
|
||||
loading: () => const [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
padding: .all(24),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
error: (error, _) => [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
||||
child: Text("error_loading_partners".tr(args: [error.toString()])),
|
||||
padding: const .symmetric(horizontal: 24, vertical: 8),
|
||||
child: Text(context.t.error_loading_partners(error: error)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -329,11 +329,11 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget {
|
|||
}
|
||||
|
||||
@visibleForTesting
|
||||
final driftSharedWithPartnerProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref) {
|
||||
final sharedWithPartnerProvider = StreamProvider.autoDispose<Iterable<Partner>>((ref) {
|
||||
final currentUser = ref.watch(currentUserProvider);
|
||||
if (currentUser == null) {
|
||||
// TODO: Refactor with a route guard to avoid this check in every provider
|
||||
return const Stream.empty();
|
||||
return const .empty();
|
||||
}
|
||||
|
||||
return ref.watch(partnerServiceProvider).search(currentUser.id, .sharedWith);
|
||||
|
|
@ -344,7 +344,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final partnerSharedWithAsync = ref.watch(driftSharedWithPartnerProvider);
|
||||
final partnerSharedWithAsync = ref.watch(sharedWithPartnerProvider);
|
||||
final partners = partnerSharedWithAsync.valueOrNull ?? [];
|
||||
|
||||
return SliverPadding(
|
||||
|
|
@ -399,7 +399,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
|
|||
'partners'.t(context: context),
|
||||
style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500),
|
||||
),
|
||||
onTap: () => context.pushRoute(const DriftPartnerRoute()),
|
||||
onTap: () => context.pushRoute(const PartnerRoute()),
|
||||
),
|
||||
_PartnerList(partners: partners.toList()),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -63,7 +63,9 @@ class _InfoBoxState extends ConsumerState<_InfoBox> {
|
|||
}
|
||||
|
||||
try {
|
||||
await ref.read(partnerServiceProvider).update(widget.partner.id, user.id, inTimeline: !_inTimeline);
|
||||
await ref
|
||||
.read(partnerServiceProvider)
|
||||
.update(sharedById: widget.partner.id, sharedWithId: user.id, inTimeline: !_inTimeline);
|
||||
|
||||
setState(() {
|
||||
_inTimeline = !_inTimeline;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import 'package:immich_mobile/pages/common/splash_screen.page.dart';
|
|||
import 'package:immich_mobile/pages/common/tab_shell.page.dart';
|
||||
import 'package:immich_mobile/pages/library/folder/folder.page.dart';
|
||||
import 'package:immich_mobile/pages/library/locked/pin_auth.page.dart';
|
||||
import 'package:immich_mobile/pages/library/partner/drift_partner.page.dart';
|
||||
import 'package:immich_mobile/pages/library/partner/partner.page.dart';
|
||||
import 'package:immich_mobile/pages/library/shared_link/shared_link.page.dart';
|
||||
import 'package:immich_mobile/pages/library/shared_link/shared_link_edit.page.dart';
|
||||
import 'package:immich_mobile/pages/login/change_password.page.dart';
|
||||
|
|
@ -176,7 +176,7 @@ class AppRouter extends RootStackRouter {
|
|||
AutoRoute(page: DriftPlaceRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPlaceDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftUserSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftPartnerRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: PartnerRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: DriftUploadDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
AutoRoute(page: SyncStatusRoute.page, guards: [_duplicateGuard]),
|
||||
AutoRoute(page: DriftPeopleCollectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||
|
|
|
|||
|
|
@ -869,22 +869,6 @@ class DriftPartnerDetailRouteArgs {
|
|||
int get hashCode => key.hashCode ^ partner.hashCode;
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [DriftPartnerPage]
|
||||
class DriftPartnerRoute extends PageRouteInfo<void> {
|
||||
const DriftPartnerRoute({List<PageRouteInfo>? children})
|
||||
: super(DriftPartnerRoute.name, initialChildren: children);
|
||||
|
||||
static const String name = 'DriftPartnerRoute';
|
||||
|
||||
static PageInfo page = PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const DriftPartnerPage();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [DriftPeopleCollectionPage]
|
||||
class DriftPeopleCollectionRoute extends PageRouteInfo<void> {
|
||||
|
|
@ -1456,6 +1440,22 @@ class MapLocationPickerRouteArgs {
|
|||
int get hashCode => key.hashCode ^ initialLatLng.hashCode;
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [PartnerPage]
|
||||
class PartnerRoute extends PageRouteInfo<void> {
|
||||
const PartnerRoute({List<PageRouteInfo>? children})
|
||||
: super(PartnerRoute.name, initialChildren: children);
|
||||
|
||||
static const String name = 'PartnerRoute';
|
||||
|
||||
static PageInfo page = PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const PartnerPage();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [PinAuthPage]
|
||||
class PinAuthRoute extends PageRouteInfo<PinAuthRouteArgs> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/constants/enums.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/partner.repository.dart';
|
||||
|
||||
import '../repository_context.dart';
|
||||
|
|
@ -25,7 +24,7 @@ void main() {
|
|||
await ctx.newPartner(sharedById: me.id, sharedWithId: recipient.id);
|
||||
await ctx.newPartner(sharedById: sharer.id, sharedWithId: me.id);
|
||||
|
||||
final result = await sut.search(me.id, PartnerDirection.sharedBy).first;
|
||||
final result = await sut.search(me.id, .sharedBy).first;
|
||||
|
||||
expect(result.map((partner) => partner.id), unorderedEquals([recipient.id]));
|
||||
});
|
||||
|
|
@ -37,7 +36,7 @@ void main() {
|
|||
await ctx.newPartner(sharedById: me.id, sharedWithId: recipient.id);
|
||||
await ctx.newPartner(sharedById: sharer.id, sharedWithId: me.id);
|
||||
|
||||
final result = await sut.search(me.id, PartnerDirection.sharedWith).first;
|
||||
final result = await sut.search(me.id, .sharedWith).first;
|
||||
|
||||
expect(result.map((partner) => partner.id), unorderedEquals([sharer.id]));
|
||||
});
|
||||
|
|
@ -46,7 +45,7 @@ void main() {
|
|||
final me = await ctx.newUser();
|
||||
final recipient = await ctx.newUser();
|
||||
|
||||
final ids = sut.search(me.id, PartnerDirection.sharedBy).map((partners) => partners.map((p) => p.id).toList());
|
||||
final ids = sut.search(me.id, .sharedBy).map((partners) => partners.map((p) => p.id).toList());
|
||||
final expectation = expectLater(
|
||||
ids,
|
||||
emitsInOrder([
|
||||
|
|
@ -65,7 +64,7 @@ void main() {
|
|||
final me = await ctx.newUser();
|
||||
final partner = await ctx.newUser();
|
||||
|
||||
await sut.create(partner.id, me.id);
|
||||
await sut.create(sharedById: me.id, sharedWithId: partner.id);
|
||||
|
||||
final result = (await sut.search(me.id, .sharedBy).first).first;
|
||||
expect(result.id, partner.id);
|
||||
|
|
@ -79,9 +78,9 @@ void main() {
|
|||
final sharer = await ctx.newUser();
|
||||
await ctx.newPartner(sharedById: sharer.id, sharedWithId: me.id, inTimeline: false);
|
||||
|
||||
await sut.update(sharer.id, me.id, inTimeline: true);
|
||||
await sut.update(sharedById: sharer.id, sharedWithId: me.id, inTimeline: true);
|
||||
|
||||
final result = await sut.get(sharer.id, me.id);
|
||||
final result = await sut.get(sharedById: sharer.id, sharedWithId: me.id);
|
||||
expect(result.inTimeline, isTrue);
|
||||
});
|
||||
});
|
||||
|
|
@ -92,7 +91,7 @@ void main() {
|
|||
final recipient = await ctx.newUser();
|
||||
await ctx.newPartner(sharedById: me.id, sharedWithId: recipient.id);
|
||||
|
||||
await sut.delete(recipient.id, me.id);
|
||||
await sut.delete(sharedById: me.id, sharedWithId: recipient.id);
|
||||
|
||||
final rows = await ctx.db.select(ctx.db.partnerEntity).get();
|
||||
expect(rows, isEmpty);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ void main() {
|
|||
final me = await ctx.newUser();
|
||||
final partner = await ctx.newUser();
|
||||
|
||||
await sut.create(partner.id, me.id);
|
||||
await sut.create(sharedById: me.id, sharedWithId: partner.id);
|
||||
|
||||
verify(() => ctx.partnerApi.create(partner.id)).called(1);
|
||||
final shared = await sut.search(me.id, .sharedBy).first;
|
||||
|
|
@ -86,7 +86,7 @@ void main() {
|
|||
final recipient = await ctx.newUser();
|
||||
await ctx.newPartner(sharedById: me.id, sharedWithId: recipient.id);
|
||||
|
||||
await sut.delete(recipient.id, me.id);
|
||||
await sut.delete(sharedById: me.id, sharedWithId: recipient.id);
|
||||
|
||||
verify(() => ctx.partnerApi.delete(recipient.id)).called(1);
|
||||
final shared = await sut.search(me.id, .sharedBy).first;
|
||||
|
|
@ -100,10 +100,10 @@ void main() {
|
|||
final sharer = await ctx.newUser();
|
||||
await ctx.newPartner(sharedById: sharer.id, sharedWithId: me.id, inTimeline: false);
|
||||
|
||||
await sut.update(sharer.id, me.id, inTimeline: true);
|
||||
await sut.update(sharedById: sharer.id, sharedWithId: me.id, inTimeline: true);
|
||||
|
||||
verify(() => ctx.partnerApi.update(sharer.id, inTimeline: true)).called(1);
|
||||
final partner = await ctx.partnerRepository.get(sharer.id, me.id);
|
||||
final partner = await ctx.partnerRepository.get(sharedById: sharer.id, sharedWithId: me.id);
|
||||
expect(partner.inTimeline, isTrue);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/pages/library/partner/drift_partner.page.dart';
|
||||
import 'package:immich_mobile/pages/library/partner/partner.page.dart';
|
||||
|
||||
import '../factories/partner_user_factory.dart';
|
||||
import '../factories/user_factory.dart';
|
||||
|
|
@ -16,32 +16,16 @@ void main() {
|
|||
|
||||
group('PartnerSharedByList', () {
|
||||
testWidgets('shows the empty-state add button when there are no partners', (tester) async {
|
||||
await tester.pumpTestWidget(
|
||||
PartnerSharedByList(partners: const [], onAddPartner: () {}, onRemovePartner: (_) {}),
|
||||
);
|
||||
await tester.pumpTestWidget(PartnerSharedByList(partners: const [], onAdd: () {}, onRemove: (_) {}));
|
||||
|
||||
expect(find.byType(ListView), findsNothing);
|
||||
expect(find.widgetWithIcon(ElevatedButton, Icons.person_add), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('invokes onAddPartner when the empty-state button is tapped', (tester) async {
|
||||
var addCalls = 0;
|
||||
await tester.pumpTestWidget(
|
||||
PartnerSharedByList(partners: const [], onAddPartner: () => addCalls++, onRemovePartner: (_) {}),
|
||||
);
|
||||
|
||||
await tester.tap(find.widgetWithIcon(ElevatedButton, Icons.person_add));
|
||||
await tester.pump();
|
||||
|
||||
expect(addCalls, 1);
|
||||
});
|
||||
|
||||
testWidgets('renders a tile per partner with name and email', (tester) async {
|
||||
final partner1 = PartnerFactory.create();
|
||||
final partner2 = PartnerFactory.create();
|
||||
await tester.pumpTestWidget(
|
||||
PartnerSharedByList(partners: [partner1, partner2], onAddPartner: () {}, onRemovePartner: (_) {}),
|
||||
);
|
||||
await tester.pumpTestWidget(PartnerSharedByList(partners: [partner1, partner2], onAdd: () {}, onRemove: (_) {}));
|
||||
|
||||
expect(find.byType(ListTile), findsNWidgets(2));
|
||||
expect(find.text(partner1.name), findsOneWidget);
|
||||
|
|
@ -55,7 +39,7 @@ void main() {
|
|||
final partner2 = PartnerFactory.create();
|
||||
Partner? removed;
|
||||
await tester.pumpTestWidget(
|
||||
PartnerSharedByList(partners: [partner1, partner2], onAddPartner: () {}, onRemovePartner: (p) => removed = p),
|
||||
PartnerSharedByList(partners: [partner1, partner2], onAdd: () {}, onRemove: (p) => removed = p),
|
||||
);
|
||||
|
||||
await tester.tap(find.byIcon(Icons.person_remove).first);
|
||||
|
|
@ -81,7 +65,7 @@ void main() {
|
|||
}
|
||||
|
||||
List<Override> withCandidates(List<User> candidates) => [
|
||||
candidatesProvider.overrideWith((ref) => Stream<Iterable<User>>.value(candidates)),
|
||||
candidatesStateProvider.overrideWith((ref) => Stream<Iterable<User>>.value(candidates)),
|
||||
];
|
||||
|
||||
testWidgets('renders an option per candidate fetched from the provider', (tester) async {
|
||||
|
|
|
|||
Loading…
Reference in New Issue