mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 16:56:19 +01:00
Fallback to our metadata extractor if file not supported by nextcloud server
This commit is contained in:
parent
114b52d0e9
commit
c1915b393a
3 changed files with 57 additions and 28 deletions
|
@ -34,8 +34,12 @@ class _SyncByApp {
|
||||||
account: account.toDb(),
|
account: account.toDb(),
|
||||||
fileIds: fileIds,
|
fileIds: fileIds,
|
||||||
);
|
);
|
||||||
for (final f in files) {
|
for (final dbF in files) {
|
||||||
final result = await _syncOne(f);
|
final f = DbFileConverter.fromDb(
|
||||||
|
account.userId.toCaseInsensitiveString(),
|
||||||
|
dbF,
|
||||||
|
);
|
||||||
|
final result = await syncOne(f);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
yield result;
|
yield result;
|
||||||
}
|
}
|
||||||
|
@ -45,16 +49,12 @@ class _SyncByApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> _syncOne(DbFile file) async {
|
Future<File?> syncOne(File file) async {
|
||||||
final f = DbFileConverter.fromDb(
|
_log.fine("[syncOne] Syncing ${file.path}");
|
||||||
account.userId.toCaseInsensitiveString(),
|
|
||||||
file,
|
|
||||||
);
|
|
||||||
_log.fine("[_syncOne] Syncing ${file.relativePath}");
|
|
||||||
try {
|
try {
|
||||||
OrNull<Metadata>? metadataUpdate;
|
OrNull<Metadata>? metadataUpdate;
|
||||||
OrNull<ImageLocation>? locationUpdate;
|
OrNull<ImageLocation>? locationUpdate;
|
||||||
if (f.metadata == null) {
|
if (file.metadata == null) {
|
||||||
// since we need to download multiple images in their original size,
|
// since we need to download multiple images in their original size,
|
||||||
// we only do it with WiFi
|
// we only do it with WiFi
|
||||||
await wifiEnsurer();
|
await wifiEnsurer();
|
||||||
|
@ -62,21 +62,21 @@ class _SyncByApp {
|
||||||
if (!_shouldRun) {
|
if (!_shouldRun) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
_log.fine("[_syncOne] Updating metadata for ${f.path}");
|
_log.fine("[syncOne] Updating metadata for ${file.path}");
|
||||||
final binary = await GetFileBinary(fileRepo)(account, f);
|
final binary = await GetFileBinary(fileRepo)(account, file);
|
||||||
final metadata =
|
final metadata =
|
||||||
(await LoadMetadata().loadRemote(account, f, binary)).copyWith(
|
(await LoadMetadata().loadRemote(account, file, binary)).copyWith(
|
||||||
fileEtag: f.etag,
|
fileEtag: file.etag,
|
||||||
);
|
);
|
||||||
metadataUpdate = OrNull(metadata);
|
metadataUpdate = OrNull(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
final lat = (metadataUpdate?.obj ?? f.metadata)?.exif?.gpsLatitudeDeg;
|
final lat = (metadataUpdate?.obj ?? file.metadata)?.exif?.gpsLatitudeDeg;
|
||||||
final lng = (metadataUpdate?.obj ?? f.metadata)?.exif?.gpsLongitudeDeg;
|
final lng = (metadataUpdate?.obj ?? file.metadata)?.exif?.gpsLongitudeDeg;
|
||||||
try {
|
try {
|
||||||
ImageLocation? location;
|
ImageLocation? location;
|
||||||
if (lat != null && lng != null) {
|
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);
|
final l = await _geocoder(lat, lng);
|
||||||
if (l != null) {
|
if (l != null) {
|
||||||
location = l.toImageLocation();
|
location = l.toImageLocation();
|
||||||
|
@ -84,7 +84,7 @@ class _SyncByApp {
|
||||||
}
|
}
|
||||||
locationUpdate = OrNull(location ?? ImageLocation.empty());
|
locationUpdate = OrNull(location ?? ImageLocation.empty());
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.severe("[_syncOne] Failed while reverse geocoding: ${f.path}", e,
|
_log.severe("[syncOne] Failed while reverse geocoding: ${file.path}", e,
|
||||||
stackTrace);
|
stackTrace);
|
||||||
// if failed, we skip updating the location
|
// if failed, we skip updating the location
|
||||||
}
|
}
|
||||||
|
@ -92,16 +92,16 @@ class _SyncByApp {
|
||||||
if (metadataUpdate != null || locationUpdate != null) {
|
if (metadataUpdate != null || locationUpdate != null) {
|
||||||
await UpdateProperty(fileRepo: fileRepo2)(
|
await UpdateProperty(fileRepo: fileRepo2)(
|
||||||
account,
|
account,
|
||||||
f,
|
file,
|
||||||
metadata: metadataUpdate,
|
metadata: metadataUpdate,
|
||||||
location: locationUpdate,
|
location: locationUpdate,
|
||||||
);
|
);
|
||||||
return f;
|
return file;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.severe("[_syncOne] Failed while updating metadata: ${f.path}", e,
|
_log.severe("[syncOne] Failed while updating metadata: ${file.path}", e,
|
||||||
stackTrace);
|
stackTrace);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ class _SyncByServer {
|
||||||
required this.fileRepo2,
|
required this.fileRepo2,
|
||||||
required this.db,
|
required this.db,
|
||||||
this.interrupter,
|
this.interrupter,
|
||||||
|
required this.fallback,
|
||||||
}) {
|
}) {
|
||||||
interrupter?.listen((event) {
|
interrupter?.listen((event) {
|
||||||
_shouldRun = false;
|
_shouldRun = false;
|
||||||
|
@ -20,17 +21,20 @@ class _SyncByServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<File> syncFiles({
|
Stream<File> syncFiles({
|
||||||
|
required List<int> fileIds,
|
||||||
required List<String> relativePaths,
|
required List<String> relativePaths,
|
||||||
}) async* {
|
}) async* {
|
||||||
final dirs = relativePaths.map(dirname).toSet();
|
final dirs = relativePaths.map(dirname).toSet();
|
||||||
for (final dir in dirs) {
|
for (final dir in dirs) {
|
||||||
yield* _syncDir(
|
yield* _syncDir(
|
||||||
|
fileIds: fileIds,
|
||||||
dir: File(path: file_util.unstripPath(account, dir)),
|
dir: File(path: file_util.unstripPath(account, dir)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<File> _syncDir({
|
Stream<File> _syncDir({
|
||||||
|
required List<int> fileIds,
|
||||||
required File dir,
|
required File dir,
|
||||||
}) async* {
|
}) async* {
|
||||||
try {
|
try {
|
||||||
|
@ -38,8 +42,16 @@ class _SyncByServer {
|
||||||
final files = await fileRepoRemote.list(account, dir);
|
final files = await fileRepoRemote.list(account, dir);
|
||||||
await FileSqliteCacheUpdater(db)(account, dir, remote: files);
|
await FileSqliteCacheUpdater(db)(account, dir, remote: files);
|
||||||
for (final f in files) {
|
for (final f in files) {
|
||||||
|
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) {
|
if (f.metadata != null && f.location == null) {
|
||||||
final result = await _syncOne(f);
|
result = await _syncOne(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
yield result;
|
yield result;
|
||||||
}
|
}
|
||||||
|
@ -47,13 +59,13 @@ class _SyncByServer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (e, stackTrace) {
|
} catch (e, stackTrace) {
|
||||||
_log.severe("[_syncDir] Failed to sync dir: $dir", e, stackTrace);
|
_log.severe("[_syncDir] Failed to sync dir: $dir", e, stackTrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> _syncOne(File file) async {
|
Future<File?> _syncOne(File file) async {
|
||||||
|
_log.fine("[_syncOne] Syncing ${file.path}");
|
||||||
try {
|
try {
|
||||||
final lat = file.metadata!.exif?.gpsLatitudeDeg;
|
final lat = file.metadata!.exif?.gpsLatitudeDeg;
|
||||||
final lng = file.metadata!.exif?.gpsLongitudeDeg;
|
final lng = file.metadata!.exif?.gpsLongitudeDeg;
|
||||||
|
@ -85,7 +97,13 @@ class _SyncByServer {
|
||||||
final FileRepo2 fileRepo2;
|
final FileRepo2 fileRepo2;
|
||||||
final NpDb db;
|
final NpDb db;
|
||||||
final Stream<void>? interrupter;
|
final Stream<void>? interrupter;
|
||||||
|
final _SyncByApp fallback;
|
||||||
|
|
||||||
final _geocoder = ReverseGeocoder();
|
final _geocoder = ReverseGeocoder();
|
||||||
var _shouldRun = true;
|
var _shouldRun = true;
|
||||||
|
|
||||||
|
static const _supportedMimes = [
|
||||||
|
"image/jpeg",
|
||||||
|
"image/webp",
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class SyncMetadata {
|
||||||
}
|
}
|
||||||
final files = await db.getFilesByMissingMetadata(
|
final files = await db.getFilesByMissingMetadata(
|
||||||
account: account.toDb(),
|
account: account.toDb(),
|
||||||
mimes: file_util.metadataSupportedFormatMimes,
|
mimes: file_util.supportedImageFormatMimes,
|
||||||
ownerId: account.userId.toCaseInsensitiveString(),
|
ownerId: account.userId.toCaseInsensitiveString(),
|
||||||
);
|
);
|
||||||
_log.info("[syncAccount] Missing count: ${files.items.length}");
|
_log.info("[syncAccount] Missing count: ${files.items.length}");
|
||||||
|
@ -79,12 +79,23 @@ class SyncMetadata {
|
||||||
|
|
||||||
Stream<File> _doWithServer(
|
Stream<File> _doWithServer(
|
||||||
Account account, DbFileMissingMetadataResult files) async* {
|
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(
|
final op = _SyncByServer(
|
||||||
account: account,
|
account: account,
|
||||||
fileRepoRemote: fileRepoRemote,
|
fileRepoRemote: fileRepoRemote,
|
||||||
fileRepo2: fileRepo2,
|
fileRepo2: fileRepo2,
|
||||||
db: db,
|
db: db,
|
||||||
interrupter: interrupter,
|
interrupter: interrupter,
|
||||||
|
fallback: fallback,
|
||||||
);
|
);
|
||||||
await op.init();
|
await op.init();
|
||||||
final stream = op.syncFiles(
|
final stream = op.syncFiles(
|
||||||
|
|
Loading…
Reference in a new issue