From 4205cc0b00a9ee720b0957181d38a1e64e6134a5 Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 8 Dec 2022 16:24:43 -0700 Subject: [PATCH 1/9] Cleanup --- lib/common_libs.dart | 1 - lib/ui/common/controls/scroll_decorator.dart | 4 ++-- lib/ui/common/fade_color_transition.dart | 4 ++-- lib/ui/common/listenable_builder.dart | 11 ----------- .../common/modals/fullscreen_url_img_viewer.dart | 4 ++-- .../artifact_carousel_screen.dart | 3 +-- .../artifact_details/artifact_details_screen.dart | 1 - .../collectible_found_screen.dart | 2 +- lib/ui/screens/collection/collection_screen.dart | 1 - lib/ui/screens/editorial/editorial_screen.dart | 4 ++-- .../editorial/widgets/_circular_title_bar.dart | 4 ++-- lib/ui/screens/editorial/widgets/_title_text.dart | 8 ++++---- lib/ui/screens/home/wonders_home_screen.dart | 1 - lib/ui/screens/timeline/timeline_screen.dart | 2 +- .../timeline/widgets/_bottom_scrubber.dart | 4 ++-- .../timeline/widgets/_scrolling_viewport.dart | 12 ++++++------ .../wonder_events/widgets/_events_list.dart | 4 ++-- .../colosseum_illustration.dart | 15 +++++++-------- .../common/animated_clouds.dart | 5 +++-- .../common/paint_textures.dart | 12 +++++++++--- 20 files changed, 46 insertions(+), 56 deletions(-) delete mode 100644 lib/ui/common/listenable_builder.dart diff --git a/lib/common_libs.dart b/lib/common_libs.dart index 54f17731..c9578c57 100644 --- a/lib/common_libs.dart +++ b/lib/common_libs.dart @@ -26,5 +26,4 @@ export 'package:wonders/ui/common/controls/buttons.dart'; export 'package:wonders/ui/common/controls/circle_buttons.dart'; export 'package:wonders/ui/common/controls/scroll_decorator.dart'; export 'package:wonders/ui/common/controls/app_image.dart'; -export 'package:wonders/ui/common/listenable_builder.dart'; export 'package:flutter_animate/flutter_animate.dart'; diff --git a/lib/ui/common/controls/scroll_decorator.dart b/lib/ui/common/controls/scroll_decorator.dart index 0800c2bd..959e8913 100644 --- a/lib/ui/common/controls/scroll_decorator.dart +++ b/lib/ui/common/controls/scroll_decorator.dart @@ -123,8 +123,8 @@ class _ScrollDecoratorState extends State { @override Widget build(BuildContext context) { content = widget.builder(currentController); - return ListenableBuilder( - listenable: currentController, + return AnimatedBuilder( + animation: currentController, builder: (_, __) { return Stack( children: [ diff --git a/lib/ui/common/fade_color_transition.dart b/lib/ui/common/fade_color_transition.dart index b3b971f7..fd394a4b 100644 --- a/lib/ui/common/fade_color_transition.dart +++ b/lib/ui/common/fade_color_transition.dart @@ -8,8 +8,8 @@ class FadeColorTransition extends StatelessWidget { final Color color; @override - Widget build(BuildContext context) => ListenableBuilder( - listenable: animation, + Widget build(BuildContext context) => AnimatedBuilder( + animation: animation, builder: (_, __) => Container(color: color.withOpacity(animation.value)), ); } diff --git a/lib/ui/common/listenable_builder.dart b/lib/ui/common/listenable_builder.dart deleted file mode 100644 index 060ae972..00000000 --- a/lib/ui/common/listenable_builder.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:flutter/cupertino.dart'; - -/// Replacement for the built in [AnimatedBuilder] because that name is semantically confusing. -class ListenableBuilder extends AnimatedBuilder { - const ListenableBuilder({ - super.key, - required Listenable listenable, - required super.builder, - super.child, - }) : super(animation: listenable); -} diff --git a/lib/ui/common/modals/fullscreen_url_img_viewer.dart b/lib/ui/common/modals/fullscreen_url_img_viewer.dart index b1e1ea37..5e5571cc 100644 --- a/lib/ui/common/modals/fullscreen_url_img_viewer.dart +++ b/lib/ui/common/modals/fullscreen_url_img_viewer.dart @@ -26,8 +26,8 @@ class _FullscreenUrlImgViewerState extends State { @override Widget build(BuildContext context) { - Widget content = ListenableBuilder( - listenable: _isZoomed, + Widget content = AnimatedBuilder( + animation: _isZoomed, builder: (_, __) { final bool enableSwipe = !_isZoomed.value && widget.urls.length > 1; return PageView.builder( diff --git a/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart b/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart index 2d6525c7..b55c34c8 100644 --- a/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart +++ b/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart @@ -1,4 +1,3 @@ -import 'dart:math' as math; import 'dart:ui'; import 'package:wonders/common_libs.dart'; @@ -9,8 +8,8 @@ import 'package:wonders/ui/common/controls/simple_header.dart'; import 'package:wonders/ui/common/static_text_scale.dart'; part 'widgets/_blurred_image_bg.dart'; -part 'widgets/_collapsing_carousel_item.dart'; part 'widgets/_bottom_text_content.dart'; +part 'widgets/_collapsing_carousel_item.dart'; class ArtifactCarouselScreen extends StatefulWidget { final WonderType type; diff --git a/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart b/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart index 0e92c2ba..2e430c1f 100644 --- a/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart +++ b/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart @@ -1,5 +1,4 @@ import 'package:wonders/common_libs.dart'; -import 'package:wonders/logic/common/string_utils.dart'; import 'package:wonders/logic/data/artifact_data.dart'; import 'package:wonders/ui/common/compass_divider.dart'; import 'package:wonders/ui/common/controls/app_loading_indicator.dart'; diff --git a/lib/ui/screens/collectible_found/collectible_found_screen.dart b/lib/ui/screens/collectible_found/collectible_found_screen.dart index 42384047..217f52ef 100644 --- a/lib/ui/screens/collectible_found/collectible_found_screen.dart +++ b/lib/ui/screens/collectible_found/collectible_found_screen.dart @@ -1,6 +1,6 @@ +import 'package:particle_field/particle_field.dart'; import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/data/collectible_data.dart'; -import 'package:particle_field/particle_field.dart'; import 'package:wonders/ui/common/centered_box.dart'; part 'widgets/_animated_ribbon.dart'; diff --git a/lib/ui/screens/collection/collection_screen.dart b/lib/ui/screens/collection/collection_screen.dart index 14067f94..ca4fc66d 100644 --- a/lib/ui/screens/collection/collection_screen.dart +++ b/lib/ui/screens/collection/collection_screen.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/collectibles_logic.dart'; -import 'package:wonders/logic/common/string_utils.dart'; import 'package:wonders/logic/data/collectible_data.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/centered_box.dart'; diff --git a/lib/ui/screens/editorial/editorial_screen.dart b/lib/ui/screens/editorial/editorial_screen.dart index be22eddd..03f9af00 100644 --- a/lib/ui/screens/editorial/editorial_screen.dart +++ b/lib/ui/screens/editorial/editorial_screen.dart @@ -165,8 +165,8 @@ class _WonderEditorialScreenState extends State { ), /// Home Btn - ListenableBuilder( - listenable: _scroller, + AnimatedBuilder( + animation: _scroller, builder: (_, child) { return AnimatedOpacity( opacity: _scrollPos.value > 0 ? 0 : 1, diff --git a/lib/ui/screens/editorial/widgets/_circular_title_bar.dart b/lib/ui/screens/editorial/widgets/_circular_title_bar.dart index 9ffca6a5..f4c3ac5e 100644 --- a/lib/ui/screens/editorial/widgets/_circular_title_bar.dart +++ b/lib/ui/screens/editorial/widgets/_circular_title_bar.dart @@ -94,8 +94,8 @@ class _AnimatedCircleWithTextState extends State<_AnimatedCircleWithText> with S @override Widget build(_) { - return ListenableBuilder( - listenable: _anim, + return AnimatedBuilder( + animation: _anim, builder: (_, __) { var rot = _prevIndex > widget.index ? -pi : pi; return Transform.rotate( diff --git a/lib/ui/screens/editorial/widgets/_title_text.dart b/lib/ui/screens/editorial/widgets/_title_text.dart index 59f5e050..b7d324e5 100644 --- a/lib/ui/screens/editorial/widgets/_title_text.dart +++ b/lib/ui/screens/editorial/widgets/_title_text.dart @@ -49,8 +49,8 @@ class _TitleText extends StatelessWidget { /// Wonder title text Semantics( sortKey: OrdinalSortKey(0), - child: ListenableBuilder( - listenable: scroller, + child: AnimatedBuilder( + animation: scroller, builder: (_, __) { final yPos = ContextUtils.getGlobalPos(context)?.dy ?? 0; bool enableHero = yPos > -100; @@ -71,8 +71,8 @@ class _TitleText extends StatelessWidget { ExcludeSemantics( child: Padding( padding: EdgeInsets.symmetric(horizontal: $styles.insets.md), - child: ListenableBuilder( - listenable: scroller, + child: AnimatedBuilder( + animation: scroller, builder: (_, __) => CompassDivider( isExpanded: scroller.position.pixels <= 0, linesColor: data.type.fgColor, diff --git a/lib/ui/screens/home/wonders_home_screen.dart b/lib/ui/screens/home/wonders_home_screen.dart index 349ad5e2..bae6e4fd 100644 --- a/lib/ui/screens/home/wonders_home_screen.dart +++ b/lib/ui/screens/home/wonders_home_screen.dart @@ -1,5 +1,4 @@ import 'package:wonders/common_libs.dart'; -import 'package:wonders/logic/common/string_utils.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/app_icons.dart'; import 'package:wonders/ui/common/controls/app_page_indicator.dart'; diff --git a/lib/ui/screens/timeline/timeline_screen.dart b/lib/ui/screens/timeline/timeline_screen.dart index 7e20656f..e61281d4 100644 --- a/lib/ui/screens/timeline/timeline_screen.dart +++ b/lib/ui/screens/timeline/timeline_screen.dart @@ -16,6 +16,7 @@ import 'package:wonders/ui/common/timeline_event_card.dart'; import 'package:wonders/ui/common/utils/app_haptics.dart'; import 'package:wonders/ui/common/wonders_timeline_builder.dart'; +part 'widgets/_animated_era_text.dart'; part 'widgets/_bottom_scrubber.dart'; part 'widgets/_dashed_divider_with_year.dart'; part 'widgets/_event_markers.dart'; @@ -24,7 +25,6 @@ part 'widgets/_scrolling_viewport.dart'; part 'widgets/_scrolling_viewport_controller.dart'; part 'widgets/_timeline_section.dart'; part 'widgets/_year_markers.dart'; -part 'widgets/_animated_era_text.dart'; class TimelineScreen extends StatefulWidget { final WonderType? type; diff --git a/lib/ui/screens/timeline/widgets/_bottom_scrubber.dart b/lib/ui/screens/timeline/widgets/_bottom_scrubber.dart index a66cf08a..24f3d1a6 100644 --- a/lib/ui/screens/timeline/widgets/_bottom_scrubber.dart +++ b/lib/ui/screens/timeline/widgets/_bottom_scrubber.dart @@ -57,8 +57,8 @@ class _BottomScrubber extends StatelessWidget { ), /// Visible area, follows the position of scroller - ListenableBuilder( - listenable: scroller, + AnimatedBuilder( + animation: scroller, builder: (_, __) { ScrollPosition? pos; if (scroller.hasClients) pos = scroller.position; diff --git a/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart b/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart index 8a5a9c36..9d2c90be 100644 --- a/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart +++ b/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart @@ -61,8 +61,8 @@ class _ScalingViewportState extends State<_ScrollingViewport> { // Dashed line with a year that changes as we scroll IgnorePointer( ignoringSemantics: false, - child: ListenableBuilder( - listenable: controller.scroller, + child: AnimatedBuilder( + animation: controller.scroller, builder: (_, __) { return _DashedDividerWithYear(controller.calculateYearFromScrollPos()); }, @@ -79,8 +79,8 @@ class _ScalingViewportState extends State<_ScrollingViewport> { Widget buildTimelineSection(WonderData data) { return ClipRRect( borderRadius: BorderRadius.circular(99), - child: ListenableBuilder( - listenable: controller.scroller, + child: AnimatedBuilder( + animation: controller.scroller, builder: (_, __) => TimelineSection( data, controller.calculateYearFromScrollPos(), @@ -127,8 +127,8 @@ class _ScalingViewportState extends State<_ScrollingViewport> { ), /// Event Markers, rebuilds on scroll - ListenableBuilder( - listenable: controller.scroller, + AnimatedBuilder( + animation: controller.scroller, builder: (_, __) => _EventMarkers( controller.calculateYearFromScrollPos(), onEventChanged: _handleEventMarkerChanged, diff --git a/lib/ui/screens/wonder_events/widgets/_events_list.dart b/lib/ui/screens/wonder_events/widgets/_events_list.dart index 8d86b3a4..9f8a128a 100644 --- a/lib/ui/screens/wonder_events/widgets/_events_list.dart +++ b/lib/ui/screens/wonder_events/widgets/_events_list.dart @@ -103,8 +103,8 @@ class _EventsListState extends State<_EventsList> { /// Wraps the list in a scroll listener Widget _buildScrollingListWithBlur() { - return ListenableBuilder( - listenable: _scroller, + return AnimatedBuilder( + animation: _scroller, child: _buildScrollingList(), builder: (_, child) { bool showBackdrop = true; diff --git a/lib/ui/wonder_illustrations/colosseum_illustration.dart b/lib/ui/wonder_illustrations/colosseum_illustration.dart index 68ff54ea..2bad0dcd 100644 --- a/lib/ui/wonder_illustrations/colosseum_illustration.dart +++ b/lib/ui/wonder_illustrations/colosseum_illustration.dart @@ -2,7 +2,6 @@ import 'package:wonders/common_libs.dart'; import 'package:wonders/ui/common/fade_color_transition.dart'; import 'package:wonders/ui/wonder_illustrations/common/illustration_piece.dart'; import 'package:wonders/ui/wonder_illustrations/common/paint_textures.dart'; -import 'package:wonders/ui/wonder_illustrations/common/wonder_hero.dart'; import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_builder.dart'; import 'package:wonders/ui/wonder_illustrations/common/wonder_illustration_config.dart'; @@ -47,13 +46,13 @@ class ColosseumIllustration extends StatelessWidget { List _buildMg(BuildContext context, Animation anim) { return [ - IllustrationPiece( - fileName: 'colosseum.png', - enableHero: true, - heightFactor: .6, - minHeight: 200, - zoomAmt: .15, - fractionalOffset: Offset(0, config.shortMode ? .10: -.1), + IllustrationPiece( + fileName: 'colosseum.png', + enableHero: true, + heightFactor: .6, + minHeight: 200, + zoomAmt: .15, + fractionalOffset: Offset(0, config.shortMode ? .10 : -.1), ) ]; } diff --git a/lib/ui/wonder_illustrations/common/animated_clouds.dart b/lib/ui/wonder_illustrations/common/animated_clouds.dart index 44d0a94a..7fa15ec6 100644 --- a/lib/ui/wonder_illustrations/common/animated_clouds.dart +++ b/lib/ui/wonder_illustrations/common/animated_clouds.dart @@ -1,4 +1,5 @@ import 'dart:async'; + import 'package:wonders/common_libs.dart'; import 'package:wonders/ui/common/utils/context_utils.dart'; @@ -90,8 +91,8 @@ class _AnimatedCloudsState extends State with SingleTickerProvid return RepaintBoundary( child: ClipRect( child: OverflowBox( - child: ListenableBuilder( - listenable: _anim, + child: AnimatedBuilder( + animation: _anim, builder: (_, __) { // A stack with 2 sets of clouds, one set is moving out of view while the other moves in. return Stack( diff --git a/lib/ui/wonder_illustrations/common/paint_textures.dart b/lib/ui/wonder_illustrations/common/paint_textures.dart index b2b7a1d7..192ecf78 100644 --- a/lib/ui/wonder_illustrations/common/paint_textures.dart +++ b/lib/ui/wonder_illustrations/common/paint_textures.dart @@ -12,13 +12,19 @@ class IllustrationTexture extends StatelessWidget { final Animation? opacity; @override - Widget build(BuildContext context) => ListenableBuilder( - listenable: opacity ?? AlwaysStoppedAnimation(1), + Widget build(BuildContext context) => AnimatedBuilder( + animation: opacity ?? AlwaysStoppedAnimation(1), builder: (context, child) => ClipRect( child: Transform.scale( scaleX: scale * (flipX ? -1 : 1), scaleY: scale * (flipY ? -1 : 1), - child: Image.asset(path, repeat: ImageRepeat.repeat, fit: BoxFit.contain, alignment: Alignment.topCenter, color: color, opacity: opacity, cacheWidth: 2048)), + child: Image.asset(path, + repeat: ImageRepeat.repeat, + fit: BoxFit.contain, + alignment: Alignment.topCenter, + color: color, + opacity: opacity, + cacheWidth: 2048)), ), ); } From a4f2daffecb27d9fa99b42f580677ae75ab42ec9 Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 8 Dec 2022 18:50:27 -0700 Subject: [PATCH 2/9] Add cupertino page routes for all full-screen dialogs --- lib/logic/app_logic.dart | 1 + lib/ui/common/utils/page_routes.dart | 24 +++++++++++-------- .../artifact_details_screen.dart | 12 +++++----- .../widgets/{_header.dart => _image_btn.dart} | 4 ++-- .../{_content.dart => _info_column.dart} | 4 ++-- .../screens/photo_gallery/photo_gallery.dart | 15 ++++++------ 6 files changed, 32 insertions(+), 28 deletions(-) rename lib/ui/screens/artifact/artifact_details/widgets/{_header.dart => _image_btn.dart} (92%) rename lib/ui/screens/artifact/artifact_details/widgets/{_content.dart => _info_column.dart} (96%) diff --git a/lib/logic/app_logic.dart b/lib/logic/app_logic.dart index 48900654..fcdedcc5 100644 --- a/lib/logic/app_logic.dart +++ b/lib/logic/app_logic.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:desktop_window/desktop_window.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/common/platform_info.dart'; diff --git a/lib/ui/common/utils/page_routes.dart b/lib/ui/common/utils/page_routes.dart index ecb3b5f7..cd3d23ec 100644 --- a/lib/ui/common/utils/page_routes.dart +++ b/lib/ui/common/utils/page_routes.dart @@ -1,17 +1,21 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; class PageRoutes { static const Duration kDefaultDuration = Duration(milliseconds: 300); static Route dialog(Widget child, [Duration duration = kDefaultDuration, bool opaque = false]) { - return PageRouteBuilder( - transitionDuration: duration, - reverseTransitionDuration: duration, - pageBuilder: (context, animation, secondaryAnimation) => child, - opaque: opaque, - fullscreenDialog: true, - transitionsBuilder: (context, animation, secondaryAnimation, child) => - FadeTransition(opacity: animation, child: child), - ); + // Use cupertino routes for all dialogs so we get the 'swipe right to go back' behavior + return CupertinoPageRoute(builder: (_) => child); + + // SB: Removed this in favor of Cupertino routes, we could restor with a `useFade` option + // return PageRouteBuilder( + // transitionDuration: duration, + // reverseTransitionDuration: duration, + // pageBuilder: (context, animation, secondaryAnimation) => child, + // opaque: opaque, + // fullscreenDialog: true, + // transitionsBuilder: (context, animation, secondaryAnimation, child) => + // FadeTransition(opacity: animation, child: child), + // ); } } diff --git a/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart b/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart index 2e430c1f..a94006a0 100644 --- a/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart +++ b/lib/ui/screens/artifact/artifact_details/artifact_details_screen.dart @@ -5,8 +5,8 @@ import 'package:wonders/ui/common/controls/app_loading_indicator.dart'; import 'package:wonders/ui/common/gradient_container.dart'; import 'package:wonders/ui/common/modals/fullscreen_url_img_viewer.dart'; -part 'widgets/_content.dart'; -part 'widgets/_header.dart'; +part 'widgets/_info_column.dart'; +part 'widgets/_image_btn.dart'; class ArtifactDetailsScreen extends StatefulWidget { const ArtifactDetailsScreen({Key? key, required this.artifactId}) : super(key: key); @@ -36,8 +36,8 @@ class _ArtifactDetailsScreenState extends State { } else { content = hzMode ? Row(children: [ - Expanded(child: _Header(data: data!)), - Expanded(child: Center(child: SizedBox(width: 600, child: _Content(data: data)))), + Expanded(child: _ImageBtn(data: data!)), + Expanded(child: Center(child: SizedBox(width: 600, child: _InfoColumn(data: data)))), ]) : CustomScrollView( slivers: [ @@ -47,9 +47,9 @@ class _ArtifactDetailsScreenState extends State { leading: SizedBox.shrink(), expandedHeight: context.heightPx * .5, collapsedHeight: context.heightPx * .35, - flexibleSpace: _Header(data: data!), + flexibleSpace: _ImageBtn(data: data!), ), - SliverToBoxAdapter(child: _Content(data: data)), + SliverToBoxAdapter(child: _InfoColumn(data: data)), ], ); } diff --git a/lib/ui/screens/artifact/artifact_details/widgets/_header.dart b/lib/ui/screens/artifact/artifact_details/widgets/_image_btn.dart similarity index 92% rename from lib/ui/screens/artifact/artifact_details/widgets/_header.dart rename to lib/ui/screens/artifact/artifact_details/widgets/_image_btn.dart index e30cd837..2ae8f924 100644 --- a/lib/ui/screens/artifact/artifact_details/widgets/_header.dart +++ b/lib/ui/screens/artifact/artifact_details/widgets/_image_btn.dart @@ -1,7 +1,7 @@ part of '../artifact_details_screen.dart'; -class _Header extends StatelessWidget { - const _Header({Key? key, required this.data}) : super(key: key); +class _ImageBtn extends StatelessWidget { + const _ImageBtn({Key? key, required this.data}) : super(key: key); final ArtifactData data; @override diff --git a/lib/ui/screens/artifact/artifact_details/widgets/_content.dart b/lib/ui/screens/artifact/artifact_details/widgets/_info_column.dart similarity index 96% rename from lib/ui/screens/artifact/artifact_details/widgets/_content.dart rename to lib/ui/screens/artifact/artifact_details/widgets/_info_column.dart index 78104017..20e62568 100644 --- a/lib/ui/screens/artifact/artifact_details/widgets/_content.dart +++ b/lib/ui/screens/artifact/artifact_details/widgets/_info_column.dart @@ -1,7 +1,7 @@ part of '../artifact_details_screen.dart'; -class _Content extends StatelessWidget { - const _Content({Key? key, required this.data}) : super(key: key); +class _InfoColumn extends StatelessWidget { + const _InfoColumn({Key? key, required this.data}) : super(key: key); final ArtifactData data; @override diff --git a/lib/ui/screens/photo_gallery/photo_gallery.dart b/lib/ui/screens/photo_gallery/photo_gallery.dart index 571d38d2..3b593654 100644 --- a/lib/ui/screens/photo_gallery/photo_gallery.dart +++ b/lib/ui/screens/photo_gallery/photo_gallery.dart @@ -107,15 +107,14 @@ class _PhotoGalleryState extends State { Future _handleImageTapped(int index) async { if (_index == index) { - int? newIndex = await Navigator.push( + final urls = _photoIds.value.map((e) { + return UnsplashPhotoData.getSelfHostedUrl(e, UnsplashPhotoSize.med); + }).toList(); + int? newIndex = await appLogic.showFullscreenDialogRoute( context, - CupertinoPageRoute(builder: (_) { - final urls = _photoIds.value.map((e) { - return UnsplashPhotoData.getSelfHostedUrl(e, UnsplashPhotoSize.med); - }).toList(); - return FullscreenUrlImgViewer(urls: urls, index: _index); - }), + FullscreenUrlImgViewer(urls: urls, index: _index), ); + if (newIndex != null) { _setIndex(newIndex, skipAnimation: true); } @@ -148,7 +147,7 @@ class _PhotoGalleryState extends State { gridOffset += Offset(0, -context.mq.padding.top / 2); final offsetTweenDuration = _skipNextOffsetTween ? Duration.zero : swipeDuration; final cutoutTweenDuration = _skipNextOffsetTween ? Duration.zero : swipeDuration * .5; - return _AnimatedCutoutOverlay( + return _AnimatedCutoutOverlay( animationKey: ValueKey(_index), cutoutSize: imgSize, swipeDir: _lastSwipeDir, From dbe051961d0ba45fcc2d22491d2e7201e91b70da Mon Sep 17 00:00:00 2001 From: Shawn Date: Thu, 8 Dec 2022 19:08:59 -0700 Subject: [PATCH 3/9] Close search suggestions when tapping outside the suggestion area --- .../artifact_search_screen.dart | 18 +++--- .../widgets/_search_input.dart | 60 +++++++++++-------- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart b/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart index 1204e722..7fd4bec7 100644 --- a/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart +++ b/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart @@ -38,7 +38,7 @@ class _ArtifactSearchScreenState extends State with GetItS @override void initState() { - _search(); + _updateResults(); panelController.addListener(() { AppHaptics.lightImpact(); }); @@ -47,16 +47,18 @@ class _ArtifactSearchScreenState extends State with GetItS void _handleSearchSubmitted(String query) { _query = query; - _search(); + _updateResults(); } void _handleTimelineChanged(double start, double end) { _startYear = start; _endYear = end; - _filter(); + _updateFilter(); } - void _search() { + void _handleResultPressed(SearchData o) => context.push(ScreenPaths.artifact(o.id.toString())); + + void _updateResults() { if (_query.isEmpty) { _searchResults = wonder.searchData; } else { @@ -66,10 +68,10 @@ class _ArtifactSearchScreenState extends State with GetItS _searchResults = wonder.searchData.where((o) => o.title.contains(q) || o.keywords.contains(q)).toList(); } vizController.value = _searchResults; - _filter(); + _updateFilter(); } - void _filter() { + void _updateFilter() { _filteredResults = _searchResults.where((o) => o.year >= _startYear && o.year <= _endYear).toList(); setState(() {}); } @@ -79,7 +81,7 @@ class _ArtifactSearchScreenState extends State with GetItS // tone down the orange just a bit: vizController.color = Color.lerp($styles.colors.accent1, $styles.colors.black, 0.2)!; Widget content = GestureDetector( - onTap: () => WidgetsBinding.instance.focusManager.primaryFocus?.unfocus(), + onTap: FocusManager.instance.primaryFocus?.unfocus, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -101,7 +103,7 @@ class _ArtifactSearchScreenState extends State with GetItS ? _buildEmptyIndicator(context) : _ResultsGrid( searchResults: _filteredResults, - onPressed: (o) => context.push(ScreenPaths.artifact(o.id.toString())), + onPressed: _handleResultPressed, ), ), ), diff --git a/lib/ui/screens/artifact/artifact_search/widgets/_search_input.dart b/lib/ui/screens/artifact/artifact_search/widgets/_search_input.dart index 8d9f4a10..fe77c687 100644 --- a/lib/ui/screens/artifact/artifact_search/widgets/_search_input.dart +++ b/lib/ui/screens/artifact/artifact_search/widgets/_search_input.dart @@ -34,36 +34,46 @@ class _SearchInput extends StatelessWidget { Widget _buildSuggestionsView(BuildContext context, onSelected, Iterable results, BoxConstraints constraints) { List items = results.map((str) => _buildSuggestion(context, str, () => onSelected(str))).toList(); items.insert(0, _buildSuggestionTitle(context)); - - return TopLeft( - child: Container( - margin: EdgeInsets.only(top: $styles.insets.xxs), - width: constraints.maxWidth, - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: $styles.colors.black.withOpacity(0.25), - blurRadius: 4, - offset: Offset(0, 4), - ), - ], - ), - child: Container( - padding: EdgeInsets.all($styles.insets.xs), - decoration: BoxDecoration( - color: $styles.colors.offWhite.withOpacity(0.92), - borderRadius: BorderRadius.circular($styles.insets.xs), + return Stack( + children: [ + ExcludeSemantics( + child: AppBtn.basic( + onPressed: FocusManager.instance.primaryFocus!.unfocus, + semanticLabel: '', + child: SizedBox.expand(), ), - child: ConstrainedBox( - constraints: BoxConstraints(maxHeight: 200), - child: ListView( + ), + TopLeft( + child: Container( + margin: EdgeInsets.only(top: $styles.insets.xxs), + width: constraints.maxWidth, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: $styles.colors.black.withOpacity(0.25), + blurRadius: 4, + offset: Offset(0, 4), + ), + ], + ), + child: Container( padding: EdgeInsets.all($styles.insets.xs), - shrinkWrap: true, - children: items, + decoration: BoxDecoration( + color: $styles.colors.offWhite.withOpacity(0.92), + borderRadius: BorderRadius.circular($styles.insets.xs), + ), + child: ConstrainedBox( + constraints: BoxConstraints(maxHeight: 200), + child: ListView( + padding: EdgeInsets.all($styles.insets.xs), + shrinkWrap: true, + children: items, + ), + ), ), ), ), - ), + ], ); } From e5f55ef9db7dab4ce1d4b18d89626f3f3d512614 Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 12 Dec 2022 11:50:24 -0700 Subject: [PATCH 4/9] Fix comments --- lib/ui/common/utils/page_routes.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/common/utils/page_routes.dart b/lib/ui/common/utils/page_routes.dart index cd3d23ec..0c5166a1 100644 --- a/lib/ui/common/utils/page_routes.dart +++ b/lib/ui/common/utils/page_routes.dart @@ -7,7 +7,7 @@ class PageRoutes { // Use cupertino routes for all dialogs so we get the 'swipe right to go back' behavior return CupertinoPageRoute(builder: (_) => child); - // SB: Removed this in favor of Cupertino routes, we could restor with a `useFade` option + // SB: Removed this in favor of Cupertino routes, we could restore with a `useFade` option // return PageRouteBuilder( // transitionDuration: duration, // reverseTransitionDuration: duration, From a3e13de6ba1a71335744da677e036f5948d78ef2 Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 19 Dec 2022 12:18:47 -0700 Subject: [PATCH 5/9] Remove error handler delegate, don't need it. --- lib/logic/app_logic.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/logic/app_logic.dart b/lib/logic/app_logic.dart index 61f697b5..337469a1 100644 --- a/lib/logic/app_logic.dart +++ b/lib/logic/app_logic.dart @@ -27,8 +27,6 @@ class AppLogic { /// Loads settings, sets up services etc. Future bootstrap() async { debugPrint('bootstrap app, deviceSize: $deviceSize, isTablet: $isDesktopOrTablet'); - // Default error handler - FlutterError.onError = _handleFlutterError; // Set min-sizes for desktop apps if (PlatformInfo.isDesktop) { @@ -90,10 +88,6 @@ class AppLogic { SystemChrome.setPreferredOrientations(orientations); } - void _handleFlutterError(FlutterErrorDetails details) { - FlutterError.dumpErrorToConsole(details); - } - Future showFullscreenDialogRoute(BuildContext context, Widget child) async { return await Navigator.of(context).push( PageRoutes.dialog(child, $styles.times.pageTransition), From 9463be0bcda5f7a6dd07b1db41e0ea5aa0097bff Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 19 Dec 2022 13:43:30 -0700 Subject: [PATCH 6/9] Update line endings --- lib/logic/app_logic.dart | 14 +++-- lib/ui/common/collectible_item.dart | 2 +- lib/ui/common/utils/page_routes.dart | 24 ++++---- lib/ui/screens/home/wonders_home_screen.dart | 1 + .../wonder_details_tab_menu.dart | 57 ++++++++++++++----- 5 files changed, 66 insertions(+), 32 deletions(-) diff --git a/lib/logic/app_logic.dart b/lib/logic/app_logic.dart index 337469a1..0e0d90ce 100644 --- a/lib/logic/app_logic.dart +++ b/lib/logic/app_logic.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:desktop_window/desktop_window.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/common/platform_info.dart'; @@ -12,11 +11,12 @@ class AppLogic { /// The router will use this to prevent redirects while bootstrapping. bool isBootstrapComplete = false; - bool get isDesktopOrTablet => PlatformInfo.isDesktopOrWeb || deviceSize.shortestSide > 480; + bool get isLandscapeEnabled => + PlatformInfo.isDesktopOrWeb || deviceSize.shortestSide > 500; /// Support portrait and landscape on desktop, web and tablets. Stick to portrait for phones. /// A return value of null indicated both orientations are supported. - Axis? get supportedOrientations => isDesktopOrTablet ? null : Axis.vertical; + Axis? get supportedOrientations => isLandscapeEnabled ? null : Axis.vertical; Size get deviceSize { final w = WidgetsBinding.instance.platformDispatcher.views.first; @@ -26,7 +26,8 @@ class AppLogic { /// Initialize the app and all main actors. /// Loads settings, sets up services etc. Future bootstrap() async { - debugPrint('bootstrap app, deviceSize: $deviceSize, isTablet: $isDesktopOrTablet'); + debugPrint( + 'bootstrap app, deviceSize: $deviceSize, isTablet: $isLandscapeEnabled'); // Set min-sizes for desktop apps if (PlatformInfo.isDesktop) { @@ -88,9 +89,10 @@ class AppLogic { SystemChrome.setPreferredOrientations(orientations); } - Future showFullscreenDialogRoute(BuildContext context, Widget child) async { + Future showFullscreenDialogRoute(BuildContext context, Widget child, + {bool transparent = false}) async { return await Navigator.of(context).push( - PageRoutes.dialog(child, $styles.times.pageTransition), + PageRoutes.dialog(child, duration: $styles.times.pageTransition), ); } } diff --git a/lib/ui/common/collectible_item.dart b/lib/ui/common/collectible_item.dart index 5bb0174a..6e0b32ee 100644 --- a/lib/ui/common/collectible_item.dart +++ b/lib/ui/common/collectible_item.dart @@ -18,7 +18,7 @@ class CollectibleItem extends StatelessWidget with GetItMixin { void _handleTap(BuildContext context) async { final screen = CollectibleFoundScreen(collectible: collectible, imageProvider: _imageProvider); - appLogic.showFullscreenDialogRoute(context, screen); + appLogic.showFullscreenDialogRoute(context, screen, transparent: true); AppHaptics.mediumImpact(); // wait to update the state, to ensure the hero works properly: diff --git a/lib/ui/common/utils/page_routes.dart b/lib/ui/common/utils/page_routes.dart index 0c5166a1..d6dc04b3 100644 --- a/lib/ui/common/utils/page_routes.dart +++ b/lib/ui/common/utils/page_routes.dart @@ -3,19 +3,21 @@ import 'package:flutter/cupertino.dart'; class PageRoutes { static const Duration kDefaultDuration = Duration(milliseconds: 300); - static Route dialog(Widget child, [Duration duration = kDefaultDuration, bool opaque = false]) { + static Route dialog(Widget child, {Duration duration = kDefaultDuration, bool opaque = false}) { // Use cupertino routes for all dialogs so we get the 'swipe right to go back' behavior - return CupertinoPageRoute(builder: (_) => child); + if (opaque) { + return CupertinoPageRoute(builder: (_) => child); + } // SB: Removed this in favor of Cupertino routes, we could restore with a `useFade` option - // return PageRouteBuilder( - // transitionDuration: duration, - // reverseTransitionDuration: duration, - // pageBuilder: (context, animation, secondaryAnimation) => child, - // opaque: opaque, - // fullscreenDialog: true, - // transitionsBuilder: (context, animation, secondaryAnimation, child) => - // FadeTransition(opacity: animation, child: child), - // ); + return PageRouteBuilder( + transitionDuration: duration, + reverseTransitionDuration: duration, + pageBuilder: (context, animation, secondaryAnimation) => child, + opaque: opaque, + fullscreenDialog: true, + transitionsBuilder: (context, animation, secondaryAnimation, child) => + FadeTransition(opacity: animation, child: child), + ); } } diff --git a/lib/ui/screens/home/wonders_home_screen.dart b/lib/ui/screens/home/wonders_home_screen.dart index bae6e4fd..ae18cbb3 100644 --- a/lib/ui/screens/home/wonders_home_screen.dart +++ b/lib/ui/screens/home/wonders_home_screen.dart @@ -62,6 +62,7 @@ class _HomeScreenState extends State with SingleTickerProviderStateM WonderType? pickedWonder = await appLogic.showFullscreenDialogRoute( context, HomeMenu(data: currentWonder), + transparent: true, ); setState(() => _isMenuOpen = false); if (pickedWonder != null) { diff --git a/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart b/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart index 375a86ea..5c92955a 100644 --- a/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart +++ b/lib/ui/screens/wonder_details/wonder_details_tab_menu.dart @@ -4,7 +4,11 @@ class WonderDetailsTabMenu extends StatelessWidget { static double bottomPadding = 0; static double buttonInset = 12; - const WonderDetailsTabMenu({Key? key, required this.tabController, this.showBg = false, required this.wonderType}) + const WonderDetailsTabMenu( + {Key? key, + required this.tabController, + this.showBg = false, + required this.wonderType}) : super(key: key); final TabController tabController; @@ -32,7 +36,10 @@ class WonderDetailsTabMenu extends StatelessWidget { ), // Buttons Padding( - padding: EdgeInsets.only(left: $styles.insets.sm, right: $styles.insets.xxs, bottom: bottomPadding), + padding: EdgeInsets.only( + left: $styles.insets.sm, + right: $styles.insets.xxs, + bottom: bottomPadding), // TabButtons are a Stack with a row of icon buttons, and an illustrated home button sitting on top. // The home buttons shows / hides itself based on `showHomeBtn` // The row contains an animated placeholder gap which makes room for the icon as it transitions in. @@ -52,13 +59,21 @@ class WonderDetailsTabMenu extends StatelessWidget { borderSize: showBg ? 6 : 2, ), _TabBtn(0, tabController, - iconImg: 'editorial', label: $strings.wonderDetailsTabLabelInformation, color: iconColor), + iconImg: 'editorial', + label: $strings.wonderDetailsTabLabelInformation, + color: iconColor), _TabBtn(1, tabController, - iconImg: 'photos', label: $strings.wonderDetailsTabLabelImages, color: iconColor), + iconImg: 'photos', + label: $strings.wonderDetailsTabLabelImages, + color: iconColor), _TabBtn(2, tabController, - iconImg: 'artifacts', label: $strings.wonderDetailsTabLabelArtifacts, color: iconColor), + iconImg: 'artifacts', + label: $strings.wonderDetailsTabLabelArtifacts, + color: iconColor), _TabBtn(3, tabController, - iconImg: 'timeline', label: $strings.wonderDetailsTabLabelEvents, color: iconColor), + iconImg: 'timeline', + label: $strings.wonderDetailsTabLabelEvents, + color: iconColor), ], ), ), @@ -72,7 +87,11 @@ class WonderDetailsTabMenu extends StatelessWidget { } class _WonderHomeBtn extends StatelessWidget { - const _WonderHomeBtn({Key? key, required this.size, required this.wonderType, required this.borderSize}) + const _WonderHomeBtn( + {Key? key, + required this.size, + required this.wonderType, + required this.borderSize}) : super(key: key); final double size; @@ -94,7 +113,8 @@ class _WonderHomeBtn extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(99), color: wonderType.fgColor, - image: DecorationImage(image: AssetImage(wonderType.homeBtn), fit: BoxFit.fill), + image: DecorationImage( + image: AssetImage(wonderType.homeBtn), fit: BoxFit.fill), ), ), ); @@ -111,6 +131,9 @@ class _TabBtn extends StatelessWidget { required this.label, }) : super(key: key); + static const double _minWidth = 50; + static const double _maxWidth = 120; + final int index; final TabController tabController; final String iconImg; @@ -120,23 +143,29 @@ class _TabBtn extends StatelessWidget { @override Widget build(BuildContext context) { bool selected = tabController.index == index; - final MaterialLocalizations localizations = MaterialLocalizations.of(context); - final iconImgPath = '${ImagePaths.common}/tab-$iconImg${selected ? '-active' : ''}.png'; - String tabLabel = localizations.tabLabel(tabIndex: index + 1, tabCount: tabController.length); + final MaterialLocalizations localizations = + MaterialLocalizations.of(context); + final iconImgPath = + '${ImagePaths.common}/tab-$iconImg${selected ? '-active' : ''}.png'; + String tabLabel = localizations.tabLabel( + tabIndex: index + 1, tabCount: tabController.length); tabLabel = '$label: $tabLabel'; - final double btnWidth = (context.widthPx / 6).clamp(50, 120); + final double btnWidth = (context.widthPx / 6).clamp(_minWidth, _maxWidth); return MergeSemantics( child: Semantics( selected: selected, label: tabLabel, child: ExcludeSemantics( child: AppBtn.basic( - padding: EdgeInsets.only(top: $styles.insets.md + $styles.insets.xs, bottom: $styles.insets.sm), + padding: EdgeInsets.only( + top: $styles.insets.md + $styles.insets.xs, + bottom: $styles.insets.sm), onPressed: () => tabController.index = index, semanticLabel: label, minimumSize: Size(btnWidth, 0), // Image icon - child: Image.asset(iconImgPath, height: 32, width: 32, color: selected ? null : color), + child: Image.asset(iconImgPath, + height: 32, width: 32, color: selected ? null : color), ), ), ), From a40f7c42ce3ef72a8afcb751f35aaebf7ff42be8 Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 19 Dec 2022 14:13:25 -0700 Subject: [PATCH 7/9] Add close underlay btn to collectibles and home menu --- lib/ui/common/modals/app_modals.dart | 33 +++++++++++-------- lib/ui/common/pop_navigator_underlay.dart | 16 +++++++++ .../collectible_found_screen.dart | 15 ++++++++- lib/ui/screens/home_menu/home_menu.dart | 7 ++-- 4 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 lib/ui/common/pop_navigator_underlay.dart diff --git a/lib/ui/common/modals/app_modals.dart b/lib/ui/common/modals/app_modals.dart index d8acabe1..4ca9dd25 100644 --- a/lib/ui/common/modals/app_modals.dart +++ b/lib/ui/common/modals/app_modals.dart @@ -87,19 +87,26 @@ class _BaseContentModal extends StatelessWidget { @override Widget build(BuildContext context) { - return Padding( - padding: EdgeInsets.all($styles.insets.lg), - child: LightText( - child: SeparatedColumn( - mainAxisSize: MainAxisSize.min, - separatorBuilder: () => Gap($styles.insets.md), - children: [ - if (title != null) Text(title!, style: $styles.text.h2), - if (child != null) child!, - if (msg != null) Text(msg!, style: $styles.text.body), - Gap($styles.insets.md), - Column(children: buttons.map((e) => e).toList()) - ], + return IntrinsicHeight( + child: Center( + child: SizedBox( + width: $styles.sizes.maxContentWidth3, + child: Padding( + padding: EdgeInsets.all($styles.insets.lg), + child: LightText( + child: SeparatedColumn( + mainAxisSize: MainAxisSize.min, + separatorBuilder: () => Gap($styles.insets.md), + children: [ + if (title != null) Text(title!, style: $styles.text.h2), + if (child != null) child!, + if (msg != null) Text(msg!, style: $styles.text.body), + Gap($styles.insets.md), + Column(children: buttons.map((e) => e).toList()) + ], + ), + ), + ), ), ), ); diff --git a/lib/ui/common/pop_navigator_underlay.dart b/lib/ui/common/pop_navigator_underlay.dart new file mode 100644 index 00000000..b7aed1d7 --- /dev/null +++ b/lib/ui/common/pop_navigator_underlay.dart @@ -0,0 +1,16 @@ +import 'package:wonders/common_libs.dart'; + +class PopNavigatorUnderlay extends StatelessWidget { + const PopNavigatorUnderlay({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ExcludeSemantics( + child: AppBtn.basic( + onPressed: () => Navigator.of(context).pop(), + semanticLabel: '', + child: const SizedBox.expand(), + ), + ); + } +} diff --git a/lib/ui/screens/collectible_found/collectible_found_screen.dart b/lib/ui/screens/collectible_found/collectible_found_screen.dart index 217f52ef..93ac4324 100644 --- a/lib/ui/screens/collectible_found/collectible_found_screen.dart +++ b/lib/ui/screens/collectible_found/collectible_found_screen.dart @@ -1,7 +1,9 @@ import 'package:particle_field/particle_field.dart'; import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/data/collectible_data.dart'; +import 'package:wonders/ui/common/app_backdrop.dart'; import 'package:wonders/ui/common/centered_box.dart'; +import 'package:wonders/ui/common/pop_navigator_underlay.dart'; part 'widgets/_animated_ribbon.dart'; part 'widgets/_celebration_particles.dart'; @@ -49,8 +51,19 @@ class CollectibleFoundScreen extends StatelessWidget { Widget _buildDetail(BuildContext context) { Duration t = $styles.times.fast; return Stack(key: ValueKey('detail'), children: [ - Animate().custom(duration: t, builder: (context, ratio, _) => _buildGradient(context, 1, ratio)), + /// Background + AppBackdrop( + strength: .5, + child: Container(color: $styles.colors.greyStrong.withOpacity(.96)), + ).animate().fadeIn(), + + /// Particles _CelebrationParticles(fadeMs: (t * 6).inMilliseconds), + + /// invisible close btn + PopNavigatorUnderlay(), + + /// Content SafeArea( child: CenteredBox( width: $styles.sizes.maxContentWidth3, diff --git a/lib/ui/screens/home_menu/home_menu.dart b/lib/ui/screens/home_menu/home_menu.dart index 9a77cff0..43410a5c 100644 --- a/lib/ui/screens/home_menu/home_menu.dart +++ b/lib/ui/screens/home_menu/home_menu.dart @@ -5,6 +5,7 @@ import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/app_backdrop.dart'; import 'package:wonders/ui/common/app_icons.dart'; import 'package:wonders/ui/common/controls/locale_switcher.dart'; +import 'package:wonders/ui/common/pop_navigator_underlay.dart'; import 'package:wonders/ui/screens/home_menu/about_dialog_content.dart'; class HomeMenu extends StatelessWidget { @@ -48,11 +49,11 @@ class HomeMenu extends StatelessWidget { /// Backdrop / Underlay AppBackdrop( strength: .5, - child: Container( - color: $styles.colors.greyStrong.withOpacity(.7), - ), + child: Container(color: $styles.colors.greyStrong.withOpacity(.7)), ), + PopNavigatorUnderlay(), + SafeArea( child: PaddedRow( padding: EdgeInsets.symmetric( From 52f8d67e2dab81ff095963c40893e46de9bc6074 Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 19 Dec 2022 14:37:19 -0700 Subject: [PATCH 8/9] Fix tablet sizing in photogallery --- lib/ui/screens/photo_gallery/photo_gallery.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/ui/screens/photo_gallery/photo_gallery.dart b/lib/ui/screens/photo_gallery/photo_gallery.dart index 3b593654..aa6541bb 100644 --- a/lib/ui/screens/photo_gallery/photo_gallery.dart +++ b/lib/ui/screens/photo_gallery/photo_gallery.dart @@ -136,13 +136,10 @@ class _PhotoGalleryState extends State { return Center(child: AppLoadingIndicator()); } - Size imgSize = context.isLandscape - ? Size(context.widthPx * .5, context.heightPx * .66) - : Size(context.widthPx * .66, context.heightPx * .5); + Size imgSize = Size(context.widthPx * .5, context.heightPx * .5); imgSize = (widget.imageSize ?? imgSize) * _scale; // Get transform offset for the current _index final padding = $styles.insets.md; - var gridOffset = _calculateCurrentOffset(padding, imgSize); gridOffset += Offset(0, -context.mq.padding.top / 2); final offsetTweenDuration = _skipNextOffsetTween ? Duration.zero : swipeDuration; From 574c4503fd93ba32789f8c5aab0f68cf4a12dd66 Mon Sep 17 00:00:00 2001 From: Shawn Date: Tue, 20 Dec 2022 10:23:20 -0700 Subject: [PATCH 9/9] Latest polish tweaks --- .../{simple_header.dart => app_header.dart} | 26 ++++++++----- .../artifact_carousel_screen.dart | 6 +-- .../artifact_search_screen.dart | 4 +- .../screens/collection/collection_screen.dart | 4 +- .../editorial/widgets/_top_illustration.dart | 2 +- lib/ui/screens/timeline/timeline_screen.dart | 4 +- .../wonder_events/widgets/_events_list.dart | 4 +- .../screens/wonder_events/wonder_events.dart | 37 +++++++++++++------ .../common/animated_clouds.dart | 19 ++++++---- .../common/illustration_piece.dart | 28 ++++++++------ pubspec.lock | 4 +- pubspec.yaml | 2 +- 12 files changed, 86 insertions(+), 54 deletions(-) rename lib/ui/common/controls/{simple_header.dart => app_header.dart} (73%) diff --git a/lib/ui/common/controls/simple_header.dart b/lib/ui/common/controls/app_header.dart similarity index 73% rename from lib/ui/common/controls/simple_header.dart rename to lib/ui/common/controls/app_header.dart index 3b56101e..eabb6565 100644 --- a/lib/ui/common/controls/simple_header.dart +++ b/lib/ui/common/controls/app_header.dart @@ -1,10 +1,16 @@ import 'package:wonders/common_libs.dart'; -class SimpleHeader extends StatelessWidget { - const SimpleHeader(this.title, - {Key? key, this.subtitle, this.showBackBtn = true, this.isTransparent = false, this.onBack, this.trailing}) +class AppHeader extends StatelessWidget { + const AppHeader( + {Key? key, + this.title, + this.subtitle, + this.showBackBtn = true, + this.isTransparent = false, + this.onBack, + this.trailing}) : super(key: key); - final String title; + final String? title; final String? subtitle; final bool showBackBtn; final bool isTransparent; @@ -40,11 +46,13 @@ class SimpleHeader extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text( - title.toUpperCase(), - textHeightBehavior: TextHeightBehavior(applyHeightToFirstAscent: false), - style: $styles.text.h4.copyWith(color: $styles.colors.offWhite, fontWeight: FontWeight.w500), - ), + if (title != null) + Text( + title!.toUpperCase(), + textHeightBehavior: TextHeightBehavior(applyHeightToFirstAscent: false), + style: + $styles.text.h4.copyWith(color: $styles.colors.offWhite, fontWeight: FontWeight.w500), + ), if (subtitle != null) Text( subtitle!.toUpperCase(), diff --git a/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart b/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart index b55c34c8..08c9ac46 100644 --- a/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart +++ b/lib/ui/screens/artifact/artifact_carousel/artifact_carousel_screen.dart @@ -4,7 +4,7 @@ import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/data/highlight_data.dart'; import 'package:wonders/ui/common/app_icons.dart'; import 'package:wonders/ui/common/controls/app_page_indicator.dart'; -import 'package:wonders/ui/common/controls/simple_header.dart'; +import 'package:wonders/ui/common/controls/app_header.dart'; import 'package:wonders/ui/common/static_text_scale.dart'; part 'widgets/_blurred_image_bg.dart'; @@ -122,8 +122,8 @@ class _ArtifactScreenState extends State { ), /// Header - SimpleHeader( - $strings.artifactsTitleArtifacts, + AppHeader( + title: $strings.artifactsTitleArtifacts, showBackBtn: false, isTransparent: true, trailing: (context) => CircleBtn( diff --git a/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart b/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart index 7fd4bec7..8ea4eb58 100644 --- a/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart +++ b/lib/ui/screens/artifact/artifact_search/artifact_search_screen.dart @@ -3,7 +3,7 @@ import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/logic/data/wonders_data/search/search_data.dart'; import 'package:wonders/ui/common/app_icons.dart'; -import 'package:wonders/ui/common/controls/simple_header.dart'; +import 'package:wonders/ui/common/controls/app_header.dart'; import 'package:wonders/ui/common/static_text_scale.dart'; import 'package:wonders/ui/common/utils/app_haptics.dart'; import 'package:wonders/ui/screens/artifact/artifact_search/time_range_selector/expanding_time_range_selector.dart'; @@ -85,7 +85,7 @@ class _ArtifactSearchScreenState extends State with GetItS child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - SimpleHeader($strings.artifactsSearchTitleBrowse, subtitle: wonder.title), + AppHeader(title: $strings.artifactsSearchTitleBrowse, subtitle: wonder.title), Gap($styles.insets.xs), Padding( padding: EdgeInsets.symmetric(horizontal: $styles.insets.sm), diff --git a/lib/ui/screens/collection/collection_screen.dart b/lib/ui/screens/collection/collection_screen.dart index ca4fc66d..c194f2ce 100644 --- a/lib/ui/screens/collection/collection_screen.dart +++ b/lib/ui/screens/collection/collection_screen.dart @@ -5,7 +5,7 @@ import 'package:wonders/logic/collectibles_logic.dart'; import 'package:wonders/logic/data/collectible_data.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/centered_box.dart'; -import 'package:wonders/ui/common/controls/simple_header.dart'; +import 'package:wonders/ui/common/controls/app_header.dart'; import 'package:wonders/ui/common/modals/app_modals.dart'; part 'widgets/_collectible_image.dart'; @@ -63,7 +63,7 @@ class _CollectionScreenState extends State with GetItStateMixi children: [ Expanded( child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - SimpleHeader($strings.collectionTitleCollection), + AppHeader(title: $strings.collectionTitleCollection), _NewlyDiscoveredItemsBtn(count: discovered, onPressed: _scrollToTarget), Flexible( child: _CollectionList( diff --git a/lib/ui/screens/editorial/widgets/_top_illustration.dart b/lib/ui/screens/editorial/widgets/_top_illustration.dart index 5e716fc5..08ad0da3 100644 --- a/lib/ui/screens/editorial/widgets/_top_illustration.dart +++ b/lib/ui/screens/editorial/widgets/_top_illustration.dart @@ -11,7 +11,7 @@ class _TopIllustration extends StatelessWidget { WonderIllustration(type, config: WonderIllustrationConfig.bg(enableAnims: false, shortMode: true)), Positioned.fill( bottom: 50, - child: AnimatedClouds(wonderType: type, enableAnimations: false, opacity: .5), + child: AnimatedClouds(wonderType: type, enableAnimations: false, opacity: .5, cloudSize: 400), ), Transform.translate( // Small bump down to make sure we cover the edge between the editorial page and the sky. diff --git a/lib/ui/screens/timeline/timeline_screen.dart b/lib/ui/screens/timeline/timeline_screen.dart index e61281d4..5d21fbc8 100644 --- a/lib/ui/screens/timeline/timeline_screen.dart +++ b/lib/ui/screens/timeline/timeline_screen.dart @@ -9,7 +9,7 @@ import 'package:wonders/logic/data/timeline_data.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/blend_mask.dart'; import 'package:wonders/ui/common/centered_box.dart'; -import 'package:wonders/ui/common/controls/simple_header.dart'; +import 'package:wonders/ui/common/controls/app_header.dart'; import 'package:wonders/ui/common/dashed_line.dart'; import 'package:wonders/ui/common/list_gradient.dart'; import 'package:wonders/ui/common/timeline_event_card.dart'; @@ -55,7 +55,7 @@ class _TimelineScreenState extends State { padding: EdgeInsets.only(bottom: 0), child: Column( children: [ - SimpleHeader($strings.timelineTitleGlobalTimeline), + AppHeader(title: $strings.timelineTitleGlobalTimeline), /// Vertically scrolling timeline, manages a ScrollController. Expanded( diff --git a/lib/ui/screens/wonder_events/widgets/_events_list.dart b/lib/ui/screens/wonder_events/widgets/_events_list.dart index 9f8a128a..c0d606d3 100644 --- a/lib/ui/screens/wonder_events/widgets/_events_list.dart +++ b/lib/ui/screens/wonder_events/widgets/_events_list.dart @@ -56,7 +56,6 @@ class _EventsListState extends State<_EventsList> { } return Stack( children: [ - //TODO: Remove scrollbar on portrait SingleChildScrollView( controller: _scroller, child: Column( @@ -101,7 +100,8 @@ class _EventsListState extends State<_EventsList> { ); } - /// Wraps the list in a scroll listener + /// Wraps the list in a scroll listener that fades in an underlay as the content + /// is scrolled Widget _buildScrollingListWithBlur() { return AnimatedBuilder( animation: _scroller, diff --git a/lib/ui/screens/wonder_events/wonder_events.dart b/lib/ui/screens/wonder_events/wonder_events.dart index 4e6f7603..d4c3192a 100644 --- a/lib/ui/screens/wonder_events/wonder_events.dart +++ b/lib/ui/screens/wonder_events/wonder_events.dart @@ -4,6 +4,7 @@ import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/app_backdrop.dart'; import 'package:wonders/ui/common/app_icons.dart'; import 'package:wonders/ui/common/centered_box.dart'; +import 'package:wonders/ui/common/controls/app_header.dart'; import 'package:wonders/ui/common/curved_clippers.dart'; import 'package:wonders/ui/common/hidden_collectible.dart'; import 'package:wonders/ui/common/list_gradient.dart'; @@ -35,17 +36,20 @@ class WonderEvents extends StatelessWidget { /// Main view switches between portrait and landscape views Positioned.fill( top: $styles.insets.lg, - child: context.isLandscape ? _buildLandscape() : _buildPortrait(), + child: context.isLandscape ? _buildLandscape(context) : _buildPortrait(), ), - /// Floating TimelineBtn - Positioned( - right: $styles.insets.lg, - top: $styles.insets.lg, - child: CircleIconBtn( + /// Header w/ TimelineBtn + TopCenter( + child: AppHeader( + showBackBtn: false, + isTransparent: true, + trailing: (_) => CircleIconBtn( icon: AppIcons.timeline, onPressed: handleTimelineBtnPressed, - semanticLabel: $strings.eventsListButtonOpenGlobal)), + semanticLabel: $strings.eventsListButtonOpenGlobal), + ), + ), ], ), ), @@ -54,7 +58,7 @@ class WonderEvents extends StatelessWidget { } /// Landscape layout is a row, with the WonderImage on left and EventsList on the right - Widget _buildLandscape() { + Widget _buildLandscape(BuildContext context) { return Row( children: [ /// WonderImage w/ Timeline btn @@ -66,10 +70,19 @@ class WonderEvents extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Gap($styles.insets.lg), - Expanded(child: Center(child: _WonderImageWithTimeline(data: _data, height: 500))), + Expanded( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _WonderImageWithTimeline(data: _data, height: min(500, context.heightPx - 300)), + Gap($styles.insets.lg), + SizedBox(width: 300, child: _TimelineBtn(type: type)), + ], + ), + ), + ), Gap($styles.insets.lg), - SizedBox(width: 300, child: _TimelineBtn(type: type)), - Gap($styles.insets.xl), ], ), ), @@ -78,7 +91,7 @@ class WonderEvents extends StatelessWidget { /// EventsList Expanded( child: CenteredBox( - width: $styles.sizes.maxContentWidth1, + width: $styles.sizes.maxContentWidth2, child: _EventsList( data: _data, topHeight: 100, diff --git a/lib/ui/wonder_illustrations/common/animated_clouds.dart b/lib/ui/wonder_illustrations/common/animated_clouds.dart index 7fa15ec6..2c4b3897 100644 --- a/lib/ui/wonder_illustrations/common/animated_clouds.dart +++ b/lib/ui/wonder_illustrations/common/animated_clouds.dart @@ -3,16 +3,18 @@ import 'dart:async'; import 'package:wonders/common_libs.dart'; import 'package:wonders/ui/common/utils/context_utils.dart'; -//TODO: Make the clouds fade out and in +// TODO: Clouds should fade in and out // Shows a set of clouds that animated onto stage. // When value-key is changed, a new set of clouds will animate into place and the old ones will animate out. // Uses a random seed system, to make sure we get the same set of clouds for each wonder, without actually having to hand-position them. class AnimatedClouds extends StatefulWidget with GetItStatefulWidgetMixin { - AnimatedClouds({Key? key, this.enableAnimations = true, required this.wonderType, required this.opacity}) + AnimatedClouds( + {Key? key, this.enableAnimations = true, required this.wonderType, required this.opacity, this.cloudSize = 500}) : super(key: key); final WonderType wonderType; final bool enableAnimations; final double opacity; + final double cloudSize; @override State createState() => _AnimatedCloudsState(); } @@ -76,7 +78,7 @@ class _AnimatedCloudsState extends State with SingleTickerProvid @override Widget build(BuildContext context) { // Old clouds animate from 0 to startOffset, new clouds do the opposite. - Widget buildCloud(c, {required bool isOld, required int startOffset}) { + Widget buildCloud(_Cloud c, {required bool isOld, required int startOffset}) { // Use a positive, or negative start offset, based on index final stOffset = _clouds.indexOf(c) % 2 == 0 ? -startOffset : startOffset; // If old, we will end at the stOffset and start at 0, if new, start at stOffset, and end at 0 @@ -84,7 +86,7 @@ class _AnimatedCloudsState extends State with SingleTickerProvid return Positioned( top: c.pos.dy, left: isOld ? c.pos.dx - stOffset * curvedValue : c.pos.dx + stOffset * (1 - curvedValue), - child: c, + child: Opacity(opacity: isOld ? 1 - _anim.value : _anim.value, child: c), ); } @@ -123,19 +125,22 @@ class _AnimatedCloudsState extends State with SingleTickerProvid flipX: rnd.getBool(), flipY: rnd.getBool(), opacity: widget.opacity, + size: widget.cloudSize, ); }).toList(); } } class _Cloud extends StatelessWidget { + const _Cloud(this.pos, + {this.scale = 1, this.flipX = false, this.flipY = false, required this.opacity, required this.size}); + final Offset pos; final double scale; final bool flipX; final bool flipY; final double opacity; - - const _Cloud(this.pos, {this.scale = 1, this.flipX = false, this.flipY = false, required this.opacity}); + final double size; @override Widget build(BuildContext context) => Transform.scale( @@ -144,7 +149,7 @@ class _Cloud extends StatelessWidget { child: Image.asset( ImagePaths.cloud, opacity: AlwaysStoppedAnimation(.4 * opacity), - width: 400 * scale, + width: size * scale, fit: BoxFit.fitWidth, ), ); diff --git a/lib/ui/wonder_illustrations/common/illustration_piece.dart b/lib/ui/wonder_illustrations/common/illustration_piece.dart index 00159175..93f1a1f6 100644 --- a/lib/ui/wonder_illustrations/common/illustration_piece.dart +++ b/lib/ui/wonder_illustrations/common/illustration_piece.dart @@ -69,6 +69,7 @@ class _IllustrationPieceState extends State { final wonderBuilder = context.watch(); final type = wonderBuilder.widget.wonderType; final imgPath = '${type.assetPath}/${widget.fileName}'; + // Dynamically determine the aspect ratio of the image, so we can more easily position it if (aspectRatio == null) { aspectRatio == 0; // indicates load has started, so we don't run twice rootBundle.load(imgPath).then((img) async { @@ -111,21 +112,26 @@ class _IllustrationPieceState extends State { height * widget.fractionalOffset!.dy, ); } + Widget? content; + if (uiImage != null) { + content = Transform.translate( + offset: finalTranslation, + child: Transform.scale( + scale: 1 + (widget.zoomAmt * config.zoom) + introZoom, + child: SizedBox( + height: height, + width: height * aspectRatio!, + child: img, + ), + ), + ); + } + return Stack( children: [ if (widget.bottom != null) Positioned.fill(child: widget.bottom!.call(context)), if (uiImage != null) ...[ - Transform.translate( - offset: finalTranslation, - child: Transform.scale( - scale: 1 + (widget.zoomAmt * config.zoom) + introZoom, - child: SizedBox( - height: height, - width: height * aspectRatio!, - child: !widget.enableHero ? img : Hero(tag: '$type-${widget.fileName}', child: img), - ), - ), - ), + widget.enableHero ? Hero(tag: '$type-${widget.fileName}', child: content!) : content!, ], if (widget.top != null) Positioned.fill(child: widget.top!.call(context)), ], diff --git a/pubspec.lock b/pubspec.lock index e23bd9d3..e94d8b1c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -571,10 +571,10 @@ packages: dependency: "direct main" description: name: image_fade - sha256: "6ec32003f451f3341f1b8ebd899b97e94f80ce0d66b13e59ade41ae03c34b464" + sha256: "7296c9c53cd5de98e675ef1e27bdaa4035d6c3a45cf5b86094b2e545689b4ea6" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.2" image_gallery_saver: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 564b51c0..5d45b31d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: google_maps_flutter_web: ^0.4.0+1 go_router: ^4.2.8 http: ^0.13.5 - image_fade: ^0.6.1 + image_fade: ^0.6.2 image_gallery_saver: ^1.7.1 internet_connection_checker: ^0.0.1+3 intl: ^0.17.0