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), ), ), ),