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,27 +361,38 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
); );
Widget buildItem(EntrySetAction action) => Expanded( Widget buildItem(EntrySetAction action) => Expanded(
child: PopupMenuItem( child: Material(
value: action, shape: const RoundedRectangleBorder(
enabled: canApply(action), borderRadius: BorderRadius.all(Radius.circular(8)),
child: Tooltip( ),
message: action.getText(context), clipBehavior: Clip.antiAlias,
child: Center(child: action.getIcon()), child: PopupMenuItem(
value: action,
enabled: canApply(action),
child: Tooltip(
message: action.getText(context),
child: Center(child: action.getIcon()),
),
), ),
), ),
); );
return PopupMenuItem( return PopupMenuItem(
child: Row( child: TooltipTheme(
children: [ data: TooltipTheme.of(context).copyWith(
buildDivider(), preferBelow: false,
buildItem(EntrySetAction.rotateCCW), ),
buildDivider(), child: Row(
buildItem(EntrySetAction.rotateCW), children: [
buildDivider(), buildDivider(),
buildItem(EntrySetAction.flip), buildItem(EntrySetAction.rotateCCW),
buildDivider(), buildDivider(),
], buildItem(EntrySetAction.rotateCW),
buildDivider(),
buildItem(EntrySetAction.flip),
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, width: subRowWidth,
child: hasShootingDetails child: _ShootingRow(details!),
? Container( ),
padding: const EdgeInsets.only(top: _interRowPadding),
width: subRowWidth,
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({
opacity: animation, required BuildContext context,
child: SizeTransition( required bool visible,
axisAlignment: 1, required WidgetBuilder builder,
sizeFactor: animation, }) =>
child: child, AnimatedSwitcher(
duration: context.select<DurationsData, Duration>((v) => v.viewerOverlayChangeAnimation),
switchInCurve: Curves.easeInOutCubic,
switchOutCurve: Curves.easeInOutCubic,
transitionBuilder: (child, animation) => FadeTransition(
opacity: animation,
child: SizeTransition(
axisAlignment: 1,
sizeFactor: animation,
child: child,
),
), ),
child: visible
? Padding(
padding: const EdgeInsets.only(top: _interRowPadding),
child: builder(context),
)
: const SizedBox(),
); );
} }

View file

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