Catalog metadata: check xmp title/description to set title
This commit is contained in:
parent
e13db0dc43
commit
805b0ef51f
5 changed files with 30 additions and 10 deletions
|
@ -43,6 +43,10 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
|
|
||||||
private static final String XMP_DC_SCHEMA_NS = "http://purl.org/dc/elements/1.1/";
|
private static final String XMP_DC_SCHEMA_NS = "http://purl.org/dc/elements/1.1/";
|
||||||
private static final String XMP_SUBJECT_PROP_NAME = "dc:subject";
|
private static final String XMP_SUBJECT_PROP_NAME = "dc:subject";
|
||||||
|
private static final String XMP_TITLE_PROP_NAME = "dc:title";
|
||||||
|
private static final String XMP_DESCRIPTION_PROP_NAME = "dc:description";
|
||||||
|
private static final String XMP_GENERIC_LANG = "";
|
||||||
|
private static final String XMP_SPECIFIC_LANG = "en-US";
|
||||||
private static final Pattern videoLocationPattern = Pattern.compile("([+-][.0-9]+)([+-][.0-9]+)/?");
|
private static final Pattern videoLocationPattern = Pattern.compile("([+-][.0-9]+)([+-][.0-9]+)/?");
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
@ -207,6 +211,13 @@ public class MetadataHandler implements MethodChannel.MethodCallHandler {
|
||||||
}
|
}
|
||||||
metadataMap.put("xmpSubjects", sb.toString());
|
metadataMap.put("xmpSubjects", sb.toString());
|
||||||
}
|
}
|
||||||
|
if (xmpMeta.doesPropertyExist(XMP_DC_SCHEMA_NS, XMP_TITLE_PROP_NAME)) {
|
||||||
|
XMPProperty item = xmpMeta.getLocalizedText(XMP_DC_SCHEMA_NS, XMP_TITLE_PROP_NAME, XMP_GENERIC_LANG, XMP_SPECIFIC_LANG);
|
||||||
|
metadataMap.put("xmpTitleDescription", item.getValue());
|
||||||
|
} else if (xmpMeta.doesPropertyExist(XMP_DC_SCHEMA_NS, XMP_DESCRIPTION_PROP_NAME)) {
|
||||||
|
XMPProperty item = xmpMeta.getLocalizedText(XMP_DC_SCHEMA_NS, XMP_DESCRIPTION_PROP_NAME, XMP_GENERIC_LANG, XMP_SPECIFIC_LANG);
|
||||||
|
metadataMap.put("xmpTitleDescription", item.getValue());
|
||||||
|
}
|
||||||
} catch (XMPException e) {
|
} catch (XMPException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class ImageEntry {
|
||||||
int height;
|
int height;
|
||||||
int orientationDegrees;
|
int orientationDegrees;
|
||||||
final int sizeBytes;
|
final int sizeBytes;
|
||||||
String title;
|
String sourceTitle;
|
||||||
final int dateModifiedSecs;
|
final int dateModifiedSecs;
|
||||||
final int sourceDateTakenMillis;
|
final int sourceDateTakenMillis;
|
||||||
final String bucketDisplayName;
|
final String bucketDisplayName;
|
||||||
|
@ -41,7 +41,7 @@ class ImageEntry {
|
||||||
this.height,
|
this.height,
|
||||||
this.orientationDegrees,
|
this.orientationDegrees,
|
||||||
this.sizeBytes,
|
this.sizeBytes,
|
||||||
this.title,
|
this.sourceTitle,
|
||||||
this.dateModifiedSecs,
|
this.dateModifiedSecs,
|
||||||
this.sourceDateTakenMillis,
|
this.sourceDateTakenMillis,
|
||||||
this.bucketDisplayName,
|
this.bucketDisplayName,
|
||||||
|
@ -60,7 +60,7 @@ class ImageEntry {
|
||||||
height: map['height'] as int,
|
height: map['height'] as int,
|
||||||
orientationDegrees: map['orientationDegrees'] as int,
|
orientationDegrees: map['orientationDegrees'] as int,
|
||||||
sizeBytes: map['sizeBytes'] as int,
|
sizeBytes: map['sizeBytes'] as int,
|
||||||
title: map['title'] as String,
|
sourceTitle: map['title'] as String,
|
||||||
dateModifiedSecs: map['dateModifiedSecs'] as int,
|
dateModifiedSecs: map['dateModifiedSecs'] as int,
|
||||||
sourceDateTakenMillis: map['sourceDateTakenMillis'] as int,
|
sourceDateTakenMillis: map['sourceDateTakenMillis'] as int,
|
||||||
bucketDisplayName: map['bucketDisplayName'] as String,
|
bucketDisplayName: map['bucketDisplayName'] as String,
|
||||||
|
@ -78,7 +78,7 @@ class ImageEntry {
|
||||||
'height': height,
|
'height': height,
|
||||||
'orientationDegrees': orientationDegrees,
|
'orientationDegrees': orientationDegrees,
|
||||||
'sizeBytes': sizeBytes,
|
'sizeBytes': sizeBytes,
|
||||||
'title': title,
|
'title': sourceTitle,
|
||||||
'dateModifiedSecs': dateModifiedSecs,
|
'dateModifiedSecs': dateModifiedSecs,
|
||||||
'sourceDateTakenMillis': sourceDateTakenMillis,
|
'sourceDateTakenMillis': sourceDateTakenMillis,
|
||||||
'bucketDisplayName': bucketDisplayName,
|
'bucketDisplayName': bucketDisplayName,
|
||||||
|
@ -157,6 +157,11 @@ class ImageEntry {
|
||||||
|
|
||||||
List<String> get xmpSubjects => catalogMetadata?.xmpSubjects?.split(';')?.where((tag) => tag.isNotEmpty)?.toList() ?? [];
|
List<String> get xmpSubjects => catalogMetadata?.xmpSubjects?.split(';')?.where((tag) => tag.isNotEmpty)?.toList() ?? [];
|
||||||
|
|
||||||
|
String get title {
|
||||||
|
if (catalogMetadata != null && catalogMetadata.xmpTitleDescription.isNotEmpty) return catalogMetadata.xmpTitleDescription;
|
||||||
|
return sourceTitle;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> catalog() async {
|
Future<void> catalog() async {
|
||||||
if (isCatalogued) return;
|
if (isCatalogued) return;
|
||||||
catalogMetadata = await MetadataService.getCatalogMetadata(this);
|
catalogMetadata = await MetadataService.getCatalogMetadata(this);
|
||||||
|
@ -223,8 +228,8 @@ class ImageEntry {
|
||||||
if (path is String) this.path = path;
|
if (path is String) this.path = path;
|
||||||
final contentId = newFields['contentId'];
|
final contentId = newFields['contentId'];
|
||||||
if (contentId is int) this.contentId = contentId;
|
if (contentId is int) this.contentId = contentId;
|
||||||
final title = newFields['title'];
|
final sourceTitle = newFields['sourceTitle'];
|
||||||
if (title is String) this.title = title;
|
if (sourceTitle is String) this.sourceTitle = sourceTitle;
|
||||||
metadataChangeNotifier.notifyListeners();
|
metadataChangeNotifier.notifyListeners();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:geocoder/model.dart';
|
||||||
|
|
||||||
class CatalogMetadata {
|
class CatalogMetadata {
|
||||||
final int contentId, dateMillis, videoRotation;
|
final int contentId, dateMillis, videoRotation;
|
||||||
final String xmpSubjects;
|
final String xmpSubjects, xmpTitleDescription;
|
||||||
final double latitude, longitude;
|
final double latitude, longitude;
|
||||||
Address address;
|
Address address;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ class CatalogMetadata {
|
||||||
this.dateMillis,
|
this.dateMillis,
|
||||||
this.videoRotation,
|
this.videoRotation,
|
||||||
this.xmpSubjects,
|
this.xmpSubjects,
|
||||||
|
this.xmpTitleDescription,
|
||||||
double latitude,
|
double latitude,
|
||||||
double longitude,
|
double longitude,
|
||||||
})
|
})
|
||||||
|
@ -25,6 +26,7 @@ class CatalogMetadata {
|
||||||
dateMillis: map['dateMillis'] ?? 0,
|
dateMillis: map['dateMillis'] ?? 0,
|
||||||
videoRotation: map['videoRotation'] ?? 0,
|
videoRotation: map['videoRotation'] ?? 0,
|
||||||
xmpSubjects: map['xmpSubjects'] ?? '',
|
xmpSubjects: map['xmpSubjects'] ?? '',
|
||||||
|
xmpTitleDescription: map['xmpTitleDescription'] ?? '',
|
||||||
latitude: map['latitude'],
|
latitude: map['latitude'],
|
||||||
longitude: map['longitude'],
|
longitude: map['longitude'],
|
||||||
);
|
);
|
||||||
|
@ -35,13 +37,14 @@ class CatalogMetadata {
|
||||||
'dateMillis': dateMillis,
|
'dateMillis': dateMillis,
|
||||||
'videoRotation': videoRotation,
|
'videoRotation': videoRotation,
|
||||||
'xmpSubjects': xmpSubjects,
|
'xmpSubjects': xmpSubjects,
|
||||||
|
'xmpTitleDescription': xmpTitleDescription,
|
||||||
'latitude': latitude,
|
'latitude': latitude,
|
||||||
'longitude': longitude,
|
'longitude': longitude,
|
||||||
};
|
};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'CatalogMetadata{contentId=$contentId, dateMillis=$dateMillis, videoRotation=$videoRotation, latitude=$latitude, longitude=$longitude, xmpSubjects=$xmpSubjects}';
|
return 'CatalogMetadata{contentId=$contentId, dateMillis=$dateMillis, videoRotation=$videoRotation, latitude=$latitude, longitude=$longitude, xmpSubjects=$xmpSubjects, xmpTitleDescription=$xmpTitleDescription}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class MetadataDb {
|
||||||
_database = openDatabase(
|
_database = openDatabase(
|
||||||
await path,
|
await path,
|
||||||
onCreate: (db, version) async {
|
onCreate: (db, version) async {
|
||||||
await db.execute('CREATE TABLE $metadataTable(contentId INTEGER PRIMARY KEY, dateMillis INTEGER, videoRotation INTEGER, xmpSubjects TEXT, latitude REAL, longitude REAL)');
|
await db.execute('CREATE TABLE $metadataTable(contentId INTEGER PRIMARY KEY, dateMillis INTEGER, videoRotation INTEGER, xmpSubjects TEXT, xmpTitleDescription TEXT, latitude REAL, longitude REAL)');
|
||||||
await db.execute('CREATE TABLE $addressTable(contentId INTEGER PRIMARY KEY, addressLine TEXT, countryName TEXT, adminArea TEXT, locality TEXT)');
|
await db.execute('CREATE TABLE $addressTable(contentId INTEGER PRIMARY KEY, addressLine TEXT, countryName TEXT, adminArea TEXT, locality TEXT)');
|
||||||
await db.execute('CREATE TABLE $favouriteTable(contentId INTEGER PRIMARY KEY, path TEXT)');
|
await db.execute('CREATE TABLE $favouriteTable(contentId INTEGER PRIMARY KEY, path TEXT)');
|
||||||
},
|
},
|
||||||
|
|
|
@ -31,7 +31,8 @@ class MetadataService {
|
||||||
// 'dateMillis': date taken in milliseconds since Epoch (long)
|
// 'dateMillis': date taken in milliseconds since Epoch (long)
|
||||||
// 'latitude': latitude (double)
|
// 'latitude': latitude (double)
|
||||||
// 'longitude': longitude (double)
|
// 'longitude': longitude (double)
|
||||||
// 'xmpSubjects': space separated XMP subjects (string)
|
// 'xmpSubjects': ';' separated XMP subjects (string)
|
||||||
|
// 'xmpTitleDescription': XMP title or XMP description (string)
|
||||||
final result = await platform.invokeMethod('getCatalogMetadata', <String, dynamic>{
|
final result = await platform.invokeMethod('getCatalogMetadata', <String, dynamic>{
|
||||||
'mimeType': entry.mimeType,
|
'mimeType': entry.mimeType,
|
||||||
'path': entry.path,
|
'path': entry.path,
|
||||||
|
|
Loading…
Reference in a new issue