#361 #329 info: edit location by copying from other item

This commit is contained in:
Thibault Deckers 2022-10-25 19:23:33 +02:00
parent 68ed8adc98
commit 5b960d0a90
31 changed files with 865 additions and 242 deletions

View file

@ -6,7 +6,8 @@ All notable changes to this project will be documented in this file.
### Added ### Added
- Collection / Info: edit MP4 metadata (date / location / title / description / rating / tags / rotation) - Info: edit MP4 metadata (date / location / title / description / rating / tags / rotation)
- Info: edit location by copying from other item
- Widget: option to open collection on tap - Widget: option to open collection on tap
### Changed ### Changed

View file

@ -423,8 +423,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Standort", "editEntryLocationDialogTitle": "Standort",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Auf Karte wählen", "editEntryLocationDialogChooseOnMap": "Auf Karte wählen",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Breitengrad", "editEntryLocationDialogLatitude": "Breitengrad",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Längengrad", "editEntryLocationDialogLongitude": "Längengrad",

View file

@ -423,8 +423,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Τοποθεσια", "editEntryLocationDialogTitle": "Τοποθεσια",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Επιλογή στο χάρτη", "editEntryLocationDialogChooseOnMap": "Επιλογή στο χάρτη",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Γεωγραφικό πλάτος", "editEntryLocationDialogLatitude": "Γεωγραφικό πλάτος",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Γεωγραφικό μήκος", "editEntryLocationDialogLongitude": "Γεωγραφικό μήκος",

View file

@ -389,7 +389,8 @@
"durationDialogSeconds": "Seconds", "durationDialogSeconds": "Seconds",
"editEntryLocationDialogTitle": "Location", "editEntryLocationDialogTitle": "Location",
"editEntryLocationDialogChooseOnMapTooltip": "Choose on map", "editEntryLocationDialogSetCustom": "Set custom location",
"editEntryLocationDialogChooseOnMap": "Choose on map",
"editEntryLocationDialogLatitude": "Latitude", "editEntryLocationDialogLatitude": "Latitude",
"editEntryLocationDialogLongitude": "Longitude", "editEntryLocationDialogLongitude": "Longitude",

View file

@ -405,8 +405,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Ubicación", "editEntryLocationDialogTitle": "Ubicación",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Elegir en el mapa", "editEntryLocationDialogChooseOnMap": "Elegir en el mapa",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Latitud", "editEntryLocationDialogLatitude": "Latitud",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Longitud", "editEntryLocationDialogLongitude": "Longitud",

View file

@ -427,8 +427,8 @@
"@durationDialogSeconds": {}, "@durationDialogSeconds": {},
"editEntryLocationDialogTitle": "Lieu", "editEntryLocationDialogTitle": "Lieu",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Sélectionner sur la carte", "editEntryLocationDialogChooseOnMap": "Sélectionner sur la carte",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Latitude", "editEntryLocationDialogLatitude": "Latitude",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Longitude", "editEntryLocationDialogLongitude": "Longitude",

View file

@ -413,8 +413,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Lokasi", "editEntryLocationDialogTitle": "Lokasi",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Pilih di peta", "editEntryLocationDialogChooseOnMap": "Pilih di peta",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Garis lintang", "editEntryLocationDialogLatitude": "Garis lintang",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Garis bujur", "editEntryLocationDialogLongitude": "Garis bujur",

View file

@ -423,8 +423,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Posizione", "editEntryLocationDialogTitle": "Posizione",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Scegli sulla mappa", "editEntryLocationDialogChooseOnMap": "Scegli sulla mappa",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Latitudine", "editEntryLocationDialogLatitude": "Latitudine",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Longitudine", "editEntryLocationDialogLongitude": "Longitudine",

View file

@ -405,8 +405,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "位置情報", "editEntryLocationDialogTitle": "位置情報",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "地図上で選択", "editEntryLocationDialogChooseOnMap": "地図上で選択",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "緯度", "editEntryLocationDialogLatitude": "緯度",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "経度", "editEntryLocationDialogLongitude": "経度",

View file

@ -427,8 +427,8 @@
"@durationDialogSeconds": {}, "@durationDialogSeconds": {},
"editEntryLocationDialogTitle": "위치", "editEntryLocationDialogTitle": "위치",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "지도에서 선택", "editEntryLocationDialogChooseOnMap": "지도에서 선택",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "위도", "editEntryLocationDialogLatitude": "위도",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "경도", "editEntryLocationDialogLongitude": "경도",

View file

@ -549,8 +549,8 @@
"@editEntryDialogCopyFromItem": {}, "@editEntryDialogCopyFromItem": {},
"durationDialogMinutes": "Minutter", "durationDialogMinutes": "Minutter",
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogChooseOnMapTooltip": "Velg på kartet", "editEntryLocationDialogChooseOnMap": "Velg på kartet",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryRatingDialogTitle": "Vurdering", "editEntryRatingDialogTitle": "Vurdering",
"@editEntryRatingDialogTitle": {}, "@editEntryRatingDialogTitle": {},
"removeEntryMetadataDialogTitle": "Metadatafjerning", "removeEntryMetadataDialogTitle": "Metadatafjerning",

View file

@ -421,8 +421,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Locatie", "editEntryLocationDialogTitle": "Locatie",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Kies op kaart", "editEntryLocationDialogChooseOnMap": "Kies op kaart",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Breedtegraad", "editEntryLocationDialogLatitude": "Breedtegraad",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Lengtegraad", "editEntryLocationDialogLongitude": "Lengtegraad",

View file

@ -423,8 +423,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Localização", "editEntryLocationDialogTitle": "Localização",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Escolha no mapa", "editEntryLocationDialogChooseOnMap": "Escolha no mapa",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Latitude", "editEntryLocationDialogLatitude": "Latitude",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Longitude", "editEntryLocationDialogLongitude": "Longitude",

View file

@ -423,8 +423,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Местоположение", "editEntryLocationDialogTitle": "Местоположение",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Выбрать на карте", "editEntryLocationDialogChooseOnMap": "Выбрать на карте",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Широта", "editEntryLocationDialogLatitude": "Широта",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Долгота", "editEntryLocationDialogLongitude": "Долгота",

View file

@ -379,8 +379,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "Konum", "editEntryLocationDialogTitle": "Konum",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "Harita üzerinde seç", "editEntryLocationDialogChooseOnMap": "Harita üzerinde seç",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "Enlem", "editEntryLocationDialogLatitude": "Enlem",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "Boylam", "editEntryLocationDialogLongitude": "Boylam",

View file

@ -423,8 +423,8 @@
"@durationDialogMinutes": {}, "@durationDialogMinutes": {},
"editEntryLocationDialogTitle": "位置", "editEntryLocationDialogTitle": "位置",
"@editEntryLocationDialogTitle": {}, "@editEntryLocationDialogTitle": {},
"editEntryLocationDialogChooseOnMapTooltip": "从地图上选择", "editEntryLocationDialogChooseOnMap": "从地图上选择",
"@editEntryLocationDialogChooseOnMapTooltip": {}, "@editEntryLocationDialogChooseOnMap": {},
"editEntryLocationDialogLatitude": "纬度", "editEntryLocationDialogLatitude": "纬度",
"@editEntryLocationDialogLatitude": {}, "@editEntryLocationDialogLatitude": {},
"editEntryLocationDialogLongitude": "经度", "editEntryLocationDialogLongitude": "经度",

View file

@ -3,7 +3,8 @@ import 'dart:io';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/date_field_source.dart';
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/fields.dart'; import 'package:aves/model/metadata/fields.dart';
import 'package:aves/ref/exif.dart'; import 'package:aves/ref/exif.dart';
import 'package:aves/ref/iptc.dart'; import 'package:aves/ref/iptc.dart';

View file

@ -1,4 +1,4 @@
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/fields.dart'; import 'package:aves/model/metadata/fields.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';

View file

@ -0,0 +1,22 @@
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/widgets.dart';
extension ExtraDateEditAction on DateEditAction {
String getText(BuildContext context) {
switch (this) {
case DateEditAction.setCustom:
return context.l10n.editEntryDateDialogSetCustom;
case DateEditAction.copyField:
return context.l10n.editEntryDateDialogCopyField;
case DateEditAction.copyItem:
return context.l10n.editEntryDialogCopyFromItem;
case DateEditAction.extractFromTitle:
return context.l10n.editEntryDateDialogExtractFromTitle;
case DateEditAction.shift:
return context.l10n.editEntryDateDialogShift;
case DateEditAction.remove:
return context.l10n.actionRemove;
}
}
}

View file

@ -0,0 +1,36 @@
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/fields.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/widgets.dart';
extension ExtraDateFieldSource on DateFieldSource {
String getText(BuildContext context) {
switch (this) {
case DateFieldSource.fileModifiedDate:
return context.l10n.editEntryDateDialogSourceFileModifiedDate;
case DateFieldSource.exifDate:
return 'Exif date';
case DateFieldSource.exifDateOriginal:
return 'Exif original date';
case DateFieldSource.exifDateDigitized:
return 'Exif digitized date';
case DateFieldSource.exifGpsDate:
return 'Exif GPS date';
}
}
MetadataField? toMetadataField() {
switch (this) {
case DateFieldSource.fileModifiedDate:
return null;
case DateFieldSource.exifDate:
return MetadataField.exifDate;
case DateFieldSource.exifDateOriginal:
return MetadataField.exifDateOriginal;
case DateFieldSource.exifDateDigitized:
return MetadataField.exifDateDigitized;
case DateFieldSource.exifGpsDate:
return MetadataField.exifGpsDatestamp;
}
}
}

View file

@ -0,0 +1,46 @@
enum DateEditAction {
setCustom,
copyField,
copyItem,
extractFromTitle,
shift,
remove,
}
enum DateFieldSource {
fileModifiedDate,
exifDate,
exifDateOriginal,
exifDateDigitized,
exifGpsDate,
}
enum LocationEditAction {
chooseOnMap,
copyItem,
setCustom,
remove,
}
enum MetadataType {
// JPEG COM marker or GIF comment
comment,
// Exif: https://en.wikipedia.org/wiki/Exif
exif,
// ICC profile: https://en.wikipedia.org/wiki/ICC_profile
iccProfile,
// IPTC: https://en.wikipedia.org/wiki/IPTC_Information_Interchange_Model
iptc,
// JPEG APP0 / JFIF: https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
jfif,
// JPEG APP14 / Adobe: https://www.exiftool.org/TagNames/JPEG.html#Adobe
jpegAdobe,
// JPEG APP12 / Ducky: https://www.exiftool.org/TagNames/APP12.html#Ducky
jpegDucky,
// ISO User Data box content, etc.
mp4,
// Photoshop IRB: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
photoshopIrb,
// XMP: https://en.wikipedia.org/wiki/Extensible_Metadata_Platform
xmp,
}

View file

@ -0,0 +1,18 @@
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/widgets.dart';
extension ExtraLocationEditAction on LocationEditAction {
String getText(BuildContext context) {
switch (this) {
case LocationEditAction.chooseOnMap:
return context.l10n.editEntryLocationDialogChooseOnMap;
case LocationEditAction.copyItem:
return context.l10n.editEntryDialogCopyFromItem;
case LocationEditAction.setCustom:
return context.l10n.editEntryLocationDialogSetCustom;
case LocationEditAction.remove:
return context.l10n.actionRemove;
}
}
}

View file

@ -1,44 +1,4 @@
import 'package:aves/model/metadata/fields.dart'; import 'package:aves/model/metadata/enums/enums.dart';
enum DateEditAction {
setCustom,
copyField,
copyItem,
extractFromTitle,
shift,
remove,
}
enum DateFieldSource {
fileModifiedDate,
exifDate,
exifDateOriginal,
exifDateDigitized,
exifGpsDate,
}
enum MetadataType {
// JPEG COM marker or GIF comment
comment,
// Exif: https://en.wikipedia.org/wiki/Exif
exif,
// ICC profile: https://en.wikipedia.org/wiki/ICC_profile
iccProfile,
// IPTC: https://en.wikipedia.org/wiki/IPTC_Information_Interchange_Model
iptc,
// JPEG APP0 / JFIF: https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format
jfif,
// JPEG APP14 / Adobe: https://www.exiftool.org/TagNames/JPEG.html#Adobe
jpegAdobe,
// JPEG APP12 / Ducky: https://www.exiftool.org/TagNames/APP12.html#Ducky
jpegDucky,
// ISO User Data box content, etc.
mp4,
// Photoshop IRB: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
photoshopIrb,
// XMP: https://en.wikipedia.org/wiki/Extensible_Metadata_Platform
xmp,
}
class MetadataTypes { class MetadataTypes {
static const main = { static const main = {
@ -114,20 +74,3 @@ extension ExtraMetadataType on MetadataType {
} }
} }
} }
extension ExtraDateFieldSource on DateFieldSource {
MetadataField? toMetadataField() {
switch (this) {
case DateFieldSource.fileModifiedDate:
return null;
case DateFieldSource.exifDate:
return MetadataField.exifDate;
case DateFieldSource.exifDateOriginal:
return MetadataField.exifDateOriginal;
case DateFieldSource.exifDateDigitized:
return MetadataField.exifDateDigitized;
case DateFieldSource.exifGpsDate:
return MetadataField.exifGpsDatestamp;
}
}
}

View file

@ -1,4 +1,4 @@
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/enums.dart';
enum MetadataField { enum MetadataField {
exifDate, exifDate,

View file

@ -2,7 +2,8 @@ import 'dart:async';
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/enums/metadata_type.dart';
import 'package:aves/model/metadata/fields.dart'; import 'package:aves/model/metadata/fields.dart';
import 'package:aves/services/common/services.dart'; import 'package:aves/services/common/services.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';

View file

@ -1,7 +1,7 @@
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/entry_metadata_edition.dart'; import 'package:aves/model/entry_metadata_edition.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/ref/mime_types.dart'; import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/common/services.dart'; import 'package:aves/services/common/services.dart';
@ -33,12 +33,12 @@ mixin EntryEditorMixin {
Future<LatLng?> selectLocation(BuildContext context, Set<AvesEntry> entries, CollectionLens? collection) async { Future<LatLng?> selectLocation(BuildContext context, Set<AvesEntry> entries, CollectionLens? collection) async {
if (entries.isEmpty) return null; if (entries.isEmpty) return null;
final initialLocation = entries.firstWhereOrNull((entry) => entry.hasGps)?.latLng; final entry = entries.firstWhereOrNull((entry) => entry.hasGps) ?? entries.first;
return showDialog<LatLng>( return showDialog<LatLng>(
context: context, context: context,
builder: (context) => EditEntryLocationDialog( builder: (context) => EditEntryLocationDialog(
initialLocation: initialLocation, entry: entry,
collection: collection, collection: collection,
), ),
); );

View file

@ -8,7 +8,7 @@ import 'package:aves/model/filters/album.dart';
import 'package:aves/model/filters/trash.dart'; import 'package:aves/model/filters/trash.dart';
import 'package:aves/model/highlight.dart'; import 'package:aves/model/highlight.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/enums/enums.dart';
import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';

View file

@ -1,6 +1,8 @@
import 'package:aves/model/entry.dart'; import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/model/metadata/date_modifier.dart';
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/date_edit_action.dart';
import 'package:aves/model/metadata/enums/date_field_source.dart';
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/fields.dart'; import 'package:aves/model/metadata/fields.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
@ -36,7 +38,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
DateEditAction _action = DateEditAction.setCustom; DateEditAction _action = DateEditAction.setCustom;
DateFieldSource _copyFieldSource = DateFieldSource.fileModifiedDate; DateFieldSource _copyFieldSource = DateFieldSource.fileModifiedDate;
late AvesEntry _copyItemSource; late AvesEntry _copyItemSource;
late DateTime _setDateTime; late DateTime _customDateTime;
late ValueNotifier<int> _shiftHour, _shiftMinute; late ValueNotifier<int> _shiftHour, _shiftMinute;
late ValueNotifier<String> _shiftSign; late ValueNotifier<String> _shiftSign;
bool _showOptions = false; bool _showOptions = false;
@ -47,13 +49,13 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initSet(); _initCustom();
_initCopyItem(); _initCopyItem();
_initShift(minutesInHour); _initShift(minutesInHour);
} }
void _initSet() { void _initCustom() {
_setDateTime = widget.entry.bestDate ?? DateTime.now(); _customDateTime = widget.entry.bestDate ?? DateTime.now();
} }
void _initCopyItem() { void _initCopyItem() {
@ -84,7 +86,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
padding: const EdgeInsets.only(left: 16, top: 8, right: 16), padding: const EdgeInsets.only(left: 16, top: 8, right: 16),
child: TextDropdownButton<DateEditAction>( child: TextDropdownButton<DateEditAction>(
values: DateEditAction.values, values: DateEditAction.values,
valueText: (v) => _actionText(context, v), valueText: (v) => v.getText(context),
value: _action, value: _action,
onChanged: (v) => setState(() => _action = v!), onChanged: (v) => setState(() => _action = v!),
isExpanded: true, isExpanded: true,
@ -143,7 +145,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
padding: const EdgeInsetsDirectional.only(start: 16, end: 8), padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
child: Row( child: Row(
children: [ children: [
Expanded(child: Text(formatDateTime(_setDateTime, locale, use24hour))), Expanded(child: Text(formatDateTime(_customDateTime, locale, use24hour))),
IconButton( IconButton(
icon: const Icon(AIcons.edit), icon: const Icon(AIcons.edit),
onPressed: _editDate, onPressed: _editDate,
@ -159,7 +161,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
padding: const EdgeInsets.only(left: 16, top: 0, right: 16), padding: const EdgeInsets.only(left: 16, top: 0, right: 16),
child: TextDropdownButton<DateFieldSource>( child: TextDropdownButton<DateFieldSource>(
values: DateFieldSource.values, values: DateFieldSource.values,
valueText: (v) => _setSourceText(context, v), valueText: (v) => v.getText(context),
value: _copyFieldSource, value: _copyFieldSource,
onChanged: (v) => setState(() => _copyFieldSource = v!), onChanged: (v) => setState(() => _copyFieldSource = v!),
isExpanded: true, isExpanded: true,
@ -280,44 +282,10 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
); );
} }
String _actionText(BuildContext context, DateEditAction action) {
final l10n = context.l10n;
switch (action) {
case DateEditAction.setCustom:
return l10n.editEntryDateDialogSetCustom;
case DateEditAction.copyField:
return l10n.editEntryDateDialogCopyField;
case DateEditAction.copyItem:
return l10n.editEntryDialogCopyFromItem;
case DateEditAction.extractFromTitle:
return l10n.editEntryDateDialogExtractFromTitle;
case DateEditAction.shift:
return l10n.editEntryDateDialogShift;
case DateEditAction.remove:
return l10n.actionRemove;
}
}
String _setSourceText(BuildContext context, DateFieldSource source) {
final l10n = context.l10n;
switch (source) {
case DateFieldSource.fileModifiedDate:
return l10n.editEntryDateDialogSourceFileModifiedDate;
case DateFieldSource.exifDate:
return 'Exif date';
case DateFieldSource.exifDateOriginal:
return 'Exif original date';
case DateFieldSource.exifDateDigitized:
return 'Exif digitized date';
case DateFieldSource.exifGpsDate:
return 'Exif GPS date';
}
}
Future<void> _editDate() async { Future<void> _editDate() async {
final _date = await showDatePicker( final _date = await showDatePicker(
context: context, context: context,
initialDate: _setDateTime, initialDate: _customDateTime,
firstDate: DateTime(0), firstDate: DateTime(0),
lastDate: DateTime(2100), lastDate: DateTime(2100),
confirmText: context.l10n.nextButtonLabel, confirmText: context.l10n.nextButtonLabel,
@ -326,11 +294,11 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
final _time = await showTimePicker( final _time = await showTimePicker(
context: context, context: context,
initialTime: TimeOfDay.fromDateTime(_setDateTime), initialTime: TimeOfDay.fromDateTime(_customDateTime),
); );
if (_time == null) return; if (_time == null) return;
setState(() => _setDateTime = DateTime( setState(() => _customDateTime = DateTime(
_date.year, _date.year,
_date.month, _date.month,
_date.day, _date.day,
@ -366,7 +334,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
// whether each item supports Exif edition // whether each item supports Exif edition
switch (_action) { switch (_action) {
case DateEditAction.setCustom: case DateEditAction.setCustom:
return DateModifier.setCustom(const {}, _setDateTime); return DateModifier.setCustom(const {}, _customDateTime);
case DateEditAction.copyField: case DateEditAction.copyField:
return DateModifier.copyField(_copyFieldSource); return DateModifier.copyField(_copyFieldSource);
case DateEditAction.copyItem: case DateEditAction.copyItem:

View file

@ -1,22 +1,32 @@
import 'package:aves/model/entry.dart';
import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/enums/location_edit_action.dart';
import 'package:aves/model/settings/enums/coordinate_format.dart';
import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart'; import 'package:aves/theme/icons.dart';
import 'package:aves/theme/themes.dart';
import 'package:aves/utils/constants.dart'; import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/basic/text_dropdown_button.dart';
import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:aves/widgets/dialogs/item_pick_dialog.dart';
import 'package:aves/widgets/dialogs/item_picker.dart';
import 'package:aves/widgets/dialogs/location_pick_dialog.dart'; import 'package:aves/widgets/dialogs/location_pick_dialog.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:latlong2/latlong.dart'; import 'package:latlong2/latlong.dart';
import 'package:provider/provider.dart';
class EditEntryLocationDialog extends StatefulWidget { class EditEntryLocationDialog extends StatefulWidget {
final LatLng? initialLocation; final AvesEntry entry;
final CollectionLens? collection; final CollectionLens? collection;
const EditEntryLocationDialog({ const EditEntryLocationDialog({
super.key, super.key,
required this.initialLocation, required this.entry,
this.collection, this.collection,
}); });
@ -25,9 +35,10 @@ class EditEntryLocationDialog extends StatefulWidget {
} }
class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> { class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
_LocationAction _action = _LocationAction.set; LocationEditAction _action = LocationEditAction.chooseOnMap;
LatLng? _mapCoordinates;
late AvesEntry _copyItemSource;
final TextEditingController _latitudeController = TextEditingController(), _longitudeController = TextEditingController(); final TextEditingController _latitudeController = TextEditingController(), _longitudeController = TextEditingController();
final FocusNode _latitudeFocusNode = FocusNode(), _longitudeFocusNode = FocusNode();
final ValueNotifier<bool> _isValidNotifier = ValueNotifier(false); final ValueNotifier<bool> _isValidNotifier = ValueNotifier(false);
NumberFormat get coordinateFormatter => NumberFormat('0.000000', context.l10n.localeName); NumberFormat get coordinateFormatter => NumberFormat('0.000000', context.l10n.localeName);
@ -35,15 +46,35 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_latitudeFocusNode.addListener(_onLatLngFocusChange); _initMapCoordinates();
_longitudeFocusNode.addListener(_onLatLngFocusChange); _initCopyItem();
WidgetsBinding.instance.addPostFrameCallback((_) => _setLocation(context, widget.initialLocation)); _initCustom();
}
void _initMapCoordinates() {
_mapCoordinates = widget.entry.latLng;
}
void _initCopyItem() {
_copyItemSource = widget.entry;
}
void _initCustom() {
WidgetsBinding.instance.addPostFrameCallback((_) {
final latLng = widget.entry.latLng;
if (latLng != null) {
_latitudeController.text = coordinateFormatter.format(latLng.latitude);
_longitudeController.text = coordinateFormatter.format(latLng.longitude);
} else {
_latitudeController.text = '';
_longitudeController.text = '';
}
setState(_validate);
});
} }
@override @override
void dispose() { void dispose() {
_latitudeFocusNode.removeListener(_onLatLngFocusChange);
_longitudeFocusNode.removeListener(_onLatLngFocusChange);
_latitudeController.dispose(); _latitudeController.dispose();
_longitudeController.dispose(); _longitudeController.dispose();
super.dispose(); super.dispose();
@ -62,64 +93,36 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
return AvesDialog( return AvesDialog(
title: l10n.editEntryLocationDialogTitle, title: l10n.editEntryLocationDialogTitle,
scrollableContent: [ scrollableContent: [
RadioListTile<_LocationAction>( Padding(
value: _LocationAction.set, padding: const EdgeInsets.only(left: 16, top: 8, right: 16),
groupValue: _action, child: TextDropdownButton<LocationEditAction>(
onChanged: (v) => setState(() { values: LocationEditAction.values,
_action = v!; valueText: (v) => v.getText(context),
_validate(); value: _action,
}), onChanged: (v) => setState(() {
title: Row( _action = v!;
crossAxisAlignment: CrossAxisAlignment.start, _validate();
}),
isExpanded: true,
dropdownColor: Themes.thirdLayerColor(context),
),
),
AnimatedSwitcher(
duration: context.read<DurationsData>().formTransition,
switchInCurve: Curves.easeInOutCubic,
switchOutCurve: Curves.easeInOutCubic,
transitionBuilder: _formTransitionBuilder,
child: Column(
key: ValueKey(_action),
mainAxisSize: MainAxisSize.min,
children: [ children: [
Expanded( if (_action == LocationEditAction.chooseOnMap) _buildChooseOnMapContent(context),
child: Column( if (_action == LocationEditAction.copyItem) _buildCopyItemContent(context),
children: [ if (_action == LocationEditAction.setCustom) _buildSetCustomContent(context),
TextField(
controller: _latitudeController,
focusNode: _latitudeFocusNode,
decoration: InputDecoration(
labelText: l10n.editEntryLocationDialogLatitude,
hintText: coordinateFormatter.format(Constants.pointNemo.latitude),
),
onChanged: (_) => _validate(),
),
TextField(
controller: _longitudeController,
focusNode: _longitudeFocusNode,
decoration: InputDecoration(
labelText: l10n.editEntryLocationDialogLongitude,
hintText: coordinateFormatter.format(Constants.pointNemo.longitude),
),
onChanged: (_) => _validate(),
),
],
),
),
const SizedBox(width: 8),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: IconButton(
icon: const Icon(AIcons.map),
onPressed: _pickLocation,
tooltip: l10n.editEntryLocationDialogChooseOnMapTooltip,
),
),
], ],
), ),
contentPadding: const EdgeInsetsDirectional.only(start: 16, end: 8),
),
RadioListTile<_LocationAction>(
value: _LocationAction.remove,
groupValue: _action,
onChanged: (v) => setState(() {
_action = v!;
_latitudeFocusNode.unfocus();
_longitudeFocusNode.unfocus();
_validate();
}),
title: Text(l10n.actionRemove),
), ),
const SizedBox(height: 8),
], ],
actions: [ actions: [
TextButton( TextButton(
@ -142,22 +145,32 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
); );
} }
void _onLatLngFocusChange() { Widget _formTransitionBuilder(Widget child, Animation<double> animation) => FadeTransition(
if (_latitudeFocusNode.hasFocus || _longitudeFocusNode.hasFocus) { opacity: animation,
setState(() { child: SizeTransition(
_action = _LocationAction.set; sizeFactor: animation,
_validate(); axisAlignment: -1,
}); child: child,
} ),
} );
void _setLocation(BuildContext context, LatLng? latLng) { Widget _buildChooseOnMapContent(BuildContext context) {
_latitudeController.text = latLng != null ? coordinateFormatter.format(latLng.latitude) : ''; final l10n = context.l10n;
_longitudeController.text = latLng != null ? coordinateFormatter.format(latLng.longitude) : '';
setState(() { return Padding(
_action = _LocationAction.set; padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
_validate(); child: Row(
}); children: [
Expanded(child: _toText(context, _mapCoordinates)),
const SizedBox(width: 8),
IconButton(
icon: const Icon(AIcons.map),
onPressed: _pickLocation,
tooltip: l10n.editEntryLocationDialogChooseOnMap,
),
],
),
);
} }
Future<void> _pickLocation() async { Future<void> _pickLocation() async {
@ -176,7 +189,7 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
: null; : null;
return LocationPickDialog( return LocationPickDialog(
collection: mapCollection, collection: mapCollection,
initialLocation: _parseLatLng(), initialLocation: _mapCoordinates,
); );
}, },
fullscreenDialog: true, fullscreenDialog: true,
@ -184,7 +197,102 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
); );
if (latLng != null) { if (latLng != null) {
settings.mapDefaultCenter = latLng; settings.mapDefaultCenter = latLng;
_setLocation(context, latLng); setState(() {
_mapCoordinates = latLng;
_validate();
});
}
}
Widget _buildCopyItemContent(BuildContext context) {
return Padding(
padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
child: Row(
children: [
Expanded(child: _toText(context, _copyItemSource.latLng)),
const SizedBox(width: 8),
ItemPicker(
extent: 48,
entry: _copyItemSource,
onTap: _pickCopyItemSource,
),
],
),
);
}
Future<void> _pickCopyItemSource() async {
final _collection = widget.collection;
if (_collection == null) return;
final entry = await Navigator.push<AvesEntry>(
context,
MaterialPageRoute(
settings: const RouteSettings(name: ItemPickDialog.routeName),
builder: (context) => ItemPickDialog(
collection: CollectionLens(
source: _collection.source,
),
),
fullscreenDialog: true,
),
);
if (entry != null) {
setState(() {
_copyItemSource = entry;
_validate();
});
}
}
Widget _buildSetCustomContent(BuildContext context) {
final l10n = context.l10n;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
children: [
TextField(
controller: _latitudeController,
decoration: InputDecoration(
labelText: l10n.editEntryLocationDialogLatitude,
hintText: coordinateFormatter.format(Constants.pointNemo.latitude),
),
onChanged: (_) => _validate(),
),
TextField(
controller: _longitudeController,
decoration: InputDecoration(
labelText: l10n.editEntryLocationDialogLongitude,
hintText: coordinateFormatter.format(Constants.pointNemo.longitude),
),
onChanged: (_) => _validate(),
),
],
),
),
],
),
);
}
Text _toText(BuildContext context, LatLng? latLng) {
final l10n = context.l10n;
if (latLng != null) {
return Text(
ExtraCoordinateFormat.toDMS(l10n, latLng).join('\n'),
);
} else {
return Text(
l10n.viewerInfoUnknown,
style: TextStyle(
color: Theme.of(context).textTheme.bodySmall!.color,
),
);
} }
} }
@ -205,12 +313,18 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
return LatLng(lat, lng); return LatLng(lat, lng);
} }
Future<void> _validate() async { void _validate() {
switch (_action) { switch (_action) {
case _LocationAction.set: case LocationEditAction.chooseOnMap:
_isValidNotifier.value = _mapCoordinates != null;
break;
case LocationEditAction.copyItem:
_isValidNotifier.value = _copyItemSource.hasGps;
break;
case LocationEditAction.setCustom:
_isValidNotifier.value = _parseLatLng() != null; _isValidNotifier.value = _parseLatLng() != null;
break; break;
case _LocationAction.remove: case LocationEditAction.remove:
_isValidNotifier.value = true; _isValidNotifier.value = true;
break; break;
} }
@ -218,14 +332,18 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
void _submit(BuildContext context) { void _submit(BuildContext context) {
switch (_action) { switch (_action) {
case _LocationAction.set: case LocationEditAction.chooseOnMap:
Navigator.pop(context, _mapCoordinates);
break;
case LocationEditAction.copyItem:
Navigator.pop(context, _copyItemSource.latLng);
break;
case LocationEditAction.setCustom:
Navigator.pop(context, _parseLatLng()); Navigator.pop(context, _parseLatLng());
break; break;
case _LocationAction.remove: case LocationEditAction.remove:
Navigator.pop(context, LatLng(0, 0)); Navigator.pop(context, LatLng(0, 0));
break; break;
} }
} }
} }
enum _LocationAction { set, remove }

View file

@ -1,4 +1,5 @@
import 'package:aves/model/metadata/enums.dart'; import 'package:aves/model/metadata/enums/enums.dart';
import 'package:aves/model/metadata/enums/metadata_type.dart';
import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/enums/enums.dart';
import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/settings/settings.dart';
import 'package:aves/ref/brand_colors.dart'; import 'package:aves/ref/brand_colors.dart';

View file

@ -1,12 +1,17 @@
{ {
"de": [ "de": [
"widgetOpenPageCollection", "editEntryLocationDialogSetCustom"
"durationDialogSeconds"
], ],
"el": [ "el": [
"editEntryLocationDialogSetCustom"
],
"es": [
"widgetOpenPageHome",
"widgetOpenPageCollection", "widgetOpenPageCollection",
"durationDialogSeconds" "widgetOpenPageViewer",
"editEntryLocationDialogSetCustom"
], ],
"fa": [ "fa": [
@ -212,11 +217,11 @@
"exportEntryDialogWidth", "exportEntryDialogWidth",
"exportEntryDialogHeight", "exportEntryDialogHeight",
"renameEntryDialogLabel", "renameEntryDialogLabel",
"editEntryDialogCopyFromItem",
"editEntryDialogTargetFieldsHeader", "editEntryDialogTargetFieldsHeader",
"editEntryDateDialogTitle", "editEntryDateDialogTitle",
"editEntryDateDialogSetCustom", "editEntryDateDialogSetCustom",
"editEntryDateDialogCopyField", "editEntryDateDialogCopyField",
"editEntryDialogCopyFromItem",
"editEntryDateDialogExtractFromTitle", "editEntryDateDialogExtractFromTitle",
"editEntryDateDialogShift", "editEntryDateDialogShift",
"editEntryDateDialogSourceFileModifiedDate", "editEntryDateDialogSourceFileModifiedDate",
@ -224,7 +229,457 @@
"durationDialogMinutes", "durationDialogMinutes",
"durationDialogSeconds", "durationDialogSeconds",
"editEntryLocationDialogTitle", "editEntryLocationDialogTitle",
"editEntryLocationDialogChooseOnMapTooltip", "editEntryLocationDialogSetCustom",
"editEntryLocationDialogChooseOnMap",
"editEntryLocationDialogLatitude",
"editEntryLocationDialogLongitude",
"locationPickerUseThisLocationButton",
"editEntryRatingDialogTitle",
"removeEntryMetadataDialogTitle",
"removeEntryMetadataDialogMore",
"removeEntryMetadataMotionPhotoXmpWarningDialogMessage",
"convertMotionPhotoToStillImageWarningDialogMessage",
"videoSpeedDialogLabel",
"videoStreamSelectionDialogVideo",
"videoStreamSelectionDialogAudio",
"videoStreamSelectionDialogText",
"videoStreamSelectionDialogOff",
"videoStreamSelectionDialogTrack",
"videoStreamSelectionDialogNoSelection",
"genericSuccessFeedback",
"genericFailureFeedback",
"menuActionConfigureView",
"menuActionSelect",
"menuActionSelectAll",
"menuActionSelectNone",
"menuActionMap",
"menuActionSlideshow",
"menuActionStats",
"viewDialogSortSectionTitle",
"viewDialogGroupSectionTitle",
"viewDialogLayoutSectionTitle",
"viewDialogReverseSortOrder",
"tileLayoutMosaic",
"tileLayoutGrid",
"tileLayoutList",
"coverDialogTabCover",
"coverDialogTabApp",
"coverDialogTabColor",
"appPickDialogTitle",
"appPickDialogNone",
"aboutPageTitle",
"aboutLinkLicense",
"aboutLinkPolicy",
"aboutBugSectionTitle",
"aboutBugSaveLogInstruction",
"aboutBugCopyInfoInstruction",
"aboutBugCopyInfoButton",
"aboutBugReportInstruction",
"aboutBugReportButton",
"aboutCreditsSectionTitle",
"aboutCreditsWorldAtlas1",
"aboutCreditsWorldAtlas2",
"aboutTranslatorsSectionTitle",
"aboutLicensesSectionTitle",
"aboutLicensesBanner",
"aboutLicensesAndroidLibrariesSectionTitle",
"aboutLicensesFlutterPluginsSectionTitle",
"aboutLicensesFlutterPackagesSectionTitle",
"aboutLicensesDartPackagesSectionTitle",
"aboutLicensesShowAllButtonLabel",
"policyPageTitle",
"collectionPageTitle",
"collectionPickPageTitle",
"collectionSelectPageTitle",
"collectionActionShowTitleSearch",
"collectionActionHideTitleSearch",
"collectionActionAddShortcut",
"collectionActionEmptyBin",
"collectionActionCopy",
"collectionActionMove",
"collectionActionRescan",
"collectionActionEdit",
"collectionSearchTitlesHintText",
"collectionGroupAlbum",
"collectionGroupMonth",
"collectionGroupDay",
"collectionGroupNone",
"sectionUnknown",
"dateToday",
"dateYesterday",
"dateThisMonth",
"collectionDeleteFailureFeedback",
"collectionCopyFailureFeedback",
"collectionMoveFailureFeedback",
"collectionRenameFailureFeedback",
"collectionEditFailureFeedback",
"collectionExportFailureFeedback",
"collectionCopySuccessFeedback",
"collectionMoveSuccessFeedback",
"collectionRenameSuccessFeedback",
"collectionEditSuccessFeedback",
"collectionEmptyFavourites",
"collectionEmptyVideos",
"collectionEmptyImages",
"collectionEmptyGrantAccessButtonLabel",
"collectionSelectSectionTooltip",
"collectionDeselectSectionTooltip",
"drawerAboutButton",
"drawerSettingsButton",
"drawerCollectionAll",
"drawerCollectionFavourites",
"drawerCollectionImages",
"drawerCollectionVideos",
"drawerCollectionAnimated",
"drawerCollectionMotionPhotos",
"drawerCollectionPanoramas",
"drawerCollectionRaws",
"drawerCollectionSphericalVideos",
"drawerAlbumPage",
"drawerCountryPage",
"drawerTagPage",
"sortByDate",
"sortByName",
"sortByItemCount",
"sortBySize",
"sortByAlbumFileName",
"sortByRating",
"sortOrderNewestFirst",
"sortOrderOldestFirst",
"sortOrderAtoZ",
"sortOrderZtoA",
"sortOrderHighestFirst",
"sortOrderLowestFirst",
"sortOrderLargestFirst",
"sortOrderSmallestFirst",
"albumGroupTier",
"albumGroupType",
"albumGroupVolume",
"albumGroupNone",
"albumMimeTypeMixed",
"albumPickPageTitleCopy",
"albumPickPageTitleExport",
"albumPickPageTitleMove",
"albumPickPageTitlePick",
"albumCamera",
"albumDownload",
"albumScreenshots",
"albumScreenRecordings",
"albumVideoCaptures",
"albumPageTitle",
"albumEmpty",
"createAlbumTooltip",
"createAlbumButtonLabel",
"newFilterBanner",
"countryPageTitle",
"countryEmpty",
"tagPageTitle",
"tagEmpty",
"binPageTitle",
"searchCollectionFieldHint",
"searchRecentSectionTitle",
"searchDateSectionTitle",
"searchAlbumsSectionTitle",
"searchCountriesSectionTitle",
"searchPlacesSectionTitle",
"searchTagsSectionTitle",
"searchRatingSectionTitle",
"searchMetadataSectionTitle",
"settingsPageTitle",
"settingsSystemDefault",
"settingsDefault",
"settingsDisabled",
"settingsSearchFieldLabel",
"settingsSearchEmpty",
"settingsActionExport",
"settingsActionExportDialogTitle",
"settingsActionImport",
"settingsActionImportDialogTitle",
"appExportCovers",
"appExportFavourites",
"appExportSettings",
"settingsNavigationSectionTitle",
"settingsHomeTile",
"settingsHomeDialogTitle",
"settingsShowBottomNavigationBar",
"settingsKeepScreenOnTile",
"settingsKeepScreenOnDialogTitle",
"settingsDoubleBackExit",
"settingsConfirmationTile",
"settingsConfirmationDialogTitle",
"settingsConfirmationBeforeDeleteItems",
"settingsConfirmationBeforeMoveToBinItems",
"settingsConfirmationBeforeMoveUndatedItems",
"settingsConfirmationAfterMoveToBinItems",
"settingsNavigationDrawerTile",
"settingsNavigationDrawerEditorPageTitle",
"settingsNavigationDrawerBanner",
"settingsNavigationDrawerTabTypes",
"settingsNavigationDrawerTabAlbums",
"settingsNavigationDrawerTabPages",
"settingsNavigationDrawerAddAlbum",
"settingsThumbnailSectionTitle",
"settingsThumbnailOverlayTile",
"settingsThumbnailOverlayPageTitle",
"settingsThumbnailShowFavouriteIcon",
"settingsThumbnailShowTagIcon",
"settingsThumbnailShowLocationIcon",
"settingsThumbnailShowMotionPhotoIcon",
"settingsThumbnailShowRating",
"settingsThumbnailShowRawIcon",
"settingsThumbnailShowVideoDuration",
"settingsCollectionQuickActionsTile",
"settingsCollectionQuickActionEditorPageTitle",
"settingsCollectionQuickActionTabBrowsing",
"settingsCollectionQuickActionTabSelecting",
"settingsCollectionBrowsingQuickActionEditorBanner",
"settingsCollectionSelectionQuickActionEditorBanner",
"settingsViewerSectionTitle",
"settingsViewerGestureSideTapNext",
"settingsViewerUseCutout",
"settingsViewerMaximumBrightness",
"settingsMotionPhotoAutoPlay",
"settingsImageBackground",
"settingsViewerQuickActionsTile",
"settingsViewerQuickActionEditorPageTitle",
"settingsViewerQuickActionEditorBanner",
"settingsViewerQuickActionEditorDisplayedButtonsSectionTitle",
"settingsViewerQuickActionEditorAvailableButtonsSectionTitle",
"settingsViewerQuickActionEmpty",
"settingsViewerOverlayTile",
"settingsViewerOverlayPageTitle",
"settingsViewerShowOverlayOnOpening",
"settingsViewerShowMinimap",
"settingsViewerShowInformation",
"settingsViewerShowInformationSubtitle",
"settingsViewerShowShootingDetails",
"settingsViewerShowOverlayThumbnails",
"settingsViewerEnableOverlayBlurEffect",
"settingsViewerSlideshowTile",
"settingsViewerSlideshowPageTitle",
"settingsSlideshowRepeat",
"settingsSlideshowShuffle",
"settingsSlideshowFillScreen",
"settingsSlideshowAnimatedZoomEffect",
"settingsSlideshowTransitionTile",
"settingsSlideshowIntervalTile",
"settingsSlideshowVideoPlaybackTile",
"settingsSlideshowVideoPlaybackDialogTitle",
"settingsVideoPageTitle",
"settingsVideoSectionTitle",
"settingsVideoShowVideos",
"settingsVideoEnableHardwareAcceleration",
"settingsVideoAutoPlay",
"settingsVideoLoopModeTile",
"settingsVideoLoopModeDialogTitle",
"settingsSubtitleThemeTile",
"settingsSubtitleThemePageTitle",
"settingsSubtitleThemeSample",
"settingsSubtitleThemeTextAlignmentTile",
"settingsSubtitleThemeTextAlignmentDialogTitle",
"settingsSubtitleThemeTextSize",
"settingsSubtitleThemeShowOutline",
"settingsSubtitleThemeTextColor",
"settingsSubtitleThemeTextOpacity",
"settingsSubtitleThemeBackgroundColor",
"settingsSubtitleThemeBackgroundOpacity",
"settingsSubtitleThemeTextAlignmentLeft",
"settingsSubtitleThemeTextAlignmentCenter",
"settingsSubtitleThemeTextAlignmentRight",
"settingsVideoControlsTile",
"settingsVideoControlsPageTitle",
"settingsVideoButtonsTile",
"settingsVideoGestureDoubleTapTogglePlay",
"settingsVideoGestureSideDoubleTapSeek",
"settingsPrivacySectionTitle",
"settingsAllowInstalledAppAccess",
"settingsAllowInstalledAppAccessSubtitle",
"settingsAllowErrorReporting",
"settingsSaveSearchHistory",
"settingsEnableBin",
"settingsEnableBinSubtitle",
"settingsHiddenItemsTile",
"settingsHiddenItemsPageTitle",
"settingsHiddenItemsTabFilters",
"settingsHiddenFiltersBanner",
"settingsHiddenFiltersEmpty",
"settingsHiddenItemsTabPaths",
"settingsHiddenPathsBanner",
"addPathTooltip",
"settingsStorageAccessTile",
"settingsStorageAccessPageTitle",
"settingsStorageAccessBanner",
"settingsStorageAccessEmpty",
"settingsStorageAccessRevokeTooltip",
"settingsAccessibilitySectionTitle",
"settingsRemoveAnimationsTile",
"settingsRemoveAnimationsDialogTitle",
"settingsTimeToTakeActionTile",
"settingsDisplaySectionTitle",
"settingsThemeBrightnessTile",
"settingsThemeBrightnessDialogTitle",
"settingsThemeColorHighlights",
"settingsThemeEnableDynamicColor",
"settingsDisplayRefreshRateModeTile",
"settingsDisplayRefreshRateModeDialogTitle",
"settingsLanguageSectionTitle",
"settingsLanguageTile",
"settingsLanguagePageTitle",
"settingsCoordinateFormatTile",
"settingsCoordinateFormatDialogTitle",
"settingsUnitSystemTile",
"settingsUnitSystemDialogTitle",
"settingsScreenSaverPageTitle",
"settingsWidgetPageTitle",
"settingsWidgetShowOutline",
"settingsWidgetOpenPage",
"settingsCollectionTile",
"statsPageTitle",
"statsWithGps",
"statsTopCountriesSectionTitle",
"statsTopPlacesSectionTitle",
"statsTopTagsSectionTitle",
"statsTopAlbumsSectionTitle",
"viewerOpenPanoramaButtonLabel",
"viewerSetWallpaperButtonLabel",
"viewerErrorUnknown",
"viewerErrorDoesNotExist",
"viewerInfoPageTitle",
"viewerInfoBackToViewerTooltip",
"viewerInfoUnknown",
"viewerInfoLabelDescription",
"viewerInfoLabelTitle",
"viewerInfoLabelDate",
"viewerInfoLabelResolution",
"viewerInfoLabelSize",
"viewerInfoLabelUri",
"viewerInfoLabelPath",
"viewerInfoLabelDuration",
"viewerInfoLabelOwner",
"viewerInfoLabelCoordinates",
"viewerInfoLabelAddress",
"mapStyleDialogTitle",
"mapStyleTooltip",
"mapZoomInTooltip",
"mapZoomOutTooltip",
"mapPointNorthUpTooltip",
"mapAttributionOsmHot",
"mapAttributionStamen",
"openMapPageTooltip",
"mapEmptyRegion",
"viewerInfoOpenEmbeddedFailureFeedback",
"viewerInfoOpenLinkText",
"viewerInfoViewXmlLinkText",
"viewerInfoSearchFieldLabel",
"viewerInfoSearchEmpty",
"viewerInfoSearchSuggestionDate",
"viewerInfoSearchSuggestionDescription",
"viewerInfoSearchSuggestionDimensions",
"viewerInfoSearchSuggestionResolution",
"viewerInfoSearchSuggestionRights",
"wallpaperUseScrollEffect",
"tagEditorPageTitle",
"tagEditorPageNewTagFieldLabel",
"tagEditorPageAddTagTooltip",
"tagEditorSectionRecent",
"panoramaEnableSensorControl",
"panoramaDisableSensorControl",
"sourceViewerPageTitle",
"filePickerShowHiddenFiles",
"filePickerDoNotShowHiddenFiles",
"filePickerOpenFrom",
"filePickerNoItems",
"filePickerUseThisFolder"
],
"fr": [
"editEntryLocationDialogSetCustom"
],
"gl": [
"accessibilityAnimationsRemove",
"accessibilityAnimationsKeep",
"displayRefreshRatePreferHighest",
"displayRefreshRatePreferLowest",
"videoPlaybackSkip",
"videoPlaybackMuted",
"videoPlaybackWithSound",
"themeBrightnessLight",
"themeBrightnessDark",
"themeBrightnessBlack",
"viewerTransitionSlide",
"viewerTransitionParallax",
"viewerTransitionFade",
"viewerTransitionZoomIn",
"viewerTransitionNone",
"wallpaperTargetHome",
"wallpaperTargetLock",
"wallpaperTargetHomeLock",
"widgetOpenPageHome",
"widgetOpenPageCollection",
"widgetOpenPageViewer",
"albumTierNew",
"albumTierPinned",
"albumTierSpecial",
"albumTierApps",
"albumTierRegular",
"storageVolumeDescriptionFallbackPrimary",
"storageVolumeDescriptionFallbackNonPrimary",
"rootDirectoryDescription",
"otherDirectoryDescription",
"storageAccessDialogMessage",
"restrictedAccessDialogMessage",
"notEnoughSpaceDialogMessage",
"missingSystemFilePickerDialogMessage",
"unsupportedTypeDialogMessage",
"nameConflictDialogSingleSourceMessage",
"nameConflictDialogMultipleSourceMessage",
"addShortcutDialogLabel",
"addShortcutButtonLabel",
"noMatchingAppDialogMessage",
"binEntriesConfirmationDialogMessage",
"deleteEntriesConfirmationDialogMessage",
"moveUndatedConfirmationDialogMessage",
"moveUndatedConfirmationDialogSetDate",
"videoResumeDialogMessage",
"videoStartOverButtonLabel",
"videoResumeButtonLabel",
"setCoverDialogLatest",
"setCoverDialogAuto",
"setCoverDialogCustom",
"hideFilterConfirmationDialogMessage",
"newAlbumDialogTitle",
"newAlbumDialogNameLabel",
"newAlbumDialogNameLabelAlreadyExistsHelper",
"newAlbumDialogStorageLabel",
"renameAlbumDialogLabel",
"renameAlbumDialogLabelAlreadyExistsHelper",
"renameEntrySetPageTitle",
"renameEntrySetPagePatternFieldLabel",
"renameEntrySetPageInsertTooltip",
"renameEntrySetPagePreviewSectionTitle",
"renameProcessorCounter",
"renameProcessorName",
"deleteSingleAlbumConfirmationDialogMessage",
"deleteMultiAlbumConfirmationDialogMessage",
"exportEntryDialogFormat",
"exportEntryDialogWidth",
"exportEntryDialogHeight",
"renameEntryDialogLabel",
"editEntryDialogCopyFromItem",
"editEntryDialogTargetFieldsHeader",
"editEntryDateDialogTitle",
"editEntryDateDialogSetCustom",
"editEntryDateDialogCopyField",
"editEntryDateDialogExtractFromTitle",
"editEntryDateDialogShift",
"editEntryDateDialogSourceFileModifiedDate",
"durationDialogHours",
"durationDialogMinutes",
"durationDialogSeconds",
"editEntryLocationDialogTitle",
"editEntryLocationDialogSetCustom",
"editEntryLocationDialogChooseOnMap",
"editEntryLocationDialogLatitude", "editEntryLocationDialogLatitude",
"editEntryLocationDialogLongitude", "editEntryLocationDialogLongitude",
"locationPickerUseThisLocationButton", "locationPickerUseThisLocationButton",
@ -594,6 +1049,7 @@
"widgetOpenPageCollection", "widgetOpenPageCollection",
"widgetOpenPageViewer", "widgetOpenPageViewer",
"durationDialogSeconds", "durationDialogSeconds",
"editEntryLocationDialogSetCustom",
"tileLayoutMosaic", "tileLayoutMosaic",
"albumGroupType", "albumGroupType",
"albumMimeTypeMixed", "albumMimeTypeMixed",
@ -605,8 +1061,7 @@
], ],
"it": [ "it": [
"widgetOpenPageCollection", "editEntryLocationDialogSetCustom"
"durationDialogSeconds"
], ],
"ja": [ "ja": [
@ -621,6 +1076,7 @@
"widgetOpenPageCollection", "widgetOpenPageCollection",
"widgetOpenPageViewer", "widgetOpenPageViewer",
"durationDialogSeconds", "durationDialogSeconds",
"editEntryLocationDialogSetCustom",
"viewDialogReverseSortOrder", "viewDialogReverseSortOrder",
"tileLayoutMosaic", "tileLayoutMosaic",
"sortOrderNewestFirst", "sortOrderNewestFirst",
@ -644,6 +1100,10 @@
"wallpaperUseScrollEffect" "wallpaperUseScrollEffect"
], ],
"ko": [
"editEntryLocationDialogSetCustom"
],
"nb": [ "nb": [
"videoActionCaptureFrame", "videoActionCaptureFrame",
"videoActionSelectStreams", "videoActionSelectStreams",
@ -672,6 +1132,7 @@
"editEntryDateDialogShift", "editEntryDateDialogShift",
"editEntryDateDialogSourceFileModifiedDate", "editEntryDateDialogSourceFileModifiedDate",
"editEntryLocationDialogTitle", "editEntryLocationDialogTitle",
"editEntryLocationDialogSetCustom",
"locationPickerUseThisLocationButton", "locationPickerUseThisLocationButton",
"removeEntryMetadataMotionPhotoXmpWarningDialogMessage", "removeEntryMetadataMotionPhotoXmpWarningDialogMessage",
"videoStreamSelectionDialogText", "videoStreamSelectionDialogText",
@ -756,6 +1217,7 @@
"widgetOpenPageCollection", "widgetOpenPageCollection",
"widgetOpenPageViewer", "widgetOpenPageViewer",
"durationDialogSeconds", "durationDialogSeconds",
"editEntryLocationDialogSetCustom",
"aboutLinkPolicy", "aboutLinkPolicy",
"policyPageTitle" "policyPageTitle"
], ],
@ -870,11 +1332,11 @@
"exportEntryDialogWidth", "exportEntryDialogWidth",
"exportEntryDialogHeight", "exportEntryDialogHeight",
"renameEntryDialogLabel", "renameEntryDialogLabel",
"editEntryDialogCopyFromItem",
"editEntryDialogTargetFieldsHeader", "editEntryDialogTargetFieldsHeader",
"editEntryDateDialogTitle", "editEntryDateDialogTitle",
"editEntryDateDialogSetCustom", "editEntryDateDialogSetCustom",
"editEntryDateDialogCopyField", "editEntryDateDialogCopyField",
"editEntryDialogCopyFromItem",
"editEntryDateDialogExtractFromTitle", "editEntryDateDialogExtractFromTitle",
"editEntryDateDialogShift", "editEntryDateDialogShift",
"editEntryDateDialogSourceFileModifiedDate", "editEntryDateDialogSourceFileModifiedDate",
@ -882,7 +1344,8 @@
"durationDialogMinutes", "durationDialogMinutes",
"durationDialogSeconds", "durationDialogSeconds",
"editEntryLocationDialogTitle", "editEntryLocationDialogTitle",
"editEntryLocationDialogChooseOnMapTooltip", "editEntryLocationDialogSetCustom",
"editEntryLocationDialogChooseOnMap",
"editEntryLocationDialogLatitude", "editEntryLocationDialogLatitude",
"editEntryLocationDialogLongitude", "editEntryLocationDialogLongitude",
"locationPickerUseThisLocationButton", "locationPickerUseThisLocationButton",
@ -1245,7 +1708,11 @@
], ],
"pt": [ "pt": [
"durationDialogSeconds" "editEntryLocationDialogSetCustom"
],
"ru": [
"editEntryLocationDialogSetCustom"
], ],
"tr": [ "tr": [
@ -1273,6 +1740,7 @@
"widgetOpenPageCollection", "widgetOpenPageCollection",
"widgetOpenPageViewer", "widgetOpenPageViewer",
"durationDialogSeconds", "durationDialogSeconds",
"editEntryLocationDialogSetCustom",
"menuActionSlideshow", "menuActionSlideshow",
"viewDialogReverseSortOrder", "viewDialogReverseSortOrder",
"tileLayoutMosaic", "tileLayoutMosaic",
@ -1310,7 +1778,6 @@
], ],
"zh": [ "zh": [
"widgetOpenPageCollection", "editEntryLocationDialogSetCustom"
"durationDialogSeconds"
] ]
} }