moved motion photo video opening action from viewer to info page
This commit is contained in:
parent
3ef96826c8
commit
fedf585745
6 changed files with 95 additions and 36 deletions
|
@ -19,8 +19,6 @@ enum EntryAction {
|
|||
flip,
|
||||
// vector
|
||||
viewSource,
|
||||
// motion photo,
|
||||
viewMotionPhotoVideo,
|
||||
// external
|
||||
edit,
|
||||
open,
|
||||
|
@ -44,7 +42,6 @@ class EntryActions {
|
|||
EntryAction.copyToClipboard,
|
||||
EntryAction.print,
|
||||
EntryAction.viewSource,
|
||||
EntryAction.viewMotionPhotoVideo,
|
||||
EntryAction.rotateScreen,
|
||||
];
|
||||
|
||||
|
@ -94,9 +91,6 @@ extension ExtraEntryAction on EntryAction {
|
|||
// vector
|
||||
case EntryAction.viewSource:
|
||||
return context.l10n.entryActionViewSource;
|
||||
// motion photo
|
||||
case EntryAction.viewMotionPhotoVideo:
|
||||
return context.l10n.entryActionViewMotionPhotoVideo;
|
||||
// external
|
||||
case EntryAction.edit:
|
||||
return context.l10n.entryActionEdit;
|
||||
|
@ -162,9 +156,6 @@ extension ExtraEntryAction on EntryAction {
|
|||
// vector
|
||||
case EntryAction.viewSource:
|
||||
return AIcons.vector;
|
||||
// motion photo
|
||||
case EntryAction.viewMotionPhotoVideo:
|
||||
return AIcons.motionPhoto;
|
||||
// external
|
||||
case EntryAction.edit:
|
||||
case EntryAction.open:
|
||||
|
|
|
@ -1,4 +1,51 @@
|
|||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum EntryInfoAction {
|
||||
// general
|
||||
editDate,
|
||||
removeMetadata,
|
||||
// motion photo
|
||||
viewMotionPhotoVideo,
|
||||
}
|
||||
|
||||
class EntryInfoActions {
|
||||
static const all = [
|
||||
EntryInfoAction.editDate,
|
||||
EntryInfoAction.removeMetadata,
|
||||
EntryInfoAction.viewMotionPhotoVideo,
|
||||
];
|
||||
}
|
||||
|
||||
extension ExtraEntryInfoAction on EntryInfoAction {
|
||||
String getText(BuildContext context) {
|
||||
switch (this) {
|
||||
// general
|
||||
case EntryInfoAction.editDate:
|
||||
return context.l10n.entryInfoActionEditDate;
|
||||
case EntryInfoAction.removeMetadata:
|
||||
return context.l10n.entryInfoActionRemoveMetadata;
|
||||
// motion photo
|
||||
case EntryInfoAction.viewMotionPhotoVideo:
|
||||
return context.l10n.entryActionViewMotionPhotoVideo;
|
||||
}
|
||||
}
|
||||
|
||||
Widget getIcon() {
|
||||
return Icon(_getIconData());
|
||||
}
|
||||
|
||||
IconData _getIconData() {
|
||||
switch (this) {
|
||||
// general
|
||||
case EntryInfoAction.editDate:
|
||||
return AIcons.date;
|
||||
case EntryInfoAction.removeMetadata:
|
||||
return AIcons.clear;
|
||||
// motion photo
|
||||
case EntryInfoAction.viewMotionPhotoVideo:
|
||||
return AIcons.motionPhoto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import 'package:aves/widgets/dialogs/export_entry_dialog.dart';
|
|||
import 'package:aves/widgets/dialogs/rename_entry_dialog.dart';
|
||||
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
||||
import 'package:aves/widgets/viewer/debug/debug_page.dart';
|
||||
import 'package:aves/widgets/viewer/embedded/notifications.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';
|
||||
|
@ -81,10 +80,6 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
case EntryAction.viewSource:
|
||||
_goToSourceViewer(context, entry);
|
||||
break;
|
||||
// motion photo
|
||||
case EntryAction.viewMotionPhotoVideo:
|
||||
OpenEmbeddedDataNotification.motionPhotoVideo().dispatch(context);
|
||||
break;
|
||||
// external
|
||||
case EntryAction.edit:
|
||||
androidAppService.edit(entry.uri, entry.mimeType).then((success) {
|
||||
|
|
|
@ -7,6 +7,7 @@ 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/embedded/notifications.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
@ -15,14 +16,44 @@ class EntryInfoActionDelegate with EntryEditorMixin, FeedbackMixin, PermissionAw
|
|||
|
||||
const EntryInfoActionDelegate(this.entry);
|
||||
|
||||
bool isVisible(EntryInfoAction action) {
|
||||
switch (action) {
|
||||
// general
|
||||
case EntryInfoAction.editDate:
|
||||
case EntryInfoAction.removeMetadata:
|
||||
return true;
|
||||
// motion photo
|
||||
case EntryInfoAction.viewMotionPhotoVideo:
|
||||
return entry.isMotionPhoto;
|
||||
}
|
||||
}
|
||||
|
||||
bool canApply(EntryInfoAction action) {
|
||||
switch (action) {
|
||||
// general
|
||||
case EntryInfoAction.editDate:
|
||||
return entry.canEditExif;
|
||||
case EntryInfoAction.removeMetadata:
|
||||
return entry.canRemoveMetadata;
|
||||
// motion photo
|
||||
case EntryInfoAction.viewMotionPhotoVideo:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void onActionSelected(BuildContext context, EntryInfoAction action) async {
|
||||
switch (action) {
|
||||
// general
|
||||
case EntryInfoAction.editDate:
|
||||
await _editDate(context);
|
||||
break;
|
||||
case EntryInfoAction.removeMetadata:
|
||||
await _removeMetadata(context);
|
||||
break;
|
||||
// motion photo
|
||||
case EntryInfoAction.viewMotionPhotoVideo:
|
||||
OpenEmbeddedDataNotification.motionPhotoVideo().dispatch(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ class InfoAppBar extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final actionDelegate = EntryInfoActionDelegate(entry);
|
||||
final menuActions = EntryInfoActions.all.where(actionDelegate.isVisible);
|
||||
|
||||
return SliverAppBar(
|
||||
leading: IconButton(
|
||||
// key is expected by test driver
|
||||
|
@ -46,24 +49,11 @@ class InfoAppBar extends StatelessWidget {
|
|||
if (entry.canEdit)
|
||||
MenuIconTheme(
|
||||
child: PopupMenuButton<EntryInfoAction>(
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
value: EntryInfoAction.editDate,
|
||||
enabled: entry.canEditExif,
|
||||
child: MenuRow(text: context.l10n.entryInfoActionEditDate, icon: const Icon(AIcons.date)),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: EntryInfoAction.removeMetadata,
|
||||
enabled: entry.canRemoveMetadata,
|
||||
child: MenuRow(text: context.l10n.entryInfoActionRemoveMetadata, icon: const Icon(AIcons.clear)),
|
||||
),
|
||||
];
|
||||
},
|
||||
itemBuilder: (context) => menuActions.map((action) => _toMenuItem(context, action, enabled: actionDelegate.canApply(action))).toList(),
|
||||
onSelected: (action) async {
|
||||
// wait for the popup menu to hide before proceeding with the action
|
||||
await Future.delayed(Durations.popupMenuAnimation * timeDilation);
|
||||
EntryInfoActionDelegate(entry).onActionSelected(context, action);
|
||||
actionDelegate.onActionSelected(context, action);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -73,6 +63,14 @@ class InfoAppBar extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
PopupMenuItem<EntryInfoAction> _toMenuItem(BuildContext context, EntryInfoAction action, {required bool enabled}) {
|
||||
return PopupMenuItem(
|
||||
value: action,
|
||||
enabled: enabled,
|
||||
child: MenuRow(text: action.getText(context), icon: action.getIcon()),
|
||||
);
|
||||
}
|
||||
|
||||
void _goToSearch(BuildContext context) {
|
||||
showSearch(
|
||||
context: context,
|
||||
|
|
|
@ -65,7 +65,7 @@ class ViewerTopOverlay extends StatelessWidget {
|
|||
Widget _buildOverlay(BuildContext context, int availableCount, AvesEntry mainEntry, {AvesEntry? pageEntry}) {
|
||||
pageEntry ??= mainEntry;
|
||||
|
||||
bool _canDo(EntryAction action) {
|
||||
bool _isVisible(EntryAction action) {
|
||||
final targetEntry = EntryActions.pageActions.contains(action) ? pageEntry! : mainEntry;
|
||||
switch (action) {
|
||||
case EntryAction.toggleFavourite:
|
||||
|
@ -84,8 +84,6 @@ class ViewerTopOverlay extends StatelessWidget {
|
|||
return targetEntry.hasGps;
|
||||
case EntryAction.viewSource:
|
||||
return targetEntry.isSvg;
|
||||
case EntryAction.viewMotionPhotoVideo:
|
||||
return targetEntry.isMotionPhoto;
|
||||
case EntryAction.rotateScreen:
|
||||
return settings.isRotationLocked;
|
||||
case EntryAction.addShortcut:
|
||||
|
@ -104,9 +102,9 @@ class ViewerTopOverlay extends StatelessWidget {
|
|||
final buttonRow = Selector<Settings, bool>(
|
||||
selector: (context, s) => s.isRotationLocked,
|
||||
builder: (context, s, child) {
|
||||
final quickActions = settings.viewerQuickActions.where(_canDo).take(availableCount - 1).toList();
|
||||
final inAppActions = EntryActions.inApp.where((action) => !quickActions.contains(action)).where(_canDo).toList();
|
||||
final externalAppActions = EntryActions.externalApp.where(_canDo).toList();
|
||||
final quickActions = settings.viewerQuickActions.where(_isVisible).take(availableCount - 1).toList();
|
||||
final inAppActions = EntryActions.inApp.where((action) => !quickActions.contains(action)).where(_isVisible).toList();
|
||||
final externalAppActions = EntryActions.externalApp.where(_isVisible).toList();
|
||||
return _TopOverlayRow(
|
||||
quickActions: quickActions,
|
||||
inAppActions: inAppActions,
|
||||
|
@ -222,7 +220,6 @@ class _TopOverlayRow extends StatelessWidget {
|
|||
case EntryAction.share:
|
||||
case EntryAction.rotateScreen:
|
||||
case EntryAction.viewSource:
|
||||
case EntryAction.viewMotionPhotoVideo:
|
||||
child = IconButton(
|
||||
icon: action.getIcon() ?? const SizedBox(),
|
||||
onPressed: onPressed,
|
||||
|
|
Loading…
Reference in a new issue