aves/lib/services/metadata/metadata_edit_service.dart
2022-06-26 16:49:59 +09:00

168 lines
5.6 KiB
Dart

import 'dart:async';
import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart';
import 'package:aves/model/metadata/fields.dart';
import 'package:aves/services/common/services.dart';
import 'package:collection/collection.dart';
import 'package:flutter/services.dart';
abstract class MetadataEditService {
Future<Map<String, dynamic>> rotate(AvesEntry entry, {required bool clockwise});
Future<Map<String, dynamic>> flip(AvesEntry entry);
Future<Map<String, dynamic>> editExifDate(AvesEntry entry, DateModifier modifier);
Future<Map<String, dynamic>> editMetadata(AvesEntry entry, Map<MetadataType, dynamic> modifier, {bool autoCorrectTrailerOffset = true});
Future<Map<String, dynamic>> removeTrailerVideo(AvesEntry entry);
Future<Map<String, dynamic>> removeTypes(AvesEntry entry, Set<MetadataType> types);
}
class PlatformMetadataEditService implements MetadataEditService {
static const _platform = MethodChannel('deckers.thibault/aves/metadata_edit');
static Map<String, dynamic> _toPlatformEntryMap(AvesEntry entry) {
return {
'uri': entry.uri,
'path': entry.path,
'pageId': entry.pageId,
'mimeType': entry.mimeType,
'width': entry.width,
'height': entry.height,
'rotationDegrees': entry.rotationDegrees,
'isFlipped': entry.isFlipped,
'dateModifiedSecs': entry.dateModifiedSecs,
'sizeBytes': entry.sizeBytes,
};
}
@override
Future<Map<String, dynamic>> rotate(AvesEntry entry, {required bool clockwise}) async {
try {
// returns map with: 'rotationDegrees' 'isFlipped'
final result = await _platform.invokeMethod('rotate', <String, dynamic>{
'entry': _toPlatformEntryMap(entry),
'clockwise': clockwise,
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {
if (!entry.isMissingAtPath) {
await reportService.recordError(e, stack);
}
}
return {};
}
@override
Future<Map<String, dynamic>> flip(AvesEntry entry) async {
try {
// returns map with: 'rotationDegrees' 'isFlipped'
final result = await _platform.invokeMethod('flip', <String, dynamic>{
'entry': _toPlatformEntryMap(entry),
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {
if (!entry.isMissingAtPath) {
await reportService.recordError(e, stack);
}
}
return {};
}
@override
Future<Map<String, dynamic>> editExifDate(AvesEntry entry, DateModifier modifier) async {
try {
final result = await _platform.invokeMethod('editDate', <String, dynamic>{
'entry': _toPlatformEntryMap(entry),
'dateMillis': modifier.setDateTime?.millisecondsSinceEpoch,
'shiftMinutes': modifier.shiftMinutes,
'fields': modifier.fields.where((v) => v.type == MetadataType.exif).map((v) => v.exifInterfaceTag).whereNotNull().toList(),
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {
if (!entry.isMissingAtPath) {
await reportService.recordError(e, stack);
}
}
return {};
}
@override
Future<Map<String, dynamic>> editMetadata(
AvesEntry entry,
Map<MetadataType, dynamic> metadata, {
bool autoCorrectTrailerOffset = true,
}) async {
try {
final result = await _platform.invokeMethod('editMetadata', <String, dynamic>{
'entry': _toPlatformEntryMap(entry),
'metadata': metadata.map((type, value) => MapEntry(_toPlatformMetadataType(type), value)),
'autoCorrectTrailerOffset': autoCorrectTrailerOffset,
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {
if (!entry.isMissingAtPath) {
await reportService.recordError(e, stack);
}
}
return {};
}
@override
Future<Map<String, dynamic>> removeTrailerVideo(AvesEntry entry) async {
try {
final result = await _platform.invokeMethod('removeTrailerVideo', <String, dynamic>{
'entry': _toPlatformEntryMap(entry),
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {
if (!entry.isMissingAtPath) {
await reportService.recordError(e, stack);
}
}
return {};
}
@override
Future<Map<String, dynamic>> removeTypes(AvesEntry entry, Set<MetadataType> types) async {
try {
final result = await _platform.invokeMethod('removeTypes', <String, dynamic>{
'entry': _toPlatformEntryMap(entry),
'types': types.map(_toPlatformMetadataType).toList(),
});
if (result != null) return (result as Map).cast<String, dynamic>();
} on PlatformException catch (e, stack) {
if (!entry.isMissingAtPath) {
await reportService.recordError(e, stack);
}
}
return {};
}
String _toPlatformMetadataType(MetadataType type) {
switch (type) {
case MetadataType.comment:
return 'comment';
case MetadataType.exif:
return 'exif';
case MetadataType.iccProfile:
return 'icc_profile';
case MetadataType.iptc:
return 'iptc';
case MetadataType.jfif:
return 'jfif';
case MetadataType.jpegAdobe:
return 'jpeg_adobe';
case MetadataType.jpegDucky:
return 'jpeg_ducky';
case MetadataType.photoshopIrb:
return 'photoshop_irb';
case MetadataType.xmp:
return 'xmp';
}
}
}