nc-photos/app/lib/metadata_task_manager.dart

135 lines
3.8 KiB
Dart
Raw Normal View History

2021-04-10 06:28:12 +02:00
import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:kiwi/kiwi.dart';
2021-04-10 06:28:12 +02:00
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/di_container.dart';
2021-04-10 06:28:12 +02:00
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file_util.dart' as file_util;
2023-07-17 09:35:45 +02:00
import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/event/event.dart';
2021-04-10 06:28:12 +02:00
import 'package:nc_photos/use_case/update_missing_metadata.dart';
2022-12-16 16:01:04 +01:00
import 'package:np_codegen/np_codegen.dart';
2023-08-27 18:54:18 +02:00
import 'package:np_geocoder/np_geocoder.dart';
2022-12-08 16:39:13 +01:00
import 'package:to_string/to_string.dart';
part 'metadata_task_manager.g.dart';
2021-04-10 06:28:12 +02:00
/// Task to update metadata for missing files
2022-12-16 16:01:04 +01:00
@npLog
2022-12-08 16:39:13 +01:00
@ToString(ignorePrivate: true)
2021-04-10 06:28:12 +02:00
class MetadataTask {
MetadataTask(this._c, this.account, this.pref) : assert(require(_c));
static bool require(DiContainer c) => DiContainer.has(c, DiType.fileRepo);
2021-04-10 06:28:12 +02:00
@override
2022-12-08 16:39:13 +01:00
String toString() => _$toString();
2021-04-10 06:28:12 +02:00
Future<void> call() async {
try {
final shareFolder =
File(path: file_util.unstripPath(account, pref.getShareFolderOr()));
bool hasScanShareFolder = false;
2022-08-27 17:32:31 +02:00
final geocoder = ReverseGeocoder();
await geocoder.init();
for (final r in account.roots) {
final dir = File(path: file_util.unstripPath(account, r));
hasScanShareFolder |= file_util.isOrUnderDir(shareFolder, dir);
2024-01-12 19:18:23 +01:00
final op = UpdateMissingMetadata(
_c, const _UpdateMissingMetadataConfigProvider(), geocoder);
await for (final _ in op(account, dir)) {
if (!Pref().isEnableExifOr()) {
_log.info("[call] EXIF disabled, task ending immaturely");
op.stop();
return;
}
}
}
if (!hasScanShareFolder) {
2024-01-12 19:18:23 +01:00
final op = UpdateMissingMetadata(
_c, const _UpdateMissingMetadataConfigProvider(), geocoder);
await for (final _ in op(
account,
shareFolder,
isRecursive: false,
filter: (f) => f.ownerId != account.userId,
)) {
2021-10-27 22:40:54 +02:00
if (!Pref().isEnableExifOr()) {
_log.info("[call] EXIF disabled, task ending immaturely");
op.stop();
return;
}
2021-04-10 06:28:12 +02:00
}
}
} finally {
KiwiContainer()
.resolve<EventBus>()
2021-09-15 08:58:06 +02:00
.fire(const MetadataTaskStateChangedEvent(MetadataTaskState.idle));
2021-04-10 06:28:12 +02:00
}
}
final DiContainer _c;
2021-04-10 06:28:12 +02:00
final Account account;
2022-12-08 16:39:13 +01:00
@ignore
final AccountPref pref;
2021-04-10 06:28:12 +02:00
}
/// Manage metadata tasks to run concurrently
2022-12-16 16:01:04 +01:00
@npLog
2021-04-10 06:28:12 +02:00
class MetadataTaskManager {
factory MetadataTaskManager() {
2021-09-15 08:58:06 +02:00
_inst ??= MetadataTaskManager._();
return _inst!;
}
MetadataTaskManager._() {
_stateChangedListener.begin();
2021-04-10 06:28:12 +02:00
_handleStream();
}
/// Add a task to the queue
void addTask(MetadataTask task) {
_log.info("[addTask] New task added: $task");
_streamController.add(task);
}
MetadataTaskState get state => _currentState;
void _onMetadataTaskStateChanged(MetadataTaskStateChangedEvent ev) {
if (ev.state != _currentState) {
_currentState = ev.state;
}
}
2022-07-28 20:45:43 +02:00
Future<void> _handleStream() async {
2021-04-10 06:28:12 +02:00
await for (final task in _streamController.stream) {
2021-10-27 22:40:54 +02:00
if (Pref().isEnableExifOr()) {
2021-04-10 06:28:12 +02:00
_log.info("[_doTask] Executing task: $task");
await task();
} else {
_log.info("[_doTask] Ignoring task: $task");
}
}
}
final _streamController = StreamController<MetadataTask>.broadcast();
var _currentState = MetadataTaskState.idle;
late final _stateChangedListener =
AppEventListener<MetadataTaskStateChangedEvent>(
_onMetadataTaskStateChanged);
static MetadataTaskManager? _inst;
}
class _UpdateMissingMetadataConfigProvider
implements UpdateMissingMetadataConfigProvider {
const _UpdateMissingMetadataConfigProvider();
@override
isWifiOnly() async => Pref().shouldProcessExifWifiOnlyOr();
}