From a8bb2eb69feb11e228feebd683cb8eb97af214cb Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 27 Apr 2025 23:42:40 +0200 Subject: [PATCH] #1539 locked: review, prevent rename / metadata export --- .../entry/extensions/metadata_edition.dart | 26 +++++++++---------- lib/model/entry/extensions/props.dart | 24 ++++++++--------- .../collection/entry_set_action_delegate.dart | 2 +- lib/widgets/common/thumbnail/image.dart | 4 +-- .../viewer/action/entry_action_delegate.dart | 3 +-- .../action/entry_info_action_delegate.dart | 11 +++++--- .../viewer/overlay/wallpaper_buttons.dart | 2 +- .../viewer/visual/entry_page_view.dart | 2 +- 8 files changed, 39 insertions(+), 35 deletions(-) diff --git a/lib/model/entry/extensions/metadata_edition.dart b/lib/model/entry/extensions/metadata_edition.dart index 5e4228279..bdb583f95 100644 --- a/lib/model/entry/extensions/metadata_edition.dart +++ b/lib/model/entry/extensions/metadata_edition.dart @@ -37,7 +37,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { return {}; } - if (canEditExif && appliedModifier.fields.any((v) => v.type == MetadataType.exif)) { + if (isExifEditionSupported && appliedModifier.fields.any((v) => v.type == MetadataType.exif)) { final newFields = await metadataEditService.editExifDate(this, appliedModifier); if (newFields.isNotEmpty) { dataTypes.addAll({ @@ -47,7 +47,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { } } - if (canEditXmp && appliedModifier.fields.any((v) => v.type == MetadataType.xmp)) { + if (isXmpEditionSupported && appliedModifier.fields.any((v) => v.type == MetadataType.xmp)) { final metadata = { MetadataType.xmp: await _editXmp((descriptions) { switch (appliedModifier.action) { @@ -94,7 +94,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final missingDate = await _missingDateCheckAndExifEdit(dataTypes); - if (canEditExif) { + if (isExifEditionSupported) { // clear every GPS field final exifFields = Map.fromEntries(MetadataFields.exifGpsFields.map((k) => MapEntry(k, null))); // add latitude & longitude, if any @@ -110,7 +110,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { } metadata[MetadataType.exif] = Map.fromEntries(exifFields.entries.map((kv) => MapEntry(kv.key.toPlatform!, kv.value))); - if (canEditXmp && missingDate != null) { + if (isXmpEditionSupported && missingDate != null) { metadata[MetadataType.xmp] = await _editXmp((descriptions) { editCreateDateXmp(descriptions, missingDate); return true; @@ -236,14 +236,14 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final title = fields[DescriptionField.title]; final description = fields[DescriptionField.description]; - if (canEditExif && editDescription) { + if (isExifEditionSupported && editDescription) { metadata[MetadataType.exif] = { MetadataField.exifImageDescription.toPlatform!: null, MetadataField.exifUserComment.toPlatform!: null, }; } - if (canEditIptc) { + if (isIptcEditionSupported) { final iptc = await metadataFetchService.getIptc(this); if (iptc != null) { if (editTitle) { @@ -256,7 +256,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { } } - if (canEditXmp) { + if (isXmpEditionSupported) { metadata[MetadataType.xmp] = await _editXmp((descriptions) { var modified = false; if (editTitle) { @@ -304,7 +304,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final missingDate = await _missingDateCheckAndExifEdit(dataTypes); - if (canEditIptc) { + if (isIptcEditionSupported) { final iptc = await metadataFetchService.getIptc(this); if (iptc != null) { editIptcValues(iptc, IPTC.applicationRecord, IPTC.keywordsTag, tags); @@ -312,7 +312,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { } } - if (canEditXmp) { + if (isXmpEditionSupported) { metadata[MetadataType.xmp] = await _editXmp((descriptions) { final modified = editTagsXmp(descriptions, tags); if (modified && missingDate != null) { @@ -342,7 +342,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final missingDate = await _missingDateCheckAndExifEdit(dataTypes); - if (canEditXmp) { + if (isXmpEditionSupported) { metadata[MetadataType.xmp] = await _editXmp((descriptions) { final modified = editRatingXmp(descriptions, rating); if (modified && missingDate != null) { @@ -368,7 +368,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { final dataTypes = {}; final metadata = {}; - if (!canEditXmp) return dataTypes; + if (!isXmpEditionSupported) return dataTypes; final missingDate = await _missingDateCheckAndExifEdit(dataTypes); @@ -509,7 +509,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { return null; } - if (canEditExif) { + if (isExifEditionSupported) { final newFields = await metadataEditService.editExifDate(this, DateModifier.setCustom(const {MetadataField.exifDateOriginal}, date)); if (newFields.isNotEmpty) { dataTypes.addAll({ @@ -524,7 +524,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry { } Future _applyDateModifierToEntry(DateModifier modifier) async { - Set mainMetadataDate() => {canEditExif ? MetadataField.exifDateOriginal : MetadataField.xmpXmpCreateDate}; + Set mainMetadataDate() => {isExifEditionSupported ? MetadataField.exifDateOriginal : MetadataField.xmpXmpCreateDate}; switch (modifier.action) { case DateEditAction.copyField: diff --git a/lib/model/entry/extensions/props.dart b/lib/model/entry/extensions/props.dart index c466ebc4c..ec21ab7ba 100644 --- a/lib/model/entry/extensions/props.dart +++ b/lib/model/entry/extensions/props.dart @@ -112,29 +112,29 @@ extension ExtraAvesEntryProps on AvesEntry { bool get canEdit => !settings.isReadOnly && path != null && !trashed && (_isMediaStoreContent || _isVaultContent); - bool get canEditDate => canEdit && (canEditExif || canEditXmp); + bool get canEditDate => canEdit && (isExifEditionSupported || isXmpEditionSupported); - bool get canEditLocation => canEdit && (canEditExif || mimeType == MimeTypes.mp4); + bool get canEditLocation => canEdit && (isExifEditionSupported || mimeType == MimeTypes.mp4); - bool get canEditTitleDescription => canEdit && canEditXmp; + bool get canEditTitleDescription => canEdit && isXmpEditionSupported; - bool get canEditRating => canEdit && canEditXmp; + bool get canEditRating => canEdit && isXmpEditionSupported; - bool get canEditTags => canEdit && canEditXmp; + bool get canEditTags => canEdit && isXmpEditionSupported; - bool get canRotate => canEdit && (canEditExif || mimeType == MimeTypes.mp4); + bool get canRotate => canEdit && (isExifEditionSupported || mimeType == MimeTypes.mp4); - bool get canFlip => canEdit && canEditExif; + bool get canFlip => canEdit && isExifEditionSupported; // app support - bool get canDecode => AppSupport.canDecode(mimeType); + bool get isDecodingSupported => AppSupport.canDecode(mimeType); - bool get canEditExif => AppSupport.canEditExif(mimeType); + bool get isExifEditionSupported => AppSupport.canEditExif(mimeType); - bool get canEditIptc => AppSupport.canEditIptc(mimeType); + bool get isIptcEditionSupported => AppSupport.canEditIptc(mimeType); - bool get canEditXmp => AppSupport.canEditXmp(mimeType); + bool get isXmpEditionSupported => AppSupport.canEditXmp(mimeType); - bool get canRemoveMetadata => AppSupport.canRemoveMetadata(mimeType); + bool get isMetadataRemovalSupported => AppSupport.canRemoveMetadata(mimeType); } diff --git a/lib/widgets/collection/entry_set_action_delegate.dart b/lib/widgets/collection/entry_set_action_delegate.dart index cd359dc26..37f1be782 100644 --- a/lib/widgets/collection/entry_set_action_delegate.dart +++ b/lib/widgets/collection/entry_set_action_delegate.dart @@ -670,7 +670,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware } Future _removeMetadata(BuildContext context) async { - final entries = await _getEditableTargetItems(context, canEdit: (entry) => entry.canRemoveMetadata); + final entries = await _getEditableTargetItems(context, canEdit: (entry) => entry.isMetadataRemovalSupported); if (entries == null || entries.isEmpty) return; final types = await selectMetadataToRemove(context, entries); diff --git a/lib/widgets/common/thumbnail/image.dart b/lib/widgets/common/thumbnail/image.dart index 904d779f1..db1a8a2b3 100644 --- a/lib/widgets/common/thumbnail/image.dart +++ b/lib/widgets/common/thumbnail/image.dart @@ -103,7 +103,7 @@ class _ThumbnailImageState extends State { } void _initProvider() { - if (!entry.canDecode) return; + if (!entry.isDecodingSupported) return; _lastException = null; _providers.clear(); @@ -192,7 +192,7 @@ class _ThumbnailImageState extends State { @override Widget build(BuildContext context) { final animate = context.select((v) => v.animate); - if (!entry.canDecode || _lastException != null) { + if (!entry.isDecodingSupported || _lastException != null) { return _buildError(context, animate); } diff --git a/lib/widgets/viewer/action/entry_action_delegate.dart b/lib/widgets/viewer/action/entry_action_delegate.dart index a29b52863..a71c0fc6b 100644 --- a/lib/widgets/viewer/action/entry_action_delegate.dart +++ b/lib/widgets/viewer/action/entry_action_delegate.dart @@ -148,9 +148,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix switch (action) { case EntryAction.rotateCCW: case EntryAction.rotateCW: - return targetEntry.canRotate; case EntryAction.flip: - return targetEntry.canFlip; case EntryAction.editDate: case EntryAction.editLocation: case EntryAction.editTitleDescription: @@ -163,6 +161,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix case EntryAction.viewMotionPhotoVideo: return _metadataActionDelegate.canApply(targetEntry, action); case EntryAction.convert: + case EntryAction.rename: case EntryAction.copy: case EntryAction.move: return !availability.isLocked; diff --git a/lib/widgets/viewer/action/entry_info_action_delegate.dart b/lib/widgets/viewer/action/entry_info_action_delegate.dart index 416a25d30..86c48c0a8 100644 --- a/lib/widgets/viewer/action/entry_info_action_delegate.dart +++ b/lib/widgets/viewer/action/entry_info_action_delegate.dart @@ -67,6 +67,11 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi bool canApply(AvesEntry targetEntry, EntryAction action) { switch (action) { // general + case EntryAction.rotateCCW: + case EntryAction.rotateCW: + return targetEntry.canRotate; + case EntryAction.flip: + return targetEntry.canFlip; case EntryAction.editDate: return targetEntry.canEditDate; case EntryAction.editLocation: @@ -78,15 +83,15 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi case EntryAction.editTags: return targetEntry.canEditTags; case EntryAction.removeMetadata: - return targetEntry.canRemoveMetadata; + return targetEntry.canEdit && targetEntry.isMetadataRemovalSupported; case EntryAction.exportMetadata: - return true; + return !availability.isLocked; // GeoTIFF case EntryAction.showGeoTiffOnMap: return true; // motion photo case EntryAction.convertMotionPhotoToStillImage: - return targetEntry.canEditXmp; + return targetEntry.canEdit && targetEntry.isXmpEditionSupported; case EntryAction.viewMotionPhotoVideo: return true; default: diff --git a/lib/widgets/viewer/overlay/wallpaper_buttons.dart b/lib/widgets/viewer/overlay/wallpaper_buttons.dart index 7575c1235..2edf623b3 100644 --- a/lib/widgets/viewer/overlay/wallpaper_buttons.dart +++ b/lib/widgets/viewer/overlay/wallpaper_buttons.dart @@ -139,7 +139,7 @@ class WallpaperButtons extends StatelessWidget with FeedbackMixin { provider = MemoryImage(bytes); } } - } else if (entry.canDecode) { + } else if (entry.isDecodingSupported) { if (entry.useTiles) { // provider image is already cropped, but not rotated needOrientation = rotationDegrees != 0 || isFlipped; diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart index 17edab6a0..9ef35fabc 100644 --- a/lib/widgets/viewer/visual/entry_page_view.dart +++ b/lib/widgets/viewer/visual/entry_page_view.dart @@ -127,7 +127,7 @@ class _EntryPageViewState extends State with TickerProviderStateM } else if (!entry.displaySize.isEmpty) { if (entry.isVideo) { child = _buildVideoView(); - } else if (entry.canDecode) { + } else if (entry.isDecodingSupported) { child = _buildRasterView(); } }