1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-10 23:22:22 +02:00

feat: memories sync (#19644)

* feat: memories sync

* Update mobile/lib/infrastructure/repositories/sync_stream.repository.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update mobile/lib/infrastructure/repositories/sync_stream.repository.dart

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* show sync information

* tests and pr feedback

* pr feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Alex
2025-07-02 14:18:37 -05:00
committed by GitHub
parent 7855974a29
commit 445f9174ea
16 changed files with 3491 additions and 33 deletions

View File

@@ -1,12 +1,17 @@
import 'dart:convert';
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/memory.model.dart';
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:logging/logging.dart';
@@ -64,8 +69,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: SyncPartnerDeleteV1', e, s);
} catch (error, stackTrace) {
_logger.severe('Error: SyncPartnerDeleteV1', error, stackTrace);
rethrow;
}
}
@@ -87,8 +92,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: SyncPartnerV1', e, s);
} catch (error, stackTrace) {
_logger.severe('Error: SyncPartnerV1', error, stackTrace);
rethrow;
}
}
@@ -98,10 +103,11 @@ class SyncStreamRepository extends DriftDatabaseRepository {
String debugLabel = 'user',
}) async {
try {
await _db.remoteAssetEntity
.deleteWhere((row) => row.id.isIn(data.map((e) => e.assetId)));
} catch (e, s) {
_logger.severe('Error: deleteAssetsV1 - $debugLabel', e, s);
await _db.remoteAssetEntity.deleteWhere(
(row) => row.id.isIn(data.map((error) => error.assetId)),
);
} catch (error, stackTrace) {
_logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stackTrace);
rethrow;
}
}
@@ -136,8 +142,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: updateAssetsV1 - $debugLabel', e, s);
} catch (error, stackTrace) {
_logger.severe('Error: updateAssetsV1 - $debugLabel', error, stackTrace);
rethrow;
}
}
@@ -180,18 +186,23 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: updateAssetsExifV1 - $debugLabel', e, s);
} catch (error, stackTrace) {
_logger.severe(
'Error: updateAssetsExifV1 - $debugLabel',
error,
stackTrace,
);
rethrow;
}
}
Future<void> deleteAlbumsV1(Iterable<SyncAlbumDeleteV1> data) async {
try {
await _db.remoteAlbumEntity
.deleteWhere((row) => row.id.isIn(data.map((e) => e.albumId)));
} catch (e, s) {
_logger.severe('Error: deleteAlbumsV1', e, s);
await _db.remoteAlbumEntity.deleteWhere(
(row) => row.id.isIn(data.map((e) => e.albumId)),
);
} catch (error, stackTrace) {
_logger.severe('Error: deleteAlbumsV1', error, stackTrace);
rethrow;
}
}
@@ -218,8 +229,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: updateAlbumsV1', e, s);
} catch (error, stackTrace) {
_logger.severe('Error: updateAlbumsV1', error, stackTrace);
rethrow;
}
}
@@ -237,8 +248,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: deleteAlbumUsersV1', e, s);
} catch (error, stackTrace) {
_logger.severe('Error: deleteAlbumUsersV1', error, stackTrace);
rethrow;
}
}
@@ -264,8 +275,12 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: updateAlbumUsersV1 - $debugLabel', e, s);
} catch (error, stackTrace) {
_logger.severe(
'Error: updateAlbumUsersV1 - $debugLabel',
error,
stackTrace,
);
rethrow;
}
}
@@ -285,8 +300,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: deleteAlbumToAssetsV1', e, s);
} catch (error, stackTrace) {
_logger.severe('Error: deleteAlbumToAssetsV1', error, stackTrace);
rethrow;
}
}
@@ -310,8 +325,96 @@ class SyncStreamRepository extends DriftDatabaseRepository {
);
}
});
} catch (e, s) {
_logger.severe('Error: updateAlbumToAssetsV1 - $debugLabel', e, s);
} catch (error, stackTrace) {
_logger.severe(
'Error: updateAlbumToAssetsV1 - $debugLabel',
error,
stackTrace,
);
rethrow;
}
}
Future<void> updateMemoriesV1(Iterable<SyncMemoryV1> data) async {
try {
await _db.batch((batch) {
for (final memory in data) {
final companion = MemoryEntityCompanion(
createdAt: Value(memory.createdAt),
deletedAt: Value(memory.deletedAt),
ownerId: Value(memory.ownerId),
type: Value(memory.type.toMemoryType()),
data: Value(jsonEncode(memory.data)),
isSaved: Value(memory.isSaved),
memoryAt: Value(memory.memoryAt),
seenAt: Value.absentIfNull(memory.seenAt),
showAt: Value.absentIfNull(memory.showAt),
hideAt: Value.absentIfNull(memory.hideAt),
);
batch.insert(
_db.memoryEntity,
companion.copyWith(id: Value(memory.id)),
onConflict: DoUpdate((_) => companion),
);
}
});
} catch (error, stackTrace) {
_logger.severe('Error: updateMemoriesV1', error, stackTrace);
rethrow;
}
}
Future<void> deleteMemoriesV1(Iterable<SyncMemoryDeleteV1> data) async {
try {
await _db.memoryEntity.deleteWhere(
(row) => row.id.isIn(data.map((e) => e.memoryId)),
);
} catch (error, stackTrace) {
_logger.severe('Error: deleteMemoriesV1', error, stackTrace);
rethrow;
}
}
Future<void> updateMemoryAssetsV1(Iterable<SyncMemoryAssetV1> data) async {
try {
await _db.batch((batch) {
for (final asset in data) {
final companion = MemoryAssetEntityCompanion(
memoryId: Value(asset.memoryId),
assetId: Value(asset.assetId),
);
batch.insert(
_db.memoryAssetEntity,
companion,
onConflict: DoNothing(),
);
}
});
} catch (error, stackTrace) {
_logger.severe('Error: updateMemoryAssetsV1', error, stackTrace);
rethrow;
}
}
Future<void> deleteMemoryAssetsV1(
Iterable<SyncMemoryAssetDeleteV1> data,
) async {
try {
await _db.batch((batch) {
for (final asset in data) {
batch.delete(
_db.memoryAssetEntity,
MemoryAssetEntityCompanion(
memoryId: Value(asset.memoryId),
assetId: Value(asset.assetId),
),
);
}
});
} catch (error, stackTrace) {
_logger.severe('Error: deleteMemoryAssetsV1', error, stackTrace);
rethrow;
}
}
@@ -335,6 +438,13 @@ extension on AssetOrder {
};
}
extension on MemoryType {
MemoryTypeEnum toMemoryType() => switch (this) {
MemoryType.onThisDay => MemoryTypeEnum.onThisDay,
_ => throw Exception('Unknown MemoryType value: $this'),
};
}
extension on api.AlbumUserRole {
AlbumUserRole toAlbumUserRole() => switch (this) {
api.AlbumUserRole.editor => AlbumUserRole.editor,
@@ -357,7 +467,7 @@ extension on String {
Duration? toDuration() {
try {
final parts = split(':')
.map((e) => double.parse(e).toInt())
.map((error) => double.parse(error).toInt())
.toList(growable: false);
return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]);