2021-04-10 06:28:12 +02:00
|
|
|
import 'dart:async';
|
|
|
|
|
2021-08-15 19:06:00 +02:00
|
|
|
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';
|
2022-07-05 22:20:24 +02:00
|
|
|
import 'package:nc_photos/di_container.dart';
|
2021-04-10 06:28:12 +02:00
|
|
|
import 'package:nc_photos/entity/file.dart';
|
2021-11-16 16:06:22 +01:00
|
|
|
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';
|
2021-08-15 19:06:00 +02:00
|
|
|
import 'package:nc_photos/event/event.dart';
|
2022-08-27 17:32:31 +02:00
|
|
|
import 'package:nc_photos/reverse_geocoder.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';
|
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 {
|
2022-07-05 22:20:24 +02:00
|
|
|
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 {
|
2021-08-15 19:06:00 +02:00
|
|
|
try {
|
2021-12-07 10:03:57 +01:00
|
|
|
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();
|
2021-08-15 19:06:00 +02:00
|
|
|
for (final r in account.roots) {
|
2021-12-07 10:03:57 +01:00
|
|
|
final dir = File(path: file_util.unstripPath(account, r));
|
|
|
|
hasScanShareFolder |= file_util.isOrUnderDir(shareFolder, dir);
|
2022-08-27 17:32:31 +02:00
|
|
|
final op = UpdateMissingMetadata(_c.fileRepo,
|
|
|
|
const _UpdateMissingMetadataConfigProvider(), geocoder);
|
2021-12-07 10:03:57 +01:00
|
|
|
await for (final _ in op(account, dir)) {
|
|
|
|
if (!Pref().isEnableExifOr()) {
|
|
|
|
_log.info("[call] EXIF disabled, task ending immaturely");
|
|
|
|
op.stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!hasScanShareFolder) {
|
2022-08-27 17:32:31 +02:00
|
|
|
final op = UpdateMissingMetadata(_c.fileRepo,
|
|
|
|
const _UpdateMissingMetadataConfigProvider(), geocoder);
|
2021-12-07 10:03:57 +01:00
|
|
|
await for (final _ in op(
|
|
|
|
account,
|
|
|
|
shareFolder,
|
|
|
|
isRecursive: false,
|
2022-07-11 20:14:42 +02:00
|
|
|
filter: (f) => f.ownerId != account.userId,
|
2021-12-07 10:03:57 +01:00
|
|
|
)) {
|
2021-10-27 22:40:54 +02:00
|
|
|
if (!Pref().isEnableExifOr()) {
|
2021-08-15 19:06:00 +02:00
|
|
|
_log.info("[call] EXIF disabled, task ending immaturely");
|
|
|
|
op.stop();
|
|
|
|
return;
|
|
|
|
}
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|
|
|
|
}
|
2021-08-15 19:06:00 +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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-05 22:20:24 +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
|
2021-12-07 10:03:57 +01:00
|
|
|
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 {
|
2021-08-15 19:06:00 +02:00
|
|
|
factory MetadataTaskManager() {
|
2021-09-15 08:58:06 +02:00
|
|
|
_inst ??= MetadataTaskManager._();
|
2021-08-15 19:06:00 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2021-08-15 19:06:00 +02:00
|
|
|
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();
|
|
|
|
|
2021-08-15 19:06:00 +02:00
|
|
|
var _currentState = MetadataTaskState.idle;
|
|
|
|
late final _stateChangedListener =
|
|
|
|
AppEventListener<MetadataTaskStateChangedEvent>(
|
|
|
|
_onMetadataTaskStateChanged);
|
|
|
|
|
|
|
|
static MetadataTaskManager? _inst;
|
|
|
|
}
|
2022-06-07 20:51:37 +02:00
|
|
|
|
|
|
|
class _UpdateMissingMetadataConfigProvider
|
|
|
|
implements UpdateMissingMetadataConfigProvider {
|
|
|
|
const _UpdateMissingMetadataConfigProvider();
|
|
|
|
|
|
|
|
@override
|
|
|
|
isWifiOnly() async => Pref().shouldProcessExifWifiOnlyOr();
|
|
|
|
}
|