2022-04-09 05:23:37 +02:00
|
|
|
import 'package:battery_plus/battery_plus.dart';
|
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';
|
|
|
|
import 'package:nc_photos/connectivity_util.dart' as connectivity_util;
|
|
|
|
import 'package:nc_photos/entity/file.dart';
|
2021-08-15 19:06:00 +02:00
|
|
|
import 'package:nc_photos/event/event.dart';
|
2022-04-08 22:16:35 +02:00
|
|
|
import 'package:nc_photos/exception.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';
|
2021-07-13 06:32:05 +02:00
|
|
|
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
|
|
|
|
2022-06-07 20:51:37 +02:00
|
|
|
abstract class UpdateMissingMetadataConfigProvider {
|
|
|
|
Future<bool> isWifiOnly();
|
|
|
|
}
|
|
|
|
|
2021-04-10 06:28:12 +02:00
|
|
|
class UpdateMissingMetadata {
|
2022-06-07 20:51:37 +02:00
|
|
|
UpdateMissingMetadata(this.fileRepo, this.configProvider);
|
2021-04-10 06:28:12 +02:00
|
|
|
|
2021-12-07 10:03:57 +01:00
|
|
|
/// Update metadata for all files that support one under a dir
|
2021-04-10 06:28:12 +02:00
|
|
|
///
|
2022-02-08 06:50:03 +01:00
|
|
|
/// The returned stream would emit either File data (for each updated files)
|
|
|
|
/// or ExceptionEvent
|
2021-12-07 10:03:57 +01:00
|
|
|
///
|
|
|
|
/// 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;
|
2021-07-16 16:16:12 +02:00
|
|
|
// check if this is a federation share. Nextcloud doesn't support
|
|
|
|
// properties for such files
|
2021-12-07 10:03:57 +01:00
|
|
|
if (file.ownerId?.contains("/") == true || filter?.call(d) == false) {
|
2021-07-16 16:16:12 +02:00
|
|
|
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
|
2022-06-07 07:36:23 +02:00
|
|
|
await _ensureWifi();
|
|
|
|
await _ensureBattery();
|
2021-09-15 08:58:06 +02:00
|
|
|
KiwiContainer().resolve<EventBus>().fire(
|
|
|
|
const MetadataTaskStateChangedEvent(MetadataTaskState.prcoessing));
|
2022-06-07 07:36:23 +02:00
|
|
|
if (!_shouldRun) {
|
2021-04-10 06:28:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
_log.fine("[call] Updating metadata for ${file.path}");
|
2021-07-13 06:32:05 +02:00
|
|
|
final binary = await GetFileBinary(fileRepo)(account, file);
|
2022-04-21 21:18:57 +02:00
|
|
|
final metadata =
|
|
|
|
(await LoadMetadata().loadRemote(account, file, binary)).copyWith(
|
2021-04-10 06:28:12 +02:00
|
|
|
fileEtag: file.etag,
|
|
|
|
);
|
|
|
|
|
2021-11-01 10:50:13 +01:00
|
|
|
await UpdateProperty(fileRepo)(
|
2021-05-28 19:15:09 +02:00
|
|
|
account,
|
|
|
|
file,
|
2022-04-21 21:18:57 +02:00
|
|
|
metadata: OrNull(metadata),
|
2021-05-28 19:15:09 +02:00
|
|
|
);
|
2021-04-10 06:28:12 +02:00
|
|
|
yield file;
|
2022-04-01 18:59:18 +02:00
|
|
|
|
|
|
|
// slow down a bit to give some space for the main isolate
|
|
|
|
await Future.delayed(const Duration(milliseconds: 10));
|
2022-04-08 22:16:35 +02:00
|
|
|
} on InterruptedException catch (_) {
|
|
|
|
return;
|
2021-10-26 16:44:33 +02:00
|
|
|
} catch (e, stackTrace) {
|
2021-07-13 07:24:07 +02:00
|
|
|
_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() {
|
2022-06-07 07:36:23 +02:00
|
|
|
_shouldRun = false;
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|
|
|
|
|
2022-06-07 07:36:23 +02:00
|
|
|
Future<void> _ensureWifi() async {
|
2022-04-08 22:16:35 +02:00
|
|
|
var count = 0;
|
2022-06-07 20:51:37 +02:00
|
|
|
while (await configProvider.isWifiOnly() &&
|
|
|
|
!await connectivity_util.isWifi()) {
|
2022-06-07 07:36:23 +02:00
|
|
|
if (!_shouldRun) {
|
2022-04-08 22:16:35 +02:00
|
|
|
throw const InterruptedException();
|
|
|
|
}
|
|
|
|
// give a chance to reconnect with the WiFi network
|
2022-06-07 13:58:19 +02:00
|
|
|
if (++count >= 6) {
|
2022-04-08 22:16:35 +02:00
|
|
|
KiwiContainer().resolve<EventBus>().fire(
|
|
|
|
const MetadataTaskStateChangedEvent(
|
|
|
|
MetadataTaskState.waitingForWifi));
|
|
|
|
}
|
|
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-07 07:36:23 +02:00
|
|
|
Future<void> _ensureBattery() async {
|
2022-04-09 05:23:37 +02:00
|
|
|
while (await Battery().batteryLevel <= 15) {
|
2022-06-07 07:36:23 +02:00
|
|
|
if (!_shouldRun) {
|
2022-04-09 05:23:37 +02:00
|
|
|
throw const InterruptedException();
|
|
|
|
}
|
|
|
|
KiwiContainer().resolve<EventBus>().fire(
|
|
|
|
const MetadataTaskStateChangedEvent(MetadataTaskState.lowBattery));
|
|
|
|
await Future.delayed(const Duration(seconds: 5));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-10 06:28:12 +02:00
|
|
|
final FileRepo fileRepo;
|
2022-06-07 20:51:37 +02:00
|
|
|
final UpdateMissingMetadataConfigProvider configProvider;
|
2021-04-10 06:28:12 +02:00
|
|
|
|
2022-06-07 07:36:23 +02:00
|
|
|
bool _shouldRun = true;
|
2021-04-10 06:28:12 +02:00
|
|
|
|
|
|
|
static final _log =
|
|
|
|
Logger("use_case.update_missing_metadata.UpdateMissingMetadata");
|
|
|
|
}
|