mirror of
https://github.com/immich-app/immich.git
synced 2026-09-30 21:28:12 +08:00
fix(mobile): make EXIF provider reactive (#31552)
* fix(mobile): make EXIF provider reactive * Fix tests * Remove unnecessary invalidations
This commit is contained in:
@@ -63,13 +63,13 @@ class AssetService {
|
||||
return [asset, ...stack];
|
||||
}
|
||||
|
||||
Future<ExifInfo?> getExif(BaseAsset asset) async {
|
||||
Stream<ExifInfo?> watchExif(BaseAsset asset) {
|
||||
if (!asset.hasRemote) {
|
||||
return null;
|
||||
return Stream.value(null);
|
||||
}
|
||||
|
||||
final id = asset is LocalAsset ? asset.remoteId! : (asset as RemoteAsset).id;
|
||||
return _remoteRepository.getExif(id);
|
||||
return _remoteRepository.watchExif(id);
|
||||
}
|
||||
|
||||
Future<List<(String, String)>> getPlaces(String userId) {
|
||||
|
||||
@@ -64,12 +64,10 @@ class RemoteAssetRepository extends DatabaseAccessor<Drift> with $RemoteAssetRep
|
||||
return query.map((row) => row.toDto()).get();
|
||||
}
|
||||
|
||||
Future<ExifInfo?> getExif(String id) {
|
||||
return _db.managers.remoteExifEntity
|
||||
.filter((row) => row.assetId.id.equals(id))
|
||||
.map((row) => row.toDto())
|
||||
.getSingleOrNull();
|
||||
}
|
||||
Stream<ExifInfo?> watchExif(String id) => _db.managers.remoteExifEntity
|
||||
.filter((row) => row.assetId.id.equals(id))
|
||||
.map((row) => row.toDto())
|
||||
.watchSingleOrNull();
|
||||
|
||||
Future<List<(String, String)>> getPlaces(String userId) {
|
||||
final asset = Subquery(
|
||||
|
||||
@@ -50,7 +50,7 @@ class EditAssetAction extends AssetActionBuilder {
|
||||
try {
|
||||
// TODO(shenlong): Move all EXIF and Apply Edits logic onto the Route
|
||||
final repository = ref.read(driftProvider).remoteAssetRepository;
|
||||
final (edits, exif) = await (repository.getAssetEdits(asset.id), repository.getExif(asset.id)).wait;
|
||||
final (edits, exif) = await (repository.getAssetEdits(asset.id), repository.watchExif(asset.id).first).wait;
|
||||
if (exif == null || !context.mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/toast.provider.dart';
|
||||
import 'package:immich_mobile/utils/error_handler.dart';
|
||||
@@ -56,7 +55,7 @@ class EditDateTimeAction extends AssetActionBuilder {
|
||||
Duration? offset;
|
||||
|
||||
if (origin != null) {
|
||||
final exif = await remoteAssetRepository.getExif(origin.id);
|
||||
final exif = await remoteAssetRepository.watchExif(origin.id).first;
|
||||
|
||||
// Prefer the EXIF timezone, so the picker opens on what the asset actually shows.
|
||||
DateTime dateTime = origin.createdAt.toLocal();
|
||||
@@ -96,6 +95,5 @@ Future<void> saveDateTime(BuildContext context, WidgetRef ref, List<String> asse
|
||||
final toastService = ref.read(toastServiceProvider);
|
||||
|
||||
await ref.read(assetServiceProvider).update(assetIds, dateTime: .some(dateTime));
|
||||
ref.invalidate(assetExifProvider);
|
||||
toastService.success(message);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset_viewer/asset.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/toast.provider.dart';
|
||||
import 'package:immich_mobile/utils/error_handler.dart';
|
||||
@@ -53,7 +52,7 @@ class EditLocationAction extends AssetActionBuilder {
|
||||
try {
|
||||
LatLng? initialLatLng;
|
||||
if (origin != null) {
|
||||
final exif = await remoteAssetRepository.getExif(origin.id);
|
||||
final exif = await remoteAssetRepository.watchExif(origin.id).first;
|
||||
if (exif?.latitude != null && exif?.longitude != null) {
|
||||
initialLatLng = LatLng(exif!.latitude!, exif.longitude!);
|
||||
}
|
||||
@@ -81,6 +80,5 @@ Future<void> saveLocation(BuildContext context, WidgetRef ref, List<String> asse
|
||||
final toastService = ref.read(toastServiceProvider);
|
||||
|
||||
await ref.read(assetServiceProvider).update(assetIds, location: .some(location));
|
||||
ref.invalidate(assetExifProvider);
|
||||
toastService.success(message);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ class _AssetPropertiesSectionState extends ConsumerState<_AssetPropertiesSection
|
||||
|
||||
properties.insertAll(4, additionalProps);
|
||||
|
||||
final exif = await ref.read(assetServiceProvider).getExif(asset);
|
||||
final exif = await ref.read(assetServiceProvider).watchExif(asset).first;
|
||||
if (exif != null) {
|
||||
_addExifProperties(exif);
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,6 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
|
||||
final assetExifProvider = FutureProvider.autoDispose.family<ExifInfo?, BaseAsset>((ref, asset) {
|
||||
return ref.watch(assetServiceProvider).getExif(asset);
|
||||
final assetExifProvider = StreamProvider.autoDispose.family<ExifInfo?, BaseAsset>((ref, asset) {
|
||||
return ref.watch(assetServiceProvider).watchExif(asset);
|
||||
});
|
||||
|
||||
@@ -70,7 +70,7 @@ class RepositoryMocks {
|
||||
}
|
||||
|
||||
void _stubRemoteAssetRepository() {
|
||||
when(remoteAsset.getExif).thenAnswer((_) async => null);
|
||||
when(remoteAsset.watchExif).thenAnswer((_) => Stream.value(null));
|
||||
when(remoteAsset.getAssetEdits).thenAnswer((_) async => const []);
|
||||
when(remoteAsset.update).thenAnswer((_) async {});
|
||||
}
|
||||
@@ -269,8 +269,8 @@ extension type const LocalAssetRepositoryStub(MockLocalAssetRepository repo) imp
|
||||
|
||||
extension type const RemoteAssetRepositoryStub(MockRemoteAssetRepository repo)
|
||||
implements Stub<MockRemoteAssetRepository> {
|
||||
Future<ExifInfo?> Function() get getExif =>
|
||||
() => repo.getExif(any());
|
||||
Stream<ExifInfo?> Function() get watchExif =>
|
||||
() => repo.watchExif(any());
|
||||
|
||||
Future<List<AssetEdit>> Function() get getAssetEdits =>
|
||||
() => repo.getAssetEdits(any());
|
||||
|
||||
@@ -111,7 +111,7 @@ void main() {
|
||||
await tester.pump();
|
||||
|
||||
verify(() => context.repository.remoteAsset.repo.getAssetEdits(asset.id)).called(1);
|
||||
verify(() => context.repository.remoteAsset.repo.getExif(asset.id)).called(1);
|
||||
verify(() => context.repository.remoteAsset.repo.watchExif(asset.id)).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user