From e92cee781c6fb462a8fb1af20aff77c6bde6144f Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 6 Mar 2022 12:27:05 +0900 Subject: [PATCH] viewer: collapse motion photo pages in button row --- lib/widgets/common/thumbnail/scroller.dart | 22 ++++++++--- lib/widgets/viewer/overlay/bottom.dart | 39 +++++++++++++++---- lib/widgets/viewer/overlay/multipage.dart | 3 ++ .../viewer/overlay/viewer_button_row.dart | 7 ++-- 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/lib/widgets/common/thumbnail/scroller.dart b/lib/widgets/common/thumbnail/scroller.dart index 10ba991f2..c0bf6e344 100644 --- a/lib/widgets/common/thumbnail/scroller.dart +++ b/lib/widgets/common/thumbnail/scroller.dart @@ -15,7 +15,7 @@ class ThumbnailScroller extends StatefulWidget { final ValueNotifier indexNotifier; final void Function(int index)? onTap; final Object? Function(AvesEntry entry)? heroTagger; - final bool highlightable, showLocation; + final bool scrollable, highlightable, showLocation; const ThumbnailScroller({ Key? key, @@ -27,6 +27,7 @@ class ThumbnailScroller extends StatefulWidget { this.heroTagger, this.highlightable = false, this.showLocation = true, + this.scrollable = true, }) : super(key: key); @override @@ -46,6 +47,10 @@ class _ThumbnailScrollerState extends State { ValueNotifier get indexNotifier => widget.indexNotifier; + bool get scrollable => widget.scrollable; + + static double widthFor(int pageCount) => pageCount == 0 ? 0 : pageCount * thumbnailExtent + (pageCount - 1) * separatorWidth; + @override void initState() { super.initState(); @@ -84,13 +89,14 @@ class _ThumbnailScrollerState extends State { @override Widget build(BuildContext context) { final marginWidth = max(0.0, (widget.availableWidth - thumbnailExtent) / 2 - separatorWidth); - final padding = EdgeInsets.only(left: marginWidth + separatorWidth, right: marginWidth); + final padding = scrollable ? EdgeInsets.only(left: marginWidth + separatorWidth, right: marginWidth) : EdgeInsets.zero; return GridTheme( extent: thumbnailExtent, showLocation: widget.showLocation && settings.showThumbnailLocation, showTrash: false, child: SizedBox( + width: scrollable ? null : widthFor(entryCount), height: thumbnailExtent, child: ListView.builder( scrollDirection: Axis.horizontal, @@ -98,10 +104,12 @@ class _ThumbnailScrollerState extends State { // as of Flutter v2.10.2, `FixedExtentScrollController` can only be used with `ListWheelScrollView` // and `FixedExtentScrollPhysics` can only be used with Scrollables that uses the `FixedExtentScrollController` // so we use `KnownExtentScrollPhysics`, adapted from `FixedExtentScrollPhysics` without the constraints - physics: KnownExtentScrollPhysics( - indexToScrollOffset: indexToScrollOffset, - scrollOffsetToIndex: scrollOffsetToIndex, - ), + physics: scrollable + ? KnownExtentScrollPhysics( + indexToScrollOffset: indexToScrollOffset, + scrollOffsetToIndex: scrollOffsetToIndex, + ) + : const NeverScrollableScrollPhysics(), padding: padding, itemExtent: itemExtent, itemBuilder: (context, index) => _buildThumbnail(index), @@ -152,6 +160,8 @@ class _ThumbnailScrollerState extends State { } Future _goTo(int index) async { + if (!scrollable) return; + final targetOffset = indexToScrollOffset(index); final offsetDelta = (targetOffset - _scrollController.offset).abs(); diff --git a/lib/widgets/viewer/overlay/bottom.dart b/lib/widgets/viewer/overlay/bottom.dart index f16bd9c23..6fc54c51f 100644 --- a/lib/widgets/viewer/overlay/bottom.dart +++ b/lib/widgets/viewer/overlay/bottom.dart @@ -136,13 +136,23 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> { return Selector( selector: (context, mq) => mq.size.width, builder: (context, mqWidth, child) { + final viewerButtonRow = ViewerButtonRow( + mainEntry: mainEntry, + pageEntry: pageEntry, + scale: _buttonScale, + canToggleFavourite: widget.hasCollection, + ); + + final showMultiPageOverlay = mainEntry.isMultiPage && multiPageController != null; + final collapsedPageScroller = mainEntry.isMotionPhoto; + return SizedBox( width: mqWidth, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (mainEntry.isMultiPage && multiPageController != null) + if (showMultiPageOverlay && !collapsedPageScroller) Padding( padding: const EdgeInsets.only(bottom: 8), child: FadeTransition( @@ -150,15 +160,30 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> { child: MultiPageOverlay( controller: multiPageController, availableWidth: mqWidth, + scrollable: true, ), ), ), - ViewerButtonRow( - mainEntry: mainEntry, - pageEntry: pageEntry, - scale: _buttonScale, - canToggleFavourite: widget.hasCollection, - ), + (showMultiPageOverlay && collapsedPageScroller) + ? Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SafeArea( + top: false, + bottom: false, + child: Padding( + padding: const EdgeInsets.only(bottom: 8), + child: MultiPageOverlay( + controller: multiPageController, + availableWidth: mqWidth, + scrollable: false, + ), + ), + ), + Expanded(child: viewerButtonRow), + ], + ) + : viewerButtonRow, if (settings.showOverlayThumbnailPreview) FadeTransition( opacity: _thumbnailOpacity, diff --git a/lib/widgets/viewer/overlay/multipage.dart b/lib/widgets/viewer/overlay/multipage.dart index 3b2737b63..44507cd47 100644 --- a/lib/widgets/viewer/overlay/multipage.dart +++ b/lib/widgets/viewer/overlay/multipage.dart @@ -8,11 +8,13 @@ import 'package:provider/provider.dart'; class MultiPageOverlay extends StatefulWidget { final MultiPageController controller; final double availableWidth; + final bool scrollable; const MultiPageOverlay({ Key? key, required this.controller, required this.availableWidth, + required this.scrollable, }) : super(key: key); @override @@ -66,6 +68,7 @@ class _MultiPageOverlayState extends State { entryCount: multiPageInfo?.pageCount ?? 0, entryBuilder: (page) => multiPageInfo?.getPageEntryByIndex(page), indexNotifier: controller.pageNotifier, + scrollable: widget.scrollable, ); }, ); diff --git a/lib/widgets/viewer/overlay/viewer_button_row.dart b/lib/widgets/viewer/overlay/viewer_button_row.dart index da484af26..3b8585b77 100644 --- a/lib/widgets/viewer/overlay/viewer_button_row.dart +++ b/lib/widgets/viewer/overlay/viewer_button_row.dart @@ -105,11 +105,10 @@ class ViewerButtonRow extends StatelessWidget { return SafeArea( top: false, bottom: false, - child: Selector( - selector: (context, mq) => mq.size.width - mq.padding.horizontal, - builder: (context, mqWidth, child) { + child: LayoutBuilder( + builder: (context, constraints) { final buttonWidth = OverlayButton.getSize(context); - final availableCount = ((mqWidth - outerPadding * 2) / (buttonWidth + innerPadding)).floor(); + final availableCount = ((constraints.maxWidth - outerPadding * 2) / (buttonWidth + innerPadding)).floor(); return Selector( selector: (context, s) => s.isRotationLocked, builder: (context, s, child) {