#117 info: set date from title
This commit is contained in:
parent
91da9db1c0
commit
805005bb87
7 changed files with 93 additions and 0 deletions
|
@ -360,6 +360,8 @@
|
|||
"@editEntryDateDialogSet": {},
|
||||
"editEntryDateDialogShift": "Shift",
|
||||
"@editEntryDateDialogShift": {},
|
||||
"editEntryDateDialogFromTitle": "From title",
|
||||
"@editEntryDateDialogFromTitle": {},
|
||||
"editEntryDateDialogClear": "Clear",
|
||||
"@editEntryDateDialogClear": {},
|
||||
"editEntryDateDialogFieldSelection": "Field selection",
|
||||
|
|
|
@ -18,6 +18,7 @@ import 'package:aves/services/geocoding_service.dart';
|
|||
import 'package:aves/services/metadata/svg_metadata_service.dart';
|
||||
import 'package:aves/theme/format.dart';
|
||||
import 'package:aves/utils/change_notifier.dart';
|
||||
import 'package:aves/utils/time_utils.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:country_code/country_code.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -635,6 +636,16 @@ class AvesEntry {
|
|||
}
|
||||
|
||||
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);
|
||||
return newFields.isNotEmpty;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ enum MetadataField {
|
|||
enum DateEditAction {
|
||||
set,
|
||||
shift,
|
||||
fromTitle,
|
||||
clear,
|
||||
}
|
||||
|
||||
|
|
|
@ -13,3 +13,58 @@ extension ExtraDateTime on DateTime {
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>(
|
||||
value: DateEditAction.clear,
|
||||
groupValue: _action,
|
||||
|
@ -128,6 +134,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
|||
scrollableContent: [
|
||||
setTile,
|
||||
shiftTile,
|
||||
fromTitleTile,
|
||||
clearTile,
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 1),
|
||||
|
@ -243,6 +250,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
|||
case DateEditAction.shift:
|
||||
modifier = DateModifier(_action, _fields, shiftMinutes: _shiftMinutes);
|
||||
break;
|
||||
case DateEditAction.fromTitle:
|
||||
case DateEditAction.clear:
|
||||
modifier = DateModifier(_action, _fields);
|
||||
break;
|
||||
|
|
|
@ -15,4 +15,15 @@ void main() {
|
|||
expect(DateTime(1903, 9, 25).isAtSameDayAs(DateTime(1970, 2, 25)), false);
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
{
|
||||
"ko": [
|
||||
"editEntryDateDialogFromTitle"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
"editEntryDateDialogFromTitle",
|
||||
"aboutCreditsTranslators"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue