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; }