From 88af19ac67d2607c28e02189cb805d2accf9dfc5 Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Wed, 31 Jan 2024 01:31:52 +0800 Subject: [PATCH] Move metadata logic out of photos bloc --- app/lib/controller/account_controller.dart | 22 ++++- app/lib/controller/metadata_controller.dart | 97 +++++++++++++++++++ app/lib/controller/metadata_controller.g.dart | 15 +++ app/lib/controller/session_controller.dart | 2 + app/lib/widget/home_photos/bloc.dart | 53 +--------- app/lib/widget/home_photos/state_event.dart | 16 +-- app/lib/widget/home_photos2.dart | 8 +- app/lib/widget/home_photos2.g.dart | 11 +-- app/lib/widget/my_app.dart | 6 +- 9 files changed, 152 insertions(+), 78 deletions(-) create mode 100644 app/lib/controller/metadata_controller.dart create mode 100644 app/lib/controller/metadata_controller.g.dart diff --git a/app/lib/controller/account_controller.dart b/app/lib/controller/account_controller.dart index 9d761182..20e1e2d1 100644 --- a/app/lib/controller/account_controller.dart +++ b/app/lib/controller/account_controller.dart @@ -3,8 +3,10 @@ import 'package:nc_photos/account.dart'; import 'package:nc_photos/controller/account_pref_controller.dart'; import 'package:nc_photos/controller/collections_controller.dart'; import 'package:nc_photos/controller/files_controller.dart'; +import 'package:nc_photos/controller/metadata_controller.dart'; import 'package:nc_photos/controller/persons_controller.dart'; import 'package:nc_photos/controller/places_controller.dart'; +import 'package:nc_photos/controller/pref_controller.dart'; import 'package:nc_photos/controller/server_controller.dart'; import 'package:nc_photos/controller/session_controller.dart'; import 'package:nc_photos/controller/sharings_controller.dart'; @@ -13,6 +15,10 @@ import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/event/native_event_relay.dart'; class AccountController { + AccountController({ + required this.prefController, + }); + void setCurrentAccount(Account account) { _account = account; @@ -35,6 +41,8 @@ class AccountController { _filesController?.dispose(); _filesController = null; + _metadataController?.dispose(); + _metadataController = null; _nativeEventRelay?.dispose(); _nativeEventRelay = NativeEventRelay(filesController: filesController); } @@ -84,13 +92,22 @@ class AccountController { account: _account!, ); - FilesController get filesController => - _filesController ??= FilesController( + FilesController get filesController => _filesController ??= FilesController( KiwiContainer().resolve(), account: _account!, accountPrefController: accountPrefController, ); + MetadataController get metadataController => + _metadataController ??= MetadataController( + KiwiContainer().resolve(), + account: account, + filesController: filesController, + prefController: prefController, + ); + + PrefController prefController; + Account? _account; CollectionsController? _collectionsController; @@ -103,5 +120,6 @@ class AccountController { PlacesController? _placesController; FilesController? _filesController; + MetadataController? _metadataController; NativeEventRelay? _nativeEventRelay; } diff --git a/app/lib/controller/metadata_controller.dart b/app/lib/controller/metadata_controller.dart new file mode 100644 index 00000000..0b3e8d0e --- /dev/null +++ b/app/lib/controller/metadata_controller.dart @@ -0,0 +1,97 @@ +import 'dart:async'; + +import 'package:logging/logging.dart'; +import 'package:nc_photos/account.dart'; +import 'package:nc_photos/controller/files_controller.dart'; +import 'package:nc_photos/controller/pref_controller.dart'; +import 'package:nc_photos/db/entity_converter.dart'; +import 'package:nc_photos/di_container.dart'; +import 'package:nc_photos/entity/file_descriptor.dart'; +import 'package:nc_photos/entity/file_util.dart' as file_util; +import 'package:nc_photos/service.dart' as service; +import 'package:np_codegen/np_codegen.dart'; + +part 'metadata_controller.g.dart'; + +@npLog +class MetadataController { + MetadataController( + this._c, { + required this.account, + required this.filesController, + required this.prefController, + }) { + _subscriptions.add(filesController.stream.listen(_onFilesEvent)); + _subscriptions.add(prefController.isEnableExif.listen(_onSetEnableExif)); + } + + void dispose() { + for (final s in _subscriptions) { + s.cancel(); + } + } + + /// Normally EXIF task only run once, call this function to make it run again + /// after receiving new files + void scheduleNext() { + _hasStarted = false; + } + + Future _onFilesEvent(FilesStreamEvent ev) async { + _log.info("[_onFilesEvent]"); + if (!prefController.isEnableExif.value) { + // disabled + return; + } + if (ev.data.isNotEmpty && !ev.hasNext) { + // finished querying + if (!_hasStarted) { + await _startMetadataTask(ev.data); + } + } + } + + void _onSetEnableExif(bool value) { + _log.info("[_onSetEnableExif]"); + if (value) { + final filesState = filesController.stream.value; + if (filesState.hasNext || filesState.data.isEmpty) { + _log.info("[_onSetEnableExif] Ignored as data not ready"); + return; + } + _startMetadataTask(filesState.data); + } else { + _stopMetadataTask(); + } + } + + Future _startMetadataTask(List data) async { + _hasStarted = true; + try { + final missingCount = await _c.npDb.countFilesByFileIdsMissingMetadata( + account: account.toDb(), + fileIds: data.map((e) => e.fdId).toList(), + mimes: file_util.supportedImageFormatMimes, + ); + _log.info("[_startMetadataTask] Missing count: $missingCount"); + if (missingCount > 0) { + unawaited(service.startService()); + } + } catch (e, stackTrace) { + _log.shout( + "[_startMetadataTask] Failed starting metadata task", e, stackTrace); + } + } + + void _stopMetadataTask() { + service.stopService(); + } + + final DiContainer _c; + final Account account; + final FilesController filesController; + final PrefController prefController; + + final _subscriptions = []; + var _hasStarted = false; +} diff --git a/app/lib/controller/metadata_controller.g.dart b/app/lib/controller/metadata_controller.g.dart new file mode 100644 index 00000000..506407ee --- /dev/null +++ b/app/lib/controller/metadata_controller.g.dart @@ -0,0 +1,15 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'metadata_controller.dart'; + +// ************************************************************************** +// NpLogGenerator +// ************************************************************************** + +extension _$MetadataControllerNpLog on MetadataController { + // ignore: unused_element + Logger get _log => log; + + static final log = + Logger("controller.metadata_controller.MetadataController"); +} diff --git a/app/lib/controller/session_controller.dart b/app/lib/controller/session_controller.dart index 82d9a68e..c3af94a8 100644 --- a/app/lib/controller/session_controller.dart +++ b/app/lib/controller/session_controller.dart @@ -9,9 +9,11 @@ class SessionController { _hasFiredMetadataTaskController.close(); } + @Deprecated("Use MetadataController") ValueStream get hasFiredMetadataTask => _hasFiredMetadataTaskController.stream; + @Deprecated("Use MetadataController") void setFiredMetadataTask(bool value) { _hasFiredMetadataTaskController.add(value); } diff --git a/app/lib/widget/home_photos/bloc.dart b/app/lib/widget/home_photos/bloc.dart index b1ac1be1..9e4768ae 100644 --- a/app/lib/widget/home_photos/bloc.dart +++ b/app/lib/widget/home_photos/bloc.dart @@ -9,16 +9,16 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { required this.prefController, required this.accountPrefController, required this.collectionsController, - required this.sessionController, required this.syncController, required this.personsController, + required this.metadataController, }) : super(_State.init( zoom: prefController.homePhotosZoomLevel.value, isEnableMemoryCollection: accountPrefController.isEnableMemoryAlbum.value, )) { on<_LoadItems>(_onLoad); - on<_Reload>(_onReload); + on<_RequestRefresh>(_onRequestRefresh); on<_TransformItems>(_onTransformItems); on<_OnItemTransformed>(_onOnItemTransformed); @@ -41,7 +41,6 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { on<_SetEnableMemoryCollection>(_onSetEnableMemoryCollection); on<_SetSortByName>(_onSetSortByName); on<_SetMemoriesRange>(_onSetMemoriesRange); - on<_SetEnableExif>(_onSetEnableExif); on<_UpdateDateTimeGroup>(_onUpdateDateTimeGroup); on<_SetError>(_onSetError); @@ -56,9 +55,6 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { _subscriptions.add(prefController.memoriesRange.listen((event) { add(_SetMemoriesRange(event)); })); - _subscriptions.add(prefController.isEnableExif.listen((event) { - add(_SetEnableExif(event)); - })); } @override @@ -118,10 +114,11 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { ); } - void _onReload(_Reload ev, Emitter<_State> emit) { + void _onRequestRefresh(_RequestRefresh ev, Emitter<_State> emit) { _log.info(ev); emit(state.copyWith(syncProgress: const Progress(0))); _syncRemote(); + metadataController.scheduleNext(); } void _onTransformItems(_TransformItems ev, Emitter<_State> emit) { @@ -143,7 +140,6 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { personsController: personsController, personProvider: accountPrefController.personProvider.value, ); - _tryStartMetadataTask(); } void _onSetSelectedItems(_SetSelectedItems ev, Emitter<_State> emit) { @@ -291,15 +287,6 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { _transformItems(state.files); } - void _onSetEnableExif(_SetEnableExif ev, Emitter<_State> emit) { - _log.info(ev); - if (ev.value) { - _tryStartMetadataTask(ignoreFired: true); - } else { - _stopMetadataTask(); - } - } - void _onUpdateDateTimeGroup(_UpdateDateTimeGroup ev, Emitter<_State> emit) { _log.info(ev); _transformItems(state.files); @@ -354,45 +341,15 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger { emit(state.copyWith(selectedItems: const {})); } - Future _tryStartMetadataTask({ - bool ignoreFired = false, - }) async { - if (state.files.isNotEmpty && - prefController.isEnableExif.value && - (ignoreFired || !sessionController.hasFiredMetadataTask.value)) { - sessionController.setFiredMetadataTask(true); - try { - final missingMetadataCount = - await _c.npDb.countFilesByFileIdsMissingMetadata( - account: account.toDb(), - fileIds: state.files.map((e) => e.fdId).toList(), - mimes: file_util.supportedImageFormatMimes, - ); - _log.info( - "[_tryStartMetadataTask] Missing count: $missingMetadataCount"); - if (missingMetadataCount > 0) { - unawaited(service.startService()); - } - } catch (e, stackTrace) { - _log.shout("[_tryStartMetadataTask] Failed starting metadata task", e, - stackTrace); - } - } - } - - void _stopMetadataTask() { - service.stopService(); - } - final DiContainer _c; final Account account; final FilesController controller; final PrefController prefController; final AccountPrefController accountPrefController; final CollectionsController collectionsController; - final SessionController sessionController; final SyncController syncController; final PersonsController personsController; + final MetadataController metadataController; final _itemTransformerQueue = ComputeQueue<_ItemTransformerArgument, _ItemTransformerResult>(); diff --git a/app/lib/widget/home_photos/state_event.dart b/app/lib/widget/home_photos/state_event.dart index 29e9ccb0..efb372bc 100644 --- a/app/lib/widget/home_photos/state_event.dart +++ b/app/lib/widget/home_photos/state_event.dart @@ -65,9 +65,11 @@ class _LoadItems implements _Event { String toString() => _$toString(); } +/// User explicitly requested to refresh the data, e.g., performed the +/// pull-to-refresh action @toString -class _Reload implements _Event { - const _Reload(); +class _RequestRefresh implements _Event { + const _RequestRefresh(); @override String toString() => _$toString(); @@ -238,16 +240,6 @@ class _SetMemoriesRange implements _Event { final int value; } -@toString -class _SetEnableExif implements _Event { - const _SetEnableExif(this.value); - - @override - String toString() => _$toString(); - - final bool value; -} - @toString class _UpdateDateTimeGroup implements _Event { const _UpdateDateTimeGroup(); diff --git a/app/lib/widget/home_photos2.dart b/app/lib/widget/home_photos2.dart index b04e6a73..b29ce93c 100644 --- a/app/lib/widget/home_photos2.dart +++ b/app/lib/widget/home_photos2.dart @@ -18,11 +18,10 @@ import 'package:nc_photos/controller/account_controller.dart'; import 'package:nc_photos/controller/account_pref_controller.dart'; import 'package:nc_photos/controller/collections_controller.dart'; import 'package:nc_photos/controller/files_controller.dart'; +import 'package:nc_photos/controller/metadata_controller.dart'; import 'package:nc_photos/controller/persons_controller.dart'; import 'package:nc_photos/controller/pref_controller.dart'; -import 'package:nc_photos/controller/session_controller.dart'; import 'package:nc_photos/controller/sync_controller.dart'; -import 'package:nc_photos/db/entity_converter.dart'; import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/download_handler.dart'; import 'package:nc_photos/entity/collection.dart'; @@ -35,7 +34,6 @@ import 'package:nc_photos/flutter_util.dart' as flutter_util; import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/language_util.dart' as language_util; import 'package:nc_photos/progress_util.dart'; -import 'package:nc_photos/service.dart' as service; import 'package:nc_photos/snack_bar_manager.dart'; import 'package:nc_photos/theme.dart'; import 'package:nc_photos/theme/dimension.dart'; @@ -85,9 +83,9 @@ class HomePhotos2 extends StatelessWidget { prefController: context.read(), accountPrefController: accountController.accountPrefController, collectionsController: accountController.collectionsController, - sessionController: accountController.sessionController, syncController: accountController.syncController, personsController: accountController.personsController, + metadataController: accountController.metadataController, ), child: const _WrappedHomePhotos(), ); @@ -299,7 +297,7 @@ class _BodyState extends State<_Body> { .copyWith(scrollbars: false), child: RefreshIndicator( onRefresh: () async { - _bloc.add(const _Reload()); + _bloc.add(const _RequestRefresh()); var hasNotNull = false; await _bloc.stream.firstWhere((s) { if (s.syncProgress != null) { diff --git a/app/lib/widget/home_photos2.g.dart b/app/lib/widget/home_photos2.g.dart index e5ea0a66..00a1a537 100644 --- a/app/lib/widget/home_photos2.g.dart +++ b/app/lib/widget/home_photos2.g.dart @@ -146,10 +146,10 @@ extension _$_LoadItemsToString on _LoadItems { } } -extension _$_ReloadToString on _Reload { +extension _$_RequestRefreshToString on _RequestRefresh { String _$toString() { // ignore: unnecessary_string_interpolations - return "_Reload {}"; + return "_RequestRefresh {}"; } } @@ -273,13 +273,6 @@ extension _$_SetMemoriesRangeToString on _SetMemoriesRange { } } -extension _$_SetEnableExifToString on _SetEnableExif { - String _$toString() { - // ignore: unnecessary_string_interpolations - return "_SetEnableExif {value: $value}"; - } -} - extension _$_UpdateDateTimeGroupToString on _UpdateDateTimeGroup { String _$toString() { // ignore: unnecessary_string_interpolations diff --git a/app/lib/widget/my_app.dart b/app/lib/widget/my_app.dart index 747ddb40..d2970f30 100644 --- a/app/lib/widget/my_app.dart +++ b/app/lib/widget/my_app.dart @@ -70,10 +70,12 @@ class MyApp extends StatelessWidget { return MultiRepositoryProvider( providers: [ RepositoryProvider( - create: (_) => AccountController(), + create: (_) => PrefController(_c), ), RepositoryProvider( - create: (_) => PrefController(_c), + create: (context) => AccountController( + prefController: context.read(), + ), ), RepositoryProvider( create: (_) => _c.npDb,