moved motion photo video opening action from viewer to info page

This commit is contained in:
Thibault Deckers 2021-11-12 09:56:35 +09:00
parent 3ef96826c8
commit fedf585745
6 changed files with 95 additions and 36 deletions

View file

@ -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:

View file

@ -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;
}
}
}

View file

@ -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) {

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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,