Merge branch 'tintou/nextcloud-exif' into 'dev-nc28-exif'

Use the EXIF data provided by Nextcloud Photos

See merge request nkming2/nc-photos!75
This commit is contained in:
ming 2024-11-03 08:25:39 +00:00
commit 09ff2ec54a
6 changed files with 42 additions and 2 deletions

View file

@ -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,

View file

@ -185,6 +185,16 @@ class Metadata with EquatableMixin {
);
}
static Metadata fromPhotosIfd0(Map<String, String> metadataPhotosIfd0) {
return Metadata(
lastUpdated: null,
fileEtag: null,
imageWidth: null,
imageHeight: null,
exif: new Exif(metadataPhotosIfd0),
);
}
@override
String toString() => _$toString();

View file

@ -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<String, String>? customNamespaces,
List<String>? customProperties,
}) async {
@ -302,6 +304,7 @@ class FileWebdavDataSource implements FileDataSource {
trashbinFilename: trashbinFilename,
trashbinOriginalLocation: trashbinOriginalLocation,
trashbinDeletionTime: trashbinDeletionTime,
metadataPhotosIfd0: metadataPhotosIfd0,
customNamespaces: customNamespaces,
customProperties: customProperties,
);

View file

@ -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<String, String>? metadataPhotosIfd0;
final Map<String, String>? customProperties;
}

View file

@ -33,6 +33,7 @@ class FileParser extends XmlResponseParser {
String? trashbinFilename;
String? trashbinOriginalLocation;
DateTime? trashbinDeletionTime;
Map<String, String>? metadataPhotosIfd0;
Map<String, String>? customProperties;
for (final child in element.children.whereType<XmlElement>()) {
@ -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<XmlElement>()) {
(_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<String, String>? get metadataPhotosIfd0 => _metadataPhotosIfd0;
Map<String, String>? get customProperties => _customProperties;
final Map<String, String> namespaces;
@ -179,6 +188,7 @@ class _PropParser {
String? _trashbinFilename;
String? _trashbinOriginalLocation;
DateTime? _trashbinDeletionTime;
Map<String, String>? _metadataPhotosIfd0;
Map<String, String>? _customProperties;
}

View file

@ -72,6 +72,7 @@ class ApiFiles {
trashbinFilename,
trashbinOriginalLocation,
trashbinDeletionTime,
metadataPhotosIfd0,
Map<String, String>? customNamespaces,
List<String>? 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);
}