Fallback to our metadata extractor if file not supported by nextcloud server

This commit is contained in:
Ming Ming 2024-11-23 00:43:36 +08:00
parent 114b52d0e9
commit c1915b393a
3 changed files with 57 additions and 28 deletions

View file

@ -34,8 +34,12 @@ class _SyncByApp {
account: account.toDb(),
fileIds: fileIds,
);
for (final f in files) {
final result = await _syncOne(f);
for (final dbF in files) {
final f = DbFileConverter.fromDb(
account.userId.toCaseInsensitiveString(),
dbF,
);
final result = await syncOne(f);
if (result != null) {
yield result;
}
@ -45,16 +49,12 @@ class _SyncByApp {
}
}
Future<File?> _syncOne(DbFile file) async {
final f = DbFileConverter.fromDb(
account.userId.toCaseInsensitiveString(),
file,
);
_log.fine("[_syncOne] Syncing ${file.relativePath}");
Future<File?> syncOne(File file) async {
_log.fine("[syncOne] Syncing ${file.path}");
try {
OrNull<Metadata>? metadataUpdate;
OrNull<ImageLocation>? locationUpdate;
if (f.metadata == null) {
if (file.metadata == null) {
// since we need to download multiple images in their original size,
// we only do it with WiFi
await wifiEnsurer();
@ -62,21 +62,21 @@ class _SyncByApp {
if (!_shouldRun) {
return null;
}
_log.fine("[_syncOne] Updating metadata for ${f.path}");
final binary = await GetFileBinary(fileRepo)(account, f);
_log.fine("[syncOne] Updating metadata for ${file.path}");
final binary = await GetFileBinary(fileRepo)(account, file);
final metadata =
(await LoadMetadata().loadRemote(account, f, binary)).copyWith(
fileEtag: f.etag,
(await LoadMetadata().loadRemote(account, file, binary)).copyWith(
fileEtag: file.etag,
);
metadataUpdate = OrNull(metadata);
}
final lat = (metadataUpdate?.obj ?? f.metadata)?.exif?.gpsLatitudeDeg;
final lng = (metadataUpdate?.obj ?? f.metadata)?.exif?.gpsLongitudeDeg;
final lat = (metadataUpdate?.obj ?? file.metadata)?.exif?.gpsLatitudeDeg;
final lng = (metadataUpdate?.obj ?? file.metadata)?.exif?.gpsLongitudeDeg;
try {
ImageLocation? location;
if (lat != null && lng != null) {
_log.fine("[_syncOne] Reverse geocoding for ${f.path}");
_log.fine("[syncOne] Reverse geocoding for ${file.path}");
final l = await _geocoder(lat, lng);
if (l != null) {
location = l.toImageLocation();
@ -84,7 +84,7 @@ class _SyncByApp {
}
locationUpdate = OrNull(location ?? ImageLocation.empty());
} catch (e, stackTrace) {
_log.severe("[_syncOne] Failed while reverse geocoding: ${f.path}", e,
_log.severe("[syncOne] Failed while reverse geocoding: ${file.path}", e,
stackTrace);
// if failed, we skip updating the location
}
@ -92,16 +92,16 @@ class _SyncByApp {
if (metadataUpdate != null || locationUpdate != null) {
await UpdateProperty(fileRepo: fileRepo2)(
account,
f,
file,
metadata: metadataUpdate,
location: locationUpdate,
);
return f;
return file;
} else {
return null;
}
} catch (e, stackTrace) {
_log.severe("[_syncOne] Failed while updating metadata: ${f.path}", e,
_log.severe("[syncOne] Failed while updating metadata: ${file.path}", e,
stackTrace);
return null;
}

View file

@ -9,6 +9,7 @@ class _SyncByServer {
required this.fileRepo2,
required this.db,
this.interrupter,
required this.fallback,
}) {
interrupter?.listen((event) {
_shouldRun = false;
@ -20,17 +21,20 @@ class _SyncByServer {
}
Stream<File> syncFiles({
required List<int> fileIds,
required List<String> relativePaths,
}) async* {
final dirs = relativePaths.map(dirname).toSet();
for (final dir in dirs) {
yield* _syncDir(
fileIds: fileIds,
dir: File(path: file_util.unstripPath(account, dir)),
);
}
}
Stream<File> _syncDir({
required List<int> fileIds,
required File dir,
}) async* {
try {
@ -38,15 +42,22 @@ class _SyncByServer {
final files = await fileRepoRemote.list(account, dir);
await FileSqliteCacheUpdater(db)(account, dir, remote: files);
for (final f in files) {
if (f.metadata != null && f.location == null) {
final result = await _syncOne(f);
if (result != null) {
yield result;
}
if (!_shouldRun) {
return;
File? result;
if (!_supportedMimes.contains(f.fdMime)) {
_log.info(
"[_syncDir] File ${f.path} (mime: ${f.fdMime}) not supported by server, fallback to client");
result = await fallback.syncOne(f);
} else {
if (f.metadata != null && f.location == null) {
result = await _syncOne(f);
}
}
if (result != null) {
yield result;
}
if (!_shouldRun) {
return;
}
}
} catch (e, stackTrace) {
_log.severe("[_syncDir] Failed to sync dir: $dir", e, stackTrace);
@ -54,6 +65,7 @@ class _SyncByServer {
}
Future<File?> _syncOne(File file) async {
_log.fine("[_syncOne] Syncing ${file.path}");
try {
final lat = file.metadata!.exif?.gpsLatitudeDeg;
final lng = file.metadata!.exif?.gpsLongitudeDeg;
@ -85,7 +97,13 @@ class _SyncByServer {
final FileRepo2 fileRepo2;
final NpDb db;
final Stream<void>? interrupter;
final _SyncByApp fallback;
final _geocoder = ReverseGeocoder();
var _shouldRun = true;
static const _supportedMimes = [
"image/jpeg",
"image/webp",
];
}

View file

@ -48,7 +48,7 @@ class SyncMetadata {
}
final files = await db.getFilesByMissingMetadata(
account: account.toDb(),
mimes: file_util.metadataSupportedFormatMimes,
mimes: file_util.supportedImageFormatMimes,
ownerId: account.userId.toCaseInsensitiveString(),
);
_log.info("[syncAccount] Missing count: ${files.items.length}");
@ -79,12 +79,23 @@ class SyncMetadata {
Stream<File> _doWithServer(
Account account, DbFileMissingMetadataResult files) async* {
final fallback = _SyncByApp(
account: account,
fileRepo: fileRepo,
fileRepo2: fileRepo2,
db: db,
interrupter: interrupter,
wifiEnsurer: wifiEnsurer,
batteryEnsurer: batteryEnsurer,
);
await fallback.init();
final op = _SyncByServer(
account: account,
fileRepoRemote: fileRepoRemote,
fileRepo2: fileRepo2,
db: db,
interrupter: interrupter,
fallback: fallback,
);
await op.init();
final stream = op.syncFiles(