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
7 changes: 1 addition & 6 deletions e2e/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,8 @@ import js from '@eslint/js';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import eslintPluginUnicorn from 'eslint-plugin-unicorn';
import globals from 'globals';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import typescriptEslint from 'typescript-eslint';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

export default typescriptEslint.config([
eslintPluginUnicorn.configs.recommended,
eslintPluginPrettierRecommended,
Expand All @@ -29,7 +24,7 @@ export default typescriptEslint.config([

parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
tsconfigRootDir: import.meta.dirname,
},
},

Expand Down
29 changes: 2 additions & 27 deletions mobile/lib/domain/models/person.model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';

part 'person.model.freezed.dart';

// TODO: Remove PersonDto once Isar is removed
@freezed
abstract class PersonDto with _$PersonDto {
const factory PersonDto({
required String id,
DateTime? birthDate,
required bool isHidden,
required String name,
required String thumbnailPath,
DateTime? updatedAt,
}) = _PersonDto;
}

// Model for a person stored in the server
@freezed
abstract class DriftPerson with _$DriftPerson {
const factory DriftPerson({
required String id,
required DateTime createdAt,
required DateTime updatedAt,
required String ownerId,
required String name,
String? faceAssetId,
required bool isFavorite,
required bool isHidden,
required String? color,
DateTime? birthDate,
}) = _DriftPerson;
abstract class Person with _$Person {
const factory Person({required String id, required String name, DateTime? updatedAt, DateTime? birthDate}) = _Person;
}
10 changes: 5 additions & 5 deletions mobile/lib/domain/services/people.service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ class DriftPeopleService {

const DriftPeopleService(this._repository, this._personApiRepository);

Future<DriftPerson?> get(String personId) {
Future<Person?> get(String personId) {
return _repository.get(personId);
}

Future<List<DriftPerson>> getAssetPeople(String assetId) {
Future<List<Person>> getAssetPeople(String assetId) {
return _repository.getAssetPeople(assetId);
}

Future<List<DriftPerson>> getAllPeople({int minFaces = 3}) {
return _repository.getAllPeople(minFaces: minFaces);
Stream<List<Person>> watch({int minFaces = 3}) {
return _repository.watch(minFaces: minFaces);
}

Future<int> updateName(String personId, String name) async {
await _personApiRepository.update(personId, name: name);
return _repository.updateName(personId, name);
}

Future<int> updateBrithday(String personId, DateTime birthday) async {
Future<int> updateBirthday(String personId, DateTime birthday) async {
await _personApiRepository.update(personId, birthday: birthday);
return _repository.updateBirthday(personId, birthday);
}
Expand Down
23 changes: 5 additions & 18 deletions mobile/lib/infrastructure/repositories/people.repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ class DriftPeopleRepository extends DriftDatabaseRepository {
final Drift _db;
const DriftPeopleRepository(this._db) : super(_db);

Future<DriftPerson?> get(String personId) async {
Future<Person?> get(String personId) async {
final query = _db.select(_db.personEntity)..where((row) => row.id.equals(personId));

final result = await query.getSingleOrNull();
return result?.toDto();
}

Future<List<DriftPerson>> getAssetPeople(String assetId) async {
Future<List<Person>> getAssetPeople(String assetId) async {
// An asset can have multiple face records for the same person (e.g., metadata
// imports alongside ML detections). Use a subquery instead of a join so each
// person is returned once, regardless of how many of their faces are on the asset
Expand All @@ -33,7 +33,7 @@ class DriftPeopleRepository extends DriftDatabaseRepository {
return query.map((row) => row.toDto()).get();
}

Future<List<DriftPerson>> getAllPeople({int minFaces = 3}) async {
Stream<List<Person>> watch({int minFaces = 3}) {
final people = _db.personEntity;
final faces = _db.assetFaceEntity;
final assets = _db.remoteAssetEntity;
Expand All @@ -59,7 +59,7 @@ class DriftPeopleRepository extends DriftDatabaseRepository {
return query.map((row) {
final person = row.readTable(people);
return person.toDto();
}).get();
}).watch();
}

Future<int> updateName(String personId, String name) {
Expand All @@ -76,18 +76,5 @@ class DriftPeopleRepository extends DriftDatabaseRepository {
}

extension on PersonEntityData {
DriftPerson toDto() {
return DriftPerson(
id: id,
createdAt: createdAt,
updatedAt: updatedAt,
ownerId: ownerId,
name: name,
faceAssetId: faceAssetId,
isFavorite: isFavorite,
isHidden: isHidden,
color: color,
birthDate: birthDate,
);
}
Person toDto() => Person(id: id, updatedAt: updatedAt, name: name, birthDate: birthDate);
}
4 changes: 2 additions & 2 deletions mobile/lib/models/search/search_filter.model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class SearchFilter {
String? language;
String? assetId;
List<String>? tagIds;
Set<PersonDto> people;
Set<Person> people;
SearchLocationFilter location;
SearchCameraFilter camera;
SearchDateFilter date;
Expand Down Expand Up @@ -250,7 +250,7 @@ class SearchFilter {
String? language,
String? ocr,
String? assetId,
Set<PersonDto>? people,
Set<Person>? people,
List<String>? tagIds,
SearchLocationFilter? location,
SearchCameraFilter? camera,
Expand Down
12 changes: 4 additions & 8 deletions mobile/lib/pages/backup/drift_backup.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,11 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final backupAlbums = ref.watch(backupAlbumProvider);

Widget buildSelectedAlbumName() {
String text = context.t.backup_controller_page_backup_selected;
final albums = ref
.read(backupAlbumProvider)
.where((album) => album.backupSelection == BackupSelection.selected)
.toList();
final albums = backupAlbums.where((album) => album.backupSelection == BackupSelection.selected).toList();

if (albums.isNotEmpty) {
for (var album in albums) {
Expand Down Expand Up @@ -352,10 +351,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget {

Widget buildExcludedAlbumName() {
String text = context.t.backup_controller_page_excluded;
final albums = ref
.read(backupAlbumProvider)
.where((album) => album.backupSelection == BackupSelection.excluded)
.toList();
final albums = backupAlbums.where((album) => album.backupSelection == BackupSelection.excluded).toList();

if (albums.isNotEmpty) {
for (var album in albums) {
Expand Down
2 changes: 0 additions & 2 deletions mobile/lib/pages/common/tab_shell.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import 'package:immich_mobile/presentation/pages/search/paginated_search.provide
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart';
import 'package:immich_mobile/providers/search/search_input_focus.provider.dart';
import 'package:immich_mobile/providers/tab.provider.dart';
Expand Down Expand Up @@ -132,7 +131,6 @@ void _onNavigationSelected(TabsRouter router, int index, WidgetRef ref) {
// Library page
if (index == kLibraryTabIndex) {
ref.invalidate(localAlbumProvider);
ref.invalidate(driftGetAllPeopleProvider);
}

ref.read(hapticFeedbackProvider.notifier).selectionClick();
Expand Down
3 changes: 2 additions & 1 deletion mobile/lib/presentation/actions/delete.action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ final _stateProvider = Provider.family.autoDispose<_State?, ActionSource>((ref,

final trashEnabled = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash));
// Assets already in the trash or in the locked folder are deleted outright, irrespective of the server setting.
final trash = trashEnabled && !ownedRemote.every((asset) => asset.isTrashed || asset.isLocked);
final trash =
ownedRemote.isEmpty || (trashEnabled && !ownedRemote.every((asset) => asset.isTrashed || asset.isLocked));

return (localIds: localIds, remoteIds: ownedRemote.map((asset) => asset.id).toList(growable: false), trash: trash);
}, dependencies: [assetsActionProvider]);
Expand Down
10 changes: 7 additions & 3 deletions mobile/lib/presentation/pages/drift_album_options.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
final userId = ref.watch(authProvider).userId;
final activityEnabled = useState(album.isActivityEnabled);
final isOwner = album.ownerId == userId;
final owner = isOwner ? ref.watch(currentUserProvider) : null;
final allUsers = isOwner ? null : ref.watch(driftUsersProvider);

void showErrorMessage() {
ContextHelper(context).pop();
Expand Down Expand Up @@ -141,16 +143,18 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {

Widget buildOwnerInfo() {
if (isOwner) {
final owner = ref.read(currentUserProvider);
return ListTile(
leading: owner != null ? UserCircleAvatar(user: owner) : const SizedBox(),
title: Text(album.ownerName, style: const TextStyle(fontWeight: FontWeight.w500)),
subtitle: Text(owner?.email ?? "", style: TextStyle(color: context.colorScheme.onSurfaceSecondary)),
trailing: Text(context.t.owner, style: context.textTheme.labelLarge),
);
} else {
final usersProvider = ref.read(driftUsersProvider);
return usersProvider.maybeWhen(
if (allUsers == null) {
return const SizedBox();
}

return allUsers.maybeWhen(
data: (users) {
final user = users.firstWhereOrNull((u) => u.id == album.ownerId);

Expand Down
2 changes: 1 addition & 1 deletion mobile/lib/presentation/pages/drift_library.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class _PeopleCollectionCard extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
final people = ref.watch(driftGetAllPeopleProvider);
final people = ref.watch(getAllPeopleProvider);

return LayoutBuilder(
builder: (context, constraints) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class _DriftPeopleCollectionPageState extends ConsumerState<DriftPeopleCollectio

@override
Widget build(BuildContext context) {
final people = ref.watch(driftGetAllPeopleProvider);
final people = ref.watch(getAllPeopleProvider);

return LayoutBuilder(
builder: (context, constraints) {
Expand Down
4 changes: 2 additions & 2 deletions mobile/lib/presentation/pages/drift_person.page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'package:immich_mobile/widgets/common/person_sliver_app_bar.dart';

@RoutePage()
class DriftPersonPage extends ConsumerStatefulWidget {
final DriftPerson person;
final Person person;

const DriftPersonPage({super.key, required this.person});

Expand All @@ -23,7 +23,7 @@ class DriftPersonPage extends ConsumerStatefulWidget {
}

class _DriftPersonPageState extends ConsumerState<DriftPersonPage> {
late DriftPerson _person;
late Person _person;

@override
void initState() {
Expand Down
Loading
Loading