From 29e4666dfad852e1386f851382c7e2ebba46f8ab Mon Sep 17 00:00:00 2001 From: RanKKI Date: Tue, 18 Jun 2024 03:01:02 +1000 Subject: [PATCH] fix(mobile): asset description is not shown on the sheet when opened for the first time (#10377) * fix: invalidate asset's description when asset details changed * refactor(exif-sheet): use description from exif instead * refactor(asset-description): remove asset_description.provider * fix(asset-description): set is empty based on exifInfo.description * chore: rename service to provider --- .../asset_description.provider.dart | 87 ------------------- .../services/asset_description.service.dart | 43 ++++----- .../asset_viewer/description_input.dart | 19 ++-- .../exif_sheet/exif_bottom_sheet.dart | 6 +- 4 files changed, 32 insertions(+), 123 deletions(-) delete mode 100644 mobile/lib/providers/asset_viewer/asset_description.provider.dart diff --git a/mobile/lib/providers/asset_viewer/asset_description.provider.dart b/mobile/lib/providers/asset_viewer/asset_description.provider.dart deleted file mode 100644 index 11a622cad1e04..0000000000000 --- a/mobile/lib/providers/asset_viewer/asset_description.provider.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'dart:async'; - -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/services/asset_description.service.dart'; -import 'package:immich_mobile/entities/asset.entity.dart'; -import 'package:immich_mobile/entities/exif_info.entity.dart'; -import 'package:immich_mobile/providers/db.provider.dart'; -import 'package:isar/isar.dart'; - -class AssetDescriptionNotifier extends StateNotifier { - final Isar _db; - final AssetDescriptionService _service; - final Asset _asset; - - AssetDescriptionNotifier( - this._db, - this._service, - this._asset, - ) : super('') { - _fetchLocalDescription(); - _fetchRemoteDescription(); - } - - String get description => state; - - /// Fetches the local database value for description - /// and writes it to [state] - void _fetchLocalDescription() async { - final localExifId = _asset.exifInfo?.id; - - // Guard [localExifId] null - if (localExifId == null) { - return; - } - - // Subscribe to local changes - final exifInfo = await _db.exifInfos.get(localExifId); - - // Guard - if (exifInfo?.description == null) { - return; - } - - state = exifInfo!.description!; - } - - /// Fetches the remote value and sets the state - void _fetchRemoteDescription() async { - final remoteAssetId = _asset.remoteId; - final localExifId = _asset.exifInfo?.id; - - // Guard [remoteAssetId] and [localExifId] null - if (remoteAssetId == null || localExifId == null) { - return; - } - - // Reads the latest from the remote and writes it to DB in the service - final latest = await _service.readLatest(remoteAssetId, localExifId); - - state = latest; - } - - /// Sets the description to [description] - /// Uses the service to set the asset value - Future setDescription(String description) async { - state = description; - - final remoteAssetId = _asset.remoteId; - final localExifId = _asset.exifInfo?.id; - - // Guard [remoteAssetId] and [localExifId] null - if (remoteAssetId == null || localExifId == null) { - return; - } - - return _service.setDescription(description, remoteAssetId, localExifId); - } -} - -final assetDescriptionProvider = StateNotifierProvider.autoDispose - .family( - (ref, asset) => AssetDescriptionNotifier( - ref.watch(dbProvider), - ref.watch(assetDescriptionServiceProvider), - asset, - ), -); diff --git a/mobile/lib/services/asset_description.service.dart b/mobile/lib/services/asset_description.service.dart index 3b9bc5d567f31..66437d61e20c3 100644 --- a/mobile/lib/services/asset_description.service.dart +++ b/mobile/lib/services/asset_description.service.dart @@ -1,4 +1,5 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/entities/exif_info.entity.dart'; import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/providers/db.provider.dart'; @@ -12,46 +13,36 @@ class AssetDescriptionService { final Isar _db; final ApiService _api; - setDescription( - String description, - String remoteAssetId, - int localExifId, + Future setDescription( + Asset asset, + String newDescription, ) async { + final remoteAssetId = asset.remoteId; + final localExifId = asset.exifInfo?.id; + + // Guard [remoteAssetId] and [localExifId] null + if (remoteAssetId == null || localExifId == null) { + return; + } + final result = await _api.assetsApi.updateAsset( remoteAssetId, - UpdateAssetDto(description: description), + UpdateAssetDto(description: newDescription), ); - if (result?.exifInfo?.description != null) { + final description = result?.exifInfo?.description; + + if (description != null) { var exifInfo = await _db.exifInfos.get(localExifId); if (exifInfo != null) { - exifInfo.description = result!.exifInfo!.description; + exifInfo.description = description; await _db.writeTxn( () => _db.exifInfos.put(exifInfo), ); } } } - - Future readLatest(String assetRemoteId, int localExifId) async { - final latestAssetFromServer = - await _api.assetsApi.getAssetInfo(assetRemoteId); - final localExifInfo = await _db.exifInfos.get(localExifId); - - if (latestAssetFromServer != null && localExifInfo != null) { - localExifInfo.description = - latestAssetFromServer.exifInfo?.description ?? ''; - - await _db.writeTxn( - () => _db.exifInfos.put(localExifInfo), - ); - - return localExifInfo.description!; - } - - return ""; - } } final assetDescriptionServiceProvider = Provider( diff --git a/mobile/lib/widgets/asset_viewer/description_input.dart b/mobile/lib/widgets/asset_viewer/description_input.dart index bd67bf1d343e0..7422e433358e1 100644 --- a/mobile/lib/widgets/asset_viewer/description_input.dart +++ b/mobile/lib/widgets/asset_viewer/description_input.dart @@ -2,10 +2,11 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/entities/exif_info.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/providers/asset_viewer/asset_description.provider.dart'; import 'package:immich_mobile/entities/asset.entity.dart'; import 'package:immich_mobile/providers/user.provider.dart'; +import 'package:immich_mobile/services/asset_description.service.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; import 'package:logging/logging.dart'; @@ -13,9 +14,11 @@ class DescriptionInput extends HookConsumerWidget { DescriptionInput({ super.key, required this.asset, + this.exifInfo, }); final Asset asset; + final ExifInfo? exifInfo; final Logger _log = Logger('DescriptionInput'); @override @@ -25,25 +28,25 @@ class DescriptionInput extends HookConsumerWidget { final focusNode = useFocusNode(); final isFocus = useState(false); final isTextEmpty = useState(controller.text.isEmpty); - final descriptionProvider = - ref.watch(assetDescriptionProvider(asset).notifier); - final description = ref.watch(assetDescriptionProvider(asset)); + final descriptionProvider = ref.watch(assetDescriptionServiceProvider); + final owner = ref.watch(currentUserProvider); final hasError = useState(false); useEffect( () { - controller.text = description; - isTextEmpty.value = description.isEmpty; + controller.text = exifInfo?.description ?? ''; + isTextEmpty.value = exifInfo?.description?.isEmpty ?? true; return null; }, - [description], + [exifInfo?.description], ); submitDescription(String description) async { hasError.value = false; try { await descriptionProvider.setDescription( + asset, description, ); } catch (error, stack) { @@ -85,7 +88,7 @@ class DescriptionInput extends HookConsumerWidget { isFocus.value = false; focusNode.unfocus(); - if (description != controller.text) { + if (exifInfo?.description != controller.text) { await submitDescription(controller.text); } }, diff --git a/mobile/lib/widgets/asset_viewer/exif_sheet/exif_bottom_sheet.dart b/mobile/lib/widgets/asset_viewer/exif_sheet/exif_bottom_sheet.dart index 9a9de304caa8f..8d1694adfb5c6 100644 --- a/mobile/lib/widgets/asset_viewer/exif_sheet/exif_bottom_sheet.dart +++ b/mobile/lib/widgets/asset_viewer/exif_sheet/exif_bottom_sheet.dart @@ -73,7 +73,8 @@ class ExifBottomSheet extends HookConsumerWidget { child: Column( children: [ dateWidget, - if (asset.isRemote) DescriptionInput(asset: asset), + if (asset.isRemote) + DescriptionInput(asset: asset, exifInfo: exifInfo), ], ), ), @@ -132,7 +133,8 @@ class ExifBottomSheet extends HookConsumerWidget { child: Column( children: [ dateWidget, - if (asset.isRemote) DescriptionInput(asset: asset), + if (asset.isRemote) + DescriptionInput(asset: asset, exifInfo: exifInfo), Padding( padding: EdgeInsets.only(top: asset.isRemote ? 0 : 16.0), child: ExifLocation(