#203 info: copy date from other item
This commit is contained in:
parent
318ee1385e
commit
150e94cee5
13 changed files with 174 additions and 47 deletions
|
@ -335,6 +335,7 @@
|
||||||
"editEntryDateDialogTitle": "Date & Time",
|
"editEntryDateDialogTitle": "Date & Time",
|
||||||
"editEntryDateDialogSetCustom": "Set custom date",
|
"editEntryDateDialogSetCustom": "Set custom date",
|
||||||
"editEntryDateDialogCopyField": "Copy from other date",
|
"editEntryDateDialogCopyField": "Copy from other date",
|
||||||
|
"editEntryDateDialogCopyItem": "Copy from other item",
|
||||||
"editEntryDateDialogExtractFromTitle": "Extract from title",
|
"editEntryDateDialogExtractFromTitle": "Extract from title",
|
||||||
"editEntryDateDialogShift": "Shift",
|
"editEntryDateDialogShift": "Shift",
|
||||||
"editEntryDateDialogSourceFileModifiedDate": "File modified date",
|
"editEntryDateDialogSourceFileModifiedDate": "File modified date",
|
||||||
|
|
|
@ -42,6 +42,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
||||||
switch (appliedModifier.action) {
|
switch (appliedModifier.action) {
|
||||||
case DateEditAction.setCustom:
|
case DateEditAction.setCustom:
|
||||||
case DateEditAction.copyField:
|
case DateEditAction.copyField:
|
||||||
|
case DateEditAction.copyItem:
|
||||||
case DateEditAction.extractFromTitle:
|
case DateEditAction.extractFromTitle:
|
||||||
editCreateDateXmp(descriptions, appliedModifier.setDateTime);
|
editCreateDateXmp(descriptions, appliedModifier.setDateTime);
|
||||||
break;
|
break;
|
||||||
|
@ -319,6 +320,7 @@ extension ExtraAvesEntryMetadataEdition on AvesEntry {
|
||||||
final date = parseUnknownDateFormat(bestTitle);
|
final date = parseUnknownDateFormat(bestTitle);
|
||||||
return date != null ? DateModifier.setCustom(mainMetadataDate(), date) : null;
|
return date != null ? DateModifier.setCustom(mainMetadataDate(), date) : null;
|
||||||
case DateEditAction.setCustom:
|
case DateEditAction.setCustom:
|
||||||
|
case DateEditAction.copyItem:
|
||||||
return DateModifier.setCustom(mainMetadataDate(), modifier.setDateTime!);
|
return DateModifier.setCustom(mainMetadataDate(), modifier.setDateTime!);
|
||||||
case DateEditAction.shift:
|
case DateEditAction.shift:
|
||||||
case DateEditAction.remove:
|
case DateEditAction.remove:
|
||||||
|
|
|
@ -24,30 +24,30 @@ class DateModifier extends Equatable {
|
||||||
List<Object?> get props => [action, fields, setDateTime, copyFieldSource, shiftMinutes];
|
List<Object?> get props => [action, fields, setDateTime, copyFieldSource, shiftMinutes];
|
||||||
|
|
||||||
const DateModifier._private(
|
const DateModifier._private(
|
||||||
this.action,
|
this.action, {
|
||||||
this.fields, {
|
this.fields = const {},
|
||||||
this.setDateTime,
|
this.setDateTime,
|
||||||
this.copyFieldSource,
|
this.copyFieldSource,
|
||||||
this.shiftMinutes,
|
this.shiftMinutes,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory DateModifier.setCustom(Set<MetadataField> fields, DateTime dateTime) {
|
factory DateModifier.setCustom(Set<MetadataField> fields, DateTime dateTime) {
|
||||||
return DateModifier._private(DateEditAction.setCustom, fields, setDateTime: dateTime);
|
return DateModifier._private(DateEditAction.setCustom, fields: fields, setDateTime: dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory DateModifier.copyField(Set<MetadataField> fields, DateFieldSource copyFieldSource) {
|
factory DateModifier.copyField(DateFieldSource copyFieldSource) {
|
||||||
return DateModifier._private(DateEditAction.copyField, fields, copyFieldSource: copyFieldSource);
|
return DateModifier._private(DateEditAction.copyField, copyFieldSource: copyFieldSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory DateModifier.extractFromTitle(Set<MetadataField> fields) {
|
factory DateModifier.extractFromTitle() {
|
||||||
return DateModifier._private(DateEditAction.extractFromTitle, fields);
|
return const DateModifier._private(DateEditAction.extractFromTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory DateModifier.shift(Set<MetadataField> fields, int shiftMinutes) {
|
factory DateModifier.shift(Set<MetadataField> fields, int shiftMinutes) {
|
||||||
return DateModifier._private(DateEditAction.shift, fields, shiftMinutes: shiftMinutes);
|
return DateModifier._private(DateEditAction.shift, fields: fields, shiftMinutes: shiftMinutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
factory DateModifier.remove(Set<MetadataField> fields) {
|
factory DateModifier.remove(Set<MetadataField> fields) {
|
||||||
return DateModifier._private(DateEditAction.remove, fields);
|
return DateModifier._private(DateEditAction.remove, fields: fields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'package:aves/model/metadata/fields.dart';
|
||||||
enum DateEditAction {
|
enum DateEditAction {
|
||||||
setCustom,
|
setCustom,
|
||||||
copyField,
|
copyField,
|
||||||
|
copyItem,
|
||||||
extractFromTitle,
|
extractFromTitle,
|
||||||
shift,
|
shift,
|
||||||
remove,
|
remove,
|
||||||
|
|
|
@ -427,7 +427,8 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
||||||
final todoItems = await _getEditableTargetItems(context, canEdit: (entry) => entry.canEditDate);
|
final todoItems = await _getEditableTargetItems(context, canEdit: (entry) => entry.canEditDate);
|
||||||
if (todoItems == null || todoItems.isEmpty) return;
|
if (todoItems == null || todoItems.isEmpty) return;
|
||||||
|
|
||||||
final modifier = await selectDateModifier(context, todoItems);
|
final collection = context.read<CollectionLens>();
|
||||||
|
final modifier = await selectDateModifier(context, todoItems, collection);
|
||||||
if (modifier == null) return;
|
if (modifier == null) return;
|
||||||
|
|
||||||
await _edit(context, todoItems, (entry) => entry.editDate(modifier));
|
await _edit(context, todoItems, (entry) => entry.editDate(modifier));
|
||||||
|
|
|
@ -14,13 +14,14 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
mixin EntryEditorMixin {
|
mixin EntryEditorMixin {
|
||||||
Future<DateModifier?> selectDateModifier(BuildContext context, Set<AvesEntry> entries) async {
|
Future<DateModifier?> selectDateModifier(BuildContext context, Set<AvesEntry> entries, CollectionLens? collection) async {
|
||||||
if (entries.isEmpty) return null;
|
if (entries.isEmpty) return null;
|
||||||
|
|
||||||
final modifier = await showDialog<DateModifier>(
|
final modifier = await showDialog<DateModifier>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => EditEntryDateDialog(
|
builder: (context) => EditEntryDateDialog(
|
||||||
entry: entries.first,
|
entry: entries.first,
|
||||||
|
collection: collection,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return modifier;
|
return modifier;
|
||||||
|
|
|
@ -56,7 +56,7 @@ class GridItemSelectionOverlay<T> extends StatelessWidget {
|
||||||
return child;
|
return child;
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink();
|
: const SizedBox();
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
duration: duration,
|
duration: duration,
|
||||||
child: child,
|
child: child,
|
||||||
|
|
|
@ -2,10 +2,9 @@ import 'package:aves/model/covers.dart';
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/fx/borders.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/common/thumbnail/image.dart';
|
|
||||||
import 'package:aves/widgets/dialogs/item_pick_dialog.dart';
|
import 'package:aves/widgets/dialogs/item_pick_dialog.dart';
|
||||||
|
import 'package:aves/widgets/dialogs/item_picker.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -66,7 +65,11 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
padding: const EdgeInsets.only(top: 16),
|
padding: const EdgeInsets.only(top: 16),
|
||||||
child: _buildCover(_coverEntry!, extent),
|
child: ItemPicker(
|
||||||
|
extent: extent,
|
||||||
|
entry: _coverEntry!,
|
||||||
|
onTap: _pickEntry,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 24),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 24),
|
||||||
|
@ -103,29 +106,6 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCover(AvesEntry entry, double extent) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: _pickEntry,
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: AvesBorder.border(context),
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(32)),
|
|
||||||
),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(32)),
|
|
||||||
child: SizedBox(
|
|
||||||
width: extent,
|
|
||||||
height: extent,
|
|
||||||
child: ThumbnailImage(
|
|
||||||
entry: entry,
|
|
||||||
extent: extent,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _pickEntry() async {
|
Future<void> _pickEntry() async {
|
||||||
final _collection = widget.collection;
|
final _collection = widget.collection;
|
||||||
if (_collection == null) return;
|
if (_collection == null) return;
|
||||||
|
|
|
@ -2,6 +2,7 @@ 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.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/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/format.dart';
|
import 'package:aves/theme/format.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
|
@ -10,15 +11,19 @@ import 'package:aves/widgets/common/basic/wheel.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:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class EditEntryDateDialog extends StatefulWidget {
|
class EditEntryDateDialog extends StatefulWidget {
|
||||||
final AvesEntry entry;
|
final AvesEntry entry;
|
||||||
|
final CollectionLens? collection;
|
||||||
|
|
||||||
const EditEntryDateDialog({
|
const EditEntryDateDialog({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.entry,
|
required this.entry,
|
||||||
|
this.collection,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -28,16 +33,20 @@ class EditEntryDateDialog extends StatefulWidget {
|
||||||
class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
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 DateTime _setDateTime;
|
late DateTime _setDateTime;
|
||||||
late ValueNotifier<int> _shiftHour, _shiftMinute;
|
late ValueNotifier<int> _shiftHour, _shiftMinute;
|
||||||
late ValueNotifier<String> _shiftSign;
|
late ValueNotifier<String> _shiftSign;
|
||||||
bool _showOptions = false;
|
bool _showOptions = false;
|
||||||
final Set<MetadataField> _fields = {...DateModifier.writableDateFields};
|
final Set<MetadataField> _fields = {...DateModifier.writableDateFields};
|
||||||
|
|
||||||
|
DateTime get copyItemDate => _copyItemSource.bestDate ?? DateTime.now();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_initSet();
|
_initSet();
|
||||||
|
_initCopyItem();
|
||||||
_initShift(60);
|
_initShift(60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +54,10 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
||||||
_setDateTime = widget.entry.bestDate ?? DateTime.now();
|
_setDateTime = widget.entry.bestDate ?? DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _initCopyItem() {
|
||||||
|
_copyItemSource = widget.entry;
|
||||||
|
}
|
||||||
|
|
||||||
void _initShift(int initialMinutes) {
|
void _initShift(int initialMinutes) {
|
||||||
final abs = initialMinutes.abs();
|
final abs = initialMinutes.abs();
|
||||||
_shiftHour = ValueNotifier(abs ~/ 60);
|
_shiftHour = ValueNotifier(abs ~/ 60);
|
||||||
|
@ -91,6 +104,7 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
||||||
children: [
|
children: [
|
||||||
if (_action == DateEditAction.setCustom) _buildSetCustomContent(context),
|
if (_action == DateEditAction.setCustom) _buildSetCustomContent(context),
|
||||||
if (_action == DateEditAction.copyField) _buildCopyFieldContent(context),
|
if (_action == DateEditAction.copyField) _buildCopyFieldContent(context),
|
||||||
|
if (_action == DateEditAction.copyItem) _buildCopyItemContent(context),
|
||||||
if (_action == DateEditAction.shift) _buildShiftContent(context),
|
if (_action == DateEditAction.shift) _buildShiftContent(context),
|
||||||
(_action == DateEditAction.shift || _action == DateEditAction.remove) ? _buildDestinationFields(context) : const SizedBox(height: 8),
|
(_action == DateEditAction.shift || _action == DateEditAction.remove) ? _buildDestinationFields(context) : const SizedBox(height: 8),
|
||||||
],
|
],
|
||||||
|
@ -170,6 +184,27 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildCopyItemContent(BuildContext context) {
|
||||||
|
final l10n = context.l10n;
|
||||||
|
final locale = l10n.localeName;
|
||||||
|
final use24hour = context.select<MediaQueryData, bool>((v) => v.alwaysUse24HourFormat);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(start: 16, end: 8),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Text(formatDateTime(copyItemDate, locale, use24hour))),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
ItemPicker(
|
||||||
|
extent: 48,
|
||||||
|
entry: _copyItemSource,
|
||||||
|
onTap: _pickCopyItemSource,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildShiftContent(BuildContext context) {
|
Widget _buildShiftContent(BuildContext context) {
|
||||||
const textStyle = TextStyle(fontSize: 34);
|
const textStyle = TextStyle(fontSize: 34);
|
||||||
return Center(
|
return Center(
|
||||||
|
@ -268,6 +303,8 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
||||||
return l10n.editEntryDateDialogSetCustom;
|
return l10n.editEntryDateDialogSetCustom;
|
||||||
case DateEditAction.copyField:
|
case DateEditAction.copyField:
|
||||||
return l10n.editEntryDateDialogCopyField;
|
return l10n.editEntryDateDialogCopyField;
|
||||||
|
case DateEditAction.copyItem:
|
||||||
|
return l10n.editEntryDateDialogCopyItem;
|
||||||
case DateEditAction.extractFromTitle:
|
case DateEditAction.extractFromTitle:
|
||||||
return l10n.editEntryDateDialogExtractFromTitle;
|
return l10n.editEntryDateDialogExtractFromTitle;
|
||||||
case DateEditAction.shift:
|
case DateEditAction.shift:
|
||||||
|
@ -335,6 +372,27 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _pickCopyItemSource() async {
|
||||||
|
final _collection = widget.collection;
|
||||||
|
if (_collection == null) return;
|
||||||
|
|
||||||
|
final entry = await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
settings: const RouteSettings(name: ItemPickDialog.routeName),
|
||||||
|
builder: (context) => ItemPickDialog(
|
||||||
|
collection: CollectionLens(
|
||||||
|
source: _collection.source,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
fullscreenDialog: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (entry != null) {
|
||||||
|
setState(() => _copyItemSource = entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DateModifier _getModifier() {
|
DateModifier _getModifier() {
|
||||||
// fields to modify are only set for the `shift` and `remove` actions,
|
// fields to modify are only set for the `shift` and `remove` actions,
|
||||||
// as the effective fields for the other actions will depend on
|
// as the effective fields for the other actions will depend on
|
||||||
|
@ -343,9 +401,11 @@ class _EditEntryDateDialogState extends State<EditEntryDateDialog> {
|
||||||
case DateEditAction.setCustom:
|
case DateEditAction.setCustom:
|
||||||
return DateModifier.setCustom(const {}, _setDateTime);
|
return DateModifier.setCustom(const {}, _setDateTime);
|
||||||
case DateEditAction.copyField:
|
case DateEditAction.copyField:
|
||||||
return DateModifier.copyField(const {}, _copyFieldSource);
|
return DateModifier.copyField(_copyFieldSource);
|
||||||
|
case DateEditAction.copyItem:
|
||||||
|
return DateModifier.setCustom(const {}, copyItemDate);
|
||||||
case DateEditAction.extractFromTitle:
|
case DateEditAction.extractFromTitle:
|
||||||
return DateModifier.extractFromTitle(const {});
|
return DateModifier.extractFromTitle();
|
||||||
case DateEditAction.shift:
|
case DateEditAction.shift:
|
||||||
final shiftTotalMinutes = (_shiftHour.value * 60 + _shiftMinute.value) * (_shiftSign.value == '+' ? 1 : -1);
|
final shiftTotalMinutes = (_shiftHour.value * 60 + _shiftMinute.value) * (_shiftSign.value == '+' ? 1 : -1);
|
||||||
return DateModifier.shift(_fields, shiftTotalMinutes);
|
return DateModifier.shift(_fields, shiftTotalMinutes);
|
||||||
|
|
|
@ -2,11 +2,11 @@ import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/theme/icons.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_pick_dialog.dart';
|
||||||
|
import 'package:aves/widgets/dialogs/item_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
@ -72,11 +72,12 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
||||||
children: [
|
children: [
|
||||||
title,
|
title,
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
IconButton(
|
if (_customEntry != null)
|
||||||
icon: const Icon(AIcons.setCover),
|
ItemPicker(
|
||||||
onPressed: _isCustom ? _pickEntry : null,
|
extent: 46,
|
||||||
tooltip: context.l10n.changeTooltip,
|
entry: _customEntry!,
|
||||||
),
|
onTap: _pickEntry,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: title,
|
: title,
|
||||||
|
|
72
lib/widgets/dialogs/item_picker.dart
Normal file
72
lib/widgets/dialogs/item_picker.dart
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:aves/model/entry.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/borders.dart';
|
||||||
|
import 'package:aves/widgets/common/thumbnail/image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ItemPicker extends StatelessWidget {
|
||||||
|
final double extent;
|
||||||
|
final AvesEntry entry;
|
||||||
|
final GestureTapCallback? onTap;
|
||||||
|
|
||||||
|
const ItemPicker({
|
||||||
|
Key? key,
|
||||||
|
required this.extent,
|
||||||
|
required this.entry,
|
||||||
|
this.onTap,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final imageBorderRadius = BorderRadius.all(Radius.circular(extent * .25));
|
||||||
|
final actionBoxDimension = min(40.0, extent * .4);
|
||||||
|
final actionBoxBorderRadius = BorderRadiusDirectional.only(topStart: Radius.circular(actionBoxDimension * .6));
|
||||||
|
return Tooltip(
|
||||||
|
message: context.l10n.changeTooltip,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: AvesBorder.border(context),
|
||||||
|
borderRadius: imageBorderRadius,
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: imageBorderRadius,
|
||||||
|
child: SizedBox(
|
||||||
|
width: extent,
|
||||||
|
height: extent,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
ThumbnailImage(
|
||||||
|
entry: entry,
|
||||||
|
extent: extent,
|
||||||
|
),
|
||||||
|
PositionedDirectional(
|
||||||
|
end: -1,
|
||||||
|
bottom: -1,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).brightness == Brightness.dark ? const Color(0xAA000000) : const Color(0xCCFFFFFF),
|
||||||
|
border: AvesBorder.border(context),
|
||||||
|
borderRadius: actionBoxBorderRadius,
|
||||||
|
),
|
||||||
|
width: actionBoxDimension,
|
||||||
|
height: actionBoxDimension,
|
||||||
|
child: Icon(
|
||||||
|
AIcons.edit,
|
||||||
|
size: actionBoxDimension * .6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,7 +97,7 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _editDate(BuildContext context) async {
|
Future<void> _editDate(BuildContext context) async {
|
||||||
final modifier = await selectDateModifier(context, {entry});
|
final modifier = await selectDateModifier(context, {entry}, collection);
|
||||||
if (modifier == null) return;
|
if (modifier == null) return;
|
||||||
|
|
||||||
await edit(context, () => entry.editDate(modifier));
|
await edit(context, () => entry.editDate(modifier));
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
@ -21,6 +23,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
@ -36,6 +39,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsViewerShowOverlayThumbnails",
|
"settingsViewerShowOverlayThumbnails",
|
||||||
"settingsVideoControlsTile",
|
"settingsVideoControlsTile",
|
||||||
"settingsVideoControlsTitle",
|
"settingsVideoControlsTitle",
|
||||||
|
@ -52,6 +56,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
@ -61,6 +66,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
@ -70,6 +76,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
@ -79,6 +86,7 @@
|
||||||
"themeBrightnessLight",
|
"themeBrightnessLight",
|
||||||
"themeBrightnessDark",
|
"themeBrightnessDark",
|
||||||
"themeBrightnessBlack",
|
"themeBrightnessBlack",
|
||||||
|
"editEntryDateDialogCopyItem",
|
||||||
"settingsSectionDisplay",
|
"settingsSectionDisplay",
|
||||||
"settingsThemeBrightness",
|
"settingsThemeBrightness",
|
||||||
"settingsThemeColorful"
|
"settingsThemeColorful"
|
||||||
|
|
Loading…
Reference in a new issue