#117 info: set date from title

This commit is contained in:
Thibault Deckers 2021-10-28 15:23:31 +09:00
parent 91da9db1c0
commit 805005bb87
7 changed files with 93 additions and 0 deletions

View file

@ -360,6 +360,8 @@
"@editEntryDateDialogSet": {}, "@editEntryDateDialogSet": {},
"editEntryDateDialogShift": "Shift", "editEntryDateDialogShift": "Shift",
"@editEntryDateDialogShift": {}, "@editEntryDateDialogShift": {},
"editEntryDateDialogFromTitle": "From title",
"@editEntryDateDialogFromTitle": {},
"editEntryDateDialogClear": "Clear", "editEntryDateDialogClear": "Clear",
"@editEntryDateDialogClear": {}, "@editEntryDateDialogClear": {},
"editEntryDateDialogFieldSelection": "Field selection", "editEntryDateDialogFieldSelection": "Field selection",

View file

@ -18,6 +18,7 @@ import 'package:aves/services/geocoding_service.dart';
import 'package:aves/services/metadata/svg_metadata_service.dart'; import 'package:aves/services/metadata/svg_metadata_service.dart';
import 'package:aves/theme/format.dart'; import 'package:aves/theme/format.dart';
import 'package:aves/utils/change_notifier.dart'; import 'package:aves/utils/change_notifier.dart';
import 'package:aves/utils/time_utils.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:country_code/country_code.dart'; import 'package:country_code/country_code.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -635,6 +636,16 @@ class AvesEntry {
} }
Future<bool> editDate(DateModifier modifier) async { Future<bool> editDate(DateModifier modifier) async {
if (modifier.action == DateEditAction.fromTitle) {
final _title = bestTitle;
if (_title == null) return false;
final date = parseUnknownDateFormat(_title);
if (date == null) {
await reportService.recordError('failed to parse date from title=$_title', null);
return false;
}
modifier = DateModifier(DateEditAction.set, modifier.fields, dateTime: date);
}
final newFields = await metadataEditService.editDate(this, modifier); final newFields = await metadataEditService.editDate(this, modifier);
return newFields.isNotEmpty; return newFields.isNotEmpty;
} }

View file

@ -8,6 +8,7 @@ enum MetadataField {
enum DateEditAction { enum DateEditAction {
set, set,
shift, shift,
fromTitle,
clear, clear,
} }

View file

@ -13,3 +13,58 @@ extension ExtraDateTime on DateTime {
bool get isThisYear => isAtSameYearAs(DateTime.now()); bool get isThisYear => isAtSameYearAs(DateTime.now());
} }
final _unixStampMillisPattern = RegExp(r'\d{13}');
final _unixStampSecPattern = RegExp(r'\d{10}');
final _plainPattern = RegExp(r'(\d{8})([_-\s](\d{6})([_-\s](\d{3}))?)?');
DateTime? parseUnknownDateFormat(String s) {
var match = _unixStampMillisPattern.firstMatch(s);
if (match != null) {
final stampString = match.group(0);
if (stampString != null) {
final stampMillis = int.tryParse(stampString);
if (stampMillis != null) {
return DateTime.fromMillisecondsSinceEpoch(stampMillis, isUtc: false);
}
}
}
match = _unixStampSecPattern.firstMatch(s);
if (match != null) {
final stampString = match.group(0);
if (stampString != null) {
final stampMillis = int.tryParse(stampString);
if (stampMillis != null) {
return DateTime.fromMillisecondsSinceEpoch(stampMillis * 1000, isUtc: false);
}
}
}
match = _plainPattern.firstMatch(s);
if (match != null) {
final dateString = match.group(1);
final timeString = match.group(3);
final millisString = match.group(5);
if (dateString != null) {
final year = int.tryParse(dateString.substring(0, 4));
final month = int.tryParse(dateString.substring(4, 6));
final day = int.tryParse(dateString.substring(6, 8));
if (year != null && month != null && day != null) {
var hour = 0, minute = 0, second = 0, millis = 0;
if (timeString != null) {
hour = int.tryParse(timeString.substring(0, 2)) ?? 0;
minute = int.tryParse(timeString.substring(2, 4)) ?? 0;
second = int.tryParse(timeString.substring(4, 6)) ?? 0;
if (millisString != null) {
millis = int.tryParse(millisString) ?? 0;
}
}
return DateTime(year, month, day, hour, minute, second, millis);
}
}
}
}

View file

@ -106,6 +106,12 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
), ),
], ],
); );
final fromTitleTile = RadioListTile<DateEditAction>(
value: DateEditAction.fromTitle,
groupValue: _action,
onChanged: _updateAction,
title: _tileText(l10n.editEntryDateDialogFromTitle),
);
final clearTile = RadioListTile<DateEditAction>( final clearTile = RadioListTile<DateEditAction>(
value: DateEditAction.clear, value: DateEditAction.clear,
groupValue: _action, groupValue: _action,
@ -128,6 +134,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
scrollableContent: [ scrollableContent: [
setTile, setTile,
shiftTile, shiftTile,
fromTitleTile,
clearTile, clearTile,
Padding( Padding(
padding: const EdgeInsets.only(bottom: 1), padding: const EdgeInsets.only(bottom: 1),
@ -243,6 +250,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
case DateEditAction.shift: case DateEditAction.shift:
modifier = DateModifier(_action, _fields, shiftMinutes: _shiftMinutes); modifier = DateModifier(_action, _fields, shiftMinutes: _shiftMinutes);
break; break;
case DateEditAction.fromTitle:
case DateEditAction.clear: case DateEditAction.clear:
modifier = DateModifier(_action, _fields); modifier = DateModifier(_action, _fields);
break; break;

View file

@ -15,4 +15,15 @@ void main() {
expect(DateTime(1903, 9, 25).isAtSameDayAs(DateTime(1970, 2, 25)), false); expect(DateTime(1903, 9, 25).isAtSameDayAs(DateTime(1970, 2, 25)), false);
expect(DateTime(1929, 3, 22).isAtSameDayAs(DateTime(1929, 3, 22)), true); expect(DateTime(1929, 3, 22).isAtSameDayAs(DateTime(1929, 3, 22)), true);
}); });
test('Parse dates', () {
expect(parseUnknownDateFormat('1600995564713'), DateTime(2020, 09, 25, 09, 59, 24, 713));
expect(parseUnknownDateFormat('pre1600995564713suf'), DateTime(2020, 09, 25, 09, 59, 24, 713));
expect(parseUnknownDateFormat('1600995564'), DateTime(2020, 09, 25, 09, 59, 24, 0));
expect(parseUnknownDateFormat('pre1600995564suf'), DateTime(2020, 09, 25, 09, 59, 24, 0));
expect(parseUnknownDateFormat('IMG_20210901_142523_783'), DateTime(2021, 09, 1, 14, 25, 23, 783));
expect(parseUnknownDateFormat('Screenshot_20211028-115056_Aves'), DateTime(2021, 10, 28, 11, 50, 56, 0));
});
} }

View file

@ -1,5 +1,10 @@
{ {
"ko": [
"editEntryDateDialogFromTitle"
],
"ru": [ "ru": [
"editEntryDateDialogFromTitle",
"aboutCreditsTranslators" "aboutCreditsTranslators"
] ]
} }