refactor: exif entity (#16621)

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2025-03-06 23:28:24 +05:30
committed by GitHub
parent 4ebc25c754
commit fe931faf17
33 changed files with 502 additions and 359 deletions
+17 -13
View File
@@ -4,6 +4,7 @@ import 'dart:io';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/entities/backup_album.entity.dart';
import 'package:immich_mobile/entities/user.entity.dart';
@@ -12,16 +13,15 @@ import 'package:immich_mobile/interfaces/asset_api.interface.dart';
import 'package:immich_mobile/interfaces/asset_media.interface.dart';
import 'package:immich_mobile/interfaces/backup_album.interface.dart';
import 'package:immich_mobile/interfaces/etag.interface.dart';
import 'package:immich_mobile/interfaces/exif_info.interface.dart';
import 'package:immich_mobile/interfaces/user.interface.dart';
import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
import 'package:immich_mobile/repositories/asset.repository.dart';
import 'package:immich_mobile/repositories/asset_api.repository.dart';
import 'package:immich_mobile/repositories/asset_media.repository.dart';
import 'package:immich_mobile/repositories/backup.repository.dart';
import 'package:immich_mobile/repositories/etag.repository.dart';
import 'package:immich_mobile/repositories/exif_info.repository.dart';
import 'package:immich_mobile/repositories/user.repository.dart';
import 'package:immich_mobile/services/album.service.dart';
import 'package:immich_mobile/services/api.service.dart';
@@ -36,7 +36,7 @@ final assetServiceProvider = Provider(
(ref) => AssetService(
ref.watch(assetApiRepositoryProvider),
ref.watch(assetRepositoryProvider),
ref.watch(exifInfoRepositoryProvider),
ref.watch(exifRepositoryProvider),
ref.watch(userRepositoryProvider),
ref.watch(etagRepositoryProvider),
ref.watch(backupAlbumRepositoryProvider),
@@ -166,17 +166,18 @@ class AssetService {
/// Loads the exif information from the database. If there is none, loads
/// the exif info from the server (remote assets only)
Future<Asset> loadExif(Asset a) async {
a.exifInfo ??= await _exifInfoRepository.get(a.id);
a.exifInfo ??= (await _exifInfoRepository.get(a.id));
// fileSize is always filled on the server but not set on client
if (a.exifInfo?.fileSize == null) {
if (a.isRemote) {
final dto = await _apiService.assetsApi.getAssetInfo(a.remoteId!);
if (dto != null && dto.exifInfo != null) {
final newExif = Asset.remote(dto).exifInfo!.copyWith(id: a.id);
final newExif = Asset.remote(dto).exifInfo!.copyWith(assetId: a.id);
a.exifInfo = newExif;
if (newExif != a.exifInfo) {
if (a.isInDb) {
_assetRepository.transaction(() => _assetRepository.update(a));
await _assetRepository
.transaction(() => _assetRepository.update(a));
} else {
debugPrint("[loadExif] parameter Asset is not from DB!");
}
@@ -257,7 +258,8 @@ class AssetService {
for (var element in assets) {
element.fileCreatedAt = DateTime.parse(updatedDt);
element.exifInfo?.dateTimeOriginal = DateTime.parse(updatedDt);
element.exifInfo ??= element.exifInfo
?.copyWith(dateTimeOriginal: DateTime.parse(updatedDt));
}
await _syncService.upsertAssetsWithExif(assets);
@@ -283,8 +285,10 @@ class AssetService {
);
for (var element in assets) {
element.exifInfo?.lat = location.latitude;
element.exifInfo?.long = location.longitude;
element.exifInfo ??= element.exifInfo?.copyWith(
latitude: location.latitude,
longitude: location.longitude,
);
}
await _syncService.upsertAssetsWithExif(assets);
@@ -348,7 +352,7 @@ class AssetService {
String newDescription,
) async {
final remoteAssetId = asset.remoteId;
final localExifId = asset.exifInfo?.id;
final localExifId = asset.exifInfo?.assetId;
// Guard [remoteAssetId] and [localExifId] null
if (remoteAssetId == null || localExifId == null) {
@@ -366,14 +370,14 @@ class AssetService {
var exifInfo = await _exifInfoRepository.get(localExifId);
if (exifInfo != null) {
exifInfo.description = description;
await _exifInfoRepository.update(exifInfo);
await _exifInfoRepository
.update(exifInfo.copyWith(description: description));
}
}
}
Future<String> getDescription(Asset asset) async {
final localExifId = asset.exifInfo?.id;
final localExifId = asset.exifInfo?.assetId;
// Guard [remoteAssetId] and [localExifId] null
if (localExifId == null) {
+3 -2
View File
@@ -11,9 +11,11 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/backup_album.entity.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/exif.repository.dart';
import 'package:immich_mobile/interfaces/backup_album.interface.dart';
import 'package:immich_mobile/models/backup/backup_candidate.model.dart';
import 'package:immich_mobile/models/backup/current_upload_asset.model.dart';
@@ -28,7 +30,6 @@ import 'package:immich_mobile/repositories/auth.repository.dart';
import 'package:immich_mobile/repositories/auth_api.repository.dart';
import 'package:immich_mobile/repositories/backup.repository.dart';
import 'package:immich_mobile/repositories/etag.repository.dart';
import 'package:immich_mobile/repositories/exif_info.repository.dart';
import 'package:immich_mobile/repositories/file_media.repository.dart';
import 'package:immich_mobile/repositories/network.repository.dart';
import 'package:immich_mobile/repositories/partner_api.repository.dart';
@@ -379,7 +380,7 @@ class BackgroundService {
AlbumRepository albumRepository = AlbumRepository(db);
AssetRepository assetRepository = AssetRepository(db);
BackupAlbumRepository backupRepository = BackupAlbumRepository(db);
ExifInfoRepository exifInfoRepository = ExifInfoRepository(db);
IExifInfoRepository exifInfoRepository = IsarExifRepository(db);
ETagRepository eTagRepository = ETagRepository(db);
AlbumMediaRepository albumMediaRepository = AlbumMediaRepository();
FileMediaRepository fileMediaRepository = FileMediaRepository();
@@ -5,15 +5,16 @@ import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
import 'package:immich_mobile/domain/models/exif.model.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/entities/exif_info.entity.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/utils/exif.converter.dart';
import 'package:immich_mobile/interfaces/asset.interface.dart';
import 'package:immich_mobile/interfaces/exif_info.interface.dart';
import 'package:immich_mobile/interfaces/file_media.interface.dart';
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
import 'package:immich_mobile/repositories/asset.repository.dart';
import 'package:immich_mobile/repositories/exif_info.repository.dart';
import 'package:immich_mobile/repositories/file_media.repository.dart';
import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/utils/bootstrap.dart';
@@ -149,11 +150,11 @@ class BackupVerificationService {
) async {
if (remote.checksum == local.checksum) return false;
ExifInfo? exif = remote.exifInfo;
if (exif != null && exif.lat != null) return false;
if (exif != null && exif.latitude != null) return false;
if (exif == null || exif.fileSize == null) {
final dto = await apiService.assetsApi.getAssetInfo(remote.remoteId!);
if (dto != null && dto.exifInfo != null) {
exif = ExifInfo.fromDto(dto.exifInfo!);
exif = ExifDtoConverter.fromDto(dto.exifInfo!);
}
}
final file = await local.local!.originFile;
@@ -162,7 +163,7 @@ class BackupVerificationService {
if (exif.fileSize! == origSize || exif.fileSize! != origSize) {
final latLng = await local.local!.latlngAsync();
if (exif.lat == null &&
if (exif.latitude == null &&
latLng.latitude != null &&
(remote.fileCreatedAt.isAtSameMomentAs(local.fileCreatedAt) ||
remote.fileModifiedAt.isAtSameMomentAs(local.fileModifiedAt) ||
@@ -215,6 +216,6 @@ final backupVerificationServiceProvider = Provider(
(ref) => BackupVerificationService(
ref.watch(fileMediaRepositoryProvider),
ref.watch(assetRepositoryProvider),
ref.watch(exifInfoRepositoryProvider),
ref.watch(exifRepositoryProvider),
),
);
+5 -5
View File
@@ -1,16 +1,16 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/interfaces/exif_info.interface.dart';
import 'package:immich_mobile/repositories/exif_info.repository.dart';
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
final exifServiceProvider =
Provider((ref) => ExifService(ref.watch(exifInfoRepositoryProvider)));
Provider((ref) => ExifService(ref.watch(exifRepositoryProvider)));
class ExifService {
final IExifInfoRepository _exifInfoRepository;
ExifService(this._exifInfoRepository);
const ExifService(this._exifInfoRepository);
Future<void> clearTable() {
return _exifInfoRepository.clearTable();
return _exifInfoRepository.deleteAll();
}
}
+4 -4
View File
@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:collection/collection.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
import 'package:immich_mobile/entities/album.entity.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/entities/etag.entity.dart';
@@ -12,14 +13,13 @@ import 'package:immich_mobile/interfaces/album_api.interface.dart';
import 'package:immich_mobile/interfaces/album_media.interface.dart';
import 'package:immich_mobile/interfaces/asset.interface.dart';
import 'package:immich_mobile/interfaces/etag.interface.dart';
import 'package:immich_mobile/interfaces/exif_info.interface.dart';
import 'package:immich_mobile/interfaces/user.interface.dart';
import 'package:immich_mobile/providers/infrastructure/exif.provider.dart';
import 'package:immich_mobile/repositories/album.repository.dart';
import 'package:immich_mobile/repositories/album_api.repository.dart';
import 'package:immich_mobile/repositories/album_media.repository.dart';
import 'package:immich_mobile/repositories/asset.repository.dart';
import 'package:immich_mobile/repositories/etag.repository.dart';
import 'package:immich_mobile/repositories/exif_info.repository.dart';
import 'package:immich_mobile/repositories/user.repository.dart';
import 'package:immich_mobile/services/entity.service.dart';
import 'package:immich_mobile/services/hash.service.dart';
@@ -36,7 +36,7 @@ final syncServiceProvider = Provider(
ref.watch(albumApiRepositoryProvider),
ref.watch(albumRepositoryProvider),
ref.watch(assetRepositoryProvider),
ref.watch(exifInfoRepositoryProvider),
ref.watch(exifRepositoryProvider),
ref.watch(userRepositoryProvider),
ref.watch(etagRepositoryProvider),
),
@@ -756,7 +756,7 @@ class SyncService {
await _assetRepository.transaction(() async {
await _assetRepository.updateAll(assets);
for (final Asset added in assets) {
added.exifInfo?.id = added.id;
added.exifInfo ??= added.exifInfo?.copyWith(assetId: added.id);
}
await _exifInfoRepository.updateAll(exifInfos);
});