nc-photos/app/lib/use_case/update_missing_metadata.dart

111 lines
3.7 KiB
Dart
Raw Normal View History

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/connectivity_util.dart' as connectivity_util;
import 'package:nc_photos/entity/exif.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/event/event.dart';
2021-10-26 16:44:33 +02:00
import 'package:nc_photos/exception_event.dart';
2021-05-28 19:15:09 +02:00
import 'package:nc_photos/or_null.dart';
import 'package:nc_photos/use_case/get_file_binary.dart';
import 'package:nc_photos/use_case/load_metadata.dart';
2021-04-10 06:28:12 +02:00
import 'package:nc_photos/use_case/scan_missing_metadata.dart';
2021-05-28 19:15:09 +02:00
import 'package:nc_photos/use_case/update_property.dart';
2021-04-10 06:28:12 +02:00
class UpdateMissingMetadata {
UpdateMissingMetadata(this.fileRepo);
/// Update metadata for all files that support one under a dir
2021-04-10 06:28:12 +02:00
///
/// The returned stream would emit either File data (for each updated files)
/// or ExceptionEvent
///
/// If [isRecursive] is true, [root] and its sub dirs will be scanned,
/// otherwise only [root] will be scanned. Default to true
///
/// [filter] can be used to filter files -- return true if a file should be
/// included. If [filter] is null, all files will be included.
Stream<dynamic> call(
Account account,
File root, {
bool isRecursive = true,
bool Function(File file)? filter,
}) async* {
final dataStream = ScanMissingMetadata(fileRepo)(
account,
root,
isRecursive: isRecursive,
);
2021-04-10 06:28:12 +02:00
await for (final d in dataStream) {
2021-10-26 16:44:33 +02:00
if (d is ExceptionEvent) {
2021-04-10 06:28:12 +02:00
yield d;
continue;
}
2021-05-13 07:18:30 +02:00
final File file = d;
// check if this is a federation share. Nextcloud doesn't support
// properties for such files
if (file.ownerId?.contains("/") == true || filter?.call(d) == false) {
continue;
}
2021-04-10 06:28:12 +02:00
try {
// since we need to download multiple images in their original size,
// we only do it with WiFi
await connectivity_util.waitUntilWifi(onNoWifi: () {
KiwiContainer().resolve<EventBus>().fire(
2021-09-15 08:58:06 +02:00
const MetadataTaskStateChangedEvent(
MetadataTaskState.waitingForWifi));
});
2021-09-15 08:58:06 +02:00
KiwiContainer().resolve<EventBus>().fire(
const MetadataTaskStateChangedEvent(MetadataTaskState.prcoessing));
2021-04-10 06:28:12 +02:00
if (!shouldRun) {
return;
}
_log.fine("[call] Updating metadata for ${file.path}");
final binary = await GetFileBinary(fileRepo)(account, file);
final metadata = await LoadMetadata()(account, file, binary);
2021-07-23 22:05:57 +02:00
int? imageWidth, imageHeight;
Exif? exif;
2021-04-10 06:28:12 +02:00
if (metadata.containsKey("resolution")) {
imageWidth = metadata["resolution"]["width"];
imageHeight = metadata["resolution"]["height"];
}
if (metadata.containsKey("exif")) {
exif = Exif(metadata["exif"]);
}
final metadataObj = Metadata(
fileEtag: file.etag,
imageWidth: imageWidth,
imageHeight: imageHeight,
exif: exif,
);
2021-11-01 10:50:13 +01:00
await UpdateProperty(fileRepo)(
2021-05-28 19:15:09 +02:00
account,
file,
metadata: OrNull(metadataObj),
);
2021-04-10 06:28:12 +02:00
yield file;
// slow down a bit to give some space for the main isolate
await Future.delayed(const Duration(milliseconds: 10));
2021-10-26 16:44:33 +02:00
} catch (e, stackTrace) {
_log.severe("[call] Failed while updating metadata: ${file.path}", e,
2021-10-26 16:44:33 +02:00
stackTrace);
yield ExceptionEvent(e, stackTrace);
2021-04-10 06:28:12 +02:00
}
}
}
void stop() {
shouldRun = false;
}
final FileRepo fileRepo;
bool shouldRun = true;
static final _log =
Logger("use_case.update_missing_metadata.UpdateMissingMetadata");
}