#146 editing orientation/tags automatically sets a metadata date
This commit is contained in:
parent
da7b2ee8c1
commit
445bde2494
12 changed files with 141 additions and 96 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -8,6 +8,11 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
- Info: option to set date from other fields
|
||||
|
||||
### Changed
|
||||
|
||||
- editing an item orientation or tags automatically sets a metadata date (from the file modified
|
||||
date), if it is missing
|
||||
|
||||
## <a id="v1.5.9"></a>[v1.5.9] - 2021-12-22
|
||||
|
||||
### Added
|
||||
|
@ -41,7 +46,8 @@ All notable changes to this project will be documented in this file.
|
|||
### Changed
|
||||
|
||||
- Settings: select hidden path directory with a custom file picker instead of the native SAF one
|
||||
- Viewer: video cover (before playing the video) is now loaded at original resolution and can be zoomed
|
||||
- Viewer: video cover (before playing the video) is now loaded at original resolution and can be
|
||||
zoomed
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -79,7 +85,8 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
### Changed
|
||||
|
||||
- use build flavors to match distribution channels: `play` (same as original) and `izzy` (no Crashlytics)
|
||||
- use build flavors to match distribution channels: `play` (same as original) and `izzy` (no
|
||||
Crashlytics)
|
||||
- use 12/24 hour format settings from device to display times
|
||||
- Privacy: consent request on first launch for installed app inventory access
|
||||
- use File API to rename and delete items, when possible (primary storage, Android <11)
|
||||
|
|
|
@ -648,26 +648,28 @@ class AvesEntry {
|
|||
await locate(background: background, force: dataTypes.contains(EntryDataType.address), geocoderLocale: geocoderLocale);
|
||||
}
|
||||
|
||||
Future<Set<EntryDataType>> rotate({required bool clockwise, required bool persist}) async {
|
||||
final newFields = await metadataEditService.rotate(this, clockwise: clockwise);
|
||||
if (newFields.isEmpty) return {};
|
||||
Future<Set<EntryDataType>> _changeOrientation(Future<Map<String, dynamic>> Function() apply) async {
|
||||
final dataTypes = await setMetadataDateIfMissing();
|
||||
|
||||
await _applyNewFields(newFields, persist: persist);
|
||||
return {
|
||||
final newFields = await apply();
|
||||
// applying fields is only useful for a smoother visual change,
|
||||
// as proper refreshing and persistence happens at the caller level
|
||||
await _applyNewFields(newFields, persist: false);
|
||||
if (newFields.isNotEmpty) {
|
||||
dataTypes.addAll({
|
||||
EntryDataType.basic,
|
||||
EntryDataType.catalog,
|
||||
};
|
||||
});
|
||||
}
|
||||
return dataTypes;
|
||||
}
|
||||
|
||||
Future<Set<EntryDataType>> flip({required bool persist}) async {
|
||||
final newFields = await metadataEditService.flip(this);
|
||||
if (newFields.isEmpty) return {};
|
||||
Future<Set<EntryDataType>> rotate({required bool clockwise}) {
|
||||
return _changeOrientation(() => metadataEditService.rotate(this, clockwise: clockwise));
|
||||
}
|
||||
|
||||
await _applyNewFields(newFields, persist: persist);
|
||||
return {
|
||||
EntryDataType.basic,
|
||||
EntryDataType.catalog,
|
||||
};
|
||||
Future<Set<EntryDataType>> flip() {
|
||||
return _changeOrientation(() => metadataEditService.flip(this));
|
||||
}
|
||||
|
||||
Future<Set<EntryDataType>> editDate(DateModifier modifier) async {
|
||||
|
@ -730,6 +732,25 @@ class AvesEntry {
|
|||
};
|
||||
}
|
||||
|
||||
// when editing a file that has no metadata date,
|
||||
// we will set one, using the file modified date, if any
|
||||
Future<Set<EntryDataType>> setMetadataDateIfMissing() async {
|
||||
if (path == null) return {};
|
||||
|
||||
// make sure entry is catalogued before we check whether is has a metadata date
|
||||
if (!isCatalogued) {
|
||||
await catalog(background: false, force: false, persist: true);
|
||||
}
|
||||
final metadataDate = catalogMetadata?.dateMillis;
|
||||
if (metadataDate != null && metadataDate > 0) return {};
|
||||
|
||||
return await editDate(const DateModifier(
|
||||
DateEditAction.set,
|
||||
{MetadataField.exifDateOriginal},
|
||||
setSource: DateSetSource.fileModifiedDate,
|
||||
));
|
||||
}
|
||||
|
||||
Future<Set<EntryDataType>> removeMetadata(Set<MetadataType> types) async {
|
||||
final newFields = await metadataEditService.removeTypes(this, types);
|
||||
return newFields.isEmpty
|
||||
|
|
|
@ -43,6 +43,8 @@ extension ExtraAvesEntryXmpIptc on AvesEntry {
|
|||
static String prefixOf(String ns) => nsDefaultPrefixes[ns] ?? '';
|
||||
|
||||
Future<Set<EntryDataType>> editTags(Set<String> tags) async {
|
||||
final dataTypes = await setMetadataDateIfMissing();
|
||||
|
||||
final xmp = await metadataFetchService.getXmp(this);
|
||||
final extendedXmpString = xmp?.extendedXmpString;
|
||||
|
||||
|
@ -118,7 +120,10 @@ extension ExtraAvesEntryXmpIptc on AvesEntry {
|
|||
}
|
||||
|
||||
final newFields = await metadataEditService.setXmp(this, editedXmp);
|
||||
return newFields.isEmpty ? {} : {EntryDataType.catalog};
|
||||
if (newFields.isNotEmpty) {
|
||||
dataTypes.add(EntryDataType.catalog);
|
||||
}
|
||||
return dataTypes;
|
||||
}
|
||||
|
||||
Future<void> _setIptcKeywords(List<Map<String, dynamic>> iptc, Set<String> tags) async {
|
||||
|
|
|
@ -489,7 +489,7 @@ class EntrySetActionDelegate with EntryEditorMixin, FeedbackMixin, PermissionAwa
|
|||
final todoItems = await _getEditableItems(context, selectedItems: selectedItems, canEdit: (entry) => entry.canRotateAndFlip);
|
||||
if (todoItems == null || todoItems.isEmpty) return;
|
||||
|
||||
await _edit(context, selection, todoItems, (entry) => entry.rotate(clockwise: clockwise, persist: true));
|
||||
await _edit(context, selection, todoItems, (entry) => entry.rotate(clockwise: clockwise));
|
||||
}
|
||||
|
||||
Future<void> _flip(BuildContext context) async {
|
||||
|
@ -499,7 +499,7 @@ class EntrySetActionDelegate with EntryEditorMixin, FeedbackMixin, PermissionAwa
|
|||
final todoItems = await _getEditableItems(context, selectedItems: selectedItems, canEdit: (entry) => entry.canRotateAndFlip);
|
||||
if (todoItems == null || todoItems.isEmpty) return;
|
||||
|
||||
await _edit(context, selection, todoItems, (entry) => entry.flip(persist: true));
|
||||
await _edit(context, selection, todoItems, (entry) => entry.flip());
|
||||
}
|
||||
|
||||
Future<void> _editDate(BuildContext context) async {
|
||||
|
|
|
@ -24,20 +24,26 @@ import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
|||
import 'package:aves/widgets/dialogs/entry_editors/rename_entry_dialog.dart';
|
||||
import 'package:aves/widgets/dialogs/export_entry_dialog.dart';
|
||||
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
||||
import 'package:aves/widgets/viewer/action/printer.dart';
|
||||
import 'package:aves/widgets/viewer/action/single_entry_editor.dart';
|
||||
import 'package:aves/widgets/viewer/debug/debug_page.dart';
|
||||
import 'package:aves/widgets/viewer/info/notifications.dart';
|
||||
import 'package:aves/widgets/viewer/printer.dart';
|
||||
import 'package:aves/widgets/viewer/source_viewer_page.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
|
||||
void onActionSelected(BuildContext context, AvesEntry entry, EntryAction action) {
|
||||
class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin, SingleEntryEditorMixin {
|
||||
@override
|
||||
final AvesEntry entry;
|
||||
|
||||
EntryActionDelegate(this.entry);
|
||||
|
||||
void onActionSelected(BuildContext context, EntryAction action) {
|
||||
switch (action) {
|
||||
case EntryAction.addShortcut:
|
||||
_addShortcut(context, entry);
|
||||
_addShortcut(context);
|
||||
break;
|
||||
case EntryAction.copyToClipboard:
|
||||
androidAppService.copyToClipboard(entry.uri, entry.bestTitle).then((success) {
|
||||
|
@ -45,10 +51,10 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
});
|
||||
break;
|
||||
case EntryAction.delete:
|
||||
_delete(context, entry);
|
||||
_delete(context);
|
||||
break;
|
||||
case EntryAction.export:
|
||||
_export(context, entry);
|
||||
_export(context);
|
||||
break;
|
||||
case EntryAction.info:
|
||||
ShowInfoNotification().dispatch(context);
|
||||
|
@ -57,7 +63,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
EntryPrinter(entry).print(context);
|
||||
break;
|
||||
case EntryAction.rename:
|
||||
_rename(context, entry);
|
||||
_rename(context);
|
||||
break;
|
||||
case EntryAction.share:
|
||||
androidAppService.shareEntries({entry}).then((success) {
|
||||
|
@ -69,17 +75,17 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
break;
|
||||
// raster
|
||||
case EntryAction.rotateCCW:
|
||||
_rotate(context, entry, clockwise: false);
|
||||
_rotate(context, clockwise: false);
|
||||
break;
|
||||
case EntryAction.rotateCW:
|
||||
_rotate(context, entry, clockwise: true);
|
||||
_rotate(context, clockwise: true);
|
||||
break;
|
||||
case EntryAction.flip:
|
||||
_flip(context, entry);
|
||||
_flip(context);
|
||||
break;
|
||||
// vector
|
||||
case EntryAction.viewSource:
|
||||
_goToSourceViewer(context, entry);
|
||||
_goToSourceViewer(context);
|
||||
break;
|
||||
// external
|
||||
case EntryAction.edit:
|
||||
|
@ -108,12 +114,12 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
break;
|
||||
// debug
|
||||
case EntryAction.debug:
|
||||
_goToDebug(context, entry);
|
||||
_goToDebug(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _addShortcut(BuildContext context, AvesEntry entry) async {
|
||||
Future<void> _addShortcut(BuildContext context) async {
|
||||
final result = await showDialog<Tuple2<AvesEntry?, String>>(
|
||||
context: context,
|
||||
builder: (context) => AddShortcutDialog(
|
||||
|
@ -131,18 +137,12 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _flip(BuildContext context, AvesEntry entry) async {
|
||||
if (!await checkStoragePermission(context, {entry})) return;
|
||||
|
||||
final dataTypes = await entry.flip(persist: _isMainMode(context));
|
||||
if (dataTypes.isEmpty) showFeedback(context, context.l10n.genericFailureFeedback);
|
||||
Future<void> _flip(BuildContext context) async {
|
||||
await edit(context, entry.flip);
|
||||
}
|
||||
|
||||
Future<void> _rotate(BuildContext context, AvesEntry entry, {required bool clockwise}) async {
|
||||
if (!await checkStoragePermission(context, {entry})) return;
|
||||
|
||||
final dataTypes = await entry.rotate(clockwise: clockwise, persist: _isMainMode(context));
|
||||
if (dataTypes.isEmpty) showFeedback(context, context.l10n.genericFailureFeedback);
|
||||
Future<void> _rotate(BuildContext context, {required bool clockwise}) async {
|
||||
await edit(context, () => entry.rotate(clockwise: clockwise));
|
||||
}
|
||||
|
||||
Future<void> _rotateScreen(BuildContext context) async {
|
||||
|
@ -156,7 +156,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _delete(BuildContext context, AvesEntry entry) async {
|
||||
Future<void> _delete(BuildContext context) async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
|
@ -190,7 +190,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _export(BuildContext context, AvesEntry entry) async {
|
||||
Future<void> _export(BuildContext context) async {
|
||||
final source = context.read<CollectionSource>();
|
||||
if (!source.initialized) {
|
||||
await source.init();
|
||||
|
@ -291,7 +291,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _rename(BuildContext context, AvesEntry entry) async {
|
||||
Future<void> _rename(BuildContext context) async {
|
||||
final newName = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => RenameEntryDialog(entry: entry),
|
||||
|
@ -311,7 +311,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
|
||||
bool _isMainMode(BuildContext context) => context.read<ValueNotifier<AppMode>>().value == AppMode.main;
|
||||
|
||||
void _goToSourceViewer(BuildContext context, AvesEntry entry) {
|
||||
void _goToSourceViewer(BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
@ -323,7 +323,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
);
|
||||
}
|
||||
|
||||
void _goToDebug(BuildContext context, AvesEntry entry) {
|
||||
void _goToDebug(BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
|
@ -1,22 +1,18 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:aves/app_mode.dart';
|
||||
import 'package:aves/model/actions/entry_info_actions.dart';
|
||||
import 'package:aves/model/actions/events.dart';
|
||||
import 'package:aves/model/entry.dart';
|
||||
import 'package:aves/model/entry_xmp_iptc.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/collection_source.dart';
|
||||
import 'package:aves/services/common/services.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/entry_editor.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/permission_aware.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/viewer/action/single_entry_editor.dart';
|
||||
import 'package:aves/widgets/viewer/embedded/notifications.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EntryInfoActionDelegate with EntryEditorMixin, FeedbackMixin, PermissionAwareMixin {
|
||||
class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEditorMixin, SingleEntryEditorMixin {
|
||||
@override
|
||||
final AvesEntry entry;
|
||||
|
||||
final StreamController<ActionEvent<EntryInfoAction>> _eventStreamController = StreamController<ActionEvent<EntryInfoAction>>.broadcast();
|
||||
|
@ -74,43 +70,11 @@ class EntryInfoActionDelegate with EntryEditorMixin, FeedbackMixin, PermissionAw
|
|||
_eventStreamController.add(ActionEndedEvent(action));
|
||||
}
|
||||
|
||||
bool _isMainMode(BuildContext context) => context.read<ValueNotifier<AppMode>>().value == AppMode.main;
|
||||
|
||||
Future<void> _edit(BuildContext context, Future<Set<EntryDataType>> Function() apply) async {
|
||||
if (!await checkStoragePermission(context, {entry})) return;
|
||||
|
||||
// check before applying, because it relies on provider
|
||||
// but the widget tree may be disposed if the user navigated away
|
||||
final isMainMode = _isMainMode(context);
|
||||
|
||||
final l10n = context.l10n;
|
||||
final source = context.read<CollectionSource?>();
|
||||
source?.pauseMonitoring();
|
||||
|
||||
final dataTypes = await apply();
|
||||
final success = dataTypes.isNotEmpty;
|
||||
try {
|
||||
if (success) {
|
||||
if (isMainMode && source != null) {
|
||||
await source.refreshEntry(entry, dataTypes);
|
||||
} else {
|
||||
await entry.refresh(background: false, persist: false, dataTypes: dataTypes, geocoderLocale: settings.appliedLocale);
|
||||
}
|
||||
showFeedback(context, l10n.genericSuccessFeedback);
|
||||
} else {
|
||||
showFeedback(context, l10n.genericFailureFeedback);
|
||||
}
|
||||
} catch (e, stack) {
|
||||
await reportService.recordError(e, stack);
|
||||
}
|
||||
source?.resumeMonitoring();
|
||||
}
|
||||
|
||||
Future<void> _editDate(BuildContext context) async {
|
||||
final modifier = await selectDateModifier(context, {entry});
|
||||
if (modifier == null) return;
|
||||
|
||||
await _edit(context, () => entry.editDate(modifier));
|
||||
await edit(context, () => entry.editDate(modifier));
|
||||
}
|
||||
|
||||
Future<void> _editTags(BuildContext context) async {
|
||||
|
@ -121,13 +85,13 @@ class EntryInfoActionDelegate with EntryEditorMixin, FeedbackMixin, PermissionAw
|
|||
final currentTags = entry.tags;
|
||||
if (newTags.length == currentTags.length && newTags.every(currentTags.contains)) return;
|
||||
|
||||
await _edit(context, () => entry.editTags(newTags));
|
||||
await edit(context, () => entry.editTags(newTags));
|
||||
}
|
||||
|
||||
Future<void> _removeMetadata(BuildContext context) async {
|
||||
final types = await selectMetadataToRemove(context, {entry});
|
||||
if (types == null) return;
|
||||
|
||||
await _edit(context, () => entry.removeMetadata(types));
|
||||
await edit(context, () => entry.removeMetadata(types));
|
||||
}
|
||||
}
|
48
lib/widgets/viewer/action/single_entry_editor.dart
Normal file
48
lib/widgets/viewer/action/single_entry_editor.dart
Normal file
|
@ -0,0 +1,48 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:aves/app_mode.dart';
|
||||
import 'package:aves/model/entry.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/collection_source.dart';
|
||||
import 'package:aves/services/common/services.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/permission_aware.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
mixin SingleEntryEditorMixin on FeedbackMixin, PermissionAwareMixin {
|
||||
AvesEntry get entry;
|
||||
|
||||
bool _isMainMode(BuildContext context) => context.read<ValueNotifier<AppMode>>().value == AppMode.main;
|
||||
|
||||
Future<void> edit(BuildContext context, Future<Set<EntryDataType>> Function() apply) async {
|
||||
if (!await checkStoragePermission(context, {entry})) return;
|
||||
|
||||
// check before applying, because it relies on provider
|
||||
// but the widget tree may be disposed if the user navigated away
|
||||
final isMainMode = _isMainMode(context);
|
||||
|
||||
final l10n = context.l10n;
|
||||
final source = context.read<CollectionSource?>();
|
||||
source?.pauseMonitoring();
|
||||
|
||||
final dataTypes = await apply();
|
||||
final success = dataTypes.isNotEmpty;
|
||||
try {
|
||||
if (success) {
|
||||
if (isMainMode && source != null) {
|
||||
await source.refreshEntry(entry, dataTypes);
|
||||
} else {
|
||||
await entry.refresh(background: false, persist: false, dataTypes: dataTypes, geocoderLocale: settings.appliedLocale);
|
||||
}
|
||||
showFeedback(context, l10n.genericSuccessFeedback);
|
||||
} else {
|
||||
showFeedback(context, l10n.genericFailureFeedback);
|
||||
}
|
||||
} catch (e, stack) {
|
||||
await reportService.recordError(e, stack);
|
||||
}
|
||||
source?.resumeMonitoring();
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import 'package:aves/utils/file_utils.dart';
|
|||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||
import 'package:aves/widgets/viewer/info/common.dart';
|
||||
import 'package:aves/widgets/viewer/info/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/info/owner.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:aves/theme/icons.dart';
|
|||
import 'package:aves/widgets/common/app_bar_title.dart';
|
||||
import 'package:aves/widgets/common/basic/menu.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/viewer/info/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/info/info_search.dart';
|
||||
import 'package:aves/widgets/viewer/info/metadata/metadata_section.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
|
@ -8,9 +8,9 @@ import 'package:aves/model/source/collection_lens.dart';
|
|||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/widgets/common/basic/insets.dart';
|
||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/embedded/embedded_data_opener.dart';
|
||||
import 'package:aves/widgets/viewer/info/basic_section.dart';
|
||||
import 'package:aves/widgets/viewer/info/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/info/info_app_bar.dart';
|
||||
import 'package:aves/widgets/viewer/info/location_section.dart';
|
||||
import 'package:aves/widgets/viewer/info/metadata/metadata_section.dart';
|
||||
|
|
|
@ -9,7 +9,7 @@ import 'package:aves/widgets/common/basic/menu.dart';
|
|||
import 'package:aves/widgets/common/basic/popup_menu_button.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/fx/sweeper.dart';
|
||||
import 'package:aves/widgets/viewer/entry_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/action/entry_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
||||
import 'package:aves/widgets/viewer/overlay/minimap.dart';
|
||||
|
@ -312,7 +312,7 @@ class _TopOverlayRow extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
}
|
||||
EntryActionDelegate().onActionSelected(context, targetEntry, action);
|
||||
EntryActionDelegate(targetEntry).onActionSelected(context, action);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue