viewer quick action defaults;

viewer overlay location collapse in landscape;
popup menu icon action shape
This commit is contained in:
Thibault Deckers 2022-03-17 17:14:39 +09:00
parent a074ff5dd6
commit ad3b241e1d
5 changed files with 137 additions and 87 deletions

View file

@ -12,6 +12,8 @@ class OverlayMetadata extends Equatable {
bool get isEmpty => aperture == null && exposureTime == null && focalLength == null && iso == null; bool get isEmpty => aperture == null && exposureTime == null && focalLength == null && iso == null;
bool get isNotEmpty => !isEmpty;
const OverlayMetadata({ const OverlayMetadata({
this.aperture, this.aperture,
this.exposureTime, this.exposureTime,

View file

@ -60,9 +60,11 @@ class SettingsDefaults {
// viewer // viewer
static const viewerQuickActions = [ static const viewerQuickActions = [
EntryAction.rotateScreen,
EntryAction.toggleFavourite, EntryAction.toggleFavourite,
EntryAction.share, EntryAction.share,
EntryAction.rotateScreen, EntryAction.edit,
EntryAction.delete,
]; ];
static const showOverlayOnOpening = true; static const showOverlayOnOpening = true;
static const showOverlayMinimap = false; static const showOverlayMinimap = false;

View file

@ -361,6 +361,11 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
); );
Widget buildItem(EntrySetAction action) => Expanded( Widget buildItem(EntrySetAction action) => Expanded(
child: Material(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
clipBehavior: Clip.antiAlias,
child: PopupMenuItem( child: PopupMenuItem(
value: action, value: action,
enabled: canApply(action), enabled: canApply(action),
@ -369,9 +374,14 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
child: Center(child: action.getIcon()), child: Center(child: action.getIcon()),
), ),
), ),
),
); );
return PopupMenuItem( return PopupMenuItem(
child: TooltipTheme(
data: TooltipTheme.of(context).copyWith(
preferBelow: false,
),
child: Row( child: Row(
children: [ children: [
buildDivider(), buildDivider(),
@ -383,6 +393,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
buildDivider(), buildDivider(),
], ],
), ),
),
); );
} }

View file

@ -139,8 +139,7 @@ class ViewerDetailOverlayContent extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final infoMaxWidth = availableWidth - padding.horizontal; final infoMaxWidth = availableWidth - padding.horizontal;
final positionTitle = _PositionTitleRow(entry: pageEntry, collectionPosition: position, multiPageController: multiPageController); final positionTitle = _PositionTitleRow(entry: pageEntry, collectionPosition: position, multiPageController: multiPageController);
final hasShootingDetails = details != null && !details!.isEmpty && settings.showOverlayShootingDetails; final showShooting = settings.showOverlayShootingDetails;
final animationDuration = context.select<DurationsData, Duration>((v) => v.viewerOverlayChangeAnimation);
return DefaultTextStyle( return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!.copyWith( style: Theme.of(context).textTheme.bodyText2!.copyWith(
@ -156,40 +155,38 @@ class ViewerDetailOverlayContent extends StatelessWidget {
builder: (context, orientation, child) { builder: (context, orientation, child) {
final twoColumns = orientation == Orientation.landscape && infoMaxWidth / 2 > _subRowMinWidth; final twoColumns = orientation == Orientation.landscape && infoMaxWidth / 2 > _subRowMinWidth;
final subRowWidth = twoColumns ? min(_subRowMinWidth, infoMaxWidth / 2) : infoMaxWidth; final subRowWidth = twoColumns ? min(_subRowMinWidth, infoMaxWidth / 2) : infoMaxWidth;
final collapsedShooting = twoColumns && showShooting;
final collapsedLocation = twoColumns && !showShooting;
final rows = <Widget>[];
if (positionTitle.isNotEmpty) {
rows.add(positionTitle);
rows.add(const SizedBox(height: _interRowPadding));
}
if (twoColumns) {
rows.add(
Row(
children: [
_buildDateSubRow(subRowWidth),
if (collapsedShooting) _buildShootingSubRow(context, subRowWidth),
if (collapsedLocation) _buildLocationSubRow(context, subRowWidth),
],
),
);
} else {
rows.add(_buildDateSubRow(subRowWidth));
if (showShooting) {
rows.add(_buildShootingFullRow(context, subRowWidth));
}
}
if (!collapsedLocation) {
rows.add(_buildLocationFullRow(context));
}
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: rows,
if (positionTitle.isNotEmpty) positionTitle,
if (twoColumns)
Padding(
padding: const EdgeInsets.only(top: _interRowPadding),
child: Row(
children: [
SizedBox(
width: subRowWidth,
child: _DateRow(
entry: pageEntry,
multiPageController: multiPageController,
)),
_buildDuoShootingRow(subRowWidth, hasShootingDetails, animationDuration),
],
),
)
else ...[
Container(
padding: const EdgeInsets.only(top: _interRowPadding),
width: subRowWidth,
child: _DateRow(
entry: pageEntry,
multiPageController: multiPageController,
),
),
_buildSoloShootingRow(subRowWidth, hasShootingDetails, animationDuration),
],
_buildSoloLocationRow(animationDuration),
],
); );
}, },
), ),
@ -197,56 +194,88 @@ class ViewerDetailOverlayContent extends StatelessWidget {
); );
} }
Widget _buildSoloLocationRow(Duration animationDuration) => AnimatedSwitcher( Widget _buildDateSubRow(double subRowWidth) => SizedBox(
duration: animationDuration, width: subRowWidth,
switchInCurve: Curves.easeInOutCubic, child: _DateRow(
switchOutCurve: Curves.easeInOutCubic, entry: pageEntry,
transitionBuilder: _soloTransition, multiPageController: multiPageController,
child: pageEntry.hasGps ),
? Container(
padding: const EdgeInsets.only(top: _interRowPadding),
child: _LocationRow(entry: pageEntry),
)
: const SizedBox(),
); );
Widget _buildSoloShootingRow(double subRowWidth, bool hasShootingDetails, Duration animationDuration) => AnimatedSwitcher( Widget _buildShootingFullRow(BuildContext context, double subRowWidth) => _buildFullRowSwitcher(
duration: animationDuration, context: context,
switchInCurve: Curves.easeInOutCubic, visible: details != null && details!.isNotEmpty,
switchOutCurve: Curves.easeInOutCubic, builder: (context) => SizedBox(
transitionBuilder: _soloTransition,
child: hasShootingDetails
? Container(
padding: const EdgeInsets.only(top: _interRowPadding),
width: subRowWidth, width: subRowWidth,
child: _ShootingRow(details!), child: _ShootingRow(details!),
) ),
: const SizedBox(),
); );
Widget _buildDuoShootingRow(double subRowWidth, bool hasShootingDetails, Duration animationDuration) => AnimatedSwitcher( Widget _buildShootingSubRow(BuildContext context, double subRowWidth) => _buildSubRowSwitcher(
duration: animationDuration, context: context,
subRowWidth: subRowWidth,
visible: details != null && details!.isNotEmpty,
builder: (context) => _ShootingRow(details!),
);
Widget _buildLocationFullRow(BuildContext context) => _buildFullRowSwitcher(
context: context,
visible: pageEntry.hasGps,
builder: (context) => _LocationRow(entry: pageEntry),
);
Widget _buildLocationSubRow(BuildContext context, double subRowWidth) => _buildSubRowSwitcher(
context: context,
subRowWidth: subRowWidth,
visible: pageEntry.hasGps,
builder: (context) => _LocationRow(entry: pageEntry),
);
Widget _buildSubRowSwitcher({
required BuildContext context,
required double subRowWidth,
required bool visible,
required WidgetBuilder builder,
}) =>
AnimatedSwitcher(
duration: context.select<DurationsData, Duration>((v) => v.viewerOverlayChangeAnimation),
switchInCurve: Curves.easeInOutCubic, switchInCurve: Curves.easeInOutCubic,
switchOutCurve: Curves.easeInOutCubic, switchOutCurve: Curves.easeInOutCubic,
transitionBuilder: (child, animation) => FadeTransition( transitionBuilder: (child, animation) => FadeTransition(
opacity: animation, opacity: animation,
child: child, child: child,
), ),
child: hasShootingDetails child: visible
? SizedBox( ? SizedBox(
width: subRowWidth, width: subRowWidth,
child: _ShootingRow(details!), child: builder(context),
) )
: const SizedBox(), : const SizedBox(),
); );
static Widget _soloTransition(Widget child, Animation<double> animation) => FadeTransition( Widget _buildFullRowSwitcher({
required BuildContext context,
required bool visible,
required WidgetBuilder builder,
}) =>
AnimatedSwitcher(
duration: context.select<DurationsData, Duration>((v) => v.viewerOverlayChangeAnimation),
switchInCurve: Curves.easeInOutCubic,
switchOutCurve: Curves.easeInOutCubic,
transitionBuilder: (child, animation) => FadeTransition(
opacity: animation, opacity: animation,
child: SizeTransition( child: SizeTransition(
axisAlignment: 1, axisAlignment: 1,
sizeFactor: animation, sizeFactor: animation,
child: child, child: child,
), ),
),
child: visible
? Padding(
padding: const EdgeInsets.only(top: _interRowPadding),
child: builder(context),
)
: const SizedBox(),
); );
} }

View file

@ -352,6 +352,11 @@ class ViewerButtonRowContent extends StatelessWidget {
); );
Widget buildItem(EntryAction action) => Expanded( Widget buildItem(EntryAction action) => Expanded(
child: Material(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
clipBehavior: Clip.antiAlias,
child: PopupMenuItem( child: PopupMenuItem(
value: action, value: action,
child: Tooltip( child: Tooltip(
@ -359,6 +364,7 @@ class ViewerButtonRowContent extends StatelessWidget {
child: Center(child: action.getIcon()), child: Center(child: action.getIcon()),
), ),
), ),
),
); );
return PopupMenuItem( return PopupMenuItem(