settings: most recent fullscreen actions
This commit is contained in:
parent
dd4ac33b6d
commit
fd149c30b3
5 changed files with 109 additions and 75 deletions
|
@ -1,4 +1,5 @@
|
|||
import 'package:aves/model/collection_lens.dart';
|
||||
import 'package:aves/widgets/fullscreen/fullscreen_actions.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
@ -19,6 +20,7 @@ class Settings {
|
|||
static const collectionSortFactorKey = 'collection_sort_factor';
|
||||
static const infoMapZoomKey = 'info_map_zoom';
|
||||
static const catalogTimeZoneKey = 'catalog_time_zone';
|
||||
static const mostRecentFullscreenActionsKey = 'most_recent_fullscreen_actions';
|
||||
|
||||
Future<void> init() async {
|
||||
prefs = await SharedPreferences.getInstance();
|
||||
|
@ -60,6 +62,17 @@ class Settings {
|
|||
|
||||
set collectionSortFactor(SortFactor newValue) => setAndNotify(collectionSortFactorKey, newValue.toString());
|
||||
|
||||
List<FullscreenAction> get mostRecentFullscreenActions => getEnumListOrDefault(
|
||||
mostRecentFullscreenActionsKey,
|
||||
[
|
||||
FullscreenAction.toggleFavourite,
|
||||
FullscreenAction.share,
|
||||
FullscreenAction.delete,
|
||||
],
|
||||
FullscreenAction.values);
|
||||
|
||||
set mostRecentFullscreenActions(List<FullscreenAction> newValue) => setAndNotify(mostRecentFullscreenActionsKey, newValue.map((v) => v.toString()).toList());
|
||||
|
||||
// convenience methods
|
||||
|
||||
bool getBoolOrDefault(String key, bool defaultValue) => prefs.getKeys().contains(key) ? prefs.getBool(key) : defaultValue;
|
||||
|
@ -74,6 +87,10 @@ class Settings {
|
|||
return defaultValue;
|
||||
}
|
||||
|
||||
List<T> getEnumListOrDefault<T>(String key, List<T> defaultValue, Iterable<T> values) {
|
||||
return prefs.getStringList(key)?.map((s) => values.firstWhere((el) => el.toString() == s, orElse: () => null))?.where((el) => el != null)?.toList() ?? defaultValue;
|
||||
}
|
||||
|
||||
void setAndNotify(String key, dynamic newValue) {
|
||||
var oldValue = prefs.get(key);
|
||||
if (newValue == null) {
|
||||
|
@ -81,6 +98,9 @@ class Settings {
|
|||
} else if (newValue is String) {
|
||||
oldValue = prefs.getString(key);
|
||||
prefs.setString(key, newValue);
|
||||
} else if (newValue is List<String>) {
|
||||
oldValue = prefs.getStringList(key);
|
||||
prefs.setStringList(key, newValue);
|
||||
} else if (newValue is int) {
|
||||
oldValue = prefs.getInt(key);
|
||||
prefs.setInt(key, newValue);
|
||||
|
|
|
@ -51,6 +51,7 @@ class DebugPageState extends State<DebugPage> {
|
|||
Text('collectionGroupFactor: ${settings.collectionGroupFactor}'),
|
||||
Text('collectionSortFactor: ${settings.collectionSortFactor}'),
|
||||
Text('infoMapZoom: ${settings.infoMapZoom}'),
|
||||
Text('mostRecentFullscreenActions: ${settings.mostRecentFullscreenActions}'),
|
||||
const Divider(),
|
||||
Text('Entries: ${entries.length}'),
|
||||
Text('Catalogued: ${catalogued.length}'),
|
||||
|
|
|
@ -4,14 +4,13 @@ import 'package:aves/model/collection_lens.dart';
|
|||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/utils/android_app_service.dart';
|
||||
import 'package:aves/widgets/common/image_providers/uri_image_provider.dart';
|
||||
import 'package:aves/widgets/fullscreen/fullscreen_actions.dart';
|
||||
import 'package:flushbar/flushbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pdf/widgets.dart' as pdf;
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:printing/printing.dart';
|
||||
|
||||
enum FullscreenAction { delete, edit, info, open, openMap, print, rename, rotateCCW, rotateCW, setAs, share, toggleFavourite }
|
||||
|
||||
class FullscreenActionDelegate {
|
||||
final CollectionLens collection;
|
||||
final VoidCallback showInfo;
|
||||
|
|
55
lib/widgets/fullscreen/fullscreen_actions.dart
Normal file
55
lib/widgets/fullscreen/fullscreen_actions.dart
Normal file
|
@ -0,0 +1,55 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:outline_material_icons/outline_material_icons.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
enum FullscreenAction { delete, edit, info, open, openMap, print, rename, rotateCCW, rotateCW, setAs, share, toggleFavourite }
|
||||
|
||||
class FullscreenActions {
|
||||
static const inApp = [
|
||||
FullscreenAction.info,
|
||||
FullscreenAction.toggleFavourite,
|
||||
FullscreenAction.share,
|
||||
FullscreenAction.delete,
|
||||
FullscreenAction.rename,
|
||||
FullscreenAction.rotateCCW,
|
||||
FullscreenAction.rotateCW,
|
||||
FullscreenAction.print,
|
||||
];
|
||||
|
||||
static const externalApp = [
|
||||
FullscreenAction.edit,
|
||||
FullscreenAction.open,
|
||||
FullscreenAction.setAs,
|
||||
FullscreenAction.openMap,
|
||||
];
|
||||
|
||||
static Tuple2<String, IconData> getTextIcon(FullscreenAction action) {
|
||||
switch (action) {
|
||||
// in app actions
|
||||
case FullscreenAction.delete:
|
||||
return const Tuple2('Delete', OMIcons.delete);
|
||||
case FullscreenAction.info:
|
||||
return const Tuple2('Info', OMIcons.info);
|
||||
case FullscreenAction.rename:
|
||||
return const Tuple2('Rename', OMIcons.title);
|
||||
case FullscreenAction.rotateCCW:
|
||||
return const Tuple2('Rotate left', OMIcons.rotateLeft);
|
||||
case FullscreenAction.rotateCW:
|
||||
return const Tuple2('Rotate right', OMIcons.rotateRight);
|
||||
case FullscreenAction.print:
|
||||
return const Tuple2('Print', OMIcons.print);
|
||||
case FullscreenAction.share:
|
||||
return const Tuple2('Share', OMIcons.share);
|
||||
// external app actions
|
||||
case FullscreenAction.edit:
|
||||
return const Tuple2('Edit with…', null);
|
||||
case FullscreenAction.open:
|
||||
return const Tuple2('Open with…', null);
|
||||
case FullscreenAction.setAs:
|
||||
return const Tuple2('Set as…', null);
|
||||
case FullscreenAction.openMap:
|
||||
return const Tuple2('Show on map…', null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/model/settings.dart';
|
||||
import 'package:aves/widgets/common/fx/sweeper.dart';
|
||||
import 'package:aves/widgets/common/menu_row.dart';
|
||||
import 'package:aves/widgets/fullscreen/fullscreen_action_delegate.dart';
|
||||
import 'package:aves/widgets/fullscreen/fullscreen_actions.dart';
|
||||
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -22,6 +23,12 @@ class FullscreenTopOverlay extends StatelessWidget {
|
|||
|
||||
static const double padding = 8;
|
||||
|
||||
static const int landscapeActionCount = 3;
|
||||
|
||||
static const int portraitActionCount = 2;
|
||||
|
||||
static const List<FullscreenAction> possibleOverlayActions = FullscreenActions.inApp;
|
||||
|
||||
const FullscreenTopOverlay({
|
||||
Key key,
|
||||
@required this.entries,
|
||||
|
@ -42,35 +49,15 @@ class FullscreenTopOverlay extends StatelessWidget {
|
|||
child: Selector<MediaQueryData, Orientation>(
|
||||
selector: (c, mq) => mq.orientation,
|
||||
builder: (c, orientation, child) {
|
||||
final targetCount = orientation == Orientation.landscape ? 3 : 2;
|
||||
final targetCount = orientation == Orientation.landscape ? landscapeActionCount : portraitActionCount;
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final availableCount = (constraints.maxWidth / (kMinInteractiveDimension + padding)).floor() - 2;
|
||||
final recentActionCount = min(targetCount, availableCount);
|
||||
|
||||
final recentActions = [
|
||||
FullscreenAction.toggleFavourite,
|
||||
FullscreenAction.share,
|
||||
FullscreenAction.delete,
|
||||
FullscreenAction.info,
|
||||
FullscreenAction.rename,
|
||||
].where(_canDo).take(recentActionCount);
|
||||
final inAppActions = [
|
||||
FullscreenAction.info,
|
||||
FullscreenAction.toggleFavourite,
|
||||
FullscreenAction.share,
|
||||
FullscreenAction.delete,
|
||||
FullscreenAction.rename,
|
||||
FullscreenAction.rotateCCW,
|
||||
FullscreenAction.rotateCW,
|
||||
FullscreenAction.print,
|
||||
].where((action) => !recentActions.contains(action)).where(_canDo);
|
||||
final externalAppActions = [
|
||||
FullscreenAction.edit,
|
||||
FullscreenAction.open,
|
||||
FullscreenAction.setAs,
|
||||
FullscreenAction.openMap,
|
||||
].where(_canDo);
|
||||
final recentActions = settings.mostRecentFullscreenActions.where(_canDo).take(recentActionCount);
|
||||
final inAppActions = FullscreenActions.inApp.where((action) => !recentActions.contains(action)).where(_canDo);
|
||||
final externalAppActions = FullscreenActions.externalApp.where(_canDo);
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
|
@ -88,7 +75,12 @@ class FullscreenTopOverlay extends StatelessWidget {
|
|||
const PopupMenuDivider(),
|
||||
...externalAppActions.map(_buildPopupMenuItem),
|
||||
],
|
||||
onSelected: onActionSelected,
|
||||
onSelected: (action) {
|
||||
if (possibleOverlayActions.contains(action)) {
|
||||
settings.mostRecentFullscreenActions = [action, ...settings.mostRecentFullscreenActions].take(landscapeActionCount).toList();
|
||||
}
|
||||
onActionSelected?.call(action);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -148,37 +140,20 @@ class FullscreenTopOverlay extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.share:
|
||||
child = IconButton(
|
||||
icon: const Icon(OMIcons.share),
|
||||
onPressed: onPressed,
|
||||
tooltip: 'Share',
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.delete:
|
||||
child = IconButton(
|
||||
icon: const Icon(OMIcons.delete),
|
||||
onPressed: onPressed,
|
||||
tooltip: 'Delete',
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.info:
|
||||
child = IconButton(
|
||||
icon: const Icon(OMIcons.info),
|
||||
onPressed: onPressed,
|
||||
tooltip: 'Info',
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.share:
|
||||
case FullscreenAction.delete:
|
||||
case FullscreenAction.rename:
|
||||
child = IconButton(
|
||||
icon: const Icon(OMIcons.title),
|
||||
onPressed: onPressed,
|
||||
tooltip: 'Rename',
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.rotateCCW:
|
||||
case FullscreenAction.rotateCW:
|
||||
case FullscreenAction.print:
|
||||
final textIcon = FullscreenActions.getTextIcon(action);
|
||||
child = IconButton(
|
||||
icon: Icon(textIcon.item2),
|
||||
onPressed: onPressed,
|
||||
tooltip: textIcon.item1,
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.openMap:
|
||||
case FullscreenAction.open:
|
||||
case FullscreenAction.edit:
|
||||
|
@ -200,9 +175,6 @@ class FullscreenTopOverlay extends StatelessWidget {
|
|||
Widget child;
|
||||
switch (action) {
|
||||
// in app actions
|
||||
case FullscreenAction.info:
|
||||
child = const MenuRow(text: 'Info', icon: OMIcons.info);
|
||||
break;
|
||||
case FullscreenAction.toggleFavourite:
|
||||
child = entry.isFavouriteNotifier.value
|
||||
? const MenuRow(
|
||||
|
@ -214,36 +186,23 @@ class FullscreenTopOverlay extends StatelessWidget {
|
|||
icon: OMIcons.favoriteBorder,
|
||||
);
|
||||
break;
|
||||
case FullscreenAction.info:
|
||||
case FullscreenAction.share:
|
||||
child = const MenuRow(text: 'Share', icon: OMIcons.share);
|
||||
break;
|
||||
case FullscreenAction.delete:
|
||||
child = const MenuRow(text: 'Delete', icon: OMIcons.delete);
|
||||
break;
|
||||
case FullscreenAction.rename:
|
||||
child = const MenuRow(text: 'Rename', icon: OMIcons.title);
|
||||
break;
|
||||
case FullscreenAction.rotateCCW:
|
||||
child = const MenuRow(text: 'Rotate left', icon: OMIcons.rotateLeft);
|
||||
break;
|
||||
case FullscreenAction.rotateCW:
|
||||
child = const MenuRow(text: 'Rotate right', icon: OMIcons.rotateRight);
|
||||
break;
|
||||
case FullscreenAction.print:
|
||||
child = const MenuRow(text: 'Print', icon: OMIcons.print);
|
||||
final textIcon = FullscreenActions.getTextIcon(action);
|
||||
child = MenuRow(text: textIcon.item1, icon: textIcon.item2);
|
||||
break;
|
||||
// external app actions
|
||||
case FullscreenAction.edit:
|
||||
child = const Text('Edit with…');
|
||||
break;
|
||||
case FullscreenAction.open:
|
||||
child = const Text('Open with…');
|
||||
break;
|
||||
case FullscreenAction.setAs:
|
||||
child = const Text('Set as…');
|
||||
break;
|
||||
case FullscreenAction.openMap:
|
||||
child = const Text('Show on map…');
|
||||
final textIcon = FullscreenActions.getTextIcon(action);
|
||||
child = Text(textIcon.item1);
|
||||
break;
|
||||
}
|
||||
return PopupMenuItem(
|
||||
|
|
Loading…
Reference in a new issue