diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt index 715b155b5..d42e5ea50 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt @@ -12,7 +12,7 @@ import com.drew.metadata.xmp.XmpDirectory import deckers.thibault.aves.channel.calls.Coresult.Companion.safe import deckers.thibault.aves.channel.calls.Coresult.Companion.safeSuspend import deckers.thibault.aves.metadata.* -import deckers.thibault.aves.metadata.XMP.doesPropExist +import deckers.thibault.aves.metadata.XMP.doesPropPathExist import deckers.thibault.aves.metadata.XMP.getSafeStructField import deckers.thibault.aves.metadata.metadataextractor.Helper import deckers.thibault.aves.model.FieldMap @@ -104,7 +104,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler { try { container = xmpDirs.firstNotNullOfOrNull { val xmpMeta = it.xmpMeta - if (xmpMeta.doesPropExist(XMP.GDEVICE_DIRECTORY_PROP_NAME)) { + if (xmpMeta.doesPropPathExist(listOf(XMP.GDEVICE_CONTAINER_PROP_NAME, XMP.GDEVICE_CONTAINER_DIRECTORY_PROP_NAME))) { GoogleDeviceContainer().apply { findItems(xmpMeta) } } else { null diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/GoogleDeviceContainer.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/GoogleDeviceContainer.kt index 590b1f65d..a481c94e4 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/GoogleDeviceContainer.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/GoogleDeviceContainer.kt @@ -3,7 +3,7 @@ package deckers.thibault.aves.metadata import android.content.Context import android.net.Uri import com.adobe.internal.xmp.XMPMeta -import deckers.thibault.aves.metadata.XMP.countPropArrayItems +import deckers.thibault.aves.metadata.XMP.countPropPathArrayItems import deckers.thibault.aves.metadata.XMP.getSafeStructField import deckers.thibault.aves.utils.indexOfBytes import java.io.DataInputStream @@ -15,11 +15,12 @@ class GoogleDeviceContainer { private val offsets: MutableList = ArrayList() fun findItems(xmpMeta: XMPMeta) { - val count = xmpMeta.countPropArrayItems(XMP.GDEVICE_DIRECTORY_PROP_NAME) + val containerDirectoryPath = listOf(XMP.GDEVICE_CONTAINER_PROP_NAME, XMP.GDEVICE_CONTAINER_DIRECTORY_PROP_NAME) + val count = xmpMeta.countPropPathArrayItems(containerDirectoryPath) for (i in 1 until count + 1) { - val mimeType = xmpMeta.getSafeStructField(listOf(XMP.GDEVICE_DIRECTORY_PROP_NAME, i, XMP.GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME))?.value - val length = xmpMeta.getSafeStructField(listOf(XMP.GDEVICE_DIRECTORY_PROP_NAME, i, XMP.GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME))?.value?.toLongOrNull() - val dataUri = xmpMeta.getSafeStructField(listOf(XMP.GDEVICE_DIRECTORY_PROP_NAME, i, XMP.GDEVICE_CONTAINER_ITEM_DATA_URI_PROP_NAME))?.value + val mimeType = xmpMeta.getSafeStructField(containerDirectoryPath + listOf(i, XMP.GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME))?.value + val length = xmpMeta.getSafeStructField(containerDirectoryPath + listOf(i, XMP.GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME))?.value?.toLongOrNull() + val dataUri = xmpMeta.getSafeStructField(containerDirectoryPath + listOf(i, XMP.GDEVICE_CONTAINER_ITEM_DATA_URI_PROP_NAME))?.value if (mimeType != null && length != null && dataUri != null) { items.add( GoogleDeviceContainerItem( diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt index 737c862da..e170e9bbc 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt @@ -49,6 +49,7 @@ object XMP { private const val GCONTAINER_ITEM_NS_URI = "http://ns.google.com/photos/1.0/container/item/" private const val GDEPTH_NS_URI = "http://ns.google.com/photos/1.0/depthmap/" private const val GDEVICE_NS_URI = "http://ns.google.com/photos/dd/1.0/device/" + private const val GDEVICE_CONTAINER_NS_URI = "http://ns.google.com/photos/dd/1.0/container/" private const val GDEVICE_ITEM_NS_URI = "http://ns.google.com/photos/dd/1.0/item/" private const val GIMAGE_NS_URI = "http://ns.google.com/photos/1.0/image/" private const val GPANO_NS_URI = "http://ns.google.com/photos/1.0/panorama/" @@ -79,7 +80,8 @@ object XMP { // google portrait - val GDEVICE_DIRECTORY_PROP_NAME = XMPPropName(GDEVICE_NS_URI, "Container/Container:Directory") + val GDEVICE_CONTAINER_PROP_NAME = XMPPropName(GDEVICE_NS_URI, "Container") + val GDEVICE_CONTAINER_DIRECTORY_PROP_NAME = XMPPropName(GDEVICE_CONTAINER_NS_URI, "Directory") val GDEVICE_CONTAINER_ITEM_DATA_URI_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "DataURI") val GDEVICE_CONTAINER_ITEM_LENGTH_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "Length") val GDEVICE_CONTAINER_ITEM_MIME_PROP_NAME = XMPPropName(GDEVICE_ITEM_NS_URI, "Mime") @@ -254,10 +256,18 @@ object XMP { return doesPropertyExist(prop.nsUri, prop.toString()) } + fun XMPMeta.doesPropPathExist(props: List): Boolean { + return doesPropertyExist(props.first().nsUri, props.joinToString("/")) + } + fun XMPMeta.countPropArrayItems(prop: XMPPropName): Int { return countArrayItems(prop.nsUri, prop.toString()) } + fun XMPMeta.countPropPathArrayItems(props: List): Int { + return countArrayItems(props.first().nsUri, props.joinToString("/")) + } + fun XMPMeta.getPropArrayItemValues(prop: XMPPropName): List { val schema = prop.nsUri val propName = prop.toString() diff --git a/lib/model/entry_metadata_edition.dart b/lib/model/entry_metadata_edition.dart index 7aa91fae6..cd592f02b 100644 --- a/lib/model/entry_metadata_edition.dart +++ b/lib/model/entry_metadata_edition.dart @@ -463,7 +463,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { modified |= XMP.removeElements( descriptions, XMP.containerDirectory, - Namespaces.container, + Namespaces.gContainer, ); modified |= [ diff --git a/lib/utils/xmp_utils.dart b/lib/utils/xmp_utils.dart index 72f2b3515..f660e51d6 100644 --- a/lib/utils/xmp_utils.dart +++ b/lib/utils/xmp_utils.dart @@ -7,7 +7,6 @@ class Namespaces { static const avm = 'http://www.communicatingastronomy.org/avm/1.0/'; static const camera = 'http://pix4d.com/camera/1.0/'; static const cc = 'http://creativecommons.org/ns#'; - static const container = 'http://ns.google.com/photos/1.0/container/'; static const creatorAtom = 'http://ns.adobe.com/creatorAtom/1.0/'; static const crd = 'http://ns.adobe.com/camera-raw-defaults/1.0/'; static const crlcp = 'http://ns.adobe.com/camera-raw-embedded-lens-profile/1.0/'; @@ -26,9 +25,13 @@ class Namespaces { static const exifEx = 'http://cipa.jp/exif/1.0/'; static const gAudio = 'http://ns.google.com/photos/1.0/audio/'; static const gCamera = 'http://ns.google.com/photos/1.0/camera/'; + static const gContainer = 'http://ns.google.com/photos/1.0/container/'; static const gCreations = 'http://ns.google.com/photos/1.0/creations/'; static const gDepth = 'http://ns.google.com/photos/1.0/depthmap/'; static const gDevice = 'http://ns.google.com/photos/dd/1.0/device/'; + static const gDeviceCamera = 'http://ns.google.com/photos/dd/1.0/camera/'; + static const gDeviceContainer = 'http://ns.google.com/photos/dd/1.0/container/'; + static const gDeviceItem = 'http://ns.google.com/photos/dd/1.0/item/'; static const gFocus = 'http://ns.google.com/photos/1.0/focus/'; static const gImage = 'http://ns.google.com/photos/1.0/image/'; static const gPano = 'http://ns.google.com/photos/1.0/panorama/'; @@ -83,7 +86,6 @@ class Namespaces { avm: 'Astronomy Visualization', camera: 'Pix4D Camera', cc: 'Creative Commons', - container: 'Container', crd: 'Camera Raw Defaults', creatorAtom: 'After Effects', crs: 'Camera Raw Settings', @@ -97,6 +99,7 @@ class Namespaces { exifEx: 'Exif Ex', gAudio: 'Google Audio', gCamera: 'Google Camera', + gContainer: 'Google Container', gCreations: 'Google Creations', gDepth: 'Google Depth', gDevice: 'Google Device', @@ -138,7 +141,7 @@ class Namespaces { }; static final defaultPrefixes = { - container: 'Container', + gContainer: 'Container', dc: 'dc', gCamera: 'GCamera', microsoftPhoto: 'MicrosoftPhoto', diff --git a/lib/widgets/viewer/info/metadata/xmp_namespaces.dart b/lib/widgets/viewer/info/metadata/xmp_namespaces.dart index 1a92214f0..664b69d61 100644 --- a/lib/widgets/viewer/info/metadata/xmp_namespaces.dart +++ b/lib/widgets/viewer/info/metadata/xmp_namespaces.dart @@ -22,56 +22,62 @@ import 'package:tuple/tuple.dart'; @immutable class XmpNamespace extends Equatable { + final Map schemaRegistryPrefixes; final String nsUri, nsPrefix; final Map rawProps; @override List get props => [nsUri, nsPrefix]; - const XmpNamespace(this.nsUri, this.nsPrefix, this.rawProps); + XmpNamespace({ + required this.nsUri, + required this.schemaRegistryPrefixes, + required this.rawProps, + }) : nsPrefix = prefixForUri(schemaRegistryPrefixes, nsUri); - factory XmpNamespace.create(String nsUri, String nsPrefix, Map rawProps) { + factory XmpNamespace.create(Map schemaRegistryPrefixes, String nsPrefix, Map rawProps) { + final nsUri = schemaRegistryPrefixes[nsPrefix] ?? ''; switch (nsUri) { - case Namespaces.container: - return XmpContainer(nsPrefix, rawProps); case Namespaces.creatorAtom: - return XmpCreatorAtom(nsPrefix, rawProps); + return XmpCreatorAtom(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.crs: - return XmpCrsNamespace(nsPrefix, rawProps); + return XmpCrsNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.darktable: - return XmpDarktableNamespace(nsPrefix, rawProps); + return XmpDarktableNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.dwc: - return XmpDwcNamespace(nsPrefix, rawProps); + return XmpDwcNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.exif: - return XmpExifNamespace(nsPrefix, rawProps); + return XmpExifNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.gAudio: - return XmpGAudioNamespace(nsPrefix, rawProps); + return XmpGAudioNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); + case Namespaces.gContainer: + return XmpGContainer(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.gDepth: - return XmpGDepthNamespace(nsPrefix, rawProps); + return XmpGDepthNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.gDevice: - return XmpGDeviceNamespace(nsPrefix, rawProps); + return XmpGDeviceNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.gImage: - return XmpGImageNamespace(nsPrefix, rawProps); + return XmpGImageNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.iptc4xmpCore: - return XmpIptcCoreNamespace(nsPrefix, rawProps); + return XmpIptcCoreNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.iptc4xmpExt: - return XmpIptc4xmpExtNamespace(nsPrefix, rawProps); + return XmpIptc4xmpExtNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.mwgrs: - return XmpMgwRegionsNamespace(nsPrefix, rawProps); + return XmpMgwRegionsNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.mp: - return XmpMPNamespace(nsPrefix, rawProps); + return XmpMPNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.photoshop: - return XmpPhotoshopNamespace(nsPrefix, rawProps); + return XmpPhotoshopNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.plus: - return XmpPlusNamespace(nsPrefix, rawProps); + return XmpPlusNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.tiff: - return XmpTiffNamespace(nsPrefix, rawProps); + return XmpTiffNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.xmp: - return XmpBasicNamespace(nsPrefix, rawProps); + return XmpBasicNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); case Namespaces.xmpMM: - return XmpMMNamespace(nsPrefix, rawProps); + return XmpMMNamespace(schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); default: - return XmpNamespace(nsUri, nsPrefix, rawProps); + return XmpNamespace(nsUri: nsUri, schemaRegistryPrefixes: schemaRegistryPrefixes, rawProps: rawProps); } } @@ -130,6 +136,8 @@ class XmpNamespace extends Equatable { String formatValue(XmpProp prop) => prop.value; Map linkifyValues(List props) => {}; + + static String prefixForUri(Map schemaRegistryPrefixes, String nsUri) => schemaRegistryPrefixes.entries.firstWhereOrNull((kv) => kv.value == nsUri)?.key ?? ''; } class XmpProp implements Comparable { diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/crs.dart b/lib/widgets/viewer/info/metadata/xmp_ns/crs.dart index adc24490e..cae67a6d6 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/crs.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/crs.dart @@ -2,7 +2,7 @@ import 'package:aves/utils/xmp_utils.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; class XmpCrsNamespace extends XmpNamespace { - XmpCrsNamespace(String nsPrefix, Map rawProps) : super(Namespaces.crs, nsPrefix, rawProps); + XmpCrsNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.crs); @override late final List cards = [ diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/exif.dart b/lib/widgets/viewer/info/metadata/xmp_ns/exif.dart index 991908f0b..d0778f570 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/exif.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/exif.dart @@ -4,68 +4,69 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; // cf https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/exif.md class XmpExifNamespace extends XmpNamespace { - const XmpExifNamespace(String nsPrefix, Map rawProps) : super(Namespaces.exif, nsPrefix, rawProps); + XmpExifNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.exif); @override String formatValue(XmpProp prop) { final v = prop.value; - switch (prop.path) { - case 'exif:ColorSpace': + final field = prop.path.replaceAll(nsPrefix, ''); + switch (field) { + case 'ColorSpace': return Exif.getColorSpaceDescription(v); - case 'exif:Contrast': + case 'Contrast': return Exif.getContrastDescription(v); - case 'exif:CustomRendered': + case 'CustomRendered': return Exif.getCustomRenderedDescription(v); - case 'exif:ExifVersion': - case 'exif:FlashpixVersion': + case 'ExifVersion': + case 'FlashpixVersion': return Exif.getExifVersionDescription(v); - case 'exif:ExposureMode': + case 'ExposureMode': return Exif.getExposureModeDescription(v); - case 'exif:ExposureProgram': + case 'ExposureProgram': return Exif.getExposureProgramDescription(v); - case 'exif:FileSource': + case 'FileSource': return Exif.getFileSourceDescription(v); - case 'exif:Flash/exif:Mode': + case 'Flash/Mode': return Exif.getFlashModeDescription(v); - case 'exif:Flash/exif:Return': + case 'Flash/Return': return Exif.getFlashReturnDescription(v); - case 'exif:FocalPlaneResolutionUnit': + case 'FocalPlaneResolutionUnit': return Exif.getResolutionUnitDescription(v); - case 'exif:GainControl': + case 'GainControl': return Exif.getGainControlDescription(v); - case 'exif:LightSource': + case 'LightSource': return Exif.getLightSourceDescription(v); - case 'exif:MeteringMode': + case 'MeteringMode': return Exif.getMeteringModeDescription(v); - case 'exif:Saturation': + case 'Saturation': return Exif.getSaturationDescription(v); - case 'exif:SceneCaptureType': + case 'SceneCaptureType': return Exif.getSceneCaptureTypeDescription(v); - case 'exif:SceneType': + case 'SceneType': return Exif.getSceneTypeDescription(v); - case 'exif:SensingMethod': + case 'SensingMethod': return Exif.getSensingMethodDescription(v); - case 'exif:Sharpness': + case 'Sharpness': return Exif.getSharpnessDescription(v); - case 'exif:SubjectDistanceRange': + case 'SubjectDistanceRange': return Exif.getSubjectDistanceRangeDescription(v); - case 'exif:WhiteBalance': + case 'WhiteBalance': return Exif.getWhiteBalanceDescription(v); - case 'exif:GPSAltitudeRef': + case 'GPSAltitudeRef': return Exif.getGPSAltitudeRefDescription(v); - case 'exif:GPSDestBearingRef': - case 'exif:GPSImgDirectionRef': - case 'exif:GPSTrackRef': + case 'GPSDestBearingRef': + case 'GPSImgDirectionRef': + case 'GPSTrackRef': return Exif.getGPSDirectionRefDescription(v); - case 'exif:GPSDestDistanceRef': + case 'GPSDestDistanceRef': return Exif.getGPSDestDistanceRefDescription(v); - case 'exif:GPSDifferential': + case 'GPSDifferential': return Exif.getGPSDifferentialDescription(v); - case 'exif:GPSMeasureMode': + case 'GPSMeasureMode': return Exif.getGPSMeasureModeDescription(v); - case 'exif:GPSSpeedRef': + case 'GPSSpeedRef': return Exif.getGPSSpeedRefDescription(v); - case 'exif:GPSStatus': + case 'GPSStatus': return Exif.getGPSStatusDescription(v); default: return v; diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/google.dart b/lib/widgets/viewer/info/metadata/xmp_ns/google.dart index 53833c81b..f41516fb6 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/google.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/google.dart @@ -7,7 +7,11 @@ import 'package:collection/collection.dart'; import 'package:tuple/tuple.dart'; abstract class XmpGoogleNamespace extends XmpNamespace { - const XmpGoogleNamespace(String nsUri, String nsPrefix, Map rawProps) : super(nsUri, nsPrefix, rawProps); + XmpGoogleNamespace({ + required super.nsUri, + required super.schemaRegistryPrefixes, + required super.rawProps, + }); List> get dataProps; @@ -53,14 +57,14 @@ abstract class XmpGoogleNamespace extends XmpNamespace { } class XmpGAudioNamespace extends XmpGoogleNamespace { - const XmpGAudioNamespace(String nsPrefix, Map rawProps) : super(Namespaces.gAudio, nsPrefix, rawProps); + XmpGAudioNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gAudio); @override List> get dataProps => [Tuple2('${nsPrefix}Data', '${nsPrefix}Mime')]; } class XmpGDepthNamespace extends XmpGoogleNamespace { - const XmpGDepthNamespace(String nsPrefix, Map rawProps) : super(Namespaces.gDepth, nsPrefix, rawProps); + XmpGDepthNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gDepth); @override List> get dataProps => [ @@ -70,8 +74,16 @@ class XmpGDepthNamespace extends XmpGoogleNamespace { } class XmpGDeviceNamespace extends XmpNamespace { - XmpGDeviceNamespace(String nsPrefix, Map rawProps) : super(Namespaces.gDevice, nsPrefix, rawProps) { - final mimePattern = RegExp(nsPrefix + r'Container/Container:Directory\[(\d+)\]/Item:Mime'); + late final String _cameraNsPrefix; + late final String _containerNsPrefix; + late final String _itemNsPrefix; + + XmpGDeviceNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gDevice) { + _cameraNsPrefix = XmpNamespace.prefixForUri(schemaRegistryPrefixes, Namespaces.gDeviceCamera); + _containerNsPrefix = XmpNamespace.prefixForUri(schemaRegistryPrefixes, Namespaces.gDeviceContainer); + _itemNsPrefix = XmpNamespace.prefixForUri(schemaRegistryPrefixes, Namespaces.gDeviceItem); + + final mimePattern = RegExp(nsPrefix + r'Container/' + _containerNsPrefix + r'Directory\[(\d+)\]/' + _itemNsPrefix + r'Mime'); final originalProps = rawProps.entries.toList(); originalProps.forEach((kv) { final path = kv.key; @@ -81,7 +93,7 @@ class XmpGDeviceNamespace extends XmpNamespace { if (indexString != null) { final index = int.tryParse(indexString); if (index != null) { - final dataPath = '${nsPrefix}Container/Container:Directory[$index]/Item:Data'; + final dataPath = '${nsPrefix}Container/${_containerNsPrefix}Directory[$index]/${_itemNsPrefix}Data'; rawProps[dataPath] = '[skipped]'; } } @@ -94,16 +106,16 @@ class XmpGDeviceNamespace extends XmpNamespace { XmpCardData( RegExp(nsPrefix + r'Cameras\[(\d+)\]/(.*)'), cards: [ - XmpCardData(RegExp(r'Camera:DepthMap/(.*)')), - XmpCardData(RegExp(r'Camera:Image/(.*)')), - XmpCardData(RegExp(r'Camera:ImagingModel/(.*)')), + XmpCardData(RegExp(_cameraNsPrefix + r'DepthMap/(.*)')), + XmpCardData(RegExp(_cameraNsPrefix + r'Image/(.*)')), + XmpCardData(RegExp(_cameraNsPrefix + r'ImagingModel/(.*)')), ], ), XmpCardData( - RegExp(nsPrefix + r'Container/Container:Directory\[(\d+)\]/(.*)'), + RegExp(nsPrefix + r'Container/' + _containerNsPrefix + r'Directory\[(\d+)\]/(.*)'), spanBuilders: (index, struct) { - if (struct.containsKey('Item:Data') && struct.containsKey('Item:DataURI')) { - final dataUriProp = struct['Item:DataURI']; + if (struct.containsKey('${_itemNsPrefix}Data') && struct.containsKey('${_itemNsPrefix}DataURI')) { + final dataUriProp = struct['${_itemNsPrefix}DataURI']; if (dataUriProp != null) { return { 'Data': InfoRowGroup.linkSpanBuilder( @@ -121,17 +133,17 @@ class XmpGDeviceNamespace extends XmpNamespace { } class XmpGImageNamespace extends XmpGoogleNamespace { - const XmpGImageNamespace(String nsPrefix, Map rawProps) : super(Namespaces.gImage, nsPrefix, rawProps); + XmpGImageNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gImage); @override List> get dataProps => [Tuple2('${nsPrefix}Data', '${nsPrefix}Mime')]; } -class XmpContainer extends XmpNamespace { - XmpContainer(String nsPrefix, Map rawProps) : super(Namespaces.container, nsPrefix, rawProps); +class XmpGContainer extends XmpNamespace { + XmpGContainer({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.gContainer); @override late final List cards = [ - XmpCardData(RegExp('${nsPrefix}Directory\\[(\\d+)\\]/${nsPrefix}Item/(.*)'), title: 'Directory Item'), + XmpCardData(RegExp(nsPrefix + r'Directory\[(\d+)\]/' + nsPrefix + r'Item/(.*)'), title: 'Directory Item'), ]; } diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/misc.dart b/lib/widgets/viewer/info/metadata/xmp_ns/misc.dart index 17c31f8a2..a47ffccd3 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/misc.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/misc.dart @@ -2,7 +2,7 @@ import 'package:aves/utils/xmp_utils.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; class XmpCreatorAtom extends XmpNamespace { - XmpCreatorAtom(String nsPrefix, Map rawProps) : super(Namespaces.creatorAtom, nsPrefix, rawProps); + XmpCreatorAtom({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.creatorAtom); @override late final List cards = [ @@ -11,7 +11,7 @@ class XmpCreatorAtom extends XmpNamespace { } class XmpDarktableNamespace extends XmpNamespace { - XmpDarktableNamespace(String nsPrefix, Map rawProps) : super(Namespaces.darktable, nsPrefix, rawProps); + XmpDarktableNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.darktable); @override late final List cards = [ @@ -20,7 +20,7 @@ class XmpDarktableNamespace extends XmpNamespace { } class XmpDwcNamespace extends XmpNamespace { - XmpDwcNamespace(String nsPrefix, Map rawProps) : super(Namespaces.dwc, nsPrefix, rawProps); + XmpDwcNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.dwc); @override late final List cards = [ @@ -37,7 +37,7 @@ class XmpDwcNamespace extends XmpNamespace { } class XmpIptcCoreNamespace extends XmpNamespace { - XmpIptcCoreNamespace(String nsPrefix, Map rawProps) : super(Namespaces.iptc4xmpCore, nsPrefix, rawProps); + XmpIptcCoreNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.iptc4xmpCore); @override late final List cards = [ @@ -46,7 +46,7 @@ class XmpIptcCoreNamespace extends XmpNamespace { } class XmpIptc4xmpExtNamespace extends XmpNamespace { - XmpIptc4xmpExtNamespace(String nsPrefix, Map rawProps) : super(Namespaces.iptc4xmpExt, nsPrefix, rawProps); + XmpIptc4xmpExtNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.iptc4xmpExt); @override late final List cards = [ @@ -55,7 +55,7 @@ class XmpIptc4xmpExtNamespace extends XmpNamespace { } class XmpMPNamespace extends XmpNamespace { - XmpMPNamespace(String nsPrefix, Map rawProps) : super(Namespaces.mp, nsPrefix, rawProps); + XmpMPNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.mp); @override late final List cards = [ @@ -65,7 +65,7 @@ class XmpMPNamespace extends XmpNamespace { // cf www.metadataworkinggroup.org/pdf/mwg_guidance.pdf (down, as of 2021/02/15) class XmpMgwRegionsNamespace extends XmpNamespace { - XmpMgwRegionsNamespace(String nsPrefix, Map rawProps) : super(Namespaces.mwgrs, nsPrefix, rawProps); + XmpMgwRegionsNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.mwgrs); @override late final List cards = [ @@ -75,7 +75,7 @@ class XmpMgwRegionsNamespace extends XmpNamespace { } class XmpPlusNamespace extends XmpNamespace { - XmpPlusNamespace(String nsPrefix, Map rawProps) : super(Namespaces.plus, nsPrefix, rawProps); + XmpPlusNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.plus); @override late final List cards = [ @@ -86,7 +86,7 @@ class XmpPlusNamespace extends XmpNamespace { } class XmpMMNamespace extends XmpNamespace { - XmpMMNamespace(String nsPrefix, Map rawProps) : super(Namespaces.xmpMM, nsPrefix, rawProps); + XmpMMNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.xmpMM); @override late final List cards = [ diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/photoshop.dart b/lib/widgets/viewer/info/metadata/xmp_ns/photoshop.dart index e6a749ec7..da01fd4f3 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/photoshop.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/photoshop.dart @@ -3,7 +3,7 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; // cf https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/photoshop.md class XmpPhotoshopNamespace extends XmpNamespace { - XmpPhotoshopNamespace(String nsPrefix, Map rawProps) : super(Namespaces.photoshop, nsPrefix, rawProps); + XmpPhotoshopNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.photoshop); @override late final List cards = [ diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/tiff.dart b/lib/widgets/viewer/info/metadata/xmp_ns/tiff.dart index bf027ccf4..5ff5ed4eb 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/tiff.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/tiff.dart @@ -4,7 +4,7 @@ import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; // cf https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/tiff.md class XmpTiffNamespace extends XmpNamespace { - const XmpTiffNamespace(String nsPrefix, Map rawProps) : super(Namespaces.tiff, nsPrefix, rawProps); + XmpTiffNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.tiff); @override String formatValue(XmpProp prop) { diff --git a/lib/widgets/viewer/info/metadata/xmp_ns/xmp.dart b/lib/widgets/viewer/info/metadata/xmp_ns/xmp.dart index fceb37783..7d497e1ac 100644 --- a/lib/widgets/viewer/info/metadata/xmp_ns/xmp.dart +++ b/lib/widgets/viewer/info/metadata/xmp_ns/xmp.dart @@ -6,7 +6,7 @@ import 'package:aves/widgets/viewer/info/common.dart'; import 'package:aves/widgets/viewer/info/metadata/xmp_namespaces.dart'; class XmpBasicNamespace extends XmpNamespace { - XmpBasicNamespace(String nsPrefix, Map rawProps) : super(Namespaces.xmp, nsPrefix, rawProps); + XmpBasicNamespace({required super.schemaRegistryPrefixes, required super.rawProps}) : super(nsUri: Namespaces.xmp); @override late final List cards = [ diff --git a/lib/widgets/viewer/info/metadata/xmp_tile.dart b/lib/widgets/viewer/info/metadata/xmp_tile.dart index 3d0ac7a23..ff71933e6 100644 --- a/lib/widgets/viewer/info/metadata/xmp_tile.dart +++ b/lib/widgets/viewer/info/metadata/xmp_tile.dart @@ -56,9 +56,8 @@ class _XmpDirTileState extends State { return nsPrefix; }).entries.map((kv) { final nsPrefix = kv.key; - final nsUri = _schemaRegistryPrefixes[nsPrefix] ?? ''; final rawProps = Map.fromEntries(kv.value); - return XmpNamespace.create(nsUri, nsPrefix, rawProps); + return XmpNamespace.create(_schemaRegistryPrefixes, nsPrefix, rawProps); }).toList() ..sort((a, b) => compareAsciiUpperCase(a.displayTitle, b.displayTitle)); return AvesExpansionTile(