import 'dart:async'; import 'package:logging/logging.dart'; import 'package:nc_photos/account.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_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.prefController, }) { _subscriptions .add(prefController.isEnableExifChange.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; } /// Kickstart the metadata task, if applicable. /// /// Running the metadata task during startup may degrade the startup time, so /// we are not doing so. Instead, UI code should call this function to start /// the task whenever it sees fit /// /// Calling this function are NOT guaranteed to actually start the task void kickstart() { _log.info("[kickstart] Metadata controller enabled"); _isEnable = true; if (prefController.isEnableExifValue && !_hasStarted) { _startMetadataTask(); } } void _onSetEnableExif(bool value) { _log.info("[_onSetEnableExif]"); if (value) { if (!_isEnable) { _log.info("[_onSetEnableExif] Ignored as not enabled"); return; } _startMetadataTask(); } else { _stopMetadataTask(); } } Future _startMetadataTask() async { _hasStarted = true; try { final missingCount = await _c.npDb.countFilesByMissingMetadata( account: account.toDb(), 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 PrefController prefController; final _subscriptions = []; var _isEnable = false; var _hasStarted = false; }