import 'dart:math'; import 'package:aves/model/image_entry.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/overlay/common.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:outline_material_icons/outline_material_icons.dart'; import 'package:provider/provider.dart'; class FullscreenTopOverlay extends StatelessWidget { final List entries; final int index; final Animation scale; final EdgeInsets viewInsets, viewPadding; final Function(FullscreenAction value) onActionSelected; final bool canToggleFavourite; ImageEntry get entry => entries[index]; static const double padding = 8; const FullscreenTopOverlay({ Key key, @required this.entries, @required this.index, @required this.scale, this.canToggleFavourite = false, this.viewInsets, this.viewPadding, this.onActionSelected, }) : super(key: key); @override Widget build(BuildContext context) { return SafeArea( minimum: (viewInsets ?? EdgeInsets.zero) + (viewPadding ?? EdgeInsets.zero), child: Padding( padding: const EdgeInsets.all(padding), child: Selector( selector: (c, mq) => mq.orientation, builder: (c, orientation, child) { final targetCount = orientation == Orientation.landscape ? 3 : 2; 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); return Row( children: [ OverlayButton( scale: scale, child: ModalRoute.of(context)?.canPop ?? true ? const BackButton() : const CloseButton(), ), const Spacer(), ...recentActions.map(_buildOverlayButton), OverlayButton( scale: scale, child: PopupMenuButton( itemBuilder: (context) => [ ...inAppActions.map(_buildPopupMenuItem), const PopupMenuDivider(), ...externalAppActions.map(_buildPopupMenuItem), ], onSelected: onActionSelected, ), ), ], ); }, ); }, ), ), ); } bool _canDo(FullscreenAction action) { switch (action) { case FullscreenAction.toggleFavourite: return canToggleFavourite; case FullscreenAction.delete: case FullscreenAction.rename: return entry.canEdit; case FullscreenAction.rotateCCW: case FullscreenAction.rotateCW: return entry.canRotate; case FullscreenAction.print: return entry.canPrint; case FullscreenAction.openMap: return entry.hasGps; case FullscreenAction.share: case FullscreenAction.info: case FullscreenAction.open: case FullscreenAction.edit: case FullscreenAction.setAs: return true; } return false; } Widget _buildOverlayButton(FullscreenAction action) { Widget child; final onPressed = () => onActionSelected?.call(action); switch (action) { case FullscreenAction.toggleFavourite: child = ValueListenableBuilder( valueListenable: entry.isFavouriteNotifier, builder: (context, isFavourite, child) => Stack( alignment: Alignment.center, children: [ IconButton( icon: Icon(isFavourite ? OMIcons.favorite : OMIcons.favoriteBorder), onPressed: onPressed, tooltip: isFavourite ? 'Remove from favourites' : 'Add to favourites', ), Sweeper( builder: (context) => Icon(OMIcons.favoriteBorder, color: Colors.redAccent), toggledNotifier: entry.isFavouriteNotifier, ), ], ), ); 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.rename: child = IconButton( icon: const Icon(OMIcons.title), onPressed: onPressed, tooltip: 'Rename', ); break; case FullscreenAction.rotateCCW: case FullscreenAction.rotateCW: case FullscreenAction.print: case FullscreenAction.openMap: case FullscreenAction.open: case FullscreenAction.edit: case FullscreenAction.setAs: break; } return child != null ? Padding( padding: const EdgeInsetsDirectional.only(end: padding), child: OverlayButton( scale: scale, child: child, ), ) : const SizedBox.shrink(); } PopupMenuEntry _buildPopupMenuItem(FullscreenAction action) { 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( text: 'Remove from favourites', icon: OMIcons.favorite, ) : const MenuRow( text: 'Add to favourites', icon: OMIcons.favoriteBorder, ); break; 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); 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…'); break; } return PopupMenuItem( value: action, child: child, ); } }