diff --git a/app/lib/api/entity_converter.dart b/app/lib/api/entity_converter.dart index 75f7b28f..bcd80aed 100644 --- a/app/lib/api/entity_converter.dart +++ b/app/lib/api/entity_converter.dart @@ -50,7 +50,7 @@ class ApiFavoriteConverter { class ApiFileConverter { static File fromApi(api.File file) { - final metadata = file.customProperties?["com.nkming.nc_photos:metadata"] + var metadata = file.customProperties?["com.nkming.nc_photos:metadata"] ?.run((obj) => Metadata.fromJson( jsonDecode(obj), upgraderV1: MetadataUpgraderV1( @@ -66,6 +66,15 @@ class ApiFileConverter { logFilePath: file.href, ), )); + if (file.metadataPhotosIfd0 != null) { + final ifd0_metadata = Metadata.fromPhotosIfd0(file.metadataPhotosIfd0!); + if (metadata == null) { + metadata = ifd0_metadata; + } else { + metadata = metadata.copyWith(exif: ifd0_metadata.exif); + } + } + return File( path: _hrefToPath(file.href), contentLength: file.contentLength, diff --git a/app/lib/entity/file.dart b/app/lib/entity/file.dart index e2b03858..f88834db 100644 --- a/app/lib/entity/file.dart +++ b/app/lib/entity/file.dart @@ -185,6 +185,16 @@ class Metadata with EquatableMixin { ); } + static Metadata fromPhotosIfd0(Map metadataPhotosIfd0) { + return Metadata( + lastUpdated: null, + fileEtag: null, + imageWidth: null, + imageHeight: null, + exif: new Exif(metadataPhotosIfd0), + ); + } + @override String toString() => _$toString(); diff --git a/app/lib/entity/file/data_source.dart b/app/lib/entity/file/data_source.dart index 8a67ab95..6c87f137 100644 --- a/app/lib/entity/file/data_source.dart +++ b/app/lib/entity/file/data_source.dart @@ -55,6 +55,7 @@ class FileWebdavDataSource implements FileDataSource { trashbinFilename: 1, trashbinOriginalLocation: 1, trashbinDeletionTime: 1, + metadataPhotosIfd0: 1, customNamespaces: { "com.nkming.nc_photos": "app", }, @@ -275,6 +276,7 @@ class FileWebdavDataSource implements FileDataSource { trashbinFilename, trashbinOriginalLocation, trashbinDeletionTime, + metadataPhotosIfd0, Map? customNamespaces, List? customProperties, }) async { @@ -302,6 +304,7 @@ class FileWebdavDataSource implements FileDataSource { trashbinFilename: trashbinFilename, trashbinOriginalLocation: trashbinOriginalLocation, trashbinDeletionTime: trashbinDeletionTime, + metadataPhotosIfd0: metadataPhotosIfd0, customNamespaces: customNamespaces, customProperties: customProperties, ); diff --git a/np_api/lib/src/entity/entity.dart b/np_api/lib/src/entity/entity.dart index 20eea6e0..f73a35cb 100644 --- a/np_api/lib/src/entity/entity.dart +++ b/np_api/lib/src/entity/entity.dart @@ -84,6 +84,7 @@ class File with EquatableMixin { this.trashbinFilename, this.trashbinOriginalLocation, this.trashbinDeletionTime, + this.metadataPhotosIfd0, this.customProperties, }); @@ -106,6 +107,7 @@ class File with EquatableMixin { trashbinFilename, trashbinOriginalLocation, trashbinDeletionTime, + metadataPhotosIfd0, customProperties, ]; @@ -123,6 +125,7 @@ class File with EquatableMixin { final String? trashbinFilename; final String? trashbinOriginalLocation; final DateTime? trashbinDeletionTime; + final Map? metadataPhotosIfd0; final Map? customProperties; } diff --git a/np_api/lib/src/entity/file_parser.dart b/np_api/lib/src/entity/file_parser.dart index 8dc18c66..933af39f 100644 --- a/np_api/lib/src/entity/file_parser.dart +++ b/np_api/lib/src/entity/file_parser.dart @@ -33,6 +33,7 @@ class FileParser extends XmlResponseParser { String? trashbinFilename; String? trashbinOriginalLocation; DateTime? trashbinDeletionTime; + Map? metadataPhotosIfd0; Map? customProperties; for (final child in element.children.whereType()) { @@ -66,6 +67,7 @@ class FileParser extends XmlResponseParser { trashbinFilename = propParser.trashbinFilename; trashbinOriginalLocation = propParser.trashbinOriginalLocation; trashbinDeletionTime = propParser.trashbinDeletionTime; + metadataPhotosIfd0 = propParser.metadataPhotosIfd0; customProperties = propParser.customProperties; } } @@ -85,6 +87,7 @@ class FileParser extends XmlResponseParser { trashbinFilename: trashbinFilename, trashbinOriginalLocation: trashbinOriginalLocation, trashbinDeletionTime: trashbinDeletionTime, + metadataPhotosIfd0: metadataPhotosIfd0, customProperties: customProperties, ); } @@ -140,6 +143,11 @@ class _PropParser { prefix: "http://nextcloud.org/ns", namespaces: namespaces)) { _trashbinDeletionTime = DateTime.fromMillisecondsSinceEpoch( int.parse(child.innerText) * 1000); + } else if (child.matchQualifiedName("metadata-photos-ifd0", + prefix: "http://nextcloud.org/ns", namespaces: namespaces)) { + for (final ifd0_child in child.children.whereType()) { + (_metadataPhotosIfd0 ??= {})[ifd0_child.name.toString()] = ifd0_child.innerText; + } } else { final key = child.name.prefix == null ? child.localName @@ -162,6 +170,7 @@ class _PropParser { String? get trashbinFilename => _trashbinFilename; String? get trashbinOriginalLocation => _trashbinOriginalLocation; DateTime? get trashbinDeletionTime => _trashbinDeletionTime; + Map? get metadataPhotosIfd0 => _metadataPhotosIfd0; Map? get customProperties => _customProperties; final Map namespaces; @@ -179,6 +188,7 @@ class _PropParser { String? _trashbinFilename; String? _trashbinOriginalLocation; DateTime? _trashbinDeletionTime; + Map? _metadataPhotosIfd0; Map? _customProperties; } diff --git a/np_api/lib/src/files_api.dart b/np_api/lib/src/files_api.dart index 656a143e..1f947970 100644 --- a/np_api/lib/src/files_api.dart +++ b/np_api/lib/src/files_api.dart @@ -72,6 +72,7 @@ class ApiFiles { trashbinFilename, trashbinOriginalLocation, trashbinDeletionTime, + metadataPhotosIfd0, Map? customNamespaces, List? customProperties, }) async { @@ -96,7 +97,8 @@ class ApiFiles { richWorkspace != null || trashbinFilename != null || trashbinOriginalLocation != null || - trashbinDeletionTime != null); + trashbinDeletionTime != null || + metadataPhotosIfd0 != null); if (!hasDavNs && !hasOcNs && !hasNcNs) { // no body return await _api.request("PROPFIND", path); @@ -175,6 +177,9 @@ class ApiFiles { if (trashbinDeletionTime != null) { builder.element("nc:trashbin-deletion-time"); } + if (metadataPhotosIfd0 != null) { + builder.element("nc:metadata-photos-ifd0"); + } for (final p in customProperties ?? []) { builder.element(p); }