import 'dart:async'; import 'dart:ui'; import 'package:desktop_window/desktop_window.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:wonders/common_libs.dart'; import 'package:wonders/logic/common/platform_info.dart'; import 'package:wonders/ui/common/modals/fullscreen_video_viewer.dart'; import 'package:wonders/ui/common/utils/page_routes.dart'; class AppLogic { Size _appSize = Size.zero; /// Indicates to the rest of the app that bootstrap has not completed. /// The router will use this to prevent redirects while bootstrapping. bool isBootstrapComplete = false; /// Indicates which orientations the app will allow be default. Affects Android/iOS devices only. /// Defaults to both landscape (hz) and portrait (vt) List supportedOrientations = [Axis.vertical, Axis.horizontal]; /// Allow a view to override the currently supported orientations. For example, [FullscreenVideoViewer] always wants to enable both landscape and portrait. /// If a view sets this override, they are responsible for setting it back to null when finished. List? _supportedOrientationsOverride; set supportedOrientationsOverride(List? value) { if (_supportedOrientationsOverride != value) { _supportedOrientationsOverride = value; _updateSystemOrientation(); } } /// Initialize the app and all main actors. /// Loads settings, sets up services etc. Future bootstrap() async { debugPrint('bootstrap start...'); // Set min-sizes for desktop apps // TODO: Test on Linux and confirm whether it's safe to call there, according to issue #183 its not. if (PlatformInfo.isWindows || PlatformInfo.isMacOS) { await DesktopWindow.setMinWindowSize($styles.sizes.minAppSize); } if (kIsWeb) { // SB: This is intentionally not a debugPrint, as it's a message for users who open the console on web. print( '''Thanks for checking out Wonderous on the web! If you encounter any issues please report them at https://github.com/gskinnerTeam/flutter-wonderous-app/issues.''', ); // Required on web to automatically enable accessibility features WidgetsFlutterBinding.ensureInitialized().ensureSemantics(); } // Load any bitmaps the views might need await AppBitmaps.init(); // Set preferred refresh rate to the max possible (the OS may ignore this) if (!kIsWeb && PlatformInfo.isAndroid) { await FlutterDisplayMode.setHighRefreshRate(); } // Settings await settingsLogic.load(); // Localizations await localeLogic.load(); // Wonders Data wondersLogic.init(); // Events timelineLogic.init(); // Collectibles collectiblesLogic.init(); await collectiblesLogic.load(); // Wait at least 1 frame to give GoRouter time to catch the initial deeplink await Future.delayed(1.milliseconds); // Flag bootStrap as complete isBootstrapComplete = true; // Load initial view (replace empty initial view which is covered by a native splash screen) bool showIntro = settingsLogic.hasCompletedOnboarding.value == false; if (showIntro) { appRouter.go(ScreenPaths.intro); } else { appRouter.go(initialDeeplink ?? ScreenPaths.home); } } Future showFullscreenDialogRoute(BuildContext context, Widget child, {bool transparent = false}) async { return await Navigator.of(context).push( PageRoutes.dialog(child, duration: $styles.times.pageTransition), ); } /// Called from the UI layer once a MediaQuery has been obtained void handleAppSizeChanged(Size appSize) { /// Disable landscape layout on smaller form factors bool isSmall = display.size.shortestSide / display.devicePixelRatio < 600; supportedOrientations = isSmall ? [Axis.vertical] : [Axis.vertical, Axis.horizontal]; _updateSystemOrientation(); _appSize = appSize; } Display get display => PlatformDispatcher.instance.displays.first; bool shouldUseNavRail() => _appSize.width > _appSize.height && _appSize.height > 250; void _updateSystemOrientation() { final axisList = _supportedOrientationsOverride ?? supportedOrientations; //debugPrint('updateDeviceOrientation, supportedAxis: $axisList'); final orientations = []; if (axisList.contains(Axis.vertical)) { orientations.addAll([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); } if (axisList.contains(Axis.horizontal)) { orientations.addAll([ DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ]); } SystemChrome.setPreferredOrientations(orientations); } void precacheWonderImages(BuildContext context) { debugPrint('Skipping precache, need to figure out why it\'s not working on web.'); return; precacheImage(AssetImage('images/chichen_itza/chichen.png'), context); precacheImage(AssetImage('images/chichen_itza/foreground-left.png'), context); precacheImage(AssetImage('images/chichen_itza/foreground-right.png'), context); precacheImage(AssetImage('images/christ_the_redeemer/redeemer.png'), context); precacheImage(AssetImage('images/christ_the_redeemer/foreground-left.png'), context); precacheImage(AssetImage('images/christ_the_redeemer/foreground-right.png'), context); precacheImage(AssetImage('images/colosseum/colosseum.png'), context); precacheImage(AssetImage('images/colosseum/foreground-left.png'), context); precacheImage(AssetImage('images/colosseum/foreground-right.png'), context); precacheImage(AssetImage('images/great_wall_of_china/great-wall.png'), context); precacheImage(AssetImage('images/great_wall_of_china/foreground-left.png'), context); precacheImage(AssetImage('images/great_wall_of_china/foreground-right.png'), context); precacheImage(AssetImage('images/machu_picchu/machu-picchu.png'), context); precacheImage(AssetImage('images/machu_picchu/foreground-back.png'), context); precacheImage(AssetImage('images/machu_picchu/foreground-front.png'), context); precacheImage(AssetImage('images/petra/petra.png'), context); precacheImage(AssetImage('images/petra/foreground-left.png'), context); precacheImage(AssetImage('images/petra/foreground-right.png'), context); precacheImage(AssetImage('images/pyramids/pyramids.png'), context); precacheImage(AssetImage('images/pyramids/foreground-back.png'), context); precacheImage(AssetImage('images/pyramids/foreground-front.png'), context); precacheImage(AssetImage('images/taj_mahal/taj-mahal.png'), context); precacheImage(AssetImage('images/taj_mahal/foreground-left.png'), context); precacheImage(AssetImage('images/taj_mahal/foreground-right.png'), context); } } class AppImageCache extends WidgetsFlutterBinding { @override ImageCache createImageCache() { this.imageCache.maximumSizeBytes = 250 << 20; // 250mb return super.createImageCache(); } }