From a0f234bf471eab6dd146ee4776c95bca614202e9 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Fri, 22 Oct 2021 14:47:06 +0200 Subject: [PATCH] add compile time enviornment options ## Why? - in the future we could enable the developer options in dev builds only. This would result in better performance and smaller downloadsize. - Ability to disable catcher. Catcher limits the ability of debuging as it catches everything thrown. Also catcher won't even display the crash when the system is in dark mode (white text on white background. Probably a bug on theier side) ## How to use this? just add a `--dart-define` followed by your config after the flutter command. Further info can be found in [Readme.md](/Readme.md) --- .run/Sanmill-dev.run.xml | 7 ++ .run/Sanmill-monkey.run.xml | 7 ++ .run/Sanmill-profile.run.xml | 7 ++ .run/Sanmill-release.run.xml | 7 ++ .run/Sanmill.run.xml | 6 ++ .run/Template Flutter.run.xml | 6 ++ .vscode/launch.json | 60 +++++++++++++++ Readme.md | 15 ++++ src/ui/flutter_app/lib/main.dart | 77 ++++++++----------- src/ui/flutter_app/lib/models/temporary.dart | 4 +- .../game_settings/game_settings_page.dart | 1 + .../game_settings/reset_settings_alert.dart | 5 +- .../lib/screens/navigation_home_screen.dart | 7 +- .../lib/services/enviornment_config.dart | 34 ++++++++ .../lib/services/init_system_ui.dart | 43 +++++++++++ 15 files changed, 236 insertions(+), 50 deletions(-) create mode 100644 .run/Sanmill-dev.run.xml create mode 100644 .run/Sanmill-monkey.run.xml create mode 100644 .run/Sanmill-profile.run.xml create mode 100644 .run/Sanmill-release.run.xml create mode 100644 .run/Sanmill.run.xml create mode 100644 .run/Template Flutter.run.xml create mode 100644 .vscode/launch.json create mode 100644 src/ui/flutter_app/lib/services/enviornment_config.dart create mode 100644 src/ui/flutter_app/lib/services/init_system_ui.dart diff --git a/.run/Sanmill-dev.run.xml b/.run/Sanmill-dev.run.xml new file mode 100644 index 00000000..c143d152 --- /dev/null +++ b/.run/Sanmill-dev.run.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.run/Sanmill-monkey.run.xml b/.run/Sanmill-monkey.run.xml new file mode 100644 index 00000000..d3f4b9a2 --- /dev/null +++ b/.run/Sanmill-monkey.run.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.run/Sanmill-profile.run.xml b/.run/Sanmill-profile.run.xml new file mode 100644 index 00000000..05d4dfd5 --- /dev/null +++ b/.run/Sanmill-profile.run.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.run/Sanmill-release.run.xml b/.run/Sanmill-release.run.xml new file mode 100644 index 00000000..983a17e1 --- /dev/null +++ b/.run/Sanmill-release.run.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.run/Sanmill.run.xml b/.run/Sanmill.run.xml new file mode 100644 index 00000000..c03f8656 --- /dev/null +++ b/.run/Sanmill.run.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.run/Template Flutter.run.xml b/.run/Template Flutter.run.xml new file mode 100644 index 00000000..f1bc2d08 --- /dev/null +++ b/.run/Template Flutter.run.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..84ad841a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,60 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Sanmill", + "type": "dart", + "request": "launch", + "cwd": "src/ui/flutter_app", + "program": "lib/main.dart" + }, + { + "name": "Sanmill: Attach to Device", + "type": "dart", + "request": "attach" + }, + { + "name": "Sanmill-dev", + "type": "dart", + "request": "launch", + "cwd": "src/ui/flutter_app", + "program": "lib/main.dart", + "args": [ + "--dart-define", + "dev_mode=true", + "--dart-define", + "catcher=false" + ] + }, + { + "name": "Sanmill-monkey", + "type": "dart", + "request": "launch", + "cwd": "src/ui/flutter_app", + "program": "lib/main.dart", + "args": [ + "--dart-define", + "monkey_test=true" + ] + }, + { + "name": "Sanmill-profile", + "type": "dart", + "request": "launch", + "cwd": "src/ui/flutter_app", + "program": "lib/main.dart", + "flutterMode": "profile" + }, + { + "name": "Sanmill-release", + "type": "dart", + "request": "launch", + "cwd": "src/ui/flutter_app", + "program": "lib/main.dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/Readme.md b/Readme.md index 61c922ef..38f3cade 100644 --- a/Readme.md +++ b/Readme.md @@ -71,6 +71,21 @@ Use Qt Creator to open `millgame.pro` , or use Visual Studio to open `millgame.s Run `./flutter-init.sh` , copy `src/ui/flutter_app/android/key.properties.example` to `src/ui/flutter_app/android/key.properties`, modify it, and then use Android Studio or Visual Studio Code to open `src/ui/flutter_app` to build Flutter App. +We use compile time enviornmet configs to enable specific parts of the code: + +* `monkey_test` to prepare the app for monkey tests (references to external sites are going to be disabled) +* `dev_mode` to show the developer mode without needing to enable it first +* `catcher` to controll the use of catcher (this is on by default and needs to be disabled when needed) + +all enviornment configs can be combined and take a value of bool like: + +```shell +flutter run --dart-define catcher=false dev_mode=true +``` + +For ease of use some launch configs vor VS-Code and IntelliJ IDEA are available. Just select the +needed one in the `Run and Debug` or `Run/Debug Configurations` tab. + ## Understanding the code base and participating in the project Sanmill's improvement over the last couple of years has been a great community effort. There are a few ways to help contribute to its growth. diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index 6a999b5e..c3fa63cb 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -30,6 +30,7 @@ import 'package:sanmill/generated/intl/l10n.dart'; import 'package:sanmill/models/display.dart'; import 'package:sanmill/screens/navigation_home_screen.dart'; import 'package:sanmill/services/audios.dart'; +import 'package:sanmill/services/enviornment_config.dart'; import 'package:sanmill/services/language_info.dart'; import 'package:sanmill/services/storage/storage.dart'; import 'package:sanmill/services/storage/storage_v1.dart'; @@ -37,39 +38,30 @@ import 'package:sanmill/shared/constants.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; part 'package:sanmill/services/catcher.dart'; +part 'package:sanmill/services/init_system_ui.dart'; Future main() async { + debugPrint('Enviornment [catcher]: ${EnvironmentConfig.catcher}'); + debugPrint('Enviornment [dev_mode]: ${EnvironmentConfig.devMode}'); + debugPrint('Enviornment [monkey_test]: ${EnvironmentConfig.monkeyTest}'); + await LocalDatabaseService.initStorage(); await DatabaseV1.migrateDB(); - final catcher = Catcher( - rootWidget: const BetterFeedback( - child: SanmillApp(), - //localeOverride: Locale(Resources.of().languageCode), - ), - ensureInitialized: true, - ); - await _initCatcher(catcher); + _initUI(); - debugPrint(window.physicalSize.toString()); - debugPrint(Constants.windowAspectRatio.toString()); - - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown], - ); - - if (Platform.isAndroid && isLargeScreen) { - SystemChrome.setSystemUIOverlayStyle( - const SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - statusBarBrightness: Brightness.light, - statusBarIconBrightness: Brightness.dark, - systemNavigationBarColor: Colors.black, - systemNavigationBarIconBrightness: Brightness.dark, + if (EnvironmentConfig.catcher) { + final catcher = Catcher( + rootWidget: const BetterFeedback( + child: SanmillApp(), + //localeOverride: Locale(Resources.of().languageCode), ), + ensureInitialized: true, ); - } else if (isSmallScreen) { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); + + await _initCatcher(catcher); + } else { + runApp(const SanmillApp()); } } @@ -83,8 +75,6 @@ class SanmillApp extends StatelessWidget { final globalScaffoldKey = GlobalKey(); Audios.loadSounds(); - setSpecialCountryAndRegion(context); - return ValueListenableBuilder( valueListenable: LocalDatabaseService.listenDisplay, builder: (BuildContext context, Box displayBox, _) { @@ -95,7 +85,7 @@ class SanmillApp extends StatelessWidget { return MaterialApp( /// Add navigator key from Catcher. /// It will be used to navigate user to report page or to show dialog. - navigatorKey: Catcher.navigatorKey, + navigatorKey: EnvironmentConfig.catcher ? Catcher.navigatorKey : null, key: globalScaffoldKey, navigatorObservers: [routeObserver], localizationsDelegates: S.localizationsDelegates, @@ -104,25 +94,22 @@ class SanmillApp extends StatelessWidget { theme: AppTheme.lightThemeData, darkTheme: AppTheme.darkThemeData, debugShowCheckedModeBanner: false, - home: const _Home(), + home: Builder( + builder: (context) { + setSpecialCountryAndRegion(context); + + return Scaffold( + body: DoubleBackToCloseApp( + snackBar: SnackBar( + content: Text(S.of(context).tapBackAgainToLeave), + ), + child: const NavigationHomeScreen(), + ), + ); + }, + ), ); }, ); } } - -class _Home extends StatelessWidget { - const _Home({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: DoubleBackToCloseApp( - snackBar: SnackBar( - content: Text(S.of(context).tapBackAgainToLeave), - ), - child: const NavigationHomeScreen(), - ), - ); - } -} diff --git a/src/ui/flutter_app/lib/models/temporary.dart b/src/ui/flutter_app/lib/models/temporary.dart index 077f46e8..f19cb797 100644 --- a/src/ui/flutter_app/lib/models/temporary.dart +++ b/src/ui/flutter_app/lib/models/temporary.dart @@ -16,6 +16,8 @@ along with this program. If not, see . */ +import 'package:sanmill/services/enviornment_config.dart'; + /// Temporary data model /// /// holds temporary runtime data that isn't yet or shouldn't be saved to the LocalDatabase @@ -23,5 +25,5 @@ class Temp { const Temp._(); /// represents a temporary value for Preferences.developerMode - static bool developerMode = false; + static bool developerMode = EnvironmentConfig.devMode; } diff --git a/src/ui/flutter_app/lib/screens/game_settings/game_settings_page.dart b/src/ui/flutter_app/lib/screens/game_settings/game_settings_page.dart index 36ec8bbc..01174d9b 100644 --- a/src/ui/flutter_app/lib/screens/game_settings/game_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/game_settings/game_settings_page.dart @@ -25,6 +25,7 @@ import 'package:sanmill/generated/intl/l10n.dart'; import 'package:sanmill/models/preferences.dart'; import 'package:sanmill/models/temporary.dart'; import 'package:sanmill/screens/env_page.dart'; +import 'package:sanmill/services/enviornment_config.dart'; import 'package:sanmill/services/storage/storage.dart'; import 'package:sanmill/shared/settings/settings_card.dart'; import 'package:sanmill/shared/settings/settings_list_tile.dart'; diff --git a/src/ui/flutter_app/lib/screens/game_settings/reset_settings_alert.dart b/src/ui/flutter_app/lib/screens/game_settings/reset_settings_alert.dart index 63dcd7e7..3261c561 100644 --- a/src/ui/flutter_app/lib/screens/game_settings/reset_settings_alert.dart +++ b/src/ui/flutter_app/lib/screens/game_settings/reset_settings_alert.dart @@ -25,7 +25,10 @@ class _ResetSettingsAlert extends StatelessWidget { Future _restore(BuildContext context) async { Navigator.pop(context); - if (!LocalDatabaseService.preferences.developerMode) { + + // TODO: we should probably enable database deletion in monkey tests + //as the new storage backend supports deletion without needing an app restart + if (!EnvironmentConfig.monkeyTest) { await LocalDatabaseService.resetStorage(); } } diff --git a/src/ui/flutter_app/lib/screens/navigation_home_screen.dart b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart index 7a1b1291..20aef7d4 100644 --- a/src/ui/flutter_app/lib/screens/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart @@ -36,6 +36,7 @@ import 'package:sanmill/screens/help_screen.dart'; import 'package:sanmill/screens/personalization_settings/personalization_settings_page.dart'; import 'package:sanmill/screens/rule_settings/rule_settings_page.dart'; import 'package:sanmill/services/engine/engine.dart'; +import 'package:sanmill/services/enviornment_config.dart'; import 'package:sanmill/services/storage/storage.dart'; import 'package:sanmill/shared/constants.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; @@ -103,7 +104,7 @@ class _NavigationHomeScreenState extends State { } else if (drawerIndex == DrawerIndex.personalization) { screenView = PersonalizationSettingsPage(); } else if (drawerIndex == DrawerIndex.feedback && - !LocalDatabaseService.preferences.developerMode) { + !EnvironmentConfig.monkeyTest) { if (Platform.isWindows) { debugPrint("flutter_email_sender does not support Windows."); //_launchFeedback(); @@ -128,10 +129,10 @@ class _NavigationHomeScreenState extends State { }); } } else if (drawerIndex == DrawerIndex.Help && - !LocalDatabaseService.preferences.developerMode) { + !EnvironmentConfig.monkeyTest) { screenView = HelpScreen(); } else if (drawerIndex == DrawerIndex.About && - !LocalDatabaseService.preferences.developerMode) { + !EnvironmentConfig.monkeyTest) { screenView = AboutPage(); } else { //do in your way...... diff --git a/src/ui/flutter_app/lib/services/enviornment_config.dart b/src/ui/flutter_app/lib/services/enviornment_config.dart new file mode 100644 index 00000000..68afbef9 --- /dev/null +++ b/src/ui/flutter_app/lib/services/enviornment_config.dart @@ -0,0 +1,34 @@ +/* + This file is part of Sanmill. + Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file) + + Sanmill is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Sanmill is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/// Enviornment configutation +/// +/// Enables devs to start the app with compile time options +class EnvironmentConfig { + const EnvironmentConfig._(); + + /// gets weather we build for a monkey test + static const monkeyTest = bool.fromEnvironment('monkey_test'); + + /// gets weather we build for devMode + static const devMode = bool.fromEnvironment('dev_mode'); + + /// gets weather we want catcher to be enabled + /// defaults to true + static const catcher = bool.fromEnvironment('catcher', defaultValue: true); +} diff --git a/src/ui/flutter_app/lib/services/init_system_ui.dart b/src/ui/flutter_app/lib/services/init_system_ui.dart new file mode 100644 index 00000000..6b7e52ad --- /dev/null +++ b/src/ui/flutter_app/lib/services/init_system_ui.dart @@ -0,0 +1,43 @@ +/* + This file is part of Sanmill. + Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file) + + Sanmill is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Sanmill is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +part of 'package:sanmill/main.dart'; + +/// initializes the given [SystemChrome] ui +void _initUI() { + debugPrint(window.physicalSize.toString()); + debugPrint(Constants.windowAspectRatio.toString()); + + SystemChrome.setPreferredOrientations( + [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown], + ); + + if (Platform.isAndroid && isLargeScreen) { + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarBrightness: Brightness.light, + statusBarIconBrightness: Brightness.dark, + systemNavigationBarColor: Colors.black, + systemNavigationBarIconBrightness: Brightness.dark, + ), + ); + } else if (isSmallScreen) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); + } +}