From bb31257cc308b2e8ac0cbd9d75b49dd08531a439 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Fri, 8 Oct 2021 15:42:17 +0200 Subject: [PATCH 01/13] add linting and fix pubspec.yml --- src/ui/flutter_app/analysis_options.yaml | 10 ++++++ src/ui/flutter_app/pubspec.yaml | 41 ++++++++++++------------ 2 files changed, 31 insertions(+), 20 deletions(-) create mode 100644 src/ui/flutter_app/analysis_options.yaml diff --git a/src/ui/flutter_app/analysis_options.yaml b/src/ui/flutter_app/analysis_options.yaml new file mode 100644 index 00000000..30ac4c2e --- /dev/null +++ b/src/ui/flutter_app/analysis_options.yaml @@ -0,0 +1,10 @@ +include: package:lint/analysis_options.yaml + + +linter: + rules: + +analyzer: + exclude: + # generated code + - lib/generated/** diff --git a/src/ui/flutter_app/pubspec.yaml b/src/ui/flutter_app/pubspec.yaml index ffc3a20a..0e1ded96 100644 --- a/src/ui/flutter_app/pubspec.yaml +++ b/src/ui/flutter_app/pubspec.yaml @@ -1,37 +1,37 @@ name: sanmill description: Sanmill is a open-source, powerful UCI-like Nine Men's Morris (and its variants) program. +publish_to: none version: 1.1.37+2184 environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ">=2.12.0 <3.0.0" dependencies: - flutter: - sdk: flutter - flutter_localizations: - sdk: flutter - cupertino_icons: ^1.0.3 - soundpool: ^2.2.0 - path_provider: ^2.0.5 - package_info_plus: ^1.0.6 - uuid: ^3.0.4 - url_launcher: ^6.0.11 - intl: 0.17.0 + animated_text_kit: ^4.1.1 catcher: ^0.6.8 - stack_trace: ^1.10.0 - + cupertino_icons: ^1.0.3 + device_info_plus_platform_interface: ^2.1.0 devicelocale: ^0.4.3 double_back_to_close_app: ^2.0.1 - flutter_picker: ^2.0.2 - flutter_email_sender: ^5.0.2 feedback: git: url: git://github.com/calcitem/feedback.git - animated_text_kit: ^4.1.1 - flutter_colorpicker: ^0.6.0 - device_info_plus_platform_interface: ^2.1.0 fluentui_system_icons: ^1.1.140 + flutter: + sdk: flutter + flutter_colorpicker: ^0.6.0 + flutter_email_sender: ^5.0.2 + flutter_localizations: + sdk: flutter + flutter_picker: ^2.0.2 + intl: 0.17.0 + package_info_plus: ^1.0.6 + path_provider: ^2.0.5 + soundpool: ^2.2.0 + stack_trace: ^1.10.0 + url_launcher: ^6.0.11 + uuid: ^3.0.4 #pref: ^2.3.0 #screen_recorder: ^0.0.2 @@ -39,6 +39,7 @@ dev_dependencies: flutter_oss_licenses: ^1.0.1 flutter_test: sdk: flutter + lint: ^1.0.0 msix: ^2.1.3 flutter: @@ -67,5 +68,5 @@ msix_config: publisher_display_name: Calcitem Studio identity_name: 25314CalcitemStudio.Sanmill publisher: CN=3413C020-B420-4E0A-8687-A2C35E878F3A - capabilities: '' + capabilities: "" store: true From 5397d4ff14203b5c2f73b24130877b67c906ec07 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Fri, 8 Oct 2021 19:53:01 +0200 Subject: [PATCH 02/13] auto format on save for vsCode this enables vscode to auto format files in the flutter project. Also fixes a formatting error enable formatting only for dart files format settings.json --- .gitignore | 2 +- src/ui/flutter_app/.gitignore | 2 +- src/ui/flutter_app/.vscode/settings.json | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 src/ui/flutter_app/.vscode/settings.json diff --git a/.gitignore b/.gitignore index 5e964069..23aaa8c1 100644 --- a/.gitignore +++ b/.gitignore @@ -318,7 +318,7 @@ CMakeLists.txt.user* *.bak # visual studio code -.vscode/ +#.vscode/ # markdown temp files *.md.Html diff --git a/src/ui/flutter_app/.gitignore b/src/ui/flutter_app/.gitignore index aefa45e8..f7cda2ec 100644 --- a/src/ui/flutter_app/.gitignore +++ b/src/ui/flutter_app/.gitignore @@ -18,7 +18,7 @@ # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line # is commented out by default. -.vscode/ +#.vscode/ # Visual Studio .vs/ diff --git a/src/ui/flutter_app/.vscode/settings.json b/src/ui/flutter_app/.vscode/settings.json new file mode 100644 index 00000000..0c971f59 --- /dev/null +++ b/src/ui/flutter_app/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "[dart]": { + "editor.formatOnSave": true + } +} \ No newline at end of file From 33966c9bb238ffdd0e0f24ccf658633e731d0121 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Fri, 8 Oct 2021 19:38:27 +0200 Subject: [PATCH 03/13] replace print() with debugPrint() fixes this int rule - avoid_print (previous commit) format files --- src/ui/flutter_app/analysis_options.yaml | 4 + src/ui/flutter_app/lib/common/config.dart | 5 +- src/ui/flutter_app/lib/common/settings.dart | 15 +- .../flutter_app/lib/engine/native_engine.dart | 14 +- src/ui/flutter_app/lib/main.dart | 8 +- src/ui/flutter_app/lib/mill/game.dart | 17 ++- src/ui/flutter_app/lib/mill/position.dart | 32 ++-- src/ui/flutter_app/lib/mill/recorder.dart | 31 ++-- src/ui/flutter_app/lib/mill/types.dart | 6 +- src/ui/flutter_app/lib/services/audios.dart | 29 ++-- .../flutter_app/lib/widgets/about_page.dart | 14 +- src/ui/flutter_app/lib/widgets/board.dart | 6 +- src/ui/flutter_app/lib/widgets/dialog.dart | 4 +- src/ui/flutter_app/lib/widgets/game_page.dart | 141 +++++++++--------- .../lib/widgets/game_settings_page.dart | 48 +++--- .../flutter_app/lib/widgets/home_drawer.dart | 5 +- .../lib/widgets/navigation_home_screen.dart | 2 +- .../personalization_settings_page.dart | 20 +-- src/ui/flutter_app/lib/widgets/picker.dart | 4 +- .../lib/widgets/rule_settings_page.dart | 41 ++--- 20 files changed, 236 insertions(+), 210 deletions(-) diff --git a/src/ui/flutter_app/analysis_options.yaml b/src/ui/flutter_app/analysis_options.yaml index 30ac4c2e..d4bd2886 100644 --- a/src/ui/flutter_app/analysis_options.yaml +++ b/src/ui/flutter_app/analysis_options.yaml @@ -3,6 +3,10 @@ include: package:lint/analysis_options.yaml linter: rules: + avoid_positional_boolean_parameters: false + constant_identifier_names: false + avoid_escaping_inner_quotes: false + use_build_context_synchronously: false analyzer: exclude: diff --git a/src/ui/flutter_app/lib/common/config.dart b/src/ui/flutter_app/lib/common/config.dart index 4cd0563f..6cec4afd 100644 --- a/src/ui/flutter_app/lib/common/config.dart +++ b/src/ui/flutter_app/lib/common/config.dart @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import 'package:flutter/foundation.dart'; import 'package:sanmill/common/constants.dart'; import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/mill/rule.dart'; @@ -101,7 +102,7 @@ class Config { static bool threefoldRepetitionRule = true; static Future loadSettings() async { - print("[config] Loading settings..."); + debugPrint("[config] Loading settings..."); final settings = await Settings.instance(); @@ -215,7 +216,7 @@ class Config { settings['ThreefoldRepetitionRule'] ?? true; settingsLoaded = true; - print("[config] Loading settings done!"); + debugPrint("[config] Loading settings done!"); } static Future save() async { diff --git a/src/ui/flutter_app/lib/common/settings.dart b/src/ui/flutter_app/lib/common/settings.dart index f41c3754..fb6ecd81 100644 --- a/src/ui/flutter_app/lib/common/settings.dart +++ b/src/ui/flutter_app/lib/common/settings.dart @@ -19,6 +19,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:path_provider/path_provider.dart'; import 'package:sanmill/common/constants.dart'; @@ -33,7 +34,7 @@ class Settings { if (_instance == null) { _instance = Settings(); await _instance!._load(settingsFileName); - print("[settings] $settingsFileName loaded."); + debugPrint("[settings] $settingsFileName loaded."); } return _instance; @@ -61,14 +62,14 @@ class Settings { _file = File('${docDir.path}/$fileName'); - print("[settings] Loading $_file ..."); + debugPrint("[settings] Loading $_file ..."); try { final contents = await _file.readAsString(); _values = jsonDecode(contents); - print(_values); + debugPrint(_values.toString()); } catch (e) { - print(e); + debugPrint(e.toString()); return false; } @@ -76,13 +77,13 @@ class Settings { } Future restore() async { - print("[settings] Restoring Settings..."); + debugPrint("[settings] Restoring Settings..."); if (_file.existsSync()) { _file.deleteSync(); - print("[settings] $_file deleted"); + debugPrint("[settings] $_file deleted"); } else { - print("[settings] $_file does not exist"); + debugPrint("[settings] $_file does not exist"); } } } diff --git a/src/ui/flutter_app/lib/engine/native_engine.dart b/src/ui/flutter_app/lib/engine/native_engine.dart index 0a40674b..72fc97dc 100644 --- a/src/ui/flutter_app/lib/engine/native_engine.dart +++ b/src/ui/flutter_app/lib/engine/native_engine.dart @@ -36,7 +36,7 @@ class NativeEngine extends Engine { } Future send(String command) async { - print("[engine] send: $command"); + debugPrint("[engine] send: $command"); await platform.invokeMethod('send', command); } @@ -68,12 +68,12 @@ class NativeEngine extends Engine { await send('go'); isActive = true; } else { - print("[engine] Move now"); + debugPrint("[engine] Move now"); } final response = await waitResponse(['bestmove', 'nobestmove']); - print("[engine] response: $response"); + debugPrint("[engine] response: $response"); if (response.startsWith('bestmove')) { var best = response.substring('bestmove'.length + 1); @@ -101,7 +101,7 @@ class NativeEngine extends Engine { } if (times > timeLimit) { - print("[engine] Timeout. sleep = $sleep, times = $times"); + debugPrint("[engine] Timeout. sleep = $sleep, times = $times"); if (Config.developerMode && isActive) { throw ("Exception: waitResponse timeout."); } @@ -115,7 +115,7 @@ class NativeEngine extends Engine { if (response.startsWith(prefix)) { return response; } else { - print("[engine] Unexpected engine response: $response"); + debugPrint("[engine] Unexpected engine response: $response"); } } } @@ -128,13 +128,13 @@ class NativeEngine extends Engine { Future stopSearching() async { isActive = false; - print("[engine] Stop current thinking..."); + debugPrint("[engine] Stop current thinking..."); await send('stop'); } Future setOptions(BuildContext context) async { if (Config.settingsLoaded == false) { - print("[engine] Settings is not loaded yet, now load settings..."); + debugPrint("[engine] Settings is not loaded yet, now load settings..."); await Config.loadSettings(); } diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index 4a9a8022..5e4e7e7f 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -53,11 +53,11 @@ Future main() async { externalDirStr = "."; } } catch (e) { - print(e); + debugPrint(e.toString()); externalDirStr = "."; } String path = externalDirStr + "/" + Constants.crashLogsFileName; - print("[env] ExternalStorageDirectory: " + externalDirStr); + debugPrint("[env] ExternalStorageDirectory: $externalDirStr"); String recipients = Constants.recipients; CatcherOptions debugOptions = @@ -91,8 +91,8 @@ Future main() async { profileConfig: profileOptions, ); - print(window.physicalSize); - print(Constants.windowAspectRatio); + debugPrint(window.physicalSize.toString()); + debugPrint(Constants.windowAspectRatio.toString()); SystemChrome.setPreferredOrientations( [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown], diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index 216db1da..1a172ca9 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import 'package:flutter/foundation.dart'; import 'package:sanmill/common/config.dart'; import 'package:sanmill/engine/engine.dart'; @@ -80,8 +81,10 @@ class Game { }; bool aiIsSearching() { - print("$tag White is searching? ${isSearching[PieceColor.white]}\n" - "$tag Black is searching? ${isSearching[PieceColor.black]}\n"); + debugPrint( + "$tag White is searching? ${isSearching[PieceColor.white]}\n" + "$tag Black is searching? ${isSearching[PieceColor.black]}\n", + ); return isSearching[PieceColor.white] == true || isSearching[PieceColor.black] == true; @@ -110,8 +113,10 @@ class Game { break; } - print("$tag White is AI? ${isAi[PieceColor.white]}\n" - "$tag Black is AI? ${isAi[PieceColor.black]}\n"); + debugPrint( + "$tag White is AI? ${isAi[PieceColor.white]}\n" + "$tag Black is AI? ${isAi[PieceColor.black]}\n", + ); } select(int pos) { @@ -124,7 +129,7 @@ class Game { start(); } - print("$tag AI do move: $move"); + debugPrint("$tag AI do move: $move"); if (!position.doMove(move)) { return false; @@ -176,6 +181,6 @@ class Game { "%" + "\n"; - print("$tag $scoreInfo"); + debugPrint("$tag $scoreInfo"); } } diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index f2808ca9..b159671f 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import 'package:flutter/foundation.dart'; import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/recorder.dart'; @@ -241,7 +242,7 @@ class Position { " " + (1 + (gamePly - sideIsBlack) ~/ 2).toString(); - //print("FEN is $ss"); + //debugPrint("FEN is $ss"); return ss; } @@ -254,13 +255,13 @@ class Position { String us = _sideToMove; if (move.from == move.to) { - print("[position] Move $move.move from == to"); + debugPrint("[position] Move $move.move from == to"); return false; } if (move.type == MoveType.remove) { if (movedPiece(move.to) != us) { - print("[position] Move $move.to to != us"); + debugPrint("[position] Move $move.to to != us"); return false; } } @@ -398,7 +399,7 @@ class Position { if (st.key == i) { repetition++; if (repetition == 3) { - print("[position] Has game cycle."); + debugPrint("[position] Has game cycle."); return true; } } @@ -580,8 +581,9 @@ class Position { // not in moveTable if (md == moveDirectionNumber) { - print( - "[position] putPiece: [$s] is not in [$currentSquare]'s move table."); + debugPrint( + "[position] putPiece: [$s] is not in [$currentSquare]'s move table.", + ); return false; } } @@ -752,7 +754,7 @@ class Position { gameOverReason = reason; winner = w; - print("[position] Game over, $w win, because of $reason"); + debugPrint("[position] Game over, $w win, because of $reason"); updateScore(); } @@ -850,7 +852,7 @@ class Position { void changeSideToMove() { setSideToMove(PieceColor.opponent(_sideToMove)); st.key ^= Zobrist.side; - print("[position] $_sideToMove to move."); + debugPrint("[position] $_sideToMove to move."); /* if (phase == Phase.moving && @@ -858,7 +860,7 @@ class Position { isAllSurrounded() && !rule.mayFly && pieceOnBoardCount[sideToMove()]! >= rule.piecesAtLeastCount) { - print("[position] $_sideToMove is no way to go."); + debugPrint("[position] $_sideToMove is no way to go."); changeSideToMove(); } */ @@ -1101,18 +1103,18 @@ class Position { String errString = ""; if (recorder == null) { - print("[goto] recorder is null."); + debugPrint("[goto] recorder is null."); return "null"; } var history = recorder!.getHistory(); if (moveIndex < -1 || history.length <= moveIndex) { - print("[goto] moveIndex is out of range."); + debugPrint("[goto] moveIndex is out of range."); return "out-of-range"; } if (recorder!.cur == moveIndex) { - print("[goto] cur is equal to moveIndex."); + debugPrint("[goto] cur is equal to moveIndex."); return "equal"; } @@ -1178,7 +1180,7 @@ class Position { String moves = ""; int posAfterLastRemove = 0; - //print("recorder.movesCount = ${recorder.movesCount}"); + //debugPrint("recorder.movesCount = ${recorder.movesCount}"); for (i = recorder!.movesCount - 1; i! >= 0; i--) { //if (recorder.moveAt(i).type == MoveType.remove) break; @@ -1189,7 +1191,7 @@ class Position { posAfterLastRemove = i + 1; } - //print("[movesSinceLastRemove] posAfterLastRemove = $posAfterLastRemove"); + //debugPrint("[movesSinceLastRemove] posAfterLastRemove = $posAfterLastRemove"); for (int i = posAfterLastRemove; i < recorder!.movesCount; i++) { moves += " ${recorder!.moveAt(i).move}"; @@ -1199,7 +1201,7 @@ class Position { var idx = moves.indexOf('-('); if (idx != -1) { - //print("moves[$idx] is -("); + //debugPrint("moves[$idx] is -("); assert(false); } diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index 0bb6c359..67963b35 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import 'package:flutter/foundation.dart'; import 'package:sanmill/common/config.dart'; import 'position.dart'; @@ -58,9 +59,9 @@ class GameRecorder { } } else if ((wmd.length == 8 && wmd[2] == '-' && wmd[5] == 'x') || (wmd.length == 5 && wmd[2] == 'x')) { - print("$tag Not support parsing format oo-ooxo notation."); + debugPrint("$tag Not support parsing format oo-ooxo notation."); } else { - print("$tag Parse notation $wmd failed."); + debugPrint("$tag Parse notation $wmd failed."); } return move; @@ -83,7 +84,7 @@ class GameRecorder { move = playOkNotationToMove[playOk]!; return move; } else { - print("$tag Parse PlayOK notation $playOk failed."); + debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; } } @@ -96,7 +97,7 @@ class GameRecorder { move = "-" + playOkNotationToMove[sub]!; return move; } else { - print("$tag Parse PlayOK notation $playOk failed."); + debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; } } @@ -107,7 +108,7 @@ class GameRecorder { if (val1 >= 1 && val1 <= 24) { move = playOkNotationToMove[sub1]!; } else { - print("$tag Parse PlayOK notation $playOk failed."); + debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; } @@ -117,12 +118,12 @@ class GameRecorder { move = move + "->" + playOkNotationToMove[sub2]!; return move; } else { - print("$tag Parse PlayOK notation $playOk failed."); + debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; } } - print("$tag Not support parsing format oo-ooxo PlayOK notation."); + debugPrint("$tag Not support parsing format oo-ooxo PlayOK notation."); return ""; } @@ -233,14 +234,14 @@ class GameRecorder { if (m1 != "") { newHistory.add(Move(m1)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } String m2 = wmdNotationToMoveString(i.substring(2)); if (m2 != "") { newHistory.add(Move(m2)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } } else if (i.length == 8 && i[2] == '-' && i[5] == 'x') { @@ -249,14 +250,14 @@ class GameRecorder { if (m1 != "") { newHistory.add(Move(m1)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } String m2 = wmdNotationToMoveString(i.substring(5)); if (m2 != "") { newHistory.add(Move(m2)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } } else { @@ -265,7 +266,7 @@ class GameRecorder { if (m != "") { newHistory.add(Move(m)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } } @@ -307,7 +308,7 @@ class GameRecorder { if (m != "") { newHistory.add(Move(m)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } } else if (iX != -1) { @@ -315,14 +316,14 @@ class GameRecorder { if (m1 != "") { newHistory.add(Move(m1)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } String m2 = playOkNotationToMoveString(i.substring(iX)); if (m2 != "") { newHistory.add(Move(m2)); } else { - print("Cannot import $i"); + debugPrint("Cannot import $i"); return i; } } diff --git a/src/ui/flutter_app/lib/mill/types.dart b/src/ui/flutter_app/lib/mill/types.dart index acd007e8..e4cdaea5 100644 --- a/src/ui/flutter_app/lib/mill/types.dart +++ b/src/ui/flutter_app/lib/mill/types.dart @@ -16,6 +16,8 @@ along with this program. If not, see . */ +import 'package:flutter/foundation.dart'; + abs(value) => value > 0 ? value : -value; class Move { @@ -82,7 +84,7 @@ class Move { removed = Piece.noPiece; } else if (move == "draw") { // TODO - print("[TODO] Computer request draw"); + debugPrint("[TODO] Computer request draw"); } else { assert(false); } @@ -267,7 +269,7 @@ bool isOk(int sq) { bool ret = (sq == 0 || (sq >= sqBegin && sq < sqEnd)); if (ret == false) { - print("[types] $sq is not OK"); + debugPrint("[types] $sq is not OK"); } return ret; // TODO: SQ_NONE? diff --git a/src/ui/flutter_app/lib/services/audios.dart b/src/ui/flutter_app/lib/services/audios.dart index 3103b2eb..55851ba6 100644 --- a/src/ui/flutter_app/lib/services/audios.dart +++ b/src/ui/flutter_app/lib/services/audios.dart @@ -18,6 +18,7 @@ import 'dart:io'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:sanmill/common/config.dart'; import 'package:soundpool/soundpool.dart'; @@ -50,7 +51,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: _soundpool is null."); + debugPrint("[audio] Error: _soundpool is null."); return; } @@ -60,7 +61,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: drawSoundId is null."); + debugPrint("[audio] Error: drawSoundId is null."); return; } @@ -70,7 +71,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: flySoundId is null."); + debugPrint("[audio] Error: flySoundId is null."); return; } @@ -80,7 +81,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: goSoundId is null."); + debugPrint("[audio] Error: goSoundId is null."); return; } @@ -90,7 +91,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: illegalSoundId is null."); + debugPrint("[audio] Error: illegalSoundId is null."); return; } @@ -100,7 +101,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: loseSoundId is null."); + debugPrint("[audio] Error: loseSoundId is null."); return; } @@ -110,7 +111,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: millSoundId is null."); + debugPrint("[audio] Error: millSoundId is null."); return; } @@ -120,7 +121,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: placeSoundId is null."); + debugPrint("[audio] Error: placeSoundId is null."); return; } @@ -130,7 +131,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: removeSoundId is null."); + debugPrint("[audio] Error: removeSoundId is null."); return; } @@ -140,7 +141,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: selectSoundId is null."); + debugPrint("[audio] Error: selectSoundId is null."); return; } @@ -150,7 +151,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: winSoundId is null."); + debugPrint("[audio] Error: winSoundId is null."); return; } } @@ -164,7 +165,7 @@ class Audios { if (Config.developerMode) { assert(false); } - print("[audio] Error: soundId is null."); + debugPrint("[audio] Error: soundId is null."); return; } @@ -198,7 +199,7 @@ class Audios { } if (Platform.isWindows) { - print("audio players is not support Windows."); + debugPrint("audio players is not support Windows."); return; } @@ -212,7 +213,7 @@ class Audios { _playSound(soundId); } catch (e) { // Fallback for all errors - print(e); + debugPrint(e.toString()); } }); } diff --git a/src/ui/flutter_app/lib/widgets/about_page.dart b/src/ui/flutter_app/lib/widgets/about_page.dart index 182c0e62..25d6632f 100644 --- a/src/ui/flutter_app/lib/widgets/about_page.dart +++ b/src/ui/flutter_app/lib/widgets/about_page.dart @@ -185,7 +185,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteeIssuesURL); } else { @@ -200,7 +200,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteeEulaURL); } else { @@ -215,7 +215,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteeSourceCodeURL); } else { @@ -236,7 +236,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteeThirdPartyNoticesURL); } else { @@ -252,7 +252,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteePrivacyPolicyURL); } else { @@ -267,7 +267,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteeHelpImproveTranslateURL); } else { @@ -282,7 +282,7 @@ class _AboutPageState extends State { locale = await Devicelocale.currentLocale; } - print("$tag local = $locale"); + debugPrint("$tag local = $locale"); if (locale != null && locale.startsWith("zh_")) { _launchURL(Constants.giteeThanksURL); } else { diff --git a/src/ui/flutter_app/lib/widgets/board.dart b/src/ui/flutter_app/lib/widgets/board.dart index 24af3435..e6ad9e65 100644 --- a/src/ui/flutter_app/lib/widgets/board.dart +++ b/src/ui/flutter_app/lib/widgets/board.dart @@ -108,19 +108,19 @@ class Board extends StatelessWidget { final column = (dx - padding) ~/ squareWidth; if (column < 0 || column > 6) { - print("$tag Tap on column $column (ignored)."); + debugPrint("$tag Tap on column $column (ignored)."); return; } final row = (dy - padding) ~/ squareWidth; if (row < 0 || row > 6) { - print("$tag Tap on row $row (ignored)."); + debugPrint("$tag Tap on row $row (ignored)."); return; } final index = row * 7 + column; - print("$tag Tap on ($row, $column) <$index>"); + debugPrint("$tag Tap on ($row, $column) <$index>"); onBoardTap(context, index); }, diff --git a/src/ui/flutter_app/lib/widgets/dialog.dart b/src/ui/flutter_app/lib/widgets/dialog.dart index 5d6e02c6..5f1ddae8 100644 --- a/src/ui/flutter_app/lib/widgets/dialog.dart +++ b/src/ui/flutter_app/lib/widgets/dialog.dart @@ -48,7 +48,7 @@ void showCountdownDialog( content: StreamBuilder( stream: events.stream, builder: (BuildContext context, AsyncSnapshot snapshot) { - print("Count down: " + snapshot.data.toString()); + debugPrint("Count down: ${snapshot.data}"); if (snapshot.data == 0) { fun(); @@ -122,7 +122,7 @@ showPrivacyDialog( locale = await Devicelocale.currentLocale; } - print("[about] local = $locale"); + debugPrint("[about] local = $locale"); if (locale != null && locale.startsWith("zh_")) { eulaURL = Constants.giteeEulaURL; privacyPolicyURL = Constants.giteePrivacyPolicyURL; diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/widgets/game_page.dart index 9f60e21b..85d48d86 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_page.dart @@ -81,7 +81,7 @@ class _GamePageState extends State @override void initState() { - print("$tag Engine type: ${widget.engineType}"); + debugPrint("$tag Engine type: ${widget.engineType}"); Game.instance.setWhoIsAi(widget.engineType); @@ -97,9 +97,9 @@ class _GamePageState extends State } _setReadyState() async { - print("$tag Check if need to set Ready state..."); + debugPrint("$tag Check if need to set Ready state..."); if (!isReady && mounted && Config.settingsLoaded) { - print("$tag Set Ready State..."); + debugPrint("$tag Set Ready State..."); setState(() {}); isReady = true; timer.cancel(); @@ -145,7 +145,7 @@ class _GamePageState extends State showTip(String? tip) { if (!mounted) return; if (tip != null) { - print("[tip] $tip"); + debugPrint("[tip] $tip"); if (Config.screenReaderSupport) { //showSnackBar(context, tip); } @@ -189,7 +189,7 @@ class _GamePageState extends State onBoardTap(BuildContext context, int index) { if (!isReady) { - print("[tap] Not ready, ignore tapping."); + debugPrint("[tap] Not ready, ignore tapping."); return false; } @@ -200,7 +200,7 @@ class _GamePageState extends State if (Game.instance.engineType == EngineType.aiVsAi || Game.instance.engineType == EngineType.testViaLAN) { - print("$tag Engine type is no human, ignore tapping."); + debugPrint("$tag Engine type is no human, ignore tapping."); return false; } @@ -209,7 +209,7 @@ class _GamePageState extends State int? sq = indexToSquare[index]; if (sq == null) { - print("$tag sq is null, skip tapping."); + debugPrint("$tag sq is null, skip tapping."); return; } @@ -224,10 +224,10 @@ class _GamePageState extends State if (Game.instance.isAiToMove()) { if (Game.instance.aiIsSearching()) { - print("$tag AI is thinking, skip tapping."); + debugPrint("$tag AI is thinking, skip tapping."); return false; } else { - print("[tap] AI is not thinking. AI is to move."); + debugPrint("[tap] AI is not thinking. AI is to move."); engineToGo(false); return false; } @@ -235,7 +235,7 @@ class _GamePageState extends State } if (Game.instance.isAiToMove() || Game.instance.aiIsSearching()) { - print("[tap] AI's turn, skip tapping."); + debugPrint("[tap] AI's turn, skip tapping."); return false; } @@ -280,10 +280,10 @@ class _GamePageState extends State } } ret = true; - print("[tap] putPiece: [$sq]"); + debugPrint("[tap] putPiece: [$sq]"); break; } else { - print("[tap] putPiece: skip [$sq]"); + debugPrint("[tap] putPiece: skip [$sq]"); if (mounted) { showTip(S.of(context).tipBanPlace); if (Config.screenReaderSupport) { @@ -314,7 +314,7 @@ class _GamePageState extends State Audios.playTone(Audios.selectSoundId); Game.instance.select(index); ret = true; - print("[tap] selectPiece: [$sq]"); + debugPrint("[tap] selectPiece: [$sq]"); var us = Game.instance.sideToMove; if (position.phase == Phase.moving && @@ -322,7 +322,7 @@ class _GamePageState extends State (Game.instance.position.pieceOnBoardCount[us] == Config.flyPieceCount || Game.instance.position.pieceOnBoardCount[us] == 3)) { - print("[tap] May fly."); + debugPrint("[tap] May fly."); if (mounted) { showTip(S.of(context).tipCanMoveToAnyPoint); if (Config.screenReaderSupport) { @@ -341,7 +341,7 @@ class _GamePageState extends State break; case -2: Audios.playTone(Audios.illegalSoundId); - print("[tap] selectPiece: skip [$sq]"); + debugPrint("[tap] selectPiece: skip [$sq]"); if (mounted && position.phase != Phase.gameOver) { showTip(S.of(context).tipCannotMove); if (Config.screenReaderSupport) { @@ -352,7 +352,7 @@ class _GamePageState extends State break; case -3: Audios.playTone(Audios.illegalSoundId); - print("[tap] selectPiece: skip [$sq]"); + debugPrint("[tap] selectPiece: skip [$sq]"); if (mounted) { showTip(S.of(context).tipCanMoveOnePoint); if (Config.screenReaderSupport) { @@ -363,7 +363,7 @@ class _GamePageState extends State break; case -4: Audios.playTone(Audios.illegalSoundId); - print("[tap] selectPiece: skip [$sq]"); + debugPrint("[tap] selectPiece: skip [$sq]"); if (mounted) { showTip(S.of(context).tipSelectPieceToMove); if (Config.screenReaderSupport) { @@ -373,7 +373,7 @@ class _GamePageState extends State break; default: Audios.playTone(Audios.illegalSoundId); - print("[tap] selectPiece: skip [$sq]"); + debugPrint("[tap] selectPiece: skip [$sq]"); if (mounted) { showTip(S.of(context).tipSelectWrong); if (Config.screenReaderSupport) { @@ -393,7 +393,7 @@ class _GamePageState extends State case 0: //Audios.playTone(Audios.removeSoundId); ret = true; - print("[tap] removePiece: [$sq]"); + debugPrint("[tap] removePiece: [$sq]"); if (Game.instance.position.pieceToRemoveCount >= 1) { if (mounted) { showTip(S.of(context).tipContinueMill); @@ -420,7 +420,8 @@ class _GamePageState extends State break; case -2: Audios.playTone(Audios.illegalSoundId); - print("[tap] removePiece: Cannot Remove our pieces, skip [$sq]"); + debugPrint( + "[tap] removePiece: Cannot Remove our pieces, skip [$sq]"); if (mounted) { showTip(S.of(context).tipSelectOpponentsPiece); if (Config.screenReaderSupport) { @@ -430,8 +431,9 @@ class _GamePageState extends State break; case -3: Audios.playTone(Audios.illegalSoundId); - print( - "[tap] removePiece: Cannot remove piece from Mill, skip [$sq]"); + debugPrint( + "[tap] removePiece: Cannot remove piece from Mill, skip [$sq]", + ); if (mounted) { showTip(S.of(context).tipCannotRemovePieceFromMill); if (Config.screenReaderSupport) { @@ -443,7 +445,7 @@ class _GamePageState extends State break; default: Audios.playTone(Audios.illegalSoundId); - print("[tap] removePiece: skip [$sq]"); + debugPrint("[tap] removePiece: skip [$sq]"); if (mounted && position.phase != Phase.gameOver) { showTip(S.of(context).tipBanRemove); if (Config.screenReaderSupport) { @@ -516,23 +518,24 @@ class _GamePageState extends State engineToGo(bool isMoveNow) async { if (!mounted) { - print("[engineToGo] !mounted, skip engineToGo."); + debugPrint("[engineToGo] !mounted, skip engineToGo."); return; } // TODO - print("[engineToGo] engine type is ${widget.engineType}"); + debugPrint("[engineToGo] engine type is ${widget.engineType}"); if (isMoveNow == true) { - if (!Game.instance.isAiToMove()) { - print("[engineToGo] Human to Move. Cannot get search result now."); + if (!Game.instance.isAiToMove()!) { + debugPrint("[engineToGo] Human to Move. Cannot get search result now."); ScaffoldMessenger.of(context).clearSnackBars(); showSnackBar(context, S.of(context).notAIsTurn); return; } - if (!Game.instance.position.recorder.isClean()) { - print( - "[engineToGo] History is not clean. Cannot get search result now."); + if (!Game.instance.position.recorder!.isClean()) { + debugPrint( + "[engineToGo] History is not clean. Cannot get search result now.", + ); ScaffoldMessenger.of(context).clearSnackBars(); showSnackBar(context, S.of(context).aiIsNotThinking); return; @@ -570,15 +573,15 @@ class _GamePageState extends State late var response; if (!isMoveNow) { - print("[engineToGo] Searching..."); + debugPrint("[engineToGo] Searching..."); response = await widget.engine.search(Game.instance.position); } else { - print("[engineToGo] Get search result now..."); + debugPrint("[engineToGo] Get search result now..."); response = await widget.engine.search(null); isMoveNow = false; } - print("[engineToGo] Engine response type: ${response.type}"); + debugPrint("[engineToGo] Engine response type: ${response.type}"); switch (response.type) { case 'move': @@ -591,8 +594,9 @@ class _GamePageState extends State if (!disposed) { _animationController.reset(); } else { - print( - "[engineToGo] Disposed, so do not reset animationController."); + debugPrint( + "[engineToGo] Disposed, so do not reset animationController.", + ); } Game.instance.doMove(move.move); @@ -630,7 +634,7 @@ class _GamePageState extends State if (Game.instance.isAiToMove()) { // TODO: Move now - //print("$tag New game, AI to move, move now."); + //debugPrint("$tag New game, AI to move, move now."); //await engineToGo(true); } @@ -645,7 +649,7 @@ class _GamePageState extends State } if (Game.instance.isAiToMove()) { - print("$tag New game, AI to move."); + debugPrint("$tag New game, AI to move."); engineToGo(false); } } @@ -662,8 +666,8 @@ class _GamePageState extends State String text = data.text!; - print("Clipboard text:"); - print('$text'); + debugPrint("Clipboard text:"); + debugPrint(text); await onTakeBackAllButtonPressed(pop: false); await Game.instance.position.recorder.clear(); @@ -1006,7 +1010,8 @@ class _GamePageState extends State } if (isGoingToHistory) { - print("[TakeBack] Is going to history, ignore Take Back button press."); + debugPrint( + "[TakeBack] Is going to history, ignore Take Back button press."); return; } @@ -1187,7 +1192,7 @@ class _GamePageState extends State Config.isPrivacyPolicyAccepted = value; }); - print("[config] isPrivacyPolicyAccepted: $value"); + debugPrint("[config] isPrivacyPolicyAccepted: $value"); Config.save(); } @@ -1220,13 +1225,14 @@ class _GamePageState extends State S.of(context).drawReasonThreefoldRepetition, }; - print("$tag Game over reason: ${Game.instance.position.gameOverReason}"); + debugPrint( + "$tag Game over reason: ${Game.instance.position.gameOverReason}"); String? loseReasonStr = reasonMap[Game.instance.position.gameOverReason]; if (loseReasonStr == null) { loseReasonStr = S.of(context).gameOverUnknownReason; - print("$tag Game over reason string: $loseReasonStr"); + debugPrint("$tag Game over reason string: $loseReasonStr"); if (Config.developerMode) { assert(false); } @@ -1372,28 +1378,29 @@ class _GamePageState extends State ), actions: [ TextButton( - child: Text( - S.of(context).restart, - style: TextStyle( - fontSize: Config.fontSize, - ), + child: Text( + S.of(context).restart, + style: TextStyle( + fontSize: Config.fontSize, ), - onPressed: () { - Navigator.of(context).pop(); - Game.instance.newGame(); - if (mounted) { - showTip(S.of(context).gameStarted); - if (Config.screenReaderSupport) { - ScaffoldMessenger.of(context).clearSnackBars(); - showSnackBar(context, S.of(context).gameStarted); - } + ), + onPressed: () { + Navigator.of(context).pop(); + Game.instance.newGame(); + if (mounted) { + showTip(S.of(context).gameStarted); + if (Config.screenReaderSupport) { + ScaffoldMessenger.of(context).clearSnackBars(); + showSnackBar(context, S.of(context).gameStarted); } + } - if (Game.instance.isAiToMove()) { - print("$tag New game, AI to move."); - engineToGo(false); - } - }), + if (Game.instance.isAiToMove()!) { + debugPrint("$tag New game, AI to move."); + engineToGo(false); + } + }, + ), TextButton( child: Text( S.of(context).cancel, @@ -1892,7 +1899,7 @@ class _GamePageState extends State @override void dispose() { - print("$tag dispose"); + debugPrint("$tag dispose"); disposed = true; widget.engine.shutdown(); _animationController.dispose(); @@ -1903,7 +1910,7 @@ class _GamePageState extends State @override void didPush() async { final route = ModalRoute.of(context)!.settings.name; - print('$tag Game Page didPush route: $route'); + debugPrint('$tag Game Page didPush route: $route'); await widget.engine.setOptions(context); if (Config.languageCode != Constants.defaultLanguageCodeName) { S.load(Locale(Config.languageCode)); @@ -1914,7 +1921,7 @@ class _GamePageState extends State @override void didPopNext() async { final route = ModalRoute.of(context)!.settings.name; - print('$tag Game Page didPopNext route: $route'); + debugPrint('$tag Game Page didPopNext route: $route'); await widget.engine.setOptions(context); if (Config.languageCode != Constants.defaultLanguageCodeName) { S.load(Locale(Config.languageCode)); @@ -1924,7 +1931,7 @@ class _GamePageState extends State @override void didPushNext() async { final route = ModalRoute.of(context)!.settings.name; - print('$tag Game Page didPushNext route: $route'); + debugPrint('$tag Game Page didPushNext route: $route'); await widget.engine.setOptions(context); if (Config.languageCode != Constants.defaultLanguageCodeName) { S.load(Locale(Config.languageCode)); @@ -1934,6 +1941,6 @@ class _GamePageState extends State @override void didPop() { final route = ModalRoute.of(context)!.settings.name; - print('$tag Game Page didPop route: $route'); + debugPrint('$tag Game Page didPop route: $route'); } } diff --git a/src/ui/flutter_app/lib/widgets/game_settings_page.dart b/src/ui/flutter_app/lib/widgets/game_settings_page.dart index a03ac6c6..2ad0818c 100644 --- a/src/ui/flutter_app/lib/widgets/game_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_settings_page.dart @@ -76,7 +76,7 @@ class _GameSettingsPageState extends State { label: Config.skillLevel.round().toString(), onChanged: (value) { setState(() { - print("[config] Slider value: $value"); + debugPrint("[config] Slider value: $value"); Config.skillLevel = value.toInt(); Config.save(); }); @@ -99,7 +99,7 @@ class _GameSettingsPageState extends State { label: Config.moveTime.round().toString(), onChanged: (value) { setState(() { - print("[config] Slider value: $value"); + debugPrint("[config] Slider value: $value"); Config.moveTime = value.toInt(); Config.save(); }); @@ -392,7 +392,7 @@ class _GameSettingsPageState extends State { Config.aiMovesFirst = !value; }); - print("[config] aiMovesFirst: ${Config.aiMovesFirst}"); + debugPrint("[config] aiMovesFirst: ${Config.aiMovesFirst}"); Config.save(); } @@ -402,14 +402,14 @@ class _GameSettingsPageState extends State { Config.aiIsLazy = value; }); - print("[config] aiMovesFirst: $value"); + debugPrint("[config] aiMovesFirst: $value"); Config.save(); } setAlgorithm() { callback(int? algorithm) async { - print("[config] algorithm = $algorithm"); + debugPrint("[config] algorithm = $algorithm"); Navigator.of(context).pop(); @@ -417,7 +417,7 @@ class _GameSettingsPageState extends State { Config.algorithm = algorithm ?? 2; }); - print("[config] Config.algorithm: ${Config.algorithm}"); + debugPrint("[config] Config.algorithm: ${Config.algorithm}"); Config.save(); } @@ -464,7 +464,7 @@ class _GameSettingsPageState extends State { Config.drawOnHumanExperience = value; }); - print("[config] drawOnHumanExperience: $value"); + debugPrint("[config] drawOnHumanExperience: $value"); Config.save(); } @@ -474,7 +474,7 @@ class _GameSettingsPageState extends State { Config.considerMobility = value; }); - print("[config] considerMobility: $value"); + debugPrint("[config] considerMobility: $value"); Config.save(); } @@ -484,7 +484,7 @@ class _GameSettingsPageState extends State { Config.isAutoRestart = value; }); - print("[config] isAutoRestart: $value"); + debugPrint("[config] isAutoRestart: $value"); Config.save(); } @@ -494,7 +494,7 @@ class _GameSettingsPageState extends State { Config.isAutoChangeFirstMove = value; }); - print("[config] isAutoChangeFirstMove: $value"); + debugPrint("[config] isAutoChangeFirstMove: $value"); Config.save(); } @@ -504,7 +504,7 @@ class _GameSettingsPageState extends State { Config.resignIfMostLose = value; }); - print("[config] resignIfMostLose: $value"); + debugPrint("[config] resignIfMostLose: $value"); Config.save(); } @@ -514,7 +514,7 @@ class _GameSettingsPageState extends State { Config.shufflingEnabled = value; }); - print("[config] shufflingEnabled: $value"); + debugPrint("[config] shufflingEnabled: $value"); Config.save(); } @@ -524,7 +524,7 @@ class _GameSettingsPageState extends State { Config.learnEndgame = value; }); - print("[config] learnEndgame: $value"); + debugPrint("[config] learnEndgame: $value"); Config.save(); } @@ -534,7 +534,7 @@ class _GameSettingsPageState extends State { Config.openingBook = value; }); - print("[config] openingBook: $value"); + debugPrint("[config] openingBook: $value"); Config.save(); } @@ -544,7 +544,7 @@ class _GameSettingsPageState extends State { Config.toneEnabled = value; }); - print("[config] toneEnabled: $value"); + debugPrint("[config] toneEnabled: $value"); Config.save(); } @@ -554,7 +554,7 @@ class _GameSettingsPageState extends State { Config.keepMuteWhenTakingBack = value; }); - print("[config] keepMuteWhenTakingBack: $value"); + debugPrint("[config] keepMuteWhenTakingBack: $value"); Config.save(); } @@ -564,7 +564,7 @@ class _GameSettingsPageState extends State { Config.screenReaderSupport = value; }); - print("[config] screenReaderSupport: $value"); + debugPrint("[config] screenReaderSupport: $value"); Config.save(); } @@ -574,7 +574,7 @@ class _GameSettingsPageState extends State { Config.developerMode = value; }); - print("[config] developerMode: $value"); + debugPrint("[config] developerMode: $value"); Config.save(); } @@ -584,7 +584,7 @@ class _GameSettingsPageState extends State { Config.experimentsEnabled = value; }); - print("[config] experimentsEnabled: $value"); + debugPrint("[config] experimentsEnabled: $value"); Config.save(); } @@ -596,7 +596,7 @@ class _GameSettingsPageState extends State { Config.languageCode = value; }); - print("[config] languageCode: $value"); + debugPrint("[config] languageCode: $value"); Config.save(); } @@ -606,7 +606,7 @@ class _GameSettingsPageState extends State { Config.isPieceCountInHandShown = value; }); - print("[config] isPieceCountInHandShown: $value"); + debugPrint("[config] isPieceCountInHandShown: $value"); Config.save(); } @@ -616,7 +616,7 @@ class _GameSettingsPageState extends State { Config.isNotationsShown = value; }); - print("[config] isNotationsShown: $value"); + debugPrint("[config] isNotationsShown: $value"); Config.save(); } @@ -626,7 +626,7 @@ class _GameSettingsPageState extends State { Config.isHistoryNavigationToolbarShown = value; }); - print("[config] isHistoryNavigationToolbarShown: $value"); + debugPrint("[config] isHistoryNavigationToolbarShown: $value"); Config.save(); } @@ -636,7 +636,7 @@ class _GameSettingsPageState extends State { Config.standardNotationEnabled = value; }); - print("[config] standardNotationEnabled: $value"); + debugPrint("[config] standardNotationEnabled: $value"); Config.save(); } diff --git a/src/ui/flutter_app/lib/widgets/home_drawer.dart b/src/ui/flutter_app/lib/widgets/home_drawer.dart index 3a6a69e1..29c9b7cd 100644 --- a/src/ui/flutter_app/lib/widgets/home_drawer.dart +++ b/src/ui/flutter_app/lib/widgets/home_drawer.dart @@ -177,11 +177,12 @@ class _HomeDrawerState extends State { if (lastTapTime == null || DateTime.now().difference(lastTapTime!) > Duration(seconds: 1)) { lastTapTime = DateTime.now(); - print("$tag Tap again in one second to enable developer mode."); + debugPrint( + "$tag Tap again in one second to enable developer mode."); } else { lastTapTime = DateTime.now(); Developer.developerModeEnabled = true; - print("$tag Developer mode enabled."); + debugPrint("$tag Developer mode enabled."); } }); diff --git a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart b/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart index 9a14d059..868cea09 100644 --- a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart @@ -116,7 +116,7 @@ class _NavigationHomeScreenState extends State { } else if (drawerIndex == DrawerIndex.feedback && !Config.developerMode) { setState(() { if (Platform.isWindows) { - print("flutter_email_sender does not support Windows."); + debugPrint("flutter_email_sender does not support Windows."); //_launchFeedback(); } else { BetterFeedback.of(context).show((feedback) async { diff --git a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart index c26f7e23..e2c2d8df 100644 --- a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart @@ -98,7 +98,7 @@ class _PersonalizationSettingsPageState onPressed: () { setState(() => currentColor = pickerColor); - print("[config] pickerColor.value: ${pickerColor.value}"); + debugPrint("[config] pickerColor.value: ${pickerColor.value}"); if (colorString == S.of(context).boardColor) { Config.boardBackgroundColor = pickerColor.value; @@ -175,7 +175,7 @@ class _PersonalizationSettingsPageState label: Config.boardBorderLineWidth.toStringAsFixed(1), onChanged: (value) { setState(() { - print("[config] BoardBorderLineWidth value: $value"); + debugPrint("[config] BoardBorderLineWidth value: $value"); Config.boardBorderLineWidth = value; Config.save(); }); @@ -209,7 +209,7 @@ class _PersonalizationSettingsPageState label: Config.boardInnerLineWidth.toStringAsFixed(1), onChanged: (value) { setState(() { - print("[config] BoardInnerLineWidth value: $value"); + debugPrint("[config] BoardInnerLineWidth value: $value"); Config.boardInnerLineWidth = value; Config.save(); }); @@ -243,7 +243,7 @@ class _PersonalizationSettingsPageState label: Config.pieceWidth.toStringAsFixed(1), onChanged: (value) { setState(() { - print("[config] pieceWidth value: $value"); + debugPrint("[config] pieceWidth value: $value"); Config.pieceWidth = value; Config.save(); }); @@ -277,7 +277,7 @@ class _PersonalizationSettingsPageState label: Config.fontSize.toStringAsFixed(1), onChanged: (value) { setState(() { - print("[config] fontSize value: $value"); + debugPrint("[config] fontSize value: $value"); Config.fontSize = value; Config.save(); }); @@ -311,7 +311,7 @@ class _PersonalizationSettingsPageState label: Config.boardTop.toStringAsFixed(1), onChanged: (value) { setState(() { - print("[config] BoardTop value: $value"); + debugPrint("[config] BoardTop value: $value"); Config.boardTop = value; Config.save(); }); @@ -345,7 +345,7 @@ class _PersonalizationSettingsPageState label: Config.animationDuration.toStringAsFixed(1), onChanged: (value) { setState(() { - print("[config] AnimationDuration value: $value"); + debugPrint("[config] AnimationDuration value: $value"); Config.animationDuration = value; Config.save(); }); @@ -386,7 +386,7 @@ class _PersonalizationSettingsPageState List children(BuildContext context) { langCallback(var langCode) async { - print("[config] languageCode = $langCode"); + debugPrint("[config] languageCode = $langCode"); Navigator.of(context).pop(); @@ -395,7 +395,7 @@ class _PersonalizationSettingsPageState S.load(Locale(Resources.of().languageCode)); }); - print("[config] Config.languageCode: ${Config.languageCode}"); + debugPrint("[config] Config.languageCode: ${Config.languageCode}"); Config.save(); } @@ -629,7 +629,7 @@ class _PersonalizationSettingsPageState Config.standardNotationEnabled = value; }); - print("[config] standardNotationEnabled: $value"); + debugPrint("[config] standardNotationEnabled: $value"); Config.save(); } diff --git a/src/ui/flutter_app/lib/widgets/picker.dart b/src/ui/flutter_app/lib/widgets/picker.dart index 9e9b692b..b952b71d 100644 --- a/src/ui/flutter_app/lib/widgets/picker.dart +++ b/src/ui/flutter_app/lib/widgets/picker.dart @@ -63,9 +63,9 @@ Future showPickerNumber(BuildContext context, int begin, int end, fontSize: Config.fontSize, ), onConfirm: (Picker picker, List value) async { - print(value.toString()); + debugPrint(value.toString()); var selectValues = picker.getSelectedValues(); - print(selectValues); + debugPrint(selectValues.toString()); selectValue = selectValues[0]; }).showDialog(context); diff --git a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart b/src/ui/flutter_app/lib/widgets/rule_settings_page.dart index aa03670a..8fb6ecdd 100644 --- a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/rule_settings_page.dart @@ -220,7 +220,7 @@ class _RuleSettingsPageState extends State { setNTotalPiecesEachSide() { callback(int? piecesCount) async { - print("[config] piecesCount = $piecesCount"); + debugPrint("[config] piecesCount = $piecesCount"); Navigator.of(context).pop(); @@ -229,7 +229,7 @@ class _RuleSettingsPageState extends State { piecesCount ?? (specialCountryAndRegion == "Iran" ? 12 : 9); }); - print("[config] rule.piecesCount: ${rule.piecesCount}"); + debugPrint("[config] rule.piecesCount: ${rule.piecesCount}"); Config.save(); } @@ -281,7 +281,7 @@ class _RuleSettingsPageState extends State { setNMoveRule() { callback(int? nMoveRule) async { - print("[config] nMoveRule = $nMoveRule"); + debugPrint("[config] nMoveRule = $nMoveRule"); Navigator.of(context).pop(); @@ -289,7 +289,7 @@ class _RuleSettingsPageState extends State { rule.nMoveRule = Config.nMoveRule = nMoveRule ?? 100; }); - print("[config] rule.nMoveRule: ${rule.nMoveRule}"); + debugPrint("[config] rule.nMoveRule: ${rule.nMoveRule}"); Config.save(); } @@ -349,7 +349,7 @@ class _RuleSettingsPageState extends State { setEndgameNMoveRule() { callback(int? endgameNMoveRule) async { - print("[config] endgameNMoveRule = $endgameNMoveRule"); + debugPrint("[config] endgameNMoveRule = $endgameNMoveRule"); Navigator.of(context).pop(); @@ -358,7 +358,7 @@ class _RuleSettingsPageState extends State { Config.endgameNMoveRule = endgameNMoveRule ?? 100; }); - print("[config] rule.endgameNMoveRule: ${rule.endgameNMoveRule}"); + debugPrint("[config] rule.endgameNMoveRule: ${rule.endgameNMoveRule}"); Config.save(); } @@ -442,7 +442,7 @@ class _RuleSettingsPageState extends State { setFlyPieceCount() { callback(int? flyPieceCount) async { - print("[config] flyPieceCount = $flyPieceCount"); + debugPrint("[config] flyPieceCount = $flyPieceCount"); Navigator.of(context).pop(); @@ -450,7 +450,7 @@ class _RuleSettingsPageState extends State { rule.flyPieceCount = Config.flyPieceCount = flyPieceCount ?? 3; }); - print("[config] rule.flyPieceCount: ${rule.flyPieceCount}"); + debugPrint("[config] rule.flyPieceCount: ${rule.flyPieceCount}"); Config.save(); } @@ -489,7 +489,7 @@ class _RuleSettingsPageState extends State { rule.hasDiagonalLines = Config.hasDiagonalLines = value; }); - print("[config] rule.hasDiagonalLines: $value"); + debugPrint("[config] rule.hasDiagonalLines: $value"); Config.save(); } @@ -499,7 +499,7 @@ class _RuleSettingsPageState extends State { rule.mayFly = Config.mayFly = value; }); - print("[config] rule.mayFly: $value"); + debugPrint("[config] rule.mayFly: $value"); Config.save(); } @@ -509,7 +509,7 @@ class _RuleSettingsPageState extends State { rule.threefoldRepetitionRule = Config.threefoldRepetitionRule = value; }); - print("[config] rule.threefoldRepetitionRule: $value"); + debugPrint("[config] rule.threefoldRepetitionRule: $value"); Config.save(); } @@ -521,7 +521,7 @@ class _RuleSettingsPageState extends State { rule.hasBannedLocations = Config.hasBannedLocations = value; }); - print("[config] rule.hasBannedLocations: $value"); + debugPrint("[config] rule.hasBannedLocations: $value"); Config.save(); } @@ -532,7 +532,7 @@ class _RuleSettingsPageState extends State { Config.isWhiteLoseButNotDrawWhenBoardFull = value; }); - print("[config] rule.isWhiteLoseButNotDrawWhenBoardFull: $value"); + debugPrint("[config] rule.isWhiteLoseButNotDrawWhenBoardFull: $value"); Config.save(); } @@ -543,7 +543,8 @@ class _RuleSettingsPageState extends State { Config.mayOnlyRemoveUnplacedPieceInPlacingPhase = value; }); - print("[config] rule.mayOnlyRemoveUnplacedPieceInPlacingPhase: $value"); + debugPrint( + "[config] rule.mayOnlyRemoveUnplacedPieceInPlacingPhase: $value"); Config.save(); } @@ -555,7 +556,7 @@ class _RuleSettingsPageState extends State { rule.mayMoveInPlacingPhase = Config.mayMoveInPlacingPhase = value; }); - print("[config] rule.mayMoveInPlacingPhase: $value"); + debugPrint("[config] rule.mayMoveInPlacingPhase: $value"); Config.save(); @@ -570,7 +571,7 @@ class _RuleSettingsPageState extends State { rule.isDefenderMoveFirst = Config.isDefenderMoveFirst = value; }); - print("[config] rule.isDefenderMoveFirst: $value"); + debugPrint("[config] rule.isDefenderMoveFirst: $value"); Config.save(); } @@ -581,7 +582,7 @@ class _RuleSettingsPageState extends State { Config.isLoseButNotChangeSideWhenNoWay = value; }); - print("[config] rule.isLoseButNotChangeSideWhenNoWay: $value"); + debugPrint("[config] rule.isLoseButNotChangeSideWhenNoWay: $value"); Config.save(); } @@ -593,7 +594,7 @@ class _RuleSettingsPageState extends State { rule.mayRemoveFromMillsAlways = Config.mayRemoveFromMillsAlways = value; }); - print("[config] rule.mayRemoveFromMillsAlways: $value"); + debugPrint("[config] rule.mayRemoveFromMillsAlways: $value"); Config.save(); } @@ -603,7 +604,7 @@ class _RuleSettingsPageState extends State { rule.mayRemoveMultiple = Config.mayRemoveMultiple = value; }); - print("[config] rule.mayRemoveMultiple: $value"); + debugPrint("[config] rule.mayRemoveMultiple: $value"); Config.save(); } @@ -615,7 +616,7 @@ class _RuleSettingsPageState extends State { rule.piecesAtLeastCount = Config.piecesAtLeastCount = value; }); - print("[config] rule.piecesAtLeastCount: $value"); + debugPrint("[config] rule.piecesAtLeastCount: $value"); Config.save(); } From 6c0dd46f05a4f478c1a7514a59f4b41eb2580167 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:06:01 +0200 Subject: [PATCH 04/13] fix a ton of linting Most notably: - require_trailing_commas - prefer_const_constructors - type_annotate_public_apis - always_declare_return_types - prefer_foreach - use_string_buffers - join_return_with_assignment For now disabled rules: - avoid_positional_boolean_parameters - constant_identifier_names - avoid_escaping_inner_quotes - use_build_context_synchronously Those lint rules are going to be disabled for now as they require massive restructure and logic change of the current codebase Already fixed: - avoid_print (previous commit) --- src/ui/flutter_app/analysis_options.yaml | 1 + src/ui/flutter_app/lib/common/config.dart | 164 ++-- src/ui/flutter_app/lib/common/constants.dart | 5 +- src/ui/flutter_app/lib/common/settings.dart | 13 +- .../flutter_app/lib/engine/native_engine.dart | 108 ++- src/ui/flutter_app/lib/l10n/resources.dart | 15 +- src/ui/flutter_app/lib/main.dart | 38 +- src/ui/flutter_app/lib/mill/game.dart | 73 +- src/ui/flutter_app/lib/mill/mills.dart | 20 +- src/ui/flutter_app/lib/mill/position.dart | 184 ++-- src/ui/flutter_app/lib/mill/recorder.dart | 134 ++- src/ui/flutter_app/lib/mill/rule.dart | 2 +- src/ui/flutter_app/lib/mill/types.dart | 20 +- src/ui/flutter_app/lib/mill/zobrist.dart | 4 +- .../lib/painting/board_painter.dart | 103 ++- .../lib/painting/painter_base.dart | 6 +- .../lib/painting/pieces_painter.dart | 71 +- src/ui/flutter_app/lib/services/audios.dart | 30 +- src/ui/flutter_app/lib/style/app_theme.dart | 121 +-- .../flutter_app/lib/widgets/about_page.dart | 76 +- src/ui/flutter_app/lib/widgets/board.dart | 44 +- src/ui/flutter_app/lib/widgets/dialog.dart | 72 +- .../lib/widgets/drawer_user_controller.dart | 127 +-- src/ui/flutter_app/lib/widgets/env_page.dart | 23 +- src/ui/flutter_app/lib/widgets/game_page.dart | 836 +++++++++--------- .../lib/widgets/game_settings_page.dart | 304 +++---- .../flutter_app/lib/widgets/help_screen.dart | 14 +- .../flutter_app/lib/widgets/home_drawer.dart | 127 +-- .../flutter_app/lib/widgets/license_page.dart | 19 +- .../lib/widgets/list_item_divider.dart | 1 + .../lib/widgets/navigation_home_screen.dart | 11 +- .../lib/widgets/oss_license_page.dart | 135 +-- .../personalization_settings_page.dart | 169 ++-- src/ui/flutter_app/lib/widgets/picker.dart | 88 +- .../lib/widgets/rule_settings_page.dart | 170 ++-- .../lib/widgets/settings_card.dart | 2 +- .../lib/widgets/settings_list_tile.dart | 12 +- .../widgets/settings_switch_list_tile.dart | 4 +- src/ui/flutter_app/lib/widgets/snack_bar.dart | 23 +- src/ui/flutter_app/test/widget_test.dart | 12 +- 40 files changed, 1749 insertions(+), 1632 deletions(-) diff --git a/src/ui/flutter_app/analysis_options.yaml b/src/ui/flutter_app/analysis_options.yaml index d4bd2886..d1a1d79b 100644 --- a/src/ui/flutter_app/analysis_options.yaml +++ b/src/ui/flutter_app/analysis_options.yaml @@ -12,3 +12,4 @@ analyzer: exclude: # generated code - lib/generated/** + - lib/l10n/** diff --git a/src/ui/flutter_app/lib/common/config.dart b/src/ui/flutter_app/lib/common/config.dart index 6cec4afd..8891fda7 100644 --- a/src/ui/flutter_app/lib/common/config.dart +++ b/src/ui/flutter_app/lib/common/config.dart @@ -25,6 +25,7 @@ import 'package:sanmill/style/app_theme.dart'; import 'settings.dart'; class Config { + const Config._(); static bool settingsLoaded = false; static bool isPrivacyPolicyAccepted = false; @@ -86,8 +87,7 @@ class Config { static int piecesCount = specialCountryAndRegion == "Iran" ? 12 : 9; static int flyPieceCount = 3; static int piecesAtLeastCount = 3; - static bool hasDiagonalLines = - specialCountryAndRegion == "Iran" ? true : false; + static bool hasDiagonalLines = specialCountryAndRegion == "Iran"; static bool hasBannedLocations = false; static bool mayMoveInPlacingPhase = false; static bool isDefenderMoveFirst = false; @@ -101,119 +101,131 @@ class Config { static int endgameNMoveRule = 100; static bool threefoldRepetitionRule = true; + // TODO: use jsonSerializable static Future loadSettings() async { debugPrint("[config] Loading settings..."); final settings = await Settings.instance(); Config.isPrivacyPolicyAccepted = - settings['IsPrivacyPolicyAccepted'] ?? false; + settings['IsPrivacyPolicyAccepted'] as bool? ?? false; // Preferences - Config.toneEnabled = settings['ToneEnabled'] ?? true; - Config.keepMuteWhenTakingBack = settings['KeepMuteWhenTakingBack'] ?? true; - Config.screenReaderSupport = settings['ScreenReaderSupport'] ?? false; - Config.aiMovesFirst = settings['AiMovesFirst'] ?? false; - Config.aiIsLazy = settings['AiIsLazy'] ?? false; - Config.skillLevel = settings['SkillLevel'] ?? 1; - Config.moveTime = settings['MoveTime'] ?? 1; - Config.isAutoRestart = settings['IsAutoRestart'] ?? false; - Config.isAutoChangeFirstMove = settings['IsAutoChangeFirstMove'] ?? false; - Config.resignIfMostLose = settings['ResignIfMostLose'] ?? false; - Config.shufflingEnabled = settings['ShufflingEnabled'] ?? true; - Config.learnEndgame = settings['LearnEndgame'] ?? false; - Config.openingBook = settings['OpeningBook'] ?? false; - Config.algorithm = settings['Algorithm'] ?? 2; - Config.drawOnHumanExperience = settings['DrawOnHumanExperience'] ?? true; - Config.considerMobility = settings['ConsiderMobility'] ?? true; - Config.developerMode = settings['DeveloperMode'] ?? false; - Config.experimentsEnabled = settings['ExperimentsEnabled'] ?? false; + Config.toneEnabled = settings['ToneEnabled'] as bool? ?? true; + Config.keepMuteWhenTakingBack = + settings['KeepMuteWhenTakingBack'] as bool? ?? true; + Config.screenReaderSupport = + settings['ScreenReaderSupport'] as bool? ?? false; + Config.aiMovesFirst = settings['AiMovesFirst'] as bool? ?? false; + Config.aiIsLazy = settings['AiIsLazy'] as bool? ?? false; + Config.skillLevel = settings['SkillLevel'] as int? ?? 1; + Config.moveTime = settings['MoveTime'] as int? ?? 1; + Config.isAutoRestart = settings['IsAutoRestart'] as bool? ?? false; + Config.isAutoChangeFirstMove = + settings['IsAutoChangeFirstMove'] as bool? ?? false; + Config.resignIfMostLose = settings['ResignIfMostLose'] as bool? ?? false; + Config.shufflingEnabled = settings['ShufflingEnabled'] as bool? ?? true; + Config.learnEndgame = settings['LearnEndgame'] as bool? ?? false; + Config.openingBook = settings['OpeningBook'] as bool? ?? false; + Config.algorithm = settings['Algorithm'] as int? ?? 2; + Config.drawOnHumanExperience = + settings['DrawOnHumanExperience'] as bool? ?? true; + Config.considerMobility = settings['ConsiderMobility'] as bool? ?? true; + Config.developerMode = settings['DeveloperMode'] as bool? ?? false; + Config.experimentsEnabled = + settings['ExperimentsEnabled'] as bool? ?? false; // Display - Config.languageCode = - settings['LanguageCode'] ?? Constants.defaultLanguageCodeName; + Config.languageCode = settings['LanguageCode'] as String? ?? + Constants.defaultLanguageCodeName; Config.standardNotationEnabled = - settings['StandardNotationEnabled'] ?? true; + settings['StandardNotationEnabled'] as bool? ?? true; Config.isPieceCountInHandShown = - settings['IsPieceCountInHandShown'] ?? true; - Config.isNotationsShown = settings['IsNotationsShown'] ?? false; + settings['IsPieceCountInHandShown'] as bool? ?? true; + Config.isNotationsShown = settings['IsNotationsShown'] as bool? ?? false; Config.isHistoryNavigationToolbarShown = - settings['IsHistoryNavigationToolbarShown'] ?? false; - Config.boardBorderLineWidth = settings['BoardBorderLineWidth'] ?? 2; - Config.boardInnerLineWidth = settings['BoardInnerLineWidth'] ?? 2; - Config.pieceWidth = settings['PieceWidth'] ?? 0.9; - Config.fontSize = settings['FontSize'] ?? 16.0; - Config.boardTop = settings['BoardTop'] ?? (isLargeScreen() ? 75 : 36); - Config.animationDuration = settings['AnimationDuration'] ?? 0; + settings['IsHistoryNavigationToolbarShown'] as bool? ?? false; + Config.boardBorderLineWidth = + settings['BoardBorderLineWidth'] as double? ?? 2; + Config.boardInnerLineWidth = + settings['BoardInnerLineWidth'] as double? ?? 2; + Config.pieceWidth = settings['PieceWidth'] as double? ?? 0.9; + Config.fontSize = settings['FontSize'] as double? ?? 16.0; + Config.boardTop = + settings['BoardTop'] as double? ?? (isLargeScreen() ? 75 : 36); + Config.animationDuration = settings['AnimationDuration'] as double? ?? 0; // Color Config.boardLineColor = - settings['BoardLineColor'] ?? AppTheme.boardLineColor.value; - Config.darkBackgroundColor = - settings['DarkBackgroundColor'] ?? AppTheme.darkBackgroundColor.value; - Config.boardBackgroundColor = - settings['BoardBackgroundColor'] ?? AppTheme.boardBackgroundColor.value; + settings['BoardLineColor'] as int? ?? AppTheme.boardLineColor.value; + Config.darkBackgroundColor = settings['DarkBackgroundColor'] as int? ?? + AppTheme.darkBackgroundColor.value; + Config.boardBackgroundColor = settings['BoardBackgroundColor'] as int? ?? + AppTheme.boardBackgroundColor.value; Config.whitePieceColor = - settings['WhitePieceColor'] ?? AppTheme.whitePieceColor.value; + settings['WhitePieceColor'] as int? ?? AppTheme.whitePieceColor.value; Config.blackPieceColor = - settings['BlackPieceColor'] ?? AppTheme.blackPieceColor.value; - Config.pieceHighlightColor = - settings['PieceHighlightColor'] ?? AppTheme.pieceHighlightColor.value; + settings['BlackPieceColor'] as int? ?? AppTheme.blackPieceColor.value; + Config.pieceHighlightColor = settings['PieceHighlightColor'] as int? ?? + AppTheme.pieceHighlightColor.value; Config.messageColor = - settings['MessageColor'] ?? AppTheme.messageColor.value; - Config.drawerColor = settings['DrawerColor'] ?? AppTheme.drawerColor.value; - Config.drawerBackgroundColor = settings['DrawerBackgroundColor'] ?? + settings['MessageColor'] as int? ?? AppTheme.messageColor.value; + Config.drawerColor = + settings['DrawerColor'] as int? ?? AppTheme.drawerColor.value; + Config.drawerBackgroundColor = settings['DrawerBackgroundColor'] as int? ?? AppTheme.drawerBackgroundColor.value; Config.drawerTextColor = - settings['DrawerTextColor'] ?? AppTheme.drawerTextColor.value; - Config.drawerHighlightItemColor = settings['DrawerHighlightItemColor'] ?? - AppTheme.drawerHighlightItemColor.value; + settings['DrawerTextColor'] as int? ?? AppTheme.drawerTextColor.value; + Config.drawerHighlightItemColor = + settings['DrawerHighlightItemColor'] as int? ?? + AppTheme.drawerHighlightItemColor.value; Config.mainToolbarBackgroundColor = - settings['MainToolbarBackgroundColor'] ?? + settings['MainToolbarBackgroundColor'] as int? ?? AppTheme.mainToolbarBackgroundColor.value; - Config.mainToolbarIconColor = - settings['MainToolbarIconColor'] ?? AppTheme.mainToolbarIconColor.value; + Config.mainToolbarIconColor = settings['MainToolbarIconColor'] as int? ?? + AppTheme.mainToolbarIconColor.value; Config.navigationToolbarBackgroundColor = - settings['NavigationToolbarBackgroundColor'] ?? + settings['NavigationToolbarBackgroundColor'] as int? ?? AppTheme.navigationToolbarBackgroundColor.value; Config.navigationToolbarIconColor = - settings['NavigationToolbarIconColor'] ?? + settings['NavigationToolbarIconColor'] as int? ?? AppTheme.navigationToolbarIconColor.value; // Rules - rule.piecesCount = Config.piecesCount = - settings['PiecesCount'] ?? (specialCountryAndRegion == "Iran" ? 12 : 9); - rule.flyPieceCount = Config.flyPieceCount = settings['FlyPieceCount'] ?? 3; + rule.piecesCount = Config.piecesCount = settings['PiecesCount'] as int? ?? + (specialCountryAndRegion == "Iran" ? 12 : 9); + rule.flyPieceCount = + Config.flyPieceCount = settings['FlyPieceCount'] as int? ?? 3; rule.piecesAtLeastCount = - Config.piecesAtLeastCount = settings['PiecesAtLeastCount'] ?? 3; + Config.piecesAtLeastCount = settings['PiecesAtLeastCount'] as int? ?? 3; rule.hasDiagonalLines = Config.hasDiagonalLines = - settings['HasDiagonalLines'] ?? - (specialCountryAndRegion == "Iran" ? true : false); - rule.hasBannedLocations = - Config.hasBannedLocations = settings['HasBannedLocations'] ?? false; + settings['HasDiagonalLines'] as bool? ?? + (specialCountryAndRegion == "Iran"); + rule.hasBannedLocations = Config.hasBannedLocations = + settings['HasBannedLocations'] as bool? ?? false; rule.mayMoveInPlacingPhase = Config.mayMoveInPlacingPhase = - settings['MayMoveInPlacingPhase'] ?? false; - rule.isDefenderMoveFirst = - Config.isDefenderMoveFirst = settings['IsDefenderMoveFirst'] ?? false; - rule.mayRemoveMultiple = - Config.mayRemoveMultiple = settings['MayRemoveMultiple'] ?? false; + settings['MayMoveInPlacingPhase'] as bool? ?? false; + rule.isDefenderMoveFirst = Config.isDefenderMoveFirst = + settings['IsDefenderMoveFirst'] as bool? ?? false; + rule.mayRemoveMultiple = Config.mayRemoveMultiple = + settings['MayRemoveMultiple'] as bool? ?? false; rule.mayRemoveFromMillsAlways = Config.mayRemoveFromMillsAlways = - settings['MayRemoveFromMillsAlways'] ?? false; - rule.mayOnlyRemoveUnplacedPieceInPlacingPhase = - Config.mayOnlyRemoveUnplacedPieceInPlacingPhase = - settings['MayOnlyRemoveUnplacedPieceInPlacingPhase'] ?? false; + settings['MayRemoveFromMillsAlways'] as bool? ?? false; + rule.mayOnlyRemoveUnplacedPieceInPlacingPhase = Config + .mayOnlyRemoveUnplacedPieceInPlacingPhase = + settings['MayOnlyRemoveUnplacedPieceInPlacingPhase'] as bool? ?? false; rule.isWhiteLoseButNotDrawWhenBoardFull = Config.isWhiteLoseButNotDrawWhenBoardFull = - settings['IsWhiteLoseButNotDrawWhenBoardFull'] ?? true; + settings['IsWhiteLoseButNotDrawWhenBoardFull'] as bool? ?? true; rule.isLoseButNotChangeSideWhenNoWay = Config.isLoseButNotChangeSideWhenNoWay = - settings['IsLoseButNotChangeSideWhenNoWay'] ?? true; - rule.mayFly = Config.mayFly = settings['MayFly'] ?? true; - rule.nMoveRule = Config.nMoveRule = settings['NMoveRule'] ?? 100; + settings['IsLoseButNotChangeSideWhenNoWay'] as bool? ?? true; + rule.mayFly = Config.mayFly = settings['MayFly'] as bool? ?? true; + rule.nMoveRule = Config.nMoveRule = settings['NMoveRule'] as int? ?? 100; rule.endgameNMoveRule = - Config.endgameNMoveRule = settings['EndgameNMoveRule'] ?? 100; + Config.endgameNMoveRule = settings['EndgameNMoveRule'] as int? ?? 100; rule.threefoldRepetitionRule = Config.threefoldRepetitionRule = - settings['ThreefoldRepetitionRule'] ?? true; + settings['ThreefoldRepetitionRule'] as bool? ?? true; settingsLoaded = true; debugPrint("[config] Loading settings done!"); diff --git a/src/ui/flutter_app/lib/common/constants.dart b/src/ui/flutter_app/lib/common/constants.dart index 9e30601a..5f094e5a 100644 --- a/src/ui/flutter_app/lib/common/constants.dart +++ b/src/ui/flutter_app/lib/common/constants.dart @@ -19,6 +19,7 @@ import 'dart:ui'; class Constants { + const Constants._(); static String appName = "Mill"; static String authorAccount = "calcitem"; static String projectName = "Sanmill"; @@ -53,8 +54,8 @@ class Constants { static String githubEulaURL = "$githubRepoWiKiURL/EULA"; static String giteeEulaURL = "$giteeRepoWiKiURL/EULA_zh"; - static String githubSourceCodeURL = "$githubRepoURL"; - static String giteeSourceCodeURL = "$giteeRepoURL"; + static String githubSourceCodeURL = githubRepoURL; + static String giteeSourceCodeURL = giteeRepoURL; static String githubThirdPartyNoticesURL = "$githubRepoWiKiURL/third-party_notices"; diff --git a/src/ui/flutter_app/lib/common/settings.dart b/src/ui/flutter_app/lib/common/settings.dart index fb6ecd81..9d115aec 100644 --- a/src/ui/flutter_app/lib/common/settings.dart +++ b/src/ui/flutter_app/lib/common/settings.dart @@ -30,19 +30,20 @@ class Settings { late File _file; Map? _values = {}; - static instance() async { + // TODO: add constructor + static Future instance() async { if (_instance == null) { _instance = Settings(); await _instance!._load(settingsFileName); debugPrint("[settings] $settingsFileName loaded."); } - return _instance; + return _instance!; } - operator [](String key) => _values![key]; + dynamic operator [](String key) => _values![key]; - operator []=(String key, dynamic value) => _values![key] = value; + void operator []=(String key, dynamic value) => _values![key] = value; Future commit() async { _file.create(recursive: true); @@ -58,7 +59,7 @@ class Settings { Future _load(String fileName) async { // TODO: main() ExternalStorage // var docDir = await getExternalStorageDirectory(); - var docDir = await getApplicationDocumentsDirectory(); + final docDir = await getApplicationDocumentsDirectory(); _file = File('${docDir.path}/$fileName'); @@ -66,7 +67,7 @@ class Settings { try { final contents = await _file.readAsString(); - _values = jsonDecode(contents); + _values = jsonDecode(contents) as Map?; debugPrint(_values.toString()); } catch (e) { debugPrint(e.toString()); diff --git a/src/ui/flutter_app/lib/engine/native_engine.dart b/src/ui/flutter_app/lib/engine/native_engine.dart index 72fc97dc..f4459297 100644 --- a/src/ui/flutter_app/lib/engine/native_engine.dart +++ b/src/ui/flutter_app/lib/engine/native_engine.dart @@ -27,12 +27,13 @@ import 'package:sanmill/mill/types.dart'; import 'engine.dart'; class NativeEngine extends Engine { - static const platform = const MethodChannel('com.calcitem.sanmill/engine'); + static const platform = MethodChannel('com.calcitem.sanmill/engine'); bool isActive = false; + @override Future startup() async { await platform.invokeMethod('startup'); - await waitResponse(['uciok'], sleep: 100, times: 0); + await waitResponse(['uciok']); } Future send(String command) async { @@ -41,20 +42,21 @@ class NativeEngine extends Engine { } Future read() async { - return await platform.invokeMethod('read'); + return platform.invokeMethod('read'); } + @override Future shutdown() async { isActive = false; await platform.invokeMethod('shutdown'); } Future isReady() async { - return await platform.invokeMethod('isReady'); + return platform.invokeMethod('isReady'); } - FutureOr isThinking() async { - return await platform.invokeMethod('isThinking'); + Future isThinking() async { + return platform.invokeMethod('isThinking') as Future; } @override @@ -91,8 +93,11 @@ class NativeEngine extends Engine { return EngineResponse('timeout'); } - Future waitResponse(List prefixes, - {sleep = 100, times = 0}) async { + Future waitResponse( + List prefixes, { + int sleep = 100, + int times = 0, + }) async { var timeLimit = Config.developerMode ? 100 : 6000; if (Config.moveTime > 0) { @@ -103,7 +108,7 @@ class NativeEngine extends Engine { if (times > timeLimit) { debugPrint("[engine] Timeout. sleep = $sleep, times = $times"); if (Config.developerMode && isActive) { - throw ("Exception: waitResponse timeout."); + throw "Exception: waitResponse timeout."; } return ''; } @@ -111,7 +116,7 @@ class NativeEngine extends Engine { final response = await read(); if (response != null) { - for (var prefix in prefixes) { + for (final prefix in prefixes) { if (response.startsWith(prefix)) { return response; } else { @@ -132,50 +137,85 @@ class NativeEngine extends Engine { await send('stop'); } + @override Future setOptions(BuildContext context) async { if (Config.settingsLoaded == false) { debugPrint("[engine] Settings is not loaded yet, now load settings..."); await Config.loadSettings(); } - await send('setoption name DeveloperMode value ${Config.developerMode}'); - await send('setoption name Algorithm value ${Config.algorithm}'); await send( - 'setoption name DrawOnHumanExperience value ${Config.drawOnHumanExperience}'); + 'setoption name DeveloperMode value ${Config.developerMode}', + ); await send( - 'setoption name ConsiderMobility value ${Config.considerMobility}'); - await send('setoption name SkillLevel value ${Config.skillLevel}'); - await send('setoption name MoveTime value ${Config.moveTime}'); - await send('setoption name AiIsLazy value ${Config.aiIsLazy}'); - await send('setoption name Shuffling value ${Config.shufflingEnabled}'); - await send('setoption name PiecesCount value ${Config.piecesCount}'); - await send('setoption name FlyPieceCount value ${Config.flyPieceCount}'); + 'setoption name Algorithm value ${Config.algorithm}', + ); await send( - 'setoption name PiecesAtLeastCount value ${Config.piecesAtLeastCount}'); + 'setoption name DrawOnHumanExperience value ${Config.drawOnHumanExperience}', + ); await send( - 'setoption name HasDiagonalLines value ${Config.hasDiagonalLines}'); + 'setoption name ConsiderMobility value ${Config.considerMobility}', + ); await send( - 'setoption name HasBannedLocations value ${Config.hasBannedLocations}'); + 'setoption name SkillLevel value ${Config.skillLevel}', + ); await send( - 'setoption name MayMoveInPlacingPhase value ${Config.mayMoveInPlacingPhase}'); + 'setoption name MoveTime value ${Config.moveTime}', + ); await send( - 'setoption name IsDefenderMoveFirst value ${Config.isDefenderMoveFirst}'); + 'setoption name AiIsLazy value ${Config.aiIsLazy}', + ); await send( - 'setoption name MayRemoveMultiple value ${Config.mayRemoveMultiple}'); + 'setoption name Shuffling value ${Config.shufflingEnabled}', + ); await send( - 'setoption name MayRemoveFromMillsAlways value ${Config.mayRemoveFromMillsAlways}'); + 'setoption name PiecesCount value ${Config.piecesCount}', + ); await send( - 'setoption name MayOnlyRemoveUnplacedPieceInPlacingPhase value ${Config.mayOnlyRemoveUnplacedPieceInPlacingPhase}'); + 'setoption name FlyPieceCount value ${Config.flyPieceCount}', + ); await send( - 'setoption name IsWhiteLoseButNotDrawWhenBoardFull value ${Config.isWhiteLoseButNotDrawWhenBoardFull}'); + 'setoption name PiecesAtLeastCount value ${Config.piecesAtLeastCount}', + ); await send( - 'setoption name IsLoseButNotChangeSideWhenNoWay value ${Config.isLoseButNotChangeSideWhenNoWay}'); - await send('setoption name MayFly value ${Config.mayFly}'); - await send('setoption name NMoveRule value ${Config.nMoveRule}'); + 'setoption name HasDiagonalLines value ${Config.hasDiagonalLines}', + ); await send( - 'setoption name EndgameNMoveRule value ${Config.endgameNMoveRule}'); + 'setoption name HasBannedLocations value ${Config.hasBannedLocations}', + ); await send( - 'setoption name ThreefoldRepetitionRule value ${Config.threefoldRepetitionRule}'); + 'setoption name MayMoveInPlacingPhase value ${Config.mayMoveInPlacingPhase}', + ); + await send( + 'setoption name IsDefenderMoveFirst value ${Config.isDefenderMoveFirst}', + ); + await send( + 'setoption name MayRemoveMultiple value ${Config.mayRemoveMultiple}', + ); + await send( + 'setoption name MayRemoveFromMillsAlways value ${Config.mayRemoveFromMillsAlways}', + ); + await send( + 'setoption name MayOnlyRemoveUnplacedPieceInPlacingPhase value ${Config.mayOnlyRemoveUnplacedPieceInPlacingPhase}', + ); + await send( + 'setoption name IsWhiteLoseButNotDrawWhenBoardFull value ${Config.isWhiteLoseButNotDrawWhenBoardFull}', + ); + await send( + 'setoption name IsLoseButNotChangeSideWhenNoWay value ${Config.isLoseButNotChangeSideWhenNoWay}', + ); + await send( + 'setoption name MayFly value ${Config.mayFly}', + ); + await send( + 'setoption name NMoveRule value ${Config.nMoveRule}', + ); + await send( + 'setoption name EndgameNMoveRule value ${Config.endgameNMoveRule}', + ); + await send( + 'setoption name ThreefoldRepetitionRule value ${Config.threefoldRepetitionRule}', + ); } String getPositionFen(Position position) { diff --git a/src/ui/flutter_app/lib/l10n/resources.dart b/src/ui/flutter_app/lib/l10n/resources.dart index 727c9e03..9ff69dff 100644 --- a/src/ui/flutter_app/lib/l10n/resources.dart +++ b/src/ui/flutter_app/lib/l10n/resources.dart @@ -505,7 +505,7 @@ class Resources { } Strings get strings { - Strings? ret = languageCodeToStrings[languageCode]; + final Strings? ret = languageCodeToStrings[languageCode]; if (ret == null) { return EnglishStrings(); @@ -519,8 +519,9 @@ class Resources { } } -setLanguage(BuildContext context, var callback) async { - var languageColumn = Column( +Future setLanguage( + BuildContext context, Function(String?)? callback) async { + final languageColumn = Column( mainAxisSize: MainAxisSize.min, children: [ RadioListTile( @@ -530,7 +531,7 @@ setLanguage(BuildContext context, var callback) async { value: Constants.defaultLanguageCodeName, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), for (var i in languageCodeToStrings.keys) RadioListTile( activeColor: AppTheme.switchListTileActiveColor, @@ -563,7 +564,7 @@ enum Bidirectionality { } Bidirectionality getBidirectionality(BuildContext context) { - Locale currentLocale = Localizations.localeOf(context); + final Locale currentLocale = Localizations.localeOf(context); if (currentLocale.languageCode == "ar" || currentLocale.languageCode == "fa" || currentLocale.languageCode == "he" || @@ -578,8 +579,8 @@ Bidirectionality getBidirectionality(BuildContext context) { String specialCountryAndRegion = ""; -setSpecialCountryAndRegion(BuildContext context) { - Locale currentLocale = Localizations.localeOf(context); +void setSpecialCountryAndRegion(BuildContext context) { + final Locale currentLocale = Localizations.localeOf(context); switch (currentLocale.countryCode) { case "IR": diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index 5e4e7e7f..d1a32443 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -37,18 +37,19 @@ import 'package:sanmill/widgets/navigation_home_screen.dart'; import 'services/audios.dart'; Future main() async { - var catcher = Catcher( - rootWidget: BetterFeedback( - child: SanmillApp(), - //localeOverride: Locale(Resources.of().languageCode), - ), - ensureInitialized: true); + final catcher = Catcher( + rootWidget: BetterFeedback( + child: SanmillApp(), + //localeOverride: Locale(Resources.of().languageCode), + ), + ensureInitialized: true, + ); String externalDirStr; try { - Directory? externalDir = await getExternalStorageDirectory(); + final Directory? externalDir = await getExternalStorageDirectory(); if (externalDir != null) { - externalDirStr = externalDir.path.toString(); + externalDirStr = externalDir.path; } else { externalDirStr = "."; } @@ -56,12 +57,11 @@ Future main() async { debugPrint(e.toString()); externalDirStr = "."; } - String path = externalDirStr + "/" + Constants.crashLogsFileName; + final String path = "$externalDirStr/${Constants.crashLogsFileName}"; debugPrint("[env] ExternalStorageDirectory: $externalDirStr"); - String recipients = Constants.recipients; + final String recipients = Constants.recipients; - CatcherOptions debugOptions = - CatcherOptions(PageReportMode(showStackTrace: true), [ + final CatcherOptions debugOptions = CatcherOptions(PageReportMode(), [ ConsoleHandler(), FileHandler(File(path), printLogs: true), EmailManualHandler([recipients], printLogs: true) @@ -71,14 +71,12 @@ Future main() async { /// Release configuration. /// Same as above, but once user accepts dialog, /// user will be prompted to send email with crash to support. - CatcherOptions releaseOptions = - CatcherOptions(PageReportMode(showStackTrace: true), [ + final CatcherOptions releaseOptions = CatcherOptions(PageReportMode(), [ FileHandler(File(path), printLogs: true), EmailManualHandler([recipients], printLogs: true) ]); - CatcherOptions profileOptions = - CatcherOptions(PageReportMode(showStackTrace: true), [ + final CatcherOptions profileOptions = CatcherOptions(PageReportMode(), [ ConsoleHandler(), FileHandler(File(path), printLogs: true), EmailManualHandler([recipients], printLogs: true) @@ -100,7 +98,7 @@ Future main() async { if (Platform.isAndroid && isLargeScreen()) { SystemChrome.setSystemUIOverlayStyle( - SystemUiOverlayStyle( + const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarBrightness: Brightness.light, statusBarIconBrightness: Brightness.dark, @@ -111,7 +109,7 @@ Future main() async { } if (isSmallScreen()) { - SystemChrome.setEnabledSystemUIOverlays([]); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); } } @@ -146,7 +144,7 @@ class _SanmillAppState extends State { navigatorKey: Catcher.navigatorKey, key: globalScaffoldKey, navigatorObservers: [routeObserver], - localizationsDelegates: [ + localizationsDelegates: const [ // ... app-specific localization delegate[s] here S.delegate, GlobalMaterialLocalizations.delegate, @@ -159,10 +157,10 @@ class _SanmillAppState extends State { debugShowCheckedModeBanner: false, home: Scaffold( body: DoubleBackToCloseApp( - child: NavigationHomeScreen(), snackBar: SnackBar( content: Text(Resources.of().strings.tapBackAgainToLeave), ), + child: NavigationHomeScreen(), ), ), /* diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index 1a172ca9..2804caf4 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -30,27 +30,27 @@ class Game { static Game? _instance; final String tag = "[game]"; - static get instance { - _instance ??= Game(); - return _instance; + // TODO: use constructor + static Game get instance { + return _instance ??= Game(); } - init() { + void init() { _position = Position(); - _focusIndex = _blurIndex = invalidIndex; + focusIndex = blurIndex = invalidIndex; } - start() { + void start() { position.reset(); setWhoIsAi(engineType); } - newGame() { + void newGame() { position.phase = Phase.ready; start(); position.init(); - _focusIndex = _blurIndex = invalidIndex; + focusIndex = blurIndex = invalidIndex; moveHistory = [""]; sideToMove = PieceColor.white; } @@ -64,16 +64,10 @@ class Game { List moveHistory = [""]; Position _position = Position(); - get position => _position; + Position get position => _position; - int _focusIndex = invalidIndex; - int _blurIndex = invalidIndex; - - get focusIndex => _focusIndex; - set focusIndex(index) => _focusIndex = index; - - get blurIndex => _blurIndex; - set blurIndex(index) => _blurIndex = index; + int focusIndex = invalidIndex; + int blurIndex = invalidIndex; Map isSearching = { PieceColor.white: false, @@ -119,9 +113,9 @@ class Game { ); } - select(int pos) { - _focusIndex = pos; - _blurIndex = invalidIndex; + void select(int pos) { + focusIndex = pos; + blurIndex = invalidIndex; } bool doMove(String move) { @@ -144,42 +138,23 @@ class Game { return true; } - printStat() { + void printStat() { double whiteWinRate = 0; double blackWinRate = 0; double drawRate = 0; - int total = position.score[PieceColor.white] + - position.score[PieceColor.black] + - position.score[PieceColor.draw] ?? - 0; + final int total = position.score[PieceColor.white]! + + position.score[PieceColor.black]! + + position.score[PieceColor.draw]!; - if (total == 0) { - whiteWinRate = 0; - blackWinRate = 0; - drawRate = 0; - } else { - whiteWinRate = position.score[PieceColor.white] * 100 / total ?? 0; - blackWinRate = position.score[PieceColor.black] * 100 / total ?? 0; - drawRate = position.score[PieceColor.draw] * 100 / total ?? 0; + if (total != 0) { + whiteWinRate = position.score[PieceColor.white]! * 100 / total; + blackWinRate = position.score[PieceColor.black]! * 100 / total; + drawRate = position.score[PieceColor.draw]! * 100 / total; } - String scoreInfo = "Score: " + - position.score[PieceColor.white].toString() + - " : " + - position.score[PieceColor.black].toString() + - " : " + - position.score[PieceColor.draw].toString() + - "\ttotal: " + - total.toString() + - "\n" + - whiteWinRate.toString() + - "% : " + - blackWinRate.toString() + - "% : " + - drawRate.toString() + - "%" + - "\n"; + final String scoreInfo = + "Score: ${position.score[PieceColor.white]} : ${position.score[PieceColor.black]} : ${position.score[PieceColor.draw]}\ttotal: $total\n$whiteWinRate% : $blackWinRate% : $drawRate%\n"; debugPrint("$tag $scoreInfo"); } diff --git a/src/ui/flutter_app/lib/mill/mills.dart b/src/ui/flutter_app/lib/mill/mills.dart index 513941d6..19cbee5e 100644 --- a/src/ui/flutter_app/lib/mill/mills.dart +++ b/src/ui/flutter_app/lib/mill/mills.dart @@ -1,4 +1,4 @@ -/* +/* This file is part of Sanmill. Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file) @@ -20,6 +20,8 @@ import 'position.dart'; import 'rule.dart'; class Mills { + const Mills._(); + static void adjacentSquaresInit() { // Note: Not follow order of MoveDirection array const adjacentSquares = [ @@ -31,7 +33,6 @@ class Mills { /* 5 */ [0, 0, 0, 0], /* 6 */ [0, 0, 0, 0], /* 7 */ [0, 0, 0, 0], - /* 8 */ [16, 9, 15, 0], /* 9 */ [10, 8, 0, 0], /* 10 */ [18, 11, 9, 0], @@ -40,7 +41,6 @@ class Mills { /* 13 */ [14, 12, 0, 0], /* 14 */ [22, 15, 13, 0], /* 15 */ [8, 14, 0, 0], - /* 16 */ [8, 24, 17, 23], /* 17 */ [18, 16, 0, 0], /* 18 */ [10, 26, 19, 17], @@ -49,7 +49,6 @@ class Mills { /* 21 */ [22, 20, 0, 0], /* 22 */ [14, 30, 23, 21], /* 23 */ [16, 22, 0, 0], - /* 24 */ [16, 25, 31, 0], /* 25 */ [26, 24, 0, 0], /* 26 */ [18, 27, 25, 0], @@ -58,7 +57,6 @@ class Mills { /* 29 */ [30, 28, 0, 0], /* 30 */ [22, 31, 29, 0], /* 31 */ [24, 30, 0, 0], - /* 32 */ [0, 0, 0, 0], /* 33 */ [0, 0, 0, 0], /* 34 */ [0, 0, 0, 0], @@ -78,7 +76,6 @@ class Mills { /* 5 */ [0, 0, 0, 0], /* 6 */ [0, 0, 0, 0], /* 7 */ [0, 0, 0, 0], - /* 8 */ [9, 15, 16, 0], /* 9 */ [17, 8, 10, 0], /* 10 */ [9, 11, 18, 0], @@ -87,7 +84,6 @@ class Mills { /* 13 */ [21, 12, 14, 0], /* 14 */ [13, 15, 22, 0], /* 15 */ [23, 8, 14, 0], - /* 16 */ [17, 23, 8, 24], /* 17 */ [9, 25, 16, 18], /* 18 */ [17, 19, 10, 26], @@ -96,7 +92,6 @@ class Mills { /* 21 */ [13, 29, 20, 22], /* 22 */ [21, 23, 14, 30], /* 23 */ [15, 31, 16, 22], - /* 24 */ [25, 31, 16, 0], /* 25 */ [17, 24, 26, 0], /* 26 */ [25, 27, 18, 0], @@ -105,7 +100,6 @@ class Mills { /* 29 */ [21, 28, 30, 0], /* 30 */ [29, 31, 22, 0], /* 31 */ [23, 24, 30, 0], - /* 32 */ [0, 0, 0, 0], /* 33 */ [0, 0, 0, 0], /* 34 */ [0, 0, 0, 0], @@ -165,7 +159,6 @@ class Mills { [0, 0], [0, 0] ], - /* 8 */ [ [16, 24], [9, 15], @@ -206,7 +199,6 @@ class Mills { [13, 14], [8, 9] ], - /* 16 */ [ [8, 24], [17, 23], @@ -247,7 +239,6 @@ class Mills { [21, 22], [16, 17] ], - /* 24 */ [ [8, 16], [25, 31], @@ -288,7 +279,6 @@ class Mills { [29, 30], [24, 25] ], - /* 32 */ [ [0, 0], [0, 0], @@ -372,7 +362,6 @@ class Mills { [0, 0], [0, 0] ], - /* 8 */ [ [16, 24], [9, 15], @@ -413,7 +402,6 @@ class Mills { [13, 14], [8, 9] ], - /* 16 */ [ [8, 24], [17, 23], @@ -454,7 +442,6 @@ class Mills { [21, 22], [16, 17] ], - /* 24 */ [ [8, 16], [25, 31], @@ -495,7 +482,6 @@ class Mills { [29, 30], [24, 25] ], - /* 32 */ [ [0, 0], [0, 0], diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index b159671f..122b07dc 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -82,17 +82,25 @@ class Position { String? record; - static late var millTable; - static late var adjacentSquares; + static late List>> millTable; + static late List> adjacentSquares; late Move move; + Position() { + init(); + } + Position.clone(Position other) { _grid = []; - other._grid.forEach((piece) => _grid.add(piece)); + for (final piece in other._grid) { + _grid.add(piece); + } board = []; - other.board.forEach((piece) => board.add(piece)); + for (final piece in other.board) { + board.add(piece); + } recorder = other.recorder; @@ -139,7 +147,7 @@ class Position { return false; } - init() { + void init() { for (var i = 0; i < _grid.length; i++) { _grid[i] = Piece.noPiece; } @@ -156,95 +164,83 @@ class Position { recorder = GameRecorder(lastPositionWithRemove: fen()); } - Position() { - init(); - } - /// fen() returns a FEN representation of the position. String fen() { - var ss = ''; + final buffer = StringBuffer(); // Piece placement data for (var file = 1; file <= fileNumber; file++) { for (var rank = 1; rank <= rankNumber; rank++) { final piece = pieceOnGrid(squareToIndex[makeSquare(file, rank)]!); - ss += piece; + buffer.write(piece); } - if (file == 3) - ss += ' '; - else - ss += '/'; + if (file == 3) { + buffer.write(' '); + } else { + buffer.write('/'); + } } // Active color - ss += _sideToMove == PieceColor.white ? "w" : "b"; + buffer.write(_sideToMove == PieceColor.white ? "w" : "b"); - ss += " "; + buffer.write(" "); // Phrase switch (phase) { case Phase.none: - ss += "n"; + buffer.write("n"); break; case Phase.ready: - ss += "r"; + buffer.write("r"); break; case Phase.placing: - ss += "p"; + buffer.write("p"); break; case Phase.moving: - ss += "m"; + buffer.write("m"); break; case Phase.gameOver: - ss += "o"; + buffer.write("o"); break; default: - ss += "?"; + buffer.write("?"); break; } - ss += " "; + buffer.write(" "); // Action switch (action) { case Act.place: - ss += "p"; + buffer.write("p"); break; case Act.select: - ss += "s"; + buffer.write("s"); break; case Act.remove: - ss += "r"; + buffer.write("r"); break; default: - ss += "?"; + buffer.write("?"); break; } - ss += " "; + buffer.write(" "); - ss += pieceOnBoardCount[PieceColor.white].toString() + - " " + - pieceInHandCount[PieceColor.white].toString() + - " " + - pieceOnBoardCount[PieceColor.black].toString() + - " " + - pieceInHandCount[PieceColor.black].toString() + - " " + - pieceToRemoveCount.toString() + - " "; + buffer.write( + "${pieceOnBoardCount[PieceColor.white]} ${pieceInHandCount[PieceColor.white]} ${pieceOnBoardCount[PieceColor.black]} ${pieceInHandCount[PieceColor.black]} $pieceToRemoveCount ", + ); - int sideIsBlack = _sideToMove == PieceColor.black ? 1 : 0; + final int sideIsBlack = _sideToMove == PieceColor.black ? 1 : 0; - ss += st.rule50.toString() + - " " + - (1 + (gamePly - sideIsBlack) ~/ 2).toString(); + buffer.write("${st.rule50} ${1 + (gamePly - sideIsBlack) ~/ 2}"); //debugPrint("FEN is $ss"); - return ss; + return buffer.toString(); } /// Position::legal() tests whether a pseudo-legal move is legal @@ -252,7 +248,7 @@ class Position { bool legal(Move move) { if (!isOk(move.from) || !isOk(move.to)) return false; - String us = _sideToMove; + final String us = _sideToMove; if (move.from == move.to) { debugPrint("[position] Move $move.move from == to"); @@ -312,11 +308,11 @@ class Position { bool ret = false; - Move m = Move(move); + final Move m = Move(move); switch (m.type) { case MoveType.remove: - ret = (removePiece(m.to) == 0); + ret = removePiece(m.to) == 0; if (ret) { // Reset rule 50 counter st.rule50 = 0; @@ -350,13 +346,15 @@ class Position { ++st.pliesFromNull; if (record != null && record!.length > "-(1,2)".length) { - if (posKeyHistory.length == 0 || - (posKeyHistory.length > 0 && + if (posKeyHistory.isEmpty || + (posKeyHistory.isNotEmpty && st.key != posKeyHistory[posKeyHistory.length - 1])) { posKeyHistory.add(st.key); if (rule.threefoldRepetitionRule && hasGameCycle()) { setGameOver( - PieceColor.draw, GameOverReason.drawReasonThreefoldRepetition); + PieceColor.draw, + GameOverReason.drawReasonThreefoldRepetition, + ); } } } else { @@ -377,7 +375,7 @@ class Position { } } - int size = ss.length; + final int size = ss.length; for (int i = size - 1; i >= 0; i--) { if (ss[i].move.type == MoveType.remove) { @@ -395,7 +393,7 @@ class Position { bool hasGameCycle() { int repetition = 0; // Note: Engine is global val - for (var i in posKeyHistory) { + for (final i in posKeyHistory) { if (st.key == i) { repetition++; if (repetition == 3) { @@ -465,7 +463,7 @@ class Position { bool putPiece(int s) { var piece = Piece.noPiece; - var us = _sideToMove; + final us = _sideToMove; if (phase == Phase.gameOver || action != Act.place || @@ -491,17 +489,19 @@ class Position { _grid[squareToIndex[s]!] = piece; board[s] = piece; - record = "(" + fileOf(s).toString() + "," + rankOf(s).toString() + ")"; + record = "(${fileOf(s)},${rankOf(s)})"; updateKey(s); currentSquare = s; - int n = millsCount(currentSquare); + final int n = millsCount(currentSquare); if (n == 0) { - assert(pieceInHandCount[PieceColor.white]! >= 0 && - pieceInHandCount[PieceColor.black]! >= 0); + assert( + pieceInHandCount[PieceColor.white]! >= 0 && + pieceInHandCount[PieceColor.black]! >= 0, + ); if (pieceInHandCount[PieceColor.white] == 0 && pieceInHandCount[PieceColor.black] == 0) { @@ -588,15 +588,8 @@ class Position { } } - record = "(" + - fileOf(currentSquare).toString() + - "," + - rankOf(currentSquare).toString() + - ")->(" + - fileOf(s).toString() + - "," + - rankOf(s).toString() + - ")"; + record = + "(${fileOf(currentSquare)},${rankOf(currentSquare)})->(${fileOf(s)},${rankOf(s)})"; st.rule50++; @@ -608,7 +601,7 @@ class Position { _grid[squareToIndex[currentSquare]!] = Piece.noPiece; currentSquare = s; - int n = millsCount(currentSquare); + final int n = millsCount(currentSquare); // midgame if (n == 0) { @@ -664,7 +657,7 @@ class Position { board[s] = _grid[squareToIndex[s]!] = Piece.noPiece; } - record = "-(" + fileOf(s).toString() + "," + rankOf(s).toString() + ")"; + record = "-(${fileOf(s)},${rankOf(s)})"; st.rule50 = 0; // TODO: Need to move out? if (pieceOnBoardCount[them] != null) { @@ -728,7 +721,7 @@ class Position { currentSquare = sq; action = Act.place; - Game.instance.blurIndex = squareToIndex[sq]; + Game.instance.blurIndex = squareToIndex[sq]!; return 0; } @@ -815,7 +808,9 @@ class Position { if (phase == Phase.moving && action == Act.select && isAllSurrounded()) { if (rule.isLoseButNotChangeSideWhenNoWay) { setGameOver( - PieceColor.opponent(sideToMove()), GameOverReason.loseReasonNoWay); + PieceColor.opponent(sideToMove()), + GameOverReason.loseReasonNoWay, + ); return true; } else { changeSideToMove(); // TODO: Need? @@ -867,7 +862,7 @@ class Position { } int updateKey(int s) { - String pieceType = colorOn(s); + final String pieceType = colorOn(s); st.key ^= Zobrist.psq[pieceColorIndex[pieceType]!][s]; @@ -881,7 +876,7 @@ class Position { int updateKeyMisc() { st.key = st.key << Zobrist.KEY_MISC_BIT >> Zobrist.KEY_MISC_BIT; - st.key |= (pieceToRemoveCount) << (32 - Zobrist.KEY_MISC_BIT); + st.key |= pieceToRemoveCount << (32 - Zobrist.KEY_MISC_BIT); return st.key; } @@ -922,10 +917,10 @@ class Position { int millsCount(int s) { int n = 0; - List idx = [0, 0, 0]; + final List idx = [0, 0, 0]; int min = 0; int? temp = 0; - String m = colorOn(s); + final String m = colorOn(s); for (int i = 0; i < idx.length; i++) { idx[0] = s; @@ -996,7 +991,7 @@ class Position { for (int d = moveDirectionBegin; d < moveDirectionNumber; d++) { moveSquare = adjacentSquares[s][d]; - if (moveSquare != 0 && board[moveSquare!] == Piece.noPiece) { + if (moveSquare != 0 && board[moveSquare] == Piece.noPiece) { return false; } } @@ -1007,10 +1002,10 @@ class Position { bool isStarSquare(int s) { if (rule.hasDiagonalLines == true) { - return (s == 17 || s == 19 || s == 21 || s == 23); + return s == 17 || s == 19 || s == 21 || s == 23; } - return (s == 16 || s == 18 || s == 20 || s == 22); + return s == 16 || s == 18 || s == 20 || s == 22; } /////////////////////////////////////////////////////////////////////////////// @@ -1073,7 +1068,7 @@ class Position { for (int f = 1; f < fileExNumber; f++) { for (int r = 0; r < rankNumber; r++) { - int s = f * rankNumber + r; + final int s = f * rankNumber + r; if (board[s] == Piece.whiteStone) { if (pieceOnBoardCount[PieceColor.white] != null) { pieceOnBoardCount[PieceColor.white] = @@ -1107,7 +1102,7 @@ class Position { return "null"; } - var history = recorder!.getHistory(); + final history = recorder!.history; if (moveIndex < -1 || history.length <= moveIndex) { debugPrint("[goto] moveIndex is out of range."); return "out-of-range"; @@ -1119,21 +1114,21 @@ class Position { } // Backup context - var engineTypeBackup = Game.instance.engineType; + final engineTypeBackup = Game.instance.engineType; Game.instance.engineType = EngineType.humanVsHuman; Game.instance.setWhoIsAi(EngineType.humanVsHuman); - var historyBack = history; + final historyBack = history; - await Game.instance.newGame(); + Game.instance.newGame(); if (moveIndex == -1) { errString = ""; } for (var i = 0; i <= moveIndex; i++) { - if (Game.instance.doMove(history[i].move) == false) { + if (Game.instance.doMove(history[i].move!) == false) { errString = history[i].move!; break; } @@ -1145,7 +1140,7 @@ class Position { // Restore context Game.instance.engineType = engineTypeBackup; Game.instance.setWhoIsAi(engineTypeBackup); - recorder!.setHistory(historyBack); + recorder!.history = historyBack; recorder!.cur = moveIndex; return errString; @@ -1172,12 +1167,12 @@ class Position { } Future stepForwardAll() async { - return _gotoHistory(recorder!.getHistory().length - 1); + return _gotoHistory(recorder!.history.length - 1); } String movesSinceLastRemove() { int? i = 0; - String moves = ""; + final buffer = StringBuffer(); int posAfterLastRemove = 0; //debugPrint("recorder.movesCount = ${recorder.movesCount}"); @@ -1194,25 +1189,26 @@ class Position { //debugPrint("[movesSinceLastRemove] posAfterLastRemove = $posAfterLastRemove"); for (int i = posAfterLastRemove; i < recorder!.movesCount; i++) { - moves += " ${recorder!.moveAt(i).move}"; + buffer.write(" ${recorder!.moveAt(i).move}"); } - //print("moves = $moves"); + final String moves = buffer.toString(); + //debugPrint("moves = $moves"); - var idx = moves.indexOf('-('); + final idx = moves.indexOf('-('); if (idx != -1) { //debugPrint("moves[$idx] is -("); assert(false); } - return moves.length > 0 ? moves.substring(1) : ''; + return moves.isNotEmpty ? moves.substring(1) : ''; } - get moveHistoryText => recorder!.buildMoveHistoryText(); + String get moveHistoryText => recorder!.buildMoveHistoryText(); - get side => _sideToMove; + String get side => _sideToMove; - get lastMove => recorder!.last; + Move? get lastMove => recorder!.last; - get lastPositionWithRemove => recorder!.lastPositionWithRemove; + String? get lastPositionWithRemove => recorder!.lastPositionWithRemove; } diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index 67963b35..6dec910d 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -26,25 +26,17 @@ import 'types.dart'; class GameRecorder { int cur = -1; String? lastPositionWithRemove = ""; - var _history = []; + List history = []; final tag = "[GameRecorder]"; GameRecorder({this.cur = -1, this.lastPositionWithRemove}); - List getHistory() { - return _history; - } - - void setHistory(List newHistory) { - _history = newHistory; - } - String wmdNotationToMoveString(String wmd) { String move = ""; if (wmd.length == 3 && wmd[0] == "x") { if (wmdNotationToMove[wmd.substring(1, 3)] != null) { - move = '-' + wmdNotationToMove[wmd.substring(1, 3)]!; + move = '-${wmdNotationToMove[wmd.substring(1, 3)]!}'; } } else if (wmd.length == 2) { if (wmdNotationToMove[wmd] != null) { @@ -53,9 +45,8 @@ class GameRecorder { } else if (wmd.length == 5 && wmd[2] == '-') { if (wmdNotationToMove[(wmd.substring(0, 2))] != null && wmdNotationToMove[(wmd.substring(3, 5))] != null) { - move = wmdNotationToMove[(wmd.substring(0, 2))]! + - '->' + - wmdNotationToMove[(wmd.substring(3, 5))]!; + move = + '${wmdNotationToMove[(wmd.substring(0, 2))]!}->${wmdNotationToMove[(wmd.substring(3, 5))]!}'; } } else if ((wmd.length == 8 && wmd[2] == '-' && wmd[5] == 'x') || (wmd.length == 5 && wmd[2] == 'x')) { @@ -70,19 +61,18 @@ class GameRecorder { String playOkNotationToMoveString(String playOk) { String move = ""; - if (playOk.length == 0) { + if (playOk.isEmpty) { return ""; } - var iDash = playOk.indexOf('-'); - var iX = playOk.indexOf('x'); + final iDash = playOk.indexOf('-'); + final iX = playOk.indexOf('x'); if (iDash == -1 && iX == -1) { // 12 - var val = int.parse(playOk); + final val = int.parse(playOk); if (val >= 1 && val <= 24) { - move = playOkNotationToMove[playOk]!; - return move; + return playOkNotationToMove[playOk]!; } else { debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; @@ -91,11 +81,10 @@ class GameRecorder { if (iX == 0) { // x12 - var sub = playOk.substring(1); - var val = int.parse(sub); + final sub = playOk.substring(1); + final val = int.parse(sub); if (val >= 1 && val <= 24) { - move = "-" + playOkNotationToMove[sub]!; - return move; + return "-${playOkNotationToMove[sub]!}"; } else { debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; @@ -103,8 +92,8 @@ class GameRecorder { } if (iDash != -1 && iX == -1) { // 12-13 - var sub1 = playOk.substring(0, iDash); - var val1 = int.parse(sub1); + final sub1 = playOk.substring(0, iDash); + final val1 = int.parse(sub1); if (val1 >= 1 && val1 <= 24) { move = playOkNotationToMove[sub1]!; } else { @@ -112,11 +101,10 @@ class GameRecorder { return ""; } - var sub2 = playOk.substring(iDash + 1); - var val2 = int.parse(sub2); + final sub2 = playOk.substring(iDash + 1); + final val2 = int.parse(sub2); if (val2 >= 1 && val2 <= 24) { - move = move + "->" + playOkNotationToMove[sub2]!; - return move; + return "$move->${playOkNotationToMove[sub2]!}"; } else { debugPrint("$tag Parse PlayOK notation $playOk failed."); return ""; @@ -142,7 +130,7 @@ class GameRecorder { return true; } - if (text.length > 0 && text[0] == '[') { + if (text.isNotEmpty && text[0] == '[') { return true; } @@ -187,8 +175,8 @@ class GameRecorder { return importGoldToken(moveList); } - List newHistory = []; - List list = moveList + final List newHistory = []; + final List list = moveList .toLowerCase() .replaceAll('\n', ' ') .replaceAll(',', ' ') @@ -224,20 +212,20 @@ class GameRecorder { i = i.trim(); if (int.tryParse(i) != null) { - i = i + '.'; + i = '$i.'; } - if (i.length > 0 && !i.endsWith(".")) { + if (i.isNotEmpty && !i.endsWith(".")) { if (i.length == 5 && i[2] == 'x') { // "a1xc3" - String m1 = wmdNotationToMoveString(i.substring(0, 2)); + final String m1 = wmdNotationToMoveString(i.substring(0, 2)); if (m1 != "") { newHistory.add(Move(m1)); } else { debugPrint("Cannot import $i"); return i; } - String m2 = wmdNotationToMoveString(i.substring(2)); + final String m2 = wmdNotationToMoveString(i.substring(2)); if (m2 != "") { newHistory.add(Move(m2)); } else { @@ -246,14 +234,14 @@ class GameRecorder { } } else if (i.length == 8 && i[2] == '-' && i[5] == 'x') { // "a1-b2xc3" - String m1 = wmdNotationToMoveString(i.substring(0, 5)); + final String m1 = wmdNotationToMoveString(i.substring(0, 5)); if (m1 != "") { newHistory.add(Move(m1)); } else { debugPrint("Cannot import $i"); return i; } - String m2 = wmdNotationToMoveString(i.substring(5)); + final String m2 = wmdNotationToMoveString(i.substring(5)); if (m2 != "") { newHistory.add(Move(m2)); } else { @@ -262,7 +250,7 @@ class GameRecorder { } } else { // no x - String m = wmdNotationToMoveString(i); + final String m = wmdNotationToMoveString(i); if (m != "") { newHistory.add(Move(m)); } else { @@ -273,8 +261,8 @@ class GameRecorder { } } - if (newHistory.length > 0) { - setHistory(newHistory); + if (newHistory.isNotEmpty) { + history = newHistory; } return ""; @@ -285,9 +273,9 @@ class GameRecorder { } String importPlayOk(String moveList) { - List newHistory = []; + final List newHistory = []; - List list = moveList + final List list = moveList .replaceAll('\n', ' ') .replaceAll(' 1/2-1/2', '') .replaceAll(' 1-0', '') @@ -298,13 +286,13 @@ class GameRecorder { for (var i in list) { i = i.trim(); - if (i.length > 0 && + if (i.isNotEmpty && !i.endsWith(".") && !i.startsWith("[") && !i.endsWith("]")) { - var iX = i.indexOf('x'); + final iX = i.indexOf('x'); if (iX == -1) { - String m = playOkNotationToMoveString(i); + final String m = playOkNotationToMoveString(i); if (m != "") { newHistory.add(Move(m)); } else { @@ -312,14 +300,14 @@ class GameRecorder { return i; } } else if (iX != -1) { - String m1 = playOkNotationToMoveString(i.substring(0, iX)); + final String m1 = playOkNotationToMoveString(i.substring(0, iX)); if (m1 != "") { newHistory.add(Move(m1)); } else { debugPrint("Cannot import $i"); return i; } - String m2 = playOkNotationToMoveString(i.substring(iX)); + final String m2 = playOkNotationToMoveString(i.substring(iX)); if (m2 != "") { newHistory.add(Move(m2)); } else { @@ -330,8 +318,8 @@ class GameRecorder { } } - if (newHistory.length > 0) { - setHistory(newHistory); + if (newHistory.isNotEmpty) { + history = newHistory; } return ""; @@ -356,16 +344,16 @@ class GameRecorder { } void jumpToTail() { - cur = _history.length - 1; + cur = history.length - 1; } void clear() { - _history.clear(); + history.clear(); cur = 0; } bool isClean() { - return cur == _history.length - 1; + return cur == history.length - 1; } void prune() { @@ -373,19 +361,19 @@ class GameRecorder { return; } - _history.removeRange(cur + 1, _history.length); + history.removeRange(cur + 1, history.length); } void moveIn(Move move, Position position) { - if (_history.length > 0) { - if (_history[_history.length - 1].move == move.move) { + if (history.isNotEmpty) { + if (history[history.length - 1].move == move.move) { //assert(false); // TODO: WAR return; } } - _history.add(move); + history.add(move); cur++; if (move.type == MoveType.remove) { @@ -394,22 +382,22 @@ class GameRecorder { } Move? removeLast() { - if (_history.isEmpty) return null; - return _history.removeLast(); + if (history.isEmpty) return null; + return history.removeLast(); } - get last => _history.isEmpty ? null : _history.last; + Move? get last => history.isEmpty ? null : history.last; - Move moveAt(int index) => _history[index]; + Move moveAt(int index) => history[index]; - get movesCount => _history.length; + int get movesCount => history.length; - get lastMove => movesCount == 0 ? null : moveAt(movesCount - 1); + Move? get lastMove => movesCount == 0 ? null : moveAt(movesCount - 1); - get lastEffectiveMove => cur == -1 ? null : moveAt(cur); + Move? get lastEffectiveMove => cur == -1 ? null : moveAt(cur); - String buildMoveHistoryText({cols = 2}) { - if (_history.length == 0) { + String buildMoveHistoryText({int cols = 2}) { + if (history.isEmpty) { return ''; } @@ -422,21 +410,21 @@ class GameRecorder { if (k % cols == 1) { num = "${(k + 1) ~/ 2}. "; if (k < 9 * cols) { - num = " " + num + " "; + num = " $num "; } } else { num = ""; } - if (i + 1 <= cur && _history[i + 1].type == MoveType.remove) { + if (i + 1 <= cur && history[i + 1].type == MoveType.remove) { moveHistoryText += - '$num${_history[i].notation}${_history[i + 1].notation} '; + '$num${history[i].notation}${history[i + 1].notation} '; i++; } else { - moveHistoryText += '$num${_history[i].notation} '; + moveHistoryText += '$num${history[i].notation} '; } k++; } else { - moveHistoryText += '${i < 9 ? ' ' : ''}${i + 1}. ${_history[i].move} '; + moveHistoryText += '${i < 9 ? ' ' : ''}${i + 1}. ${history[i].move} '; } if (Config.standardNotationEnabled) { @@ -450,8 +438,6 @@ class GameRecorder { moveHistoryText = ""; } - moveHistoryText = moveHistoryText.replaceAll(' \n', '\n'); - - return moveHistoryText; + return moveHistoryText.replaceAll(' \n', '\n'); } } diff --git a/src/ui/flutter_app/lib/mill/rule.dart b/src/ui/flutter_app/lib/mill/rule.dart index 821a1a0c..37db70e5 100644 --- a/src/ui/flutter_app/lib/mill/rule.dart +++ b/src/ui/flutter_app/lib/mill/rule.dart @@ -24,7 +24,7 @@ class Rule { int piecesCount = specialCountryAndRegion == "Iran" ? 12 : 9; int flyPieceCount = 3; int piecesAtLeastCount = 3; - bool hasDiagonalLines = specialCountryAndRegion == "Iran" ? true : false; + bool hasDiagonalLines = specialCountryAndRegion == "Iran"; bool hasBannedLocations = false; bool mayMoveInPlacingPhase = false; bool isDefenderMoveFirst = false; diff --git a/src/ui/flutter_app/lib/mill/types.dart b/src/ui/flutter_app/lib/mill/types.dart index e4cdaea5..c26c7444 100644 --- a/src/ui/flutter_app/lib/mill/types.dart +++ b/src/ui/flutter_app/lib/mill/types.dart @@ -18,7 +18,7 @@ import 'package:flutter/foundation.dart'; -abs(value) => value > 0 ? value : -value; +int abs(int value) => value > 0 ? value : -value; class Move { static const invalidMove = -1; @@ -50,7 +50,7 @@ class Move { // Used to restore fen step counter when undoing move String counterMarks = ""; - parse() { + void parse() { if (!legal(move)) { throw "Error: Invalid Move: $move"; } @@ -101,8 +101,7 @@ class Move { /// Remove: -(1,2) /// Move: (3,1)->(2,1) - Move.set(String move) { - this.move = move; + Move.set(this.move) { parse(); } @@ -113,7 +112,7 @@ class Move { if (move == null || move.length > "(3,1)->(2,1)".length) return false; - String range = "0123456789(,)->"; + const String range = "0123456789(,)->"; if (!(move[0] == '(' || move[0] == '-')) { return false; @@ -192,6 +191,7 @@ enum GameOverReason { enum PieceType { none, whiteStone, blackStone, ban, count, stone } class Piece { + const Piece._(); static const noPiece = PieceColor.none; static const whiteStone = PieceColor.white; static const blackStone = PieceColor.black; @@ -266,7 +266,7 @@ int makeSquare(int file, int rank) { } bool isOk(int sq) { - bool ret = (sq == 0 || (sq >= sqBegin && sq < sqEnd)); + final bool ret = sq == 0 || (sq >= sqBegin && sq < sqEnd); if (ret == false) { debugPrint("[types] $sq is not OK"); @@ -276,7 +276,7 @@ bool isOk(int sq) { } int fileOf(int sq) { - return (sq >> 3); + return sq >> 3; } int rankOf(int sq) { @@ -284,13 +284,11 @@ int rankOf(int sq) { } int fromSq(int move) { - move = abs(move); - return (move >> 8); + return abs(move) >> 8; } int toSq(int move) { - move = abs(move); - return (move & 0x00FF); + return abs(move) & 0x00FF; } int makeMove(int from, int to) { diff --git a/src/ui/flutter_app/lib/mill/zobrist.dart b/src/ui/flutter_app/lib/mill/zobrist.dart index e1a252fb..390cb2b5 100644 --- a/src/ui/flutter_app/lib/mill/zobrist.dart +++ b/src/ui/flutter_app/lib/mill/zobrist.dart @@ -17,8 +17,10 @@ */ class Zobrist { + const Zobrist._(); + static const int KEY_MISC_BIT = 2; - static var psq = [ + static List> psq = [ [ 0x4E421A, 0x3962FF, diff --git a/src/ui/flutter_app/lib/painting/board_painter.dart b/src/ui/flutter_app/lib/painting/board_painter.dart index 68781610..3b72c7c0 100644 --- a/src/ui/flutter_app/lib/painting/board_painter.dart +++ b/src/ui/flutter_app/lib/painting/board_painter.dart @@ -45,7 +45,7 @@ class BoardPainter extends PiecesBasePainter { return false; } - static doPaint( + static void doPaint( Canvas canvas, Paint paint, double gridWidth, @@ -56,8 +56,8 @@ class BoardPainter extends PiecesBasePainter { paint.color = Color(Config.boardLineColor); paint.style = PaintingStyle.stroke; - var left = offsetX; - var top = offsetY; + final left = offsetX; + final top = offsetY; paint.strokeWidth = Config.boardBorderLineWidth; @@ -76,27 +76,34 @@ class BoardPainter extends PiecesBasePainter { pieceInHandCountStr = pieceInHandCount.toString(); } - TextSpan textSpan = TextSpan( - style: TextStyle( - fontSize: 48, color: Color(Config.boardLineColor)), // TODO - text: pieceInHandCountStr); + final TextSpan textSpan = TextSpan( + style: TextStyle( + fontSize: 48, + color: Color(Config.boardLineColor), + ), // TODO + text: pieceInHandCountStr, + ); - TextPainter textPainter = TextPainter( - text: textSpan, - textAlign: TextAlign.center, - textDirection: TextDirection.ltr); + final TextPainter textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + ); textPainter.layout(); textPainter.paint( - canvas, - Offset(left + squareWidth * 3 - textPainter.width / 2, - top + squareWidth * 3 - textPainter.height / 2)); + canvas, + Offset( + left + squareWidth * 3 - textPainter.width / 2, + top + squareWidth * 3 - textPainter.height / 2, + ), + ); } if (Config.isNotationsShown) { - String verticalNotations = "abcdefg"; - String horizontalNotations = "7654321"; + const String verticalNotations = "abcdefg"; + const String horizontalNotations = "7654321"; String notationV = ""; String notationH = ""; @@ -104,25 +111,29 @@ class BoardPainter extends PiecesBasePainter { notationV = verticalNotations[i]; notationH = horizontalNotations[i]; - TextSpan notationSpanV = TextSpan( - style: - TextStyle(fontSize: 20, color: AppTheme.boardLineColor), // TODO + final TextSpan notationSpanV = TextSpan( + style: const TextStyle( + fontSize: 20, + color: AppTheme.boardLineColor, + ), // TODO text: notationV, ); - TextSpan notationSpanH = TextSpan( - style: - TextStyle(fontSize: 20, color: AppTheme.boardLineColor), // TODO + final TextSpan notationSpanH = TextSpan( + style: const TextStyle( + fontSize: 20, + color: AppTheme.boardLineColor, + ), // TODO text: notationH, ); - TextPainter notationPainterV = TextPainter( + final TextPainter notationPainterV = TextPainter( text: notationSpanV, textAlign: TextAlign.center, textDirection: TextDirection.ltr, ); - TextPainter notationPainterH = TextPainter( + final TextPainter notationPainterH = TextPainter( text: notationSpanH, textAlign: TextAlign.center, textDirection: TextDirection.ltr, @@ -131,37 +142,45 @@ class BoardPainter extends PiecesBasePainter { notationPainterV.layout(); notationPainterH.layout(); - var offset = (boardWidth - squareWidth * 6) / 4; + final offset = (boardWidth - squareWidth * 6) / 4; /* Show notations "a b c d e f" on board */ if (Config.developerMode) { notationPainterV.paint( canvas, - Offset(left + squareWidth * i - notationPainterV.width / 2, - top - offset - notationPainterV.height / 2), + Offset( + left + squareWidth * i - notationPainterV.width / 2, + top - offset - notationPainterV.height / 2, + ), ); } notationPainterV.paint( canvas, - Offset(left + squareWidth * i - notationPainterV.width / 2, - top + squareWidth * 6 + offset - notationPainterV.height / 2), + Offset( + left + squareWidth * i - notationPainterV.width / 2, + top + squareWidth * 6 + offset - notationPainterV.height / 2, + ), ); /* Show notations "1 2 3 4 5 6 7" on board */ notationPainterH.paint( canvas, - Offset(left - offset - notationPainterH.width / 2, - top + squareWidth * i - notationPainterH.height / 2), + Offset( + left - offset - notationPainterH.width / 2, + top + squareWidth * i - notationPainterH.height / 2, + ), ); if (Config.developerMode) { notationPainterH.paint( canvas, - Offset(left + squareWidth * 6 + offset - notationPainterH.width / 2, - top + squareWidth * i - notationPainterH.height / 2), + Offset( + left + squareWidth * 6 + offset - notationPainterH.width / 2, + top + squareWidth * i - notationPainterH.height / 2, + ), ); } } @@ -174,19 +193,27 @@ class BoardPainter extends PiecesBasePainter { ); paint.strokeWidth = Config.boardInnerLineWidth; - double bias = paint.strokeWidth / 2; + final double bias = paint.strokeWidth / 2; // File B canvas.drawRect( - Rect.fromLTWH(left + squareWidth * 1, top + squareWidth * 1, - squareWidth * 4, squareWidth * 4), + Rect.fromLTWH( + left + squareWidth * 1, + top + squareWidth * 1, + squareWidth * 4, + squareWidth * 4, + ), paint, ); // File A canvas.drawRect( - Rect.fromLTWH(left + squareWidth * 2, top + squareWidth * 2, - squareWidth * 2, squareWidth * 2), + Rect.fromLTWH( + left + squareWidth * 2, + top + squareWidth * 2, + squareWidth * 2, + squareWidth * 2, + ), paint, ); diff --git a/src/ui/flutter_app/lib/painting/painter_base.dart b/src/ui/flutter_app/lib/painting/painter_base.dart index a2e8a556..fe4898e3 100644 --- a/src/ui/flutter_app/lib/painting/painter_base.dart +++ b/src/ui/flutter_app/lib/painting/painter_base.dart @@ -23,10 +23,10 @@ abstract class PiecesBasePainter extends CustomPainter { final double width; final thePaint = Paint(); - final gridWidth; - final squareWidth; + final double gridWidth; + final double squareWidth; PiecesBasePainter({required this.width}) - : gridWidth = (width - AppTheme.boardPadding * 2), + : gridWidth = width - AppTheme.boardPadding * 2, squareWidth = (width - AppTheme.boardPadding * 2) / 7; } diff --git a/src/ui/flutter_app/lib/painting/pieces_painter.dart b/src/ui/flutter_app/lib/painting/pieces_painter.dart index 931973a4..c7b40149 100644 --- a/src/ui/flutter_app/lib/painting/pieces_painter.dart +++ b/src/ui/flutter_app/lib/painting/pieces_painter.dart @@ -25,21 +25,24 @@ import 'package:sanmill/style/app_theme.dart'; import 'painter_base.dart'; class PiecePaintParam { - // TODO: null-safety - final String? piece; - final Offset? pos; - final bool? animated; - PiecePaintParam({this.piece, this.pos, this.animated}); + final String piece; + final Offset pos; + final bool animated; + PiecePaintParam({ + required this.piece, + required this.pos, + required this.animated, + }); } class PiecesPainter extends PiecesBasePainter { final Position? position; - final int? focusIndex, blurIndex; - final animationValue; + final int? focusIndex; + final int? blurIndex; + final double animationValue; - // TODO: null-safety - double? pieceWidth = 0.0; - double? animatedPieceWidth = 0.0; + double pieceWidth = 0.0; + double animatedPieceWidth = 0.0; PiecesPainter({ required double width, @@ -74,7 +77,7 @@ class PiecesPainter extends PiecesBasePainter { return true; } - static doPaint( + static void doPaint( Canvas canvas, Paint paint, { Position? position, @@ -94,8 +97,7 @@ class PiecesPainter extends PiecesBasePainter { final shadowPath = Path(); final piecesToDraw = []; - // TODO: null-safety - Color? blurPositionColor; + late Color blurPositionColor; Color focusPositionColor; // Draw pieces on board @@ -106,8 +108,9 @@ class PiecesPainter extends PiecesBasePainter { if (piece == Piece.noPiece) continue; - var pos = Offset(left! + squareWidth! * col, top! + squareWidth * row); - var animated = (focusIndex == index); + final pos = + Offset(left! + squareWidth! * col, top! + squareWidth * row); + final animated = focusIndex == index; piecesToDraw .add(PiecePaintParam(piece: piece, pos: pos, animated: animated)); @@ -131,26 +134,26 @@ class PiecesPainter extends PiecesBasePainter { ); */ - piecesToDraw.forEach((pps) { - var pieceRadius = pieceWidth! / 2; - var pieceInnerRadius = pieceRadius * 0.99; + for (final pps in piecesToDraw) { + final pieceRadius = pieceWidth! / 2; + final pieceInnerRadius = pieceRadius * 0.99; - var animatedPieceRadius = animatedPieceWidth! / 2; - var animatedPieceInnerRadius = animatedPieceRadius * 0.99; + final animatedPieceRadius = animatedPieceWidth! / 2; + final animatedPieceInnerRadius = animatedPieceRadius * 0.99; // Draw Border of Piece switch (pps.piece) { case Piece.whiteStone: paint.color = AppTheme.whitePieceBorderColor; canvas.drawCircle( - pps.pos!, - pps.animated! ? animatedPieceRadius : pieceRadius, + pps.pos, + pps.animated ? animatedPieceRadius : pieceRadius, paint, ); paint.color = Color(Config.whitePieceColor); canvas.drawCircle( - pps.pos!, - pps.animated! ? animatedPieceInnerRadius : pieceInnerRadius, + pps.pos, + pps.animated ? animatedPieceInnerRadius : pieceInnerRadius, paint, ); blurPositionColor = Color(Config.whitePieceColor).withOpacity(0.1); @@ -158,14 +161,14 @@ class PiecesPainter extends PiecesBasePainter { case Piece.blackStone: paint.color = AppTheme.blackPieceBorderColor; canvas.drawCircle( - pps.pos!, - pps.animated! ? animatedPieceRadius : pieceRadius, + pps.pos, + pps.animated ? animatedPieceRadius : pieceRadius, paint, ); paint.color = Color(Config.blackPieceColor); canvas.drawCircle( - pps.pos!, - pps.animated! ? animatedPieceInnerRadius : pieceInnerRadius, + pps.pos, + pps.animated ? animatedPieceInnerRadius : pieceInnerRadius, paint, ); blurPositionColor = Color(Config.blackPieceColor).withOpacity(0.1); @@ -177,13 +180,14 @@ class PiecesPainter extends PiecesBasePainter { assert(false); break; } - }); + } // draw focus and blur position - if (focusIndex != invalidIndex) { - final int row = focusIndex! ~/ 7, column = focusIndex % 7; + final int row = focusIndex! ~/ 7; + final int column = focusIndex % 7; + if (focusIndex != invalidIndex) { /* focusPositionColor = Color.fromARGB( (Color(Config.whitePieceColor).alpha + @@ -215,9 +219,10 @@ class PiecesPainter extends PiecesBasePainter { } if (blurIndex != invalidIndex) { - final row = blurIndex! ~/ 7, column = blurIndex % 7; + final row = blurIndex! ~/ 7; + final column = blurIndex % 7; - paint.color = blurPositionColor!; + paint.color = blurPositionColor; paint.style = PaintingStyle.fill; canvas.drawCircle( diff --git a/src/ui/flutter_app/lib/services/audios.dart b/src/ui/flutter_app/lib/services/audios.dart index 55851ba6..35fd3a1a 100644 --- a/src/ui/flutter_app/lib/services/audios.dart +++ b/src/ui/flutter_app/lib/services/audios.dart @@ -25,20 +25,22 @@ import 'package:soundpool/soundpool.dart'; import 'package:stack_trace/stack_trace.dart'; class Audios { + const Audios._(); //static AudioPlayer? _player; static Soundpool? _soundpool; + // TODO: use enum for the sounds static int? _alarmSoundStreamId; - static var drawSoundId; - static var flySoundId; - static var goSoundId; - static var illegalSoundId; - static var loseSoundId; - static var millSoundId; - static var placeSoundId; - static var removeSoundId; - static var selectSoundId; - static var winSoundId; - static var isTemporaryMute = false; + static int? drawSoundId; + static int? flySoundId; + static int? goSoundId; + static int? illegalSoundId; + static int? loseSoundId; + static int? millSoundId; + static int? placeSoundId; + static int? removeSoundId; + static int? selectSoundId; + static int? winSoundId; + static bool isTemporaryMute = false; static Future loadSounds() async { if (Platform.isWindows) { @@ -156,7 +158,7 @@ class Audios { } } - static Future _playSound(var soundId) async { + static Future _playSound(int? soundId) async { if (Platform.isWindows) { return; } @@ -169,7 +171,7 @@ class Audios { return; } - _alarmSoundStreamId = await _soundpool!.play(await soundId); + _alarmSoundStreamId = await _soundpool!.play(soundId); } static Future _stopSound() async { @@ -190,7 +192,7 @@ class Audios { _soundpool!.dispose(); } - static playTone(var soundId) async { + static Future playTone(int? soundId) async { Chain.capture(() async { if (!Config.toneEnabled || isTemporaryMute || diff --git a/src/ui/flutter_app/lib/style/app_theme.dart b/src/ui/flutter_app/lib/style/app_theme.dart index f85fa373..5ffbd998 100644 --- a/src/ui/flutter_app/lib/style/app_theme.dart +++ b/src/ui/flutter_app/lib/style/app_theme.dart @@ -7,76 +7,79 @@ class AppTheme { AppTheme._(); // Theme data - static var lightThemeData = ThemeData( + static final lightThemeData = ThemeData( primarySwatch: AppTheme.appPrimaryColor, brightness: Brightness.light, ); - static var darkThemeData = ThemeData( + static final darkThemeData = ThemeData( primarySwatch: AppTheme.appPrimaryColor, brightness: Brightness.dark, ); // Color - static var appPrimaryColor = Colors.green; // Appbar & Dialog button - static var dialogTitleColor = appPrimaryColor; + static const appPrimaryColor = Colors.green; // Appbar & Dialog button + static const dialogTitleColor = appPrimaryColor; /// Game page - static var boardBackgroundColor = UIColors.burlyWood; - static var mainToolbarBackgroundColor = UIColors.burlyWood; - static var navigationToolbarBackgroundColor = UIColors.burlyWood; - static var boardLineColor = Color(0x996D000D); - static var whitePieceColor = Color.fromARGB(0xFF, 0xFF, 0xFF, 0xFF); - static var whitePieceBorderColor = Color.fromARGB(0xFF, 0x66, 0x00, 0x00); - static var blackPieceColor = Color.fromARGB(0xFF, 0x00, 0x00, 0x00); - static var blackPieceBorderColor = Color.fromARGB(0xFF, 0x22, 0x22, 0x22); - static var pieceHighlightColor = Colors.red; - static var messageColor = Colors.white; - static var banColor = Color.fromARGB(0xFF, 0xFF, 0x00, 0x00); // unused - static var banBorderColor = Color.fromARGB(0x80, 0xFF, 0x00, 0x00); // unused - static var mainToolbarIconColor = listTileSubtitleColor; - static var navigationToolbarIconColor = listTileSubtitleColor; - static var toolbarTextColor = mainToolbarIconColor; - static var moveHistoryTextColor = Colors.yellow; - static var moveHistoryDialogBackgroundColor = Colors.transparent; - static var infoDialogBackgroundColor = moveHistoryDialogBackgroundColor; - static var infoTextColor = moveHistoryTextColor; - static var simpleDialogOptionTextColor = Colors.yellow; + static const boardBackgroundColor = UIColors.burlyWood; + static const mainToolbarBackgroundColor = UIColors.burlyWood; + static const navigationToolbarBackgroundColor = UIColors.burlyWood; + static const boardLineColor = Color(0x996D000D); + static const whitePieceColor = Color.fromARGB(0xFF, 0xFF, 0xFF, 0xFF); + static const whitePieceBorderColor = Color.fromARGB(0xFF, 0x66, 0x00, 0x00); + static const blackPieceColor = Color.fromARGB(0xFF, 0x00, 0x00, 0x00); + static const blackPieceBorderColor = Color.fromARGB(0xFF, 0x22, 0x22, 0x22); + static const pieceHighlightColor = Colors.red; + static const messageColor = Colors.white; + static const banColor = Color.fromARGB(0xFF, 0xFF, 0x00, 0x00); // unused + static const banBorderColor = + Color.fromARGB(0x80, 0xFF, 0x00, 0x00); // unused + static const mainToolbarIconColor = listTileSubtitleColor; + static const navigationToolbarIconColor = listTileSubtitleColor; + static const toolbarTextColor = mainToolbarIconColor; + static const moveHistoryTextColor = Colors.yellow; + static const moveHistoryDialogBackgroundColor = Colors.transparent; + static const infoDialogBackgroundColor = moveHistoryDialogBackgroundColor; + static const infoTextColor = moveHistoryTextColor; + static const simpleDialogOptionTextColor = Colors.yellow; /// Settings page - static var darkBackgroundColor = UIColors.crusoe; - static var lightBackgroundColor = UIColors.papayaWhip; - static var listTileSubtitleColor = Color(0x99461220); - static var listItemDividerColor = Color(0x336D000D); - static var switchListTileActiveColor = dialogTitleColor; - static var switchListTileTitleColor = UIColors.crusoe; + static const darkBackgroundColor = UIColors.crusoe; + static const lightBackgroundColor = UIColors.papayaWhip; + static const listTileSubtitleColor = Color(0x99461220); + static const listItemDividerColor = Color(0x336D000D); + static const switchListTileActiveColor = dialogTitleColor; + static const switchListTileTitleColor = UIColors.crusoe; static const cardColor = UIColors.floralWhite; static const settingsHeaderTextColor = UIColors.crusoe; /// Help page - static var helpBackgroundColor = boardBackgroundColor; - static var helpTextColor = boardBackgroundColor; + static const helpBackgroundColor = boardBackgroundColor; + static const helpTextColor = boardBackgroundColor; /// About - static var aboutPageBackgroundColor = lightBackgroundColor; + static const aboutPageBackgroundColor = lightBackgroundColor; /// Drawer - static var drawerColor = Colors.white; - static var drawerBackgroundColor = UIColors.notWhite.withOpacity(0.5); // TODO - static var drawerHighlightItemColor = + static const drawerColor = Colors.white; + static final drawerBackgroundColor = + UIColors.notWhite.withOpacity(0.5); // TODO + static final drawerHighlightItemColor = UIColors.freeSpeechGreen.withOpacity(0.2); - static var drawerDividerColor = UIColors.grey.withOpacity(0.6); - static var drawerBoxerShadowColor = UIColors.grey.withOpacity(0.6); - static var drawerTextColor = UIColors.nearlyBlack; - static var drawerHighlightTextColor = UIColors.nearlyBlack; - static var exitTextColor = UIColors.nearlyBlack; - static var drawerIconColor = drawerTextColor; - static var drawerHighlightIconColor = drawerHighlightTextColor; - static var drawerAnimationIconColor = Colors.white; - static var exitIconColor = Colors.red; - static var drawerSplashColor = Colors.grey.withOpacity(0.1); // TODO: no use? - static var drawerHighlightColor = Colors.transparent; // TODO: no use? - static var navigationHomeScreenBackgroundColor = + static final drawerDividerColor = UIColors.grey.withOpacity(0.6); + static final drawerBoxerShadowColor = UIColors.grey.withOpacity(0.6); + static const drawerTextColor = UIColors.nearlyBlack; + static const drawerHighlightTextColor = UIColors.nearlyBlack; + static const exitTextColor = UIColors.nearlyBlack; + static const drawerIconColor = drawerTextColor; + static const drawerHighlightIconColor = drawerHighlightTextColor; + static const drawerAnimationIconColor = Colors.white; + static const exitIconColor = Colors.red; + static final drawerSplashColor = + Colors.grey.withOpacity(0.1); // TODO: no use? + static const drawerHighlightColor = Colors.transparent; // TODO: no use? + static const navigationHomeScreenBackgroundColor = UIColors.nearlyWhite; // TODO: no use? // Theme @@ -96,21 +99,24 @@ class AppTheme { showValueIndicator: ShowValueIndicator.always, minThumbSeparation: 100, thumbShape: RoundSliderThumbShape( - enabledThumbRadius: 2.0, disabledThumbRadius: 1.0), + enabledThumbRadius: 2.0, + disabledThumbRadius: 1.0, + ), rangeTrackShape: RoundedRectRangeSliderTrackShape(), tickMarkShape: RoundSliderTickMarkShape(tickMarkRadius: 2.0), valueIndicatorTextStyle: TextStyle(fontSize: 24), ); - static var simpleDialogOptionTextStyle = TextStyle( + static TextStyle simpleDialogOptionTextStyle = TextStyle( fontSize: Config.fontSize + 4.0, color: AppTheme.simpleDialogOptionTextColor, ); - static var moveHistoryTextStyle = TextStyle( - fontSize: Config.fontSize + 2.0, - height: 1.5, - color: moveHistoryTextColor); + static TextStyle moveHistoryTextStyle = TextStyle( + fontSize: Config.fontSize + 2.0, + height: 1.5, + color: moveHistoryTextColor, + ); static double boardTop = isLargeScreen() ? 75.0 : 36.0; static double boardMargin = 10.0; @@ -118,13 +124,12 @@ class AppTheme { static double boardBorderRadius = 5.0; static double boardPadding = 5.0; - static var settingsHeaderStyle = + static TextStyle settingsHeaderStyle = TextStyle(color: settingsHeaderTextColor, fontSize: Config.fontSize + 4); - static var settingsTextStyle = TextStyle(fontSize: Config.fontSize); + static TextStyle settingsTextStyle = TextStyle(fontSize: Config.fontSize); - static const cardMargin = - const EdgeInsets.symmetric(vertical: 4.0, horizontal: 0); + static const cardMargin = EdgeInsets.symmetric(vertical: 4.0); static const double drawerWidth = 250.0; diff --git a/src/ui/flutter_app/lib/widgets/about_page.dart b/src/ui/flutter_app/lib/widgets/about_page.dart index 25d6632f..7746bd75 100644 --- a/src/ui/flutter_app/lib/widgets/about_page.dart +++ b/src/ui/flutter_app/lib/widgets/about_page.dart @@ -65,13 +65,14 @@ class _AboutPageState extends State { @override Widget build(BuildContext context) { - String mode = getMode(); + final String mode = getMode(); return Scaffold( backgroundColor: AppTheme.aboutPageBackgroundColor, appBar: AppBar( - centerTitle: true, - title: Text(S.of(context).about + " " + S.of(context).appName)), + centerTitle: true, + title: Text("${S.of(context).about} ${S.of(context).appName}"), + ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( @@ -86,16 +87,16 @@ class _AboutPageState extends State { SettingsListTile( context: context, titleString: S.of(context).versionInfo, - subtitleString: Constants.projectName + " $_version" + " " + mode, + subtitleString: "${Constants.projectName} $_version $mode", onTap: _showVersionInfo, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).feedback, onTap: _launchFeedback, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).eula, @@ -103,7 +104,7 @@ class _AboutPageState extends State { _launchEULA(); }, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).license, @@ -116,7 +117,7 @@ class _AboutPageState extends State { ); }, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).sourceCode, @@ -124,7 +125,7 @@ class _AboutPageState extends State { _launchSourceCode(); }, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).privacyPolicy, @@ -132,7 +133,7 @@ class _AboutPageState extends State { _launchPrivacyPolicy(); }, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).ossLicenses, @@ -140,7 +141,7 @@ class _AboutPageState extends State { _launchThirdPartyNotices(); }, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).helpImproveTranslate, @@ -148,7 +149,7 @@ class _AboutPageState extends State { _launchHelpImproveTranslate(); }, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).thanks, @@ -156,16 +157,16 @@ class _AboutPageState extends State { _launchThanks(); }, ), - ListItemDivider(), + const ListItemDivider(), ]; } - _loadVersionInfo() async { + Future _loadVersionInfo() async { final packageInfo = await PackageInfo.fromPlatform(); if (Platform.isWindows) { setState(() { - _version = '${packageInfo.version}'; // TODO + _version = packageInfo.version; // TODO }); } else { setState(() { @@ -174,11 +175,11 @@ class _AboutPageState extends State { } } - _launchURL(String url) async { + Future _launchURL(String url) async { await launch(url); } - _launchFeedback() async { + Future _launchFeedback() async { String? locale = "en_US"; if (!Platform.isWindows) { @@ -193,7 +194,7 @@ class _AboutPageState extends State { } } - _launchEULA() async { + Future _launchEULA() async { String? locale = "en_US"; if (!Platform.isWindows) { @@ -208,7 +209,7 @@ class _AboutPageState extends State { } } - _launchSourceCode() async { + Future _launchSourceCode() async { String? locale = "en_US"; if (!Platform.isWindows) { @@ -223,12 +224,13 @@ class _AboutPageState extends State { } } - _launchThirdPartyNotices() async { + Future _launchThirdPartyNotices() async { Navigator.push( - context, - MaterialPageRoute( - builder: (context) => OssLicensesPage(), - )); + context, + MaterialPageRoute( + builder: (context) => OssLicensesPage(), + ), + ); /* String? locale = "en_US"; @@ -245,7 +247,7 @@ class _AboutPageState extends State { */ } - _launchPrivacyPolicy() async { + Future _launchPrivacyPolicy() async { String? locale = "en_US"; if (!Platform.isWindows) { @@ -260,7 +262,7 @@ class _AboutPageState extends State { } } - _launchHelpImproveTranslate() async { + Future _launchHelpImproveTranslate() async { String? locale = "en_US"; if (!Platform.isWindows) { @@ -275,7 +277,7 @@ class _AboutPageState extends State { } } - _launchThanks() async { + Future _launchThanks() async { String? locale = "en_US"; if (!Platform.isWindows) { @@ -290,7 +292,7 @@ class _AboutPageState extends State { } } - _showVersionInfo() { + void _showVersionInfo() { showDialog( context: context, barrierDismissible: true, @@ -302,15 +304,15 @@ class _AboutPageState extends State { return AlertDialog( title: Text( S.of(context).appName, - style: TextStyle(color: AppTheme.dialogTitleColor), + style: const TextStyle(color: AppTheme.dialogTitleColor), ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(S.of(context).version + ": $_version"), - SizedBox(height: AppTheme.sizedBoxHeight), - SizedBox(height: AppTheme.sizedBoxHeight), + Text("${S.of(context).version}: $_version"), + const SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text( S.of(context).copyright, style: TextStyle( @@ -332,7 +334,7 @@ class _AboutPageState extends State { ); } - _showFlutterVersionInfo() { + void _showFlutterVersionInfo() { Navigator.of(context).pop(); showDialog( @@ -346,14 +348,18 @@ class _AboutPageState extends State { return AlertDialog( title: Text( S.of(context).more, - style: TextStyle(color: AppTheme.dialogTitleColor), + style: const TextStyle(color: AppTheme.dialogTitleColor), ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "${flutterVersion.toString().replaceAll('{', '').replaceAll('}', '').replaceAll(', ', '\n')}", + flutterVersion + .toString() + .replaceAll('{', '') + .replaceAll('}', '') + .replaceAll(', ', '\n'), ), ], ), diff --git a/src/ui/flutter_app/lib/widgets/board.dart b/src/ui/flutter_app/lib/widgets/board.dart index e6ad9e65..4ecbff9f 100644 --- a/src/ui/flutter_app/lib/widgets/board.dart +++ b/src/ui/flutter_app/lib/widgets/board.dart @@ -30,8 +30,8 @@ class Board extends StatelessWidget { final double width; final double height; final Function(BuildContext, int) onBoardTap; - final animationValue; - List squareDesc = []; + final double animationValue; + final List squareDesc = []; final String tag = "[board]"; Board({ @@ -42,18 +42,15 @@ class Board extends StatelessWidget { @override Widget build(BuildContext context) { - var padding = AppTheme.boardPadding; + final padding = AppTheme.boardPadding; buildSquareDescription(context); - var container = Container( - margin: EdgeInsets.symmetric( - vertical: 0, - horizontal: 0, - ), + final container = Container( + margin: EdgeInsets.zero, child: GridView( scrollDirection: Axis.horizontal, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7, ), children: List.generate(7 * 7, (index) { @@ -70,7 +67,7 @@ class Board extends StatelessWidget { ), ); - var customPaint = CustomPaint( + final customPaint = CustomPaint( painter: BoardPainter(width: width), foregroundPainter: PiecesPainter( width: width, @@ -101,7 +98,7 @@ class Board extends StatelessWidget { */ child: boardContainer, onTapUp: (d) { - final gridWidth = (width - padding * 2); + final gridWidth = width - padding * 2; final squareWidth = gridWidth / 7; final dx = d.localPosition.dx; final dy = d.localPosition.dy; @@ -128,10 +125,10 @@ class Board extends StatelessWidget { } void buildSquareDescription(BuildContext context) { - List coordinates = []; - List pieceDesc = []; + final List coordinates = []; + final List pieceDesc = []; - var map = [ + final map = [ /* 1 */ 1, 8, @@ -190,7 +187,7 @@ class Board extends StatelessWidget { 49 ]; - var checkPoints = [ + final checkPoints = [ /* 1 */ 1, 0, @@ -249,17 +246,18 @@ class Board extends StatelessWidget { 1 ]; - bool ltr = getBidirectionality(context) == Bidirectionality.leftToRight; + final bool ltr = + getBidirectionality(context) == Bidirectionality.leftToRight; if (ltr) { - for (var file in ['a', 'b', 'c', 'd', 'e', 'f', 'g']) { - for (var rank in ['7', '6', '5', '4', '3', '2', '1']) { + for (final file in ['a', 'b', 'c', 'd', 'e', 'f', 'g']) { + for (final rank in ['7', '6', '5', '4', '3', '2', '1']) { coordinates.add("$file$rank"); } } } else { - for (var file in ['g', 'f', 'e', 'd', 'c', 'b', 'a']) { - for (var rank in ['7', '6', '5', '4', '3', '2', '1']) { + for (final file in ['g', 'f', 'e', 'd', 'c', 'b', 'a']) { + for (final rank in ['7', '6', '5', '4', '3', '2', '1']) { coordinates.add("$file$rank"); } } @@ -282,11 +280,11 @@ class Board extends StatelessWidget { squareDesc.clear(); for (var i = 0; i < 7 * 7; i++) { - var desc = pieceDesc[map[i] - 1]; + final desc = pieceDesc[map[i] - 1]; if (desc == S.of(context).emptyPoint) { - squareDesc.add(coordinates[i] + ": " + desc); + squareDesc.add("${coordinates[i]}: $desc"); } else { - squareDesc.add(desc + ": " + coordinates[i]); + squareDesc.add("$desc: ${coordinates[i]}"); } } } diff --git a/src/ui/flutter_app/lib/widgets/dialog.dart b/src/ui/flutter_app/lib/widgets/dialog.dart index 5f1ddae8..b20ef006 100644 --- a/src/ui/flutter_app/lib/widgets/dialog.dart +++ b/src/ui/flutter_app/lib/widgets/dialog.dart @@ -31,20 +31,24 @@ import 'package:url_launcher/url_launcher.dart'; int _counter = 0; Timer? _timer; -void startTimer(var counter, var events) { +void startTimer(int counter, StreamController events) { _counter = counter; if (_timer != null) { _timer!.cancel(); } - _timer = Timer.periodic(Duration(seconds: 1), (timer) { + _timer = Timer.periodic(const Duration(seconds: 1), (timer) { (_counter > 0) ? _counter-- : _timer!.cancel(); events.add(_counter); }); } void showCountdownDialog( - BuildContext ctx, var seconds, var events, void fun()) { - var alert = AlertDialog( + BuildContext ctx, + int seconds, + StreamController events, + void Function() fun, +) { + final alert = AlertDialog( content: StreamBuilder( stream: events.stream, builder: (BuildContext context, AsyncSnapshot snapshot) { @@ -57,32 +61,28 @@ void showCountdownDialog( } else {} } - return Container( + return SizedBox( height: 128, child: Column( - crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - snapshot.data != null ? '${snapshot.data.toString()}' : "10", - style: TextStyle(fontSize: 64), - ), - SizedBox( - height: 20, + snapshot.data != null ? snapshot.data.toString() : "10", + style: const TextStyle(fontSize: 64), ), + const SizedBox(height: 20), InkWell( onTap: () { Navigator.of(context).pop(); }, - child: Container( - child: Center( - child: Text( + child: Center( + child: Text( S.of(ctx).cancel, style: TextStyle( color: Colors.black, fontSize: Config.fontSize, fontWeight: FontWeight.bold, ), - )), + ), ), ), ], @@ -105,16 +105,19 @@ void showCountdownDialog( class _LinkTextSpan extends TextSpan { _LinkTextSpan({TextStyle? style, required String url, String? text}) : super( - style: style, - text: text ?? url, - recognizer: TapGestureRecognizer() - ..onTap = () { - launch(url, forceSafariVC: false); - }); + style: style, + text: text ?? url, + recognizer: TapGestureRecognizer() + ..onTap = () { + launch(url, forceSafariVC: false); + }, + ); } -showPrivacyDialog( - BuildContext context, setPrivacyPolicyAccepted(bool value)) async { +Future showPrivacyDialog( + BuildContext context, + Function(bool value) setPrivacyPolicyAccepted, +) async { String? locale = "en_US"; late String eulaURL; late String privacyPolicyURL; @@ -133,8 +136,8 @@ showPrivacyDialog( final ThemeData themeData = Theme.of(context); final TextStyle? aboutTextStyle = themeData.textTheme.bodyText1; - final TextStyle linkStyle = - themeData.textTheme.bodyText1!.copyWith(color: themeData.accentColor); + final TextStyle linkStyle = themeData.textTheme.bodyText1! + .copyWith(color: themeData.colorScheme.secondary); showDialog( context: context, @@ -179,15 +182,16 @@ showPrivacyDialog( Navigator.of(context).pop(); }, ), - Platform.isAndroid - ? TextButton( - child: Text(S.of(context).exit), - onPressed: () { - setPrivacyPolicyAccepted(false); - SystemChannels.platform.invokeMethod('SystemNavigator.pop'); - }, - ) - : Container(height: 0.0, width: 0.0), + if (Platform.isAndroid) + TextButton( + child: Text(S.of(context).exit), + onPressed: () { + setPrivacyPolicyAccepted(false); + SystemChannels.platform.invokeMethod('SystemNavigator.pop'); + }, + ) + else + const SizedBox(height: 0.0, width: 0.0), ], ), ); diff --git a/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart b/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart index 40355f77..1856a075 100644 --- a/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart +++ b/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart @@ -58,53 +58,60 @@ class _DrawerUserControllerState extends State @override void initState() { animationController = AnimationController( - duration: const Duration(milliseconds: 2000), vsync: this); + duration: const Duration(milliseconds: 2000), + vsync: this, + ); - iconAnimationController = AnimationController( - vsync: this, duration: const Duration(milliseconds: 0)); + iconAnimationController = + AnimationController(vsync: this, duration: Duration.zero); - iconAnimationController - ..animateTo(1.0, - duration: const Duration(milliseconds: 0), - curve: Curves.fastOutSlowIn); + iconAnimationController.animateTo( + 1.0, + duration: Duration.zero, + curve: Curves.fastOutSlowIn, + ); scrollController = ScrollController(initialScrollOffset: widget.drawerWidth); - scrollController - ..addListener(() { - if (scrollController.offset <= 0) { - if (scrollOffset != 1.0) { - setState(() { - scrollOffset = 1.0; - try { - widget.drawerIsOpen!(true); - } catch (_) {} - }); - } - iconAnimationController.animateTo(0.0, - duration: const Duration(milliseconds: 0), - curve: Curves.fastOutSlowIn); - } else if (scrollController.offset > 0 && - scrollController.offset < widget.drawerWidth.floor()) { - iconAnimationController.animateTo( - (scrollController.offset * 100 / (widget.drawerWidth)) / 100, - duration: const Duration(milliseconds: 0), - curve: Curves.fastOutSlowIn); - } else { - if (scrollOffset != 0.0) { - setState(() { - scrollOffset = 0.0; - try { - widget.drawerIsOpen!(false); - } catch (_) {} - }); - } - iconAnimationController.animateTo(1.0, - duration: const Duration(milliseconds: 0), - curve: Curves.fastOutSlowIn); + scrollController.addListener(() { + if (scrollController.offset <= 0) { + if (scrollOffset != 1.0) { + setState(() { + scrollOffset = 1.0; + try { + widget.drawerIsOpen!(true); + } catch (_) {} + }); } - }); + iconAnimationController.animateTo( + 0.0, + duration: Duration.zero, + curve: Curves.fastOutSlowIn, + ); + } else if (scrollController.offset > 0 && + scrollController.offset < widget.drawerWidth.floor()) { + iconAnimationController.animateTo( + (scrollController.offset * 100 / (widget.drawerWidth)) / 100, + duration: Duration.zero, + curve: Curves.fastOutSlowIn, + ); + } else { + if (scrollOffset != 0.0) { + setState(() { + scrollOffset = 0.0; + try { + widget.drawerIsOpen!(false); + } catch (_) {} + }); + } + iconAnimationController.animateTo( + 1.0, + duration: Duration.zero, + curve: Curves.fastOutSlowIn, + ); + } + }); WidgetsBinding.instance!.addPostFrameCallback((_) => getInitState()); super.initState(); @@ -119,22 +126,23 @@ class _DrawerUserControllerState extends State @override Widget build(BuildContext context) { - bool ltr = getBidirectionality(context) == Bidirectionality.leftToRight; + final bool ltr = + getBidirectionality(context) == Bidirectionality.leftToRight; // this just menu and arrow icon animation - var inkWell = InkWell( + final inkWell = InkWell( borderRadius: BorderRadius.circular(AppBar().preferredSize.height), child: Center( // if you use your own menu view UI you add form initialization - child: widget.menuView != null - ? widget.menuView - : Semantics( - label: S.of(context).mainMenu, - child: AnimatedIcon( - icon: widget.animatedIconData, - color: AppTheme.drawerAnimationIconColor, - progress: iconAnimationController), + child: widget.menuView ?? + Semantics( + label: S.of(context).mainMenu, + child: AnimatedIcon( + icon: widget.animatedIconData, + color: AppTheme.drawerAnimationIconColor, + progress: iconAnimationController, ), + ), ), onTap: () { FocusScope.of(context).requestFocus(FocusNode()); @@ -142,7 +150,7 @@ class _DrawerUserControllerState extends State }, ); - var animatedBuilder = AnimatedBuilder( + final animatedBuilder = AnimatedBuilder( animation: iconAnimationController, builder: (BuildContext context, Widget? child) { return Transform( @@ -151,15 +159,13 @@ class _DrawerUserControllerState extends State transform: Matrix4.translationValues(scrollController.offset, 0.0, 0.0), child: HomeDrawer( - screenIndex: widget.screenIndex == null - ? DrawerIndex.humanVsAi - : widget.screenIndex, + screenIndex: widget.screenIndex ?? DrawerIndex.humanVsAi, iconAnimationController: iconAnimationController, callBackIndex: (DrawerIndex? indexType) { onDrawerClick(); try { widget.onDrawerCall!(indexType!); - } catch (e) {} + } catch (_) {} }, ), ); @@ -172,7 +178,7 @@ class _DrawerUserControllerState extends State tapOffset = 10; // TODO: WAR } - var stack = Stack( + final stack = Stack( children: [ // this IgnorePointer we use as touch(user Interface) widget.screen View, // for example scrolloffset == 1 @@ -192,7 +198,8 @@ class _DrawerUserControllerState extends State ), Padding( padding: EdgeInsets.only( - top: MediaQuery.of(context).padding.top + tapOffset, left: 0), + top: MediaQuery.of(context).padding.top + tapOffset, + ), child: SizedBox( width: AppBar().preferredSize.height, height: AppBar().preferredSize.height, @@ -205,7 +212,7 @@ class _DrawerUserControllerState extends State ], ); - var row = Row( + final row = Row( children: [ SizedBox( width: widget.drawerWidth, @@ -224,7 +231,9 @@ class _DrawerUserControllerState extends State color: Color(Config.drawerColor), boxShadow: [ BoxShadow( - color: AppTheme.drawerBoxerShadowColor, blurRadius: 24), + color: AppTheme.drawerBoxerShadowColor, + blurRadius: 24, + ), ], ), child: stack, diff --git a/src/ui/flutter_app/lib/widgets/env_page.dart b/src/ui/flutter_app/lib/widgets/env_page.dart index 84356511..4b5694a8 100644 --- a/src/ui/flutter_app/lib/widgets/env_page.dart +++ b/src/ui/flutter_app/lib/widgets/env_page.dart @@ -44,17 +44,24 @@ class _EnvironmentVariablesPageState extends State { return Scaffold( appBar: AppBar( - title: Text(S.of(context).environmentVariables), centerTitle: true), + title: Text(S.of(context).environmentVariables), + centerTitle: true, + ), body: ListView( children: [ Container( - padding: const EdgeInsets.only( - top: 16, left: 16, right: 16, bottom: 16), - child: Text( - _data != "" ? _data : 'Nothing to show', - style: TextStyle(fontFamily: 'Monospace', fontSize: 12), - textAlign: TextAlign.left, - )) + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 16, + ), + child: Text( + _data != "" ? _data : 'Nothing to show', + style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), + textAlign: TextAlign.left, + ), + ), ], ), ); diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/widgets/game_page.dart index 85d48d86..9e11196e 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_page.dart @@ -74,7 +74,7 @@ class _GamePageState extends State ); */ late AnimationController _animationController; - late Animation animation; + late Animation animation; bool disposed = false; bool ltr = true; final String tag = "[game_page]"; @@ -89,14 +89,14 @@ class _GamePageState extends State Game.instance.init(); widget.engine.startup(); - timer = Timer.periodic(Duration(microseconds: 100), (Timer t) { + timer = Timer.periodic(const Duration(microseconds: 100), (Timer t) { _setReadyState(); }); _initAnimation(); } - _setReadyState() async { + Future _setReadyState() async { debugPrint("$tag Check if need to set Ready state..."); if (!isReady && mounted && Config.settingsLoaded) { debugPrint("$tag Set Ready State..."); @@ -111,7 +111,7 @@ class _GamePageState extends State } } - _initAnimation() { + void _initAnimation() { _animationController = AnimationController( vsync: this, duration: @@ -142,7 +142,7 @@ class _GamePageState extends State } } - showTip(String? tip) { + void showTip(String? tip) { if (!mounted) return; if (tip != null) { debugPrint("[tip] $tip"); @@ -160,7 +160,7 @@ class _GamePageState extends State final winner = Game.instance.position.winner; - Map colorWinStrings = { + final Map colorWinStrings = { PieceColor.white: S.of(context).whiteWin, PieceColor.black: S.of(context).blackWin, PieceColor.draw: S.of(context).isDraw @@ -187,7 +187,7 @@ class _GamePageState extends State } } - onBoardTap(BuildContext context, int index) { + dynamic onBoardTap(BuildContext context, int index) { if (!isReady) { debugPrint("[tap] Not ready, ignore tapping."); return false; @@ -206,7 +206,7 @@ class _GamePageState extends State final position = Game.instance.position; - int? sq = indexToSquare[index]; + final int? sq = indexToSquare[index]; if (sq == null) { debugPrint("$tag sq is null, skip tapping."); @@ -222,7 +222,7 @@ class _GamePageState extends State position.pieceOnBoardCount[PieceColor.black] == 0) { Game.instance.newGame(); - if (Game.instance.isAiToMove()) { + if (Game.instance.isAiToMove()!) { if (Game.instance.aiIsSearching()) { debugPrint("$tag AI is thinking, skip tapping."); return false; @@ -234,7 +234,7 @@ class _GamePageState extends State } } - if (Game.instance.isAiToMove() || Game.instance.aiIsSearching()) { + if (Game.instance.isAiToMove()! || Game.instance.aiIsSearching()) { debugPrint("[tap] AI's turn, skip tapping."); return false; } @@ -268,11 +268,11 @@ class _GamePageState extends State } } else if (mounted) { if (rule.mayOnlyRemoveUnplacedPieceInPlacingPhase) { - showTip(S - .of(context) - .tipPlaced); // TODO: HumanVsHuman - Change tip + showTip( + S.of(context).tipPlaced, + ); // TODO: HumanVsHuman - Change tip } else { - var side = Game.instance.sideToMove == PieceColor.white + final side = Game.instance.sideToMove == PieceColor.white ? S.of(context).black : S.of(context).white; showTip(side + S.of(context).tipToMove); @@ -308,7 +308,7 @@ class _GamePageState extends State } break; } - int selectRet = position.selectPiece(sq); + final int selectRet = position.selectPiece(sq); switch (selectRet) { case 0: Audios.playTone(Audios.selectSoundId); @@ -316,7 +316,7 @@ class _GamePageState extends State ret = true; debugPrint("[tap] selectPiece: [$sq]"); - var us = Game.instance.sideToMove; + final us = Game.instance.sideToMove; if (position.phase == Phase.moving && rule.mayFly && (Game.instance.position.pieceOnBoardCount[us] == @@ -387,7 +387,7 @@ class _GamePageState extends State break; case Act.remove: - int removeRet = position.removePiece(sq); + final int removeRet = position.removePiece(sq); switch (removeRet) { case 0: @@ -408,7 +408,7 @@ class _GamePageState extends State } } else { if (mounted) { - var them = Game.instance.sideToMove == PieceColor.white + final them = Game.instance.sideToMove == PieceColor.white ? S.of(context).black : S.of(context).white; if (mounted) { @@ -439,7 +439,9 @@ class _GamePageState extends State if (Config.screenReaderSupport) { ScaffoldMessenger.of(context).clearSnackBars(); showSnackBar( - context, S.of(context).tipCannotRemovePieceFromMill); + context, + S.of(context).tipCannotRemovePieceFromMill, + ); } } break; @@ -463,7 +465,7 @@ class _GamePageState extends State if (ret) { Game.instance.sideToMove = position.sideToMove() ?? PieceColor.nobody; - Game.instance.moveHistory.add(position.record); + Game.instance.moveHistory.add(position.record!); // TODO: Need Others? // Increment ply counters. In particular, @@ -473,14 +475,16 @@ class _GamePageState extends State ++position.st.rule50; ++position.st.pliesFromNull; - if (position.record.length > "-(1,2)".length) { - if (posKeyHistory.length == 0 || - (posKeyHistory.length > 0 && + if (position.record!.length > "-(1,2)".length) { + if (posKeyHistory.isEmpty || + (posKeyHistory.isNotEmpty && position.st.key != posKeyHistory[posKeyHistory.length - 1])) { posKeyHistory.add(position.st.key); if (rule.threefoldRepetitionRule && position.hasGameCycle()) { - position.setGameOver(PieceColor.draw, - GameOverReason.drawReasonThreefoldRepetition); + position.setGameOver( + PieceColor.draw, + GameOverReason.drawReasonThreefoldRepetition, + ); } } } else { @@ -489,9 +493,9 @@ class _GamePageState extends State //position.move = m; - Move m = Move(position.record); - position.recorder.prune(); - position.recorder.moveIn(m, position); + final Move m = Move(position.record); + position.recorder!.prune(); + position.recorder!.moveIn(m, position); /* if (Config.screenReaderSupport && m.notation != null) { @@ -516,7 +520,7 @@ class _GamePageState extends State return ret; } - engineToGo(bool isMoveNow) async { + Future engineToGo(bool isMoveNow) async { if (!mounted) { debugPrint("[engineToGo] !mounted, skip engineToGo."); return; @@ -544,33 +548,29 @@ class _GamePageState extends State while ((Config.isAutoRestart == true || Game.instance.position.winner == PieceColor.nobody) && - Game.instance.isAiToMove() && + Game.instance.isAiToMove()! && mounted) { if (widget.engineType == EngineType.aiVsAi) { - String score = - Game.instance.position.score[PieceColor.white].toString() + - " : " + - Game.instance.position.score[PieceColor.black].toString() + - " : " + - Game.instance.position.score[PieceColor.draw].toString(); + final String score = + "${Game.instance.position.score[PieceColor.white]} : ${Game.instance.position.score[PieceColor.black]} : ${Game.instance.position.score[PieceColor.draw]}"; showTip(score); } else { if (mounted) { showTip(S.of(context).thinking); - Move? m = Game.instance.position.recorder.lastMove; + final Move? m = Game.instance.position.recorder!.lastMove; if (Config.screenReaderSupport && Game.instance.position.action != Act.remove && m != null && m.notation != null) { - showSnackBar(context, S.of(context).human + ": " + m.notation!); + showSnackBar(context, "${S.of(context).human}: ${m.notation!}"); } } } - late var response; + late EngineResponse response; if (!isMoveNow) { debugPrint("[engineToGo] Searching..."); @@ -585,8 +585,8 @@ class _GamePageState extends State switch (response.type) { case 'move': - Move mv = response.value; - final Move move = new Move(mv.move); + final Move mv = response.value as Move; + final Move move = Move(mv.move); _animationController.duration = Duration(milliseconds: (Config.animationDuration * 1000).toInt()); @@ -599,10 +599,10 @@ class _GamePageState extends State ); } - Game.instance.doMove(move.move); + Game.instance.doMove(move.move!); showTips(); if (Config.screenReaderSupport && move.notation != null) { - showSnackBar(context, S.of(context).ai + ": " + move.notation!); + showSnackBar(context, "${S.of(context).ai}: ${move.notation!}"); } break; case 'timeout': @@ -629,10 +629,10 @@ class _GamePageState extends State } } - onStartNewGameButtonPressed() async { + Future onStartNewGameButtonPressed() async { Navigator.of(context).pop(); - if (Game.instance.isAiToMove()) { + if (Game.instance.isAiToMove()!) { // TODO: Move now //debugPrint("$tag New game, AI to move, move now."); //await engineToGo(true); @@ -648,37 +648,36 @@ class _GamePageState extends State } } - if (Game.instance.isAiToMove()) { + if (Game.instance.isAiToMove()!) { debugPrint("$tag New game, AI to move."); engineToGo(false); } } - onImportGameButtonPressed() async { + Future onImportGameButtonPressed() async { Navigator.of(context).pop(); ScaffoldMessenger.of(context).clearSnackBars(); - ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); + final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); if (data == null || data.text == null) { return; } - String text = data.text!; + final String text = data.text!; debugPrint("Clipboard text:"); debugPrint(text); await onTakeBackAllButtonPressed(pop: false); - await Game.instance.position.recorder.clear(); - var importFailedStr = await Game.instance.position.recorder.import(text); + Game.instance.position.recorder!.clear(); + final importFailedStr = Game.instance.position.recorder!.import(text); if (importFailedStr != "") { - showTip(S.of(context).cannotImport + " " + importFailedStr); + showTip("${S.of(context).cannotImport} $importFailedStr"); if (Config.screenReaderSupport) { ScaffoldMessenger.of(context).clearSnackBars(); - showSnackBar( - context, S.of(context).cannotImport + " " + importFailedStr); + showSnackBar(context, "${S.of(context).cannotImport} $importFailedStr"); } return; } @@ -692,7 +691,7 @@ class _GamePageState extends State } } - onExportGameButtonPressed() async { + Future onExportGameButtonPressed() async { Navigator.of(context).pop(); final moveHistoryText = Game.instance.position.moveHistoryText; @@ -784,62 +783,62 @@ class _GamePageState extends State } */ - onAutoReplayButtonPressed() async { + Future onAutoReplayButtonPressed() async { Navigator.of(context).pop(); await onTakeBackAllButtonPressed(pop: false); await onStepForwardAllButtonPressed(pop: false); } - onGameButtonPressed() { + void onGameButtonPressed() { showModalBottomSheet( //showDialog( context: context, backgroundColor: Colors.transparent, - builder: (BuildContext context) { - return Semantics( - label: S.of(context).game, - child: SimpleDialog( - backgroundColor: Colors.transparent, - children: [ + builder: (context) => Semantics( + label: S.of(context).game, + child: SimpleDialog( + backgroundColor: Colors.transparent, + children: [ + SimpleDialogOption( + onPressed: onStartNewGameButtonPressed, + child: Text( + S.of(context).newGame, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onImportGameButtonPressed, + child: Text( + S.of(context).importGame, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onExportGameButtonPressed, + child: Text( + S.of(context).exportGame, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + if (Config.screenReaderSupport) SimpleDialogOption( child: Text( - S.of(context).newGame, + S.of(context).close, style: AppTheme.simpleDialogOptionTextStyle, textAlign: TextAlign.center, ), - onPressed: onStartNewGameButtonPressed, - ), - SizedBox(height: AppTheme.sizedBoxHeight), - SimpleDialogOption( - child: Text( - S.of(context).importGame, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: onImportGameButtonPressed, - ), - SizedBox(height: AppTheme.sizedBoxHeight), - SimpleDialogOption( - child: Text( - S.of(context).exportGame, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: onExportGameButtonPressed, - ), - SizedBox(height: AppTheme.sizedBoxHeight), - Config.screenReaderSupport - ? SimpleDialogOption( - child: Text( - S.of(context).close, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: () => Navigator.of(context).pop(), - ) - : SizedBox(height: 1), - /* + onPressed: () => Navigator.of(context).pop(), + ) + else + const SizedBox(height: 1), + /* SizedBox(height: AppTheme.sizedBoxHeight), Config.experimentsEnabled ? SimpleDialogOption( @@ -878,7 +877,7 @@ class _GamePageState extends State ) : SizedBox(height: 1), */ - /* + /* SizedBox(height: AppTheme.sizedBoxHeight), SimpleDialogOption( child: Text( @@ -889,118 +888,125 @@ class _GamePageState extends State onPressed: onAutoReplayButtonPressed, ), */ - ], - ), - ); - }, + ], + ), + ), ); } - onOptionButtonPressed() { + void onOptionButtonPressed() { Navigator.push( context, MaterialPageRoute(builder: (context) => GameSettingsPage()), ); } - onMoveButtonPressed() { + void onMoveButtonPressed() { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, - builder: (BuildContext context) { - return Semantics( - label: S.of(context).move, - child: SimpleDialog( - backgroundColor: Colors.transparent, - children: [ - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SimpleDialogOption( - child: Text( - S.of(context).takeBack, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: onTakeBackButtonPressed, - ), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SizedBox(height: AppTheme.sizedBoxHeight), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SimpleDialogOption( - child: Text( - S.of(context).stepForward, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: onStepForwardButtonPressed, - ), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SizedBox(height: AppTheme.sizedBoxHeight), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SimpleDialogOption( - child: Text( - S.of(context).takeBackAll, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: onTakeBackAllButtonPressed, - ), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SizedBox(height: AppTheme.sizedBoxHeight), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SimpleDialogOption( - child: Text( - S.of(context).stepForwardAll, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: onStepForwardAllButtonPressed, - ), - Config.isHistoryNavigationToolbarShown - ? SizedBox(height: 1) - : SizedBox(height: AppTheme.sizedBoxHeight), + builder: (context) => Semantics( + label: S.of(context).move, + child: SimpleDialog( + backgroundColor: Colors.transparent, + children: [ + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else SimpleDialogOption( + onPressed: onTakeBackButtonPressed, child: Text( - S.of(context).showMoveList, + S.of(context).takeBack, style: AppTheme.simpleDialogOptionTextStyle, textAlign: TextAlign.center, ), - onPressed: onMoveListButtonPressed, ), - SizedBox(height: AppTheme.sizedBoxHeight), + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else + const SizedBox(height: AppTheme.sizedBoxHeight), + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else SimpleDialogOption( + onPressed: onStepForwardButtonPressed, child: Text( - S.of(context).moveNow, + S.of(context).stepForward, style: AppTheme.simpleDialogOptionTextStyle, textAlign: TextAlign.center, ), - onPressed: onMoveNowButtonPressed, ), - SizedBox(height: AppTheme.sizedBoxHeight), - Config.screenReaderSupport - ? SimpleDialogOption( - child: Text( - S.of(context).close, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - onPressed: () => Navigator.of(context).pop(), - ) - : SizedBox(height: 1), - ], - ), - ); - }, + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else + const SizedBox(height: AppTheme.sizedBoxHeight), + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else + SimpleDialogOption( + onPressed: onTakeBackAllButtonPressed, + child: Text( + S.of(context).takeBackAll, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else + const SizedBox(height: AppTheme.sizedBoxHeight), + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else + SimpleDialogOption( + onPressed: onStepForwardAllButtonPressed, + child: Text( + S.of(context).stepForwardAll, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + if (Config.isHistoryNavigationToolbarShown) + const SizedBox(height: 1) + else + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onMoveListButtonPressed, + child: Text( + S.of(context).showMoveList, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onMoveNowButtonPressed, + child: Text( + S.of(context).moveNow, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + if (Config.screenReaderSupport) + SimpleDialogOption( + child: Text( + S.of(context).close, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + onPressed: () => Navigator.of(context).pop(), + ) + else + const SizedBox(height: 1), + ], + ), + ), ); } - onGotoHistoryButtonsPressed(var func, {bool pop = true}) async { + Future onGotoHistoryButtonsPressed(Future func, + {bool pop = true}) async { if (pop == true) { Navigator.of(context).pop(); } @@ -1019,7 +1025,7 @@ class _GamePageState extends State Audios.isTemporaryMute = Config.keepMuteWhenTakingBack; - var errMove = await func; + final errMove = await func; switch (errMove) { case "": @@ -1042,7 +1048,7 @@ class _GamePageState extends State if (mounted) { String text = ""; - var pos = Game.instance.position; + final pos = Game.instance.position; /* String us = ""; @@ -1056,9 +1062,9 @@ class _GamePageState extends State } */ - var lastEffectiveMove = pos.recorder.lastEffectiveMove; + final lastEffectiveMove = pos.recorder!.lastEffectiveMove; if (lastEffectiveMove != null && lastEffectiveMove.notation != null) { - text = S.of(context).lastMove + ": " + lastEffectiveMove.notation; + text = "${S.of(context).lastMove}: ${lastEffectiveMove.notation}"; } else { text = S.of(context).atEnd; } @@ -1072,30 +1078,32 @@ class _GamePageState extends State } } - onTakeBackButtonPressed({bool pop = true}) async { + Future onTakeBackButtonPressed({bool pop = true}) async { onGotoHistoryButtonsPressed(Game.instance.position.takeBack(), pop: pop); } - onStepForwardButtonPressed({bool pop = true}) async { + Future onStepForwardButtonPressed({bool pop = true}) async { onGotoHistoryButtonsPressed(Game.instance.position.stepForward(), pop: pop); } - onTakeBackAllButtonPressed({bool pop = true}) async { + Future onTakeBackAllButtonPressed({bool pop = true}) async { onGotoHistoryButtonsPressed(Game.instance.position.takeBackAll(), pop: pop); } - onStepForwardAllButtonPressed({bool pop = true}) async { - onGotoHistoryButtonsPressed(Game.instance.position.stepForwardAll(), - pop: pop); + Future onStepForwardAllButtonPressed({bool pop = true}) async { + onGotoHistoryButtonsPressed( + Game.instance.position.stepForwardAll(), + pop: pop, + ); } - onTakeBackNButtonPressed(int n, {bool pop = true}) async { + Future onTakeBackNButtonPressed(int n, {bool pop = true}) async { onGotoHistoryButtonsPressed(Game.instance.position.takeBackN(n), pop: pop); } - onMoveListButtonPressed() { + void onMoveListButtonPressed() { final moveHistoryText = Game.instance.position.moveHistoryText; - var end = Game.instance.moveHistory.length - 1; + final end = Game.instance.moveHistory.length - 1; Navigator.of(context).pop(); ScaffoldMessenger.of(context).clearSnackBars(); @@ -1105,11 +1113,13 @@ class _GamePageState extends State builder: (BuildContext context) { return AlertDialog( backgroundColor: AppTheme.moveHistoryDialogBackgroundColor, - title: Text(S.of(context).moveList, - style: TextStyle( - color: AppTheme.moveHistoryTextColor, - fontSize: Config.fontSize + 2.0, - )), + title: Text( + S.of(context).moveList, + style: TextStyle( + color: AppTheme.moveHistoryTextColor, + fontSize: Config.fontSize + 2.0, + ), + ), content: SingleChildScrollView( child: Text( moveHistoryText, @@ -1118,30 +1128,36 @@ class _GamePageState extends State ), ), actions: [ - end > 0 - ? TextButton( - child: Text(S.of(context).rollback, - style: AppTheme.moveHistoryTextStyle), - onPressed: () async { - int selectValue = await showPickerNumber( - context, - 1, - end, - 1, - S.of(context).moves, - ); + if (end > 0) + TextButton( + child: Text( + S.of(context).rollback, + style: AppTheme.moveHistoryTextStyle, + ), + onPressed: () async { + final int selectValue = await showPickerNumber( + context, + 1, + end, + 1, + S.of(context).moves, + ); - if (selectValue != 0) { - onTakeBackNButtonPressed(selectValue); - } - }, - ) - : TextButton( - child: Text(""), - onPressed: () => Navigator.of(context).pop()), + if (selectValue != 0) { + onTakeBackNButtonPressed(selectValue); + } + }, + ) + else + TextButton( + child: const Text(""), + onPressed: () => Navigator.of(context).pop(), + ), TextButton( - child: Text(S.of(context).copy, - style: AppTheme.moveHistoryTextStyle), + child: Text( + S.of(context).copy, + style: AppTheme.moveHistoryTextStyle, + ), onPressed: () => Clipboard.setData(ClipboardData(text: moveHistoryText)) .then((_) { @@ -1150,8 +1166,10 @@ class _GamePageState extends State }), ), TextButton( - child: Text(S.of(context).cancel, - style: AppTheme.moveHistoryTextStyle), + child: Text( + S.of(context).cancel, + style: AppTheme.moveHistoryTextStyle, + ), onPressed: () => Navigator.of(context).pop(), ), ], @@ -1160,12 +1178,12 @@ class _GamePageState extends State ); } - onMoveNowButtonPressed() async { + Future onMoveNowButtonPressed() async { Navigator.of(context).pop(); await engineToGo(true); } - onInfoButtonPressed() { + void onInfoButtonPressed() { final analyzeText = getInfoText(); showDialog( context: context, @@ -1174,7 +1192,8 @@ class _GamePageState extends State return AlertDialog( backgroundColor: AppTheme.infoDialogBackgroundColor, content: SingleChildScrollView( - child: Text(analyzeText, style: AppTheme.moveHistoryTextStyle)), + child: Text(analyzeText, style: AppTheme.moveHistoryTextStyle), + ), actions: [ TextButton( child: @@ -1187,7 +1206,7 @@ class _GamePageState extends State ); } - setPrivacyPolicyAccepted(bool value) async { + Future setPrivacyPolicyAccepted(bool value) async { setState(() { Config.isPrivacyPolicyAccepted = value; }); @@ -1197,17 +1216,17 @@ class _GamePageState extends State Config.save(); } - onShowPrivacyDialog() async { + Future onShowPrivacyDialog() async { showPrivacyDialog(context, setPrivacyPolicyAccepted); } String getGameOverReasonString(GameOverReason? reason, String? winner) { //String winnerStr = // winner == Color.white ? S.of(context).white : S.of(context).black; - String loserStr = + final String loserStr = winner == PieceColor.white ? S.of(context).black : S.of(context).white; - Map reasonMap = { + final Map reasonMap = { GameOverReason.loseReasonlessThanThree: loserStr + S.of(context).loseReasonlessThanThree, GameOverReason.loseReasonResign: @@ -1241,7 +1260,7 @@ class _GamePageState extends State return loseReasonStr; } - GameResult getGameResult(var winner) { + GameResult getGameResult(String winner) { if (isAi[PieceColor.white]! && isAi[PieceColor.black]!) { return GameResult.none; } @@ -1269,8 +1288,8 @@ class _GamePageState extends State return GameResult.none; } - void showGameResult(var winner) { - GameResult result = getGameResult(winner); + void showGameResult(String winner) { + final GameResult result = getGameResult(winner); Game.instance.position.result = result; switch (result) { @@ -1286,7 +1305,7 @@ class _GamePageState extends State break; } - Map retMap = { + final Map retMap = { GameResult.win: Game.instance.engineType == EngineType.humanVsAi ? S.of(context).youWin : S.of(context).gameOver, @@ -1294,25 +1313,25 @@ class _GamePageState extends State GameResult.draw: S.of(context).isDraw }; - var dialogTitle = retMap[result]; + final dialogTitle = retMap[result]; if (dialogTitle == null) { return; } - bool isTopLevel = (Config.skillLevel == 30); // TODO: 30 + final bool isTopLevel = Config.skillLevel == 30; // TODO: 30 if (result == GameResult.win && !isTopLevel && Game.instance.engineType == EngineType.humanVsAi) { var contentStr = getGameOverReasonString( - Game.instance.position.gameOverReason, Game.instance.position.winner); + Game.instance.position.gameOverReason, + Game.instance.position.winner, + ); if (!isTopLevel) { - contentStr += "\n\n" + - S.of(context).challengeHarderLevel + - (Config.skillLevel + 1).toString() + - "!"; + contentStr += + "\n\n${S.of(context).challengeHarderLevel}${Config.skillLevel + 1}!"; } showDialog( @@ -1320,11 +1339,13 @@ class _GamePageState extends State barrierDismissible: true, builder: (BuildContext context) { return AlertDialog( - title: Text(dialogTitle, - style: TextStyle( - color: AppTheme.dialogTitleColor, - fontSize: Config.fontSize + 4, - )), + title: Text( + dialogTitle, + style: TextStyle( + color: AppTheme.dialogTitleColor, + fontSize: Config.fontSize + 4, + ), + ), content: Text( contentStr, style: TextStyle( @@ -1333,27 +1354,29 @@ class _GamePageState extends State ), actions: [ TextButton( - child: Text( - S.of(context).yes, - style: TextStyle( - fontSize: Config.fontSize, - ), + child: Text( + S.of(context).yes, + style: TextStyle( + fontSize: Config.fontSize, ), - onPressed: () async { - if (!isTopLevel) Config.skillLevel++; - Config.save(); - await widget.engine.setOptions(context); - print("[config] skillLevel: ${Config.skillLevel}"); - Navigator.of(context).pop(); - }), + ), + onPressed: () async { + if (!isTopLevel) Config.skillLevel++; + Config.save(); + await widget.engine.setOptions(context); + print("[config] skillLevel: ${Config.skillLevel}"); + Navigator.of(context).pop(); + }, + ), TextButton( - child: Text( - S.of(context).no, - style: TextStyle( - fontSize: Config.fontSize, - ), + child: Text( + S.of(context).no, + style: TextStyle( + fontSize: Config.fontSize, ), - onPressed: () => Navigator.of(context).pop()), + ), + onPressed: () => Navigator.of(context).pop(), + ), ], ); }, @@ -1364,14 +1387,18 @@ class _GamePageState extends State barrierDismissible: true, builder: (BuildContext context) { return AlertDialog( - title: Text(dialogTitle, - style: TextStyle( - color: AppTheme.dialogTitleColor, - fontSize: Config.fontSize + 4, - )), + title: Text( + dialogTitle, + style: TextStyle( + color: AppTheme.dialogTitleColor, + fontSize: Config.fontSize + 4, + ), + ), content: Text( - getGameOverReasonString(Game.instance.position.gameOverReason, - Game.instance.position.winner), + getGameOverReasonString( + Game.instance.position.gameOverReason, + Game.instance.position.winner, + ), style: TextStyle( fontSize: Config.fontSize, ), @@ -1402,13 +1429,14 @@ class _GamePageState extends State }, ), TextButton( - child: Text( - S.of(context).cancel, - style: TextStyle( - fontSize: Config.fontSize, - ), + child: Text( + S.of(context).cancel, + style: TextStyle( + fontSize: Config.fontSize, ), - onPressed: () => Navigator.of(context).pop()), + ), + onPressed: () => Navigator.of(context).pop(), + ), ], ); }, @@ -1420,7 +1448,8 @@ class _GamePageState extends State // // when screen's height/width rate is less than 16/9, limit width of board final windowSize = MediaQuery.of(context).size; - double height = windowSize.height, width = windowSize.width; + final double height = windowSize.height; + double width = windowSize.width; if (height / width < 16.0 / 9.0) { width = height * 9 / 16; @@ -1430,7 +1459,7 @@ class _GamePageState extends State } Widget createPageHeader() { - Map engineTypeToIconLeft = { + final Map engineTypeToIconLeft = { EngineType.humanVsAi: Config.aiMovesFirst ? FluentIcons.bot_24_filled : FluentIcons.person_24_filled, @@ -1441,7 +1470,7 @@ class _GamePageState extends State EngineType.testViaLAN: FluentIcons.wifi_1_24_filled, }; - Map engineTypeToIconRight = { + final Map engineTypeToIconRight = { EngineType.humanVsAi: Config.aiMovesFirst ? FluentIcons.person_24_filled : FluentIcons.bot_24_filled, @@ -1452,17 +1481,17 @@ class _GamePageState extends State EngineType.testViaLAN: FluentIcons.wifi_1_24_filled, }; - IconData iconArrow = getIconArrow(); + final IconData iconArrow = getIconArrow(); - var iconColor = Color(Config.messageColor); + final iconColor = Color(Config.messageColor); - var iconRow = Row( + final iconRow = Row( children: [ - Expanded(child: SizedBox()), + const Expanded(child: SizedBox()), Icon(engineTypeToIconLeft[widget.engineType], color: iconColor), Icon(iconArrow, color: iconColor), Icon(engineTypeToIconRight[widget.engineType], color: iconColor), - Expanded(child: SizedBox()), + const Expanded(child: SizedBox()), ], ); @@ -1474,19 +1503,21 @@ class _GamePageState extends State Container( height: 4, width: 180, - margin: EdgeInsets.only(bottom: 10), + margin: const EdgeInsets.only(bottom: 10), decoration: BoxDecoration( color: Color(Config.boardBackgroundColor), borderRadius: BorderRadius.circular(2), ), ), Container( - padding: EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( _tip!, maxLines: 1, style: TextStyle( - fontSize: Config.fontSize, color: Color(Config.messageColor)), + fontSize: Config.fontSize, + color: Color(Config.messageColor), + ), ), // TODO: Font Size ), ], @@ -1549,10 +1580,10 @@ class _GamePageState extends State String getInfoText() { String phase = ""; - String period = Config.screenReaderSupport ? "." : ""; - String comma = Config.screenReaderSupport ? "," : ""; + final String period = Config.screenReaderSupport ? "." : ""; + final String comma = Config.screenReaderSupport ? "," : ""; - var pos = Game.instance.position; + final pos = Game.instance.position; switch (pos.phase) { case Phase.placing: @@ -1565,21 +1596,8 @@ class _GamePageState extends State break; } - String pieceCountInHand = pos.phase == Phase.placing - ? S.of(context).player1 + - " " + - S.of(context).inHand + - ": " + - pos.pieceInHandCount[PieceColor.white].toString() + - comma + - "\n" + - S.of(context).player2 + - " " + - S.of(context).inHand + - ": " + - pos.pieceInHandCount[PieceColor.black].toString() + - comma + - "\n" + final String pieceCountInHand = pos.phase == Phase.placing + ? "${S.of(context).player1} ${S.of(context).inHand}: ${pos.pieceInHandCount[PieceColor.white]}$comma\n${S.of(context).player2} ${S.of(context).inHand}: ${pos.pieceInHandCount[PieceColor.black]}$comma\n" : ""; String us = ""; @@ -1592,90 +1610,43 @@ class _GamePageState extends State them = S.of(context).player1; } - String tip = (_tip == null || !Config.screenReaderSupport) ? "" : "\n$_tip"; + final String tip = + (_tip == null || !Config.screenReaderSupport) ? "" : "\n$_tip"; String lastMove = ""; - if (pos.recorder != null && - pos.recorder.lastMove != null && - pos.recorder.lastMove.notation != null) { - String n1 = pos.recorder.lastMove.notation; + if (pos.recorder?.lastMove?.notation != null) { + final String n1 = pos.recorder!.lastMove!.notation!; if (n1.startsWith("x")) { - String n2 = pos.recorder.moveAt(pos.recorder.movesCount - 2).notation; + final String n2 = + pos.recorder!.moveAt(pos.recorder!.movesCount - 2).notation!; lastMove = n2 + n1; } else { lastMove = n1; } if (Config.screenReaderSupport) { - lastMove = S.of(context).lastMove + - ": " + - them + - ", " + - lastMove + - period + - "\n"; + lastMove = "${S.of(context).lastMove}: $them, $lastMove$period\n"; } else { - lastMove = S.of(context).lastMove + ": " + lastMove + period + "\n"; + lastMove = "${S.of(context).lastMove}: $lastMove$period\n"; } } String addedPeriod = ""; if (Config.screenReaderSupport && - tip.length >= 1 && + tip.isNotEmpty && tip[tip.length - 1] != '.' && tip[tip.length - 1] != '!') { addedPeriod = "."; } - String ret = phase + - period + - "\n" + - lastMove + - S.of(context).sideToMove + - ": " + - us + - period + - tip + - addedPeriod + - "\n\n" + - S.of(context).pieceCount + - ":\n" + - pieceCountInHand + - S.of(context).player1 + - " " + - S.of(context).onBoard + - ": " + - pos.pieceOnBoardCount[PieceColor.white].toString() + - comma + - "\n" + - S.of(context).player2 + - " " + - S.of(context).onBoard + - ": " + - pos.pieceOnBoardCount[PieceColor.black].toString() + - period + - "\n\n" + - S.of(context).score + - ":\n" + - S.of(context).player1 + - ": " + - pos.score[PieceColor.white].toString() + - comma + - "\n" + - S.of(context).player2 + - ": " + - pos.score[PieceColor.black].toString() + - comma + - "\n" + - S.of(context).draw + - ": " + - pos.score[PieceColor.draw].toString() + - period; + final String ret = + "$phase$period\n$lastMove${S.of(context).sideToMove}: $us$period$tip$addedPeriod\n\n${S.of(context).pieceCount}:\n$pieceCountInHand${S.of(context).player1} ${S.of(context).onBoard}: ${pos.pieceOnBoardCount[PieceColor.white]}$comma\n${S.of(context).player2} ${S.of(context).onBoard}: ${pos.pieceOnBoardCount[PieceColor.black]}$period\n\n${S.of(context).score}:\n${S.of(context).player1}: ${pos.score[PieceColor.white]}$comma\n${S.of(context).player2}: ${pos.score[PieceColor.black]}$comma\n${S.of(context).draw}: ${pos.score[PieceColor.draw]}$period"; return ret; } Widget createToolbar() { - var gameButton = TextButton( + final gameButton = TextButton( + onPressed: onGameButtonPressed, child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1683,14 +1654,16 @@ class _GamePageState extends State FluentIcons.table_simple_24_regular, color: Color(Config.mainToolbarIconColor), ), - Text(S.of(context).game, - style: TextStyle(color: Color(Config.mainToolbarIconColor))), + Text( + S.of(context).game, + style: TextStyle(color: Color(Config.mainToolbarIconColor)), + ), ], ), - onPressed: onGameButtonPressed, ); - var optionsButton = TextButton( + final optionsButton = TextButton( + onPressed: onOptionButtonPressed, child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1698,14 +1671,16 @@ class _GamePageState extends State FluentIcons.settings_24_regular, color: Color(Config.mainToolbarIconColor), ), - Text(S.of(context).options, - style: TextStyle(color: Color(Config.mainToolbarIconColor))), + Text( + S.of(context).options, + style: TextStyle(color: Color(Config.mainToolbarIconColor)), + ), ], ), - onPressed: onOptionButtonPressed, ); - var moveButton = TextButton( + final moveButton = TextButton( + onPressed: onMoveButtonPressed, child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1713,14 +1688,16 @@ class _GamePageState extends State FluentIcons.calendar_agenda_24_regular, color: Color(Config.mainToolbarIconColor), ), - Text(S.of(context).move, - style: TextStyle(color: Color(Config.mainToolbarIconColor))), + Text( + S.of(context).move, + style: TextStyle(color: Color(Config.mainToolbarIconColor)), + ), ], ), - onPressed: onMoveButtonPressed, ); - var infoButton = TextButton( + final infoButton = TextButton( + onPressed: onInfoButtonPressed, child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1728,11 +1705,12 @@ class _GamePageState extends State FluentIcons.book_information_24_regular, color: Color(Config.mainToolbarIconColor), ), - Text(S.of(context).info, - style: TextStyle(color: Color(Config.mainToolbarIconColor))), + Text( + S.of(context).info, + style: TextStyle(color: Color(Config.mainToolbarIconColor)), + ), ], ), - onPressed: onInfoButtonPressed, ); return Container( @@ -1741,23 +1719,26 @@ class _GamePageState extends State color: Color(Config.mainToolbarBackgroundColor), ), margin: EdgeInsets.symmetric(horizontal: GamePage.screenPaddingH), - padding: EdgeInsets.symmetric(vertical: 2), - child: Row(textDirection: TextDirection.ltr, children: [ - Expanded(child: SizedBox()), - gameButton, - Expanded(child: SizedBox()), - optionsButton, - Expanded(child: SizedBox()), - moveButton, - Expanded(child: SizedBox()), //dashboard_outlined - infoButton, - Expanded(child: SizedBox()), - ]), + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + textDirection: TextDirection.ltr, + children: [ + const Expanded(child: SizedBox()), + gameButton, + const Expanded(child: SizedBox()), + optionsButton, + const Expanded(child: SizedBox()), + moveButton, + const Expanded(child: SizedBox()), //dashboard_outlined + infoButton, + const Expanded(child: SizedBox()), + ], + ), ); } Widget createHistoryNavigationToolbar() { - var takeBackAllButton = TextButton( + final takeBackAllButton = TextButton( child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1775,7 +1756,7 @@ class _GamePageState extends State onPressed: () => onTakeBackAllButtonPressed(pop: false), ); - var takeBackButton = TextButton( + final takeBackButton = TextButton( child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1793,7 +1774,7 @@ class _GamePageState extends State onPressed: () => onTakeBackButtonPressed(pop: false), ); - var stepForwardButton = TextButton( + final stepForwardButton = TextButton( child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1811,7 +1792,7 @@ class _GamePageState extends State onPressed: () => onStepForwardButtonPressed(pop: false), ); - var stepForwardAllButton = TextButton( + final stepForwardAllButton = TextButton( child: Column( // Replace with a Row for horizontal icon + text children: [ @@ -1835,25 +1816,31 @@ class _GamePageState extends State color: Color(Config.navigationToolbarBackgroundColor), ), margin: EdgeInsets.symmetric(horizontal: GamePage.screenPaddingH), - padding: EdgeInsets.symmetric(vertical: 2), - child: Row(textDirection: TextDirection.ltr, children: [ - Expanded(child: SizedBox()), - takeBackAllButton, - Expanded(child: SizedBox()), - takeBackButton, - Expanded(child: SizedBox()), - stepForwardButton, - Expanded(child: SizedBox()), //dashboard_outlined - stepForwardAllButton, - Expanded(child: SizedBox()), - ]), + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + textDirection: TextDirection.ltr, + children: [ + const Expanded(child: SizedBox()), + takeBackAllButton, + const Expanded(child: SizedBox()), + takeBackButton, + const Expanded(child: SizedBox()), + stepForwardButton, + const Expanded(child: SizedBox()), //dashboard_outlined + stepForwardAllButton, + const Expanded(child: SizedBox()), + ], + ), ); } @override void didChangeDependencies() { super.didChangeDependencies(); - routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute); + routeObserver.subscribe( + this, + ModalRoute.of(context)! as PageRoute, + ); } @override @@ -1873,15 +1860,18 @@ class _GamePageState extends State return Scaffold( backgroundColor: Color(Config.darkBackgroundColor), - body: Column(children: [ - BlockSemantics(child: header), - board, - Config.isHistoryNavigationToolbarShown - ? historyNavToolbar - : SizedBox(height: 0), - SizedBox(height: 1), - toolbar, - ]), + body: Column( + children: [ + BlockSemantics(child: header), + board, + if (Config.isHistoryNavigationToolbarShown) + historyNavToolbar + else + const SizedBox(height: 0), + const SizedBox(height: 1), + toolbar, + ], + ), /* body: Column(children: [ header, @@ -1908,7 +1898,7 @@ class _GamePageState extends State } @override - void didPush() async { + Future didPush() async { final route = ModalRoute.of(context)!.settings.name; debugPrint('$tag Game Page didPush route: $route'); await widget.engine.setOptions(context); @@ -1919,7 +1909,7 @@ class _GamePageState extends State } @override - void didPopNext() async { + Future didPopNext() async { final route = ModalRoute.of(context)!.settings.name; debugPrint('$tag Game Page didPopNext route: $route'); await widget.engine.setOptions(context); @@ -1929,7 +1919,7 @@ class _GamePageState extends State } @override - void didPushNext() async { + Future didPushNext() async { final route = ModalRoute.of(context)!.settings.name; debugPrint('$tag Game Page didPushNext route: $route'); await widget.engine.setOptions(context); diff --git a/src/ui/flutter_app/lib/widgets/game_settings_page.dart b/src/ui/flutter_app/lib/widgets/game_settings_page.dart index 2ad0818c..6ed88c53 100644 --- a/src/ui/flutter_app/lib/widgets/game_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_settings_page.dart @@ -33,6 +33,7 @@ import 'env_page.dart'; import 'list_item_divider.dart'; class Developer { + const Developer._(); static bool developerModeEnabled = false; } @@ -42,12 +43,12 @@ class GameSettingsPage extends StatefulWidget { } class _GameSettingsPageState extends State { - Color pickerColor = Color(0xFF808080); - Color currentColor = Color(0xFF808080); + Color pickerColor = const Color(0xFF808080); + Color currentColor = const Color(0xFF808080); late StreamController _events; - var algorithmNames = ['Alpha-Beta', 'PVS', 'MTD(f)']; + List algorithmNames = ['Alpha-Beta', 'PVS', 'MTD(f)']; final String tag = "[game_settings_page]"; @@ -58,12 +59,12 @@ class _GameSettingsPageState extends State { _events.add(10); } - void _restore() async { + Future _restore() async { final settings = await Settings.instance(); await settings.restore(); } - SliderTheme _skillLevelSliderTheme(context, setState) { + SliderTheme _skillLevelSliderTheme(BuildContext context, Function setState) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( @@ -73,7 +74,7 @@ class _GameSettingsPageState extends State { min: 1, max: 30, divisions: 29, - label: Config.skillLevel.round().toString(), + label: Config.skillLevel.toString(), onChanged: (value) { setState(() { debugPrint("[config] Slider value: $value"); @@ -86,17 +87,16 @@ class _GameSettingsPageState extends State { ); } - SliderTheme _moveTimeSliderTheme(context, setState) { + SliderTheme _moveTimeSliderTheme(BuildContext context, Function setState) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).moveTime, child: Slider( value: Config.moveTime.toDouble(), - min: 0, max: 60, divisions: 60, - label: Config.moveTime.round().toString(), + label: Config.moveTime.toString(), onChanged: (value) { setState(() { debugPrint("[config] Slider value: $value"); @@ -111,8 +111,8 @@ class _GameSettingsPageState extends State { // Restore - restoreFactoryDefaultSettings() async { - confirm() async { + Future restoreFactoryDefaultSettings() async { + Future confirm() async { Navigator.of(context).pop(); if (Platform.isAndroid) { showCountdownDialog(context, 10, _events, _restore); @@ -120,11 +120,12 @@ class _GameSettingsPageState extends State { _restore(); ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(S.of(context).exitAppManually))); + SnackBar(content: Text(S.of(context).exitAppManually)), + ); } } - cancel() => Navigator.of(context).pop(); + void cancel() => Navigator.of(context).pop(); var prompt = ""; @@ -136,14 +137,16 @@ class _GameSettingsPageState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text(S.of(context).restore, - style: TextStyle( - color: AppTheme.dialogTitleColor, - fontSize: Config.fontSize + 4, - )), + title: Text( + S.of(context).restore, + style: TextStyle( + color: AppTheme.dialogTitleColor, + fontSize: Config.fontSize + 4, + ), + ), content: SingleChildScrollView( child: Text( - S.of(context).restoreDefaultSettings + "?\n" + prompt, + "${S.of(context).restoreDefaultSettings}?\n$prompt", style: TextStyle( fontSize: Config.fontSize, ), @@ -151,21 +154,23 @@ class _GameSettingsPageState extends State { ), actions: [ TextButton( - child: Text( - S.of(context).ok, - style: TextStyle( - fontSize: Config.fontSize, - ), + onPressed: confirm, + child: Text( + S.of(context).ok, + style: TextStyle( + fontSize: Config.fontSize, ), - onPressed: confirm), + ), + ), TextButton( - child: Text( - S.of(context).cancel, - style: TextStyle( - fontSize: Config.fontSize, - ), + onPressed: cancel, + child: Text( + S.of(context).cancel, + style: TextStyle( + fontSize: Config.fontSize, ), - onPressed: cancel), + ), + ), ], ); }, @@ -205,7 +210,7 @@ class _GameSettingsPageState extends State { ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).difficulty, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -216,7 +221,7 @@ class _GameSettingsPageState extends State { //trailingString: "L" + Config.skillLevel.toString(), onTap: setSkillLevel, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).moveTime, @@ -224,7 +229,7 @@ class _GameSettingsPageState extends State { ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).aisPlayStyle, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -235,28 +240,28 @@ class _GameSettingsPageState extends State { trailingString: algorithmNames[Config.algorithm], onTap: setAlgorithm, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.drawOnHumanExperience, onChanged: setDrawOnHumanExperience, titleString: S.of(context).drawOnHumanExperience, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.considerMobility, onChanged: setConsiderMobility, titleString: S.of(context).considerMobility, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.aiIsLazy, onChanged: setAiIsLazy, titleString: S.of(context).passive, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.shufflingEnabled, @@ -265,33 +270,36 @@ class _GameSettingsPageState extends State { ), ], ), - !Platform.isWindows - ? SizedBox(height: AppTheme.sizedBoxHeight) - : Container(height: 0.0, width: 0.0), - !Platform.isWindows - ? Text(S.of(context).playSounds, style: AppTheme.settingsHeaderStyle) - : Container(height: 0.0, width: 0.0), - !Platform.isWindows - ? SettingsCard( + if (!Platform.isWindows) + const SizedBox(height: AppTheme.sizedBoxHeight) + else + const SizedBox(height: 0.0, width: 0.0), + if (!Platform.isWindows) + Text(S.of(context).playSounds, style: AppTheme.settingsHeaderStyle) + else + const SizedBox(height: 0.0, width: 0.0), + if (!Platform.isWindows) + SettingsCard( + context: context, + children: [ + SettingsSwitchListTile( context: context, - children: [ - SettingsSwitchListTile( - context: context, - value: Config.toneEnabled, - onChanged: setTone, - titleString: S.of(context).playSoundsInTheGame, - ), - ListItemDivider(), - SettingsSwitchListTile( - context: context, - value: Config.keepMuteWhenTakingBack, - onChanged: setKeepMuteWhenTakingBack, - titleString: S.of(context).keepMuteWhenTakingBack, - ), - ], - ) - : Container(height: 0.0, width: 0.0), - SizedBox(height: AppTheme.sizedBoxHeight), + value: Config.toneEnabled, + onChanged: setTone, + titleString: S.of(context).playSoundsInTheGame, + ), + const ListItemDivider(), + SettingsSwitchListTile( + context: context, + value: Config.keepMuteWhenTakingBack, + onChanged: setKeepMuteWhenTakingBack, + titleString: S.of(context).keepMuteWhenTakingBack, + ), + ], + ) + else + const SizedBox(height: 0.0, width: 0.0), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).accessibility, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -304,7 +312,7 @@ class _GameSettingsPageState extends State { ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).restore, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -314,80 +322,80 @@ class _GameSettingsPageState extends State { titleString: S.of(context).restoreDefaultSettings, onTap: restoreFactoryDefaultSettings, ), - ListItemDivider(), + const ListItemDivider(), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), - Developer.developerModeEnabled - ? Text(S.of(context).forDevelopers, - style: AppTheme.settingsHeaderStyle) - : SizedBox(height: 1), - Developer.developerModeEnabled - ? SettingsCard( + const SizedBox(height: AppTheme.sizedBoxHeight), + if (Developer.developerModeEnabled) + Text( + S.of(context).forDevelopers, + style: AppTheme.settingsHeaderStyle, + ) + else + const SizedBox(height: 1), + if (Developer.developerModeEnabled) + SettingsCard( + context: context, + children: [ + SettingsSwitchListTile( context: context, - children: [ - SettingsSwitchListTile( - context: context, - value: Config.developerMode, - onChanged: setDeveloperMode, - titleString: S.of(context).developerMode, - ), - ListItemDivider(), - SettingsSwitchListTile( - context: context, - value: Config.experimentsEnabled, - onChanged: setExperimentsEnabled, - titleString: S.of(context).experiments, - ), - ListItemDivider(), - SettingsSwitchListTile( - context: context, - value: Config.isAutoRestart, - onChanged: setIsAutoRestart, - titleString: S.of(context).isAutoRestart, - ), - ListItemDivider(), - SettingsListTile( - context: context, - titleString: S.of(context).environmentVariables, - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EnvironmentVariablesPage(), - ), - ); - }, - ), - ], - ) - : SizedBox(height: 1), + value: Config.developerMode, + onChanged: setDeveloperMode, + titleString: S.of(context).developerMode, + ), + const ListItemDivider(), + SettingsSwitchListTile( + context: context, + value: Config.experimentsEnabled, + onChanged: setExperimentsEnabled, + titleString: S.of(context).experiments, + ), + const ListItemDivider(), + SettingsSwitchListTile( + context: context, + value: Config.isAutoRestart, + onChanged: setIsAutoRestart, + titleString: S.of(context).isAutoRestart, + ), + const ListItemDivider(), + SettingsListTile( + context: context, + titleString: S.of(context).environmentVariables, + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => EnvironmentVariablesPage(), + ), + ); + }, + ), + ], + ) + else + const SizedBox(height: 1), ]; } - setSkillLevel() async { + Future setSkillLevel() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _skillLevelSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _skillLevelSliderTheme, ), ); } - setMoveTime() async { + Future setMoveTime() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _moveTimeSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _moveTimeSliderTheme, ), ); } - setWhoMovesFirst(bool value) async { + Future setWhoMovesFirst(bool value) async { setState(() { Config.aiMovesFirst = !value; }); @@ -397,7 +405,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setAiIsLazy(bool value) async { + Future setAiIsLazy(bool value) async { setState(() { Config.aiIsLazy = value; }); @@ -407,8 +415,8 @@ class _GameSettingsPageState extends State { Config.save(); } - setAlgorithm() { - callback(int? algorithm) async { + void setAlgorithm() { + Future callback(int? algorithm) async { debugPrint("[config] algorithm = $algorithm"); Navigator.of(context).pop(); @@ -431,35 +439,35 @@ class _GameSettingsPageState extends State { children: [ RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('Alpha-Beta'), + title: const Text('Alpha-Beta'), groupValue: Config.algorithm, value: 0, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('PVS'), + title: const Text('PVS'), groupValue: Config.algorithm, value: 1, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('MTD(f)'), + title: const Text('MTD(f)'), groupValue: Config.algorithm, value: 2, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), ], ), ), ); } - setDrawOnHumanExperience(bool value) async { + Future setDrawOnHumanExperience(bool value) async { setState(() { Config.drawOnHumanExperience = value; }); @@ -469,7 +477,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setConsiderMobility(bool value) async { + Future setConsiderMobility(bool value) async { setState(() { Config.considerMobility = value; }); @@ -479,7 +487,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setIsAutoRestart(bool value) async { + Future setIsAutoRestart(bool value) async { setState(() { Config.isAutoRestart = value; }); @@ -489,7 +497,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setIsAutoChangeFirstMove(bool value) async { + Future setIsAutoChangeFirstMove(bool value) async { setState(() { Config.isAutoChangeFirstMove = value; }); @@ -499,7 +507,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setResignIfMostLose(bool value) async { + Future setResignIfMostLose(bool value) async { setState(() { Config.resignIfMostLose = value; }); @@ -509,7 +517,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setShufflingEnabled(bool value) async { + Future setShufflingEnabled(bool value) async { setState(() { Config.shufflingEnabled = value; }); @@ -519,7 +527,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setLearnEndgame(bool value) async { + Future setLearnEndgame(bool value) async { setState(() { Config.learnEndgame = value; }); @@ -529,7 +537,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setOpeningBook(bool value) async { + Future setOpeningBook(bool value) async { setState(() { Config.openingBook = value; }); @@ -539,7 +547,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setTone(bool value) async { + Future setTone(bool value) async { setState(() { Config.toneEnabled = value; }); @@ -549,7 +557,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setKeepMuteWhenTakingBack(bool value) async { + Future setKeepMuteWhenTakingBack(bool value) async { setState(() { Config.keepMuteWhenTakingBack = value; }); @@ -559,7 +567,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setScreenReaderSupport(bool value) async { + Future setScreenReaderSupport(bool value) async { setState(() { Config.screenReaderSupport = value; }); @@ -569,7 +577,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setDeveloperMode(bool value) async { + Future setDeveloperMode(bool value) async { setState(() { Config.developerMode = value; }); @@ -579,7 +587,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setExperimentsEnabled(bool value) async { + Future setExperimentsEnabled(bool value) async { setState(() { Config.experimentsEnabled = value; }); @@ -591,7 +599,7 @@ class _GameSettingsPageState extends State { // Display - setLanguage(String value) async { + Future setLanguage(String value) async { setState(() { Config.languageCode = value; }); @@ -601,7 +609,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setIsPieceCountInHandShown(bool value) async { + Future setIsPieceCountInHandShown(bool value) async { setState(() { Config.isPieceCountInHandShown = value; }); @@ -611,7 +619,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setIsNotationsShown(bool value) async { + Future setIsNotationsShown(bool value) async { setState(() { Config.isNotationsShown = value; }); @@ -621,7 +629,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setIsHistoryNavigationToolbarShown(bool value) async { + Future setIsHistoryNavigationToolbarShown(bool value) async { setState(() { Config.isHistoryNavigationToolbarShown = value; }); @@ -631,7 +639,7 @@ class _GameSettingsPageState extends State { Config.save(); } - setStandardNotationEnabled(bool value) async { + Future setStandardNotationEnabled(bool value) async { setState(() { Config.standardNotationEnabled = value; }); diff --git a/src/ui/flutter_app/lib/widgets/help_screen.dart b/src/ui/flutter_app/lib/widgets/help_screen.dart index 6939517a..d0b2f967 100644 --- a/src/ui/flutter_app/lib/widgets/help_screen.dart +++ b/src/ui/flutter_app/lib/widgets/help_screen.dart @@ -25,10 +25,14 @@ class _HelpScreenState extends State { backgroundColor: Color(Config.darkBackgroundColor), body: ListView( children: [ - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Container( padding: const EdgeInsets.only( - top: 48, left: 16, right: 16, bottom: 16), + top: 48, + left: 16, + right: 16, + bottom: 16, + ), child: Text( S.of(context).howToPlay, style: TextStyle( @@ -40,7 +44,11 @@ class _HelpScreenState extends State { ), Container( padding: const EdgeInsets.only( - top: 16, left: 16, right: 16, bottom: 16), + top: 16, + left: 16, + right: 16, + bottom: 16, + ), child: Text( S.of(context).helpContent, style: TextStyle( diff --git a/src/ui/flutter_app/lib/widgets/home_drawer.dart b/src/ui/flutter_app/lib/widgets/home_drawer.dart index 29c9b7cd..58c668b4 100644 --- a/src/ui/flutter_app/lib/widgets/home_drawer.dart +++ b/src/ui/flutter_app/lib/widgets/home_drawer.dart @@ -49,12 +49,12 @@ class DrawerListItem { } class HomeDrawer extends StatefulWidget { - const HomeDrawer( - {Key? key, - this.screenIndex, - this.iconAnimationController, - this.callBackIndex}) - : super(key: key); + const HomeDrawer({ + Key? key, + this.screenIndex, + this.iconAnimationController, + this.callBackIndex, + }) : super(key: key); final AnimationController? iconAnimationController; final DrawerIndex? screenIndex; @@ -76,77 +76,83 @@ class _HomeDrawerState extends State { @override Widget build(BuildContext context) { - List drawerList = [ + final List drawerList = [ DrawerListItem( index: DrawerIndex.humanVsAi, title: S.of(context).humanVsAi, - icon: Icon(FluentIcons.person_24_regular), + icon: const Icon(FluentIcons.person_24_regular), ), DrawerListItem( index: DrawerIndex.humanVsHuman, title: S.of(context).humanVsHuman, - icon: Icon(FluentIcons.people_24_regular), + icon: const Icon(FluentIcons.people_24_regular), ), DrawerListItem( index: DrawerIndex.aiVsAi, title: S.of(context).aiVsAi, - icon: Icon(FluentIcons.bot_24_regular), + icon: const Icon(FluentIcons.bot_24_regular), ), DrawerListItem( index: DrawerIndex.preferences, title: S.of(context).preferences, - icon: Icon(FluentIcons.options_24_regular), + icon: const Icon(FluentIcons.options_24_regular), ), DrawerListItem( index: DrawerIndex.ruleSettings, title: S.of(context).ruleSettings, - icon: Icon(FluentIcons.task_list_ltr_24_regular), + icon: const Icon(FluentIcons.task_list_ltr_24_regular), ), DrawerListItem( index: DrawerIndex.personalization, title: S.of(context).personalization, - icon: Icon(FluentIcons.design_ideas_24_regular), + icon: const Icon(FluentIcons.design_ideas_24_regular), ), DrawerListItem( index: DrawerIndex.feedback, title: S.of(context).feedback, - icon: Icon(FluentIcons.chat_warning_24_regular), + icon: const Icon(FluentIcons.chat_warning_24_regular), ), DrawerListItem( index: DrawerIndex.Help, title: S.of(context).help, - icon: Icon(FluentIcons.question_circle_24_regular), + icon: const Icon(FluentIcons.question_circle_24_regular), ), DrawerListItem( index: DrawerIndex.About, title: S.of(context).about, - icon: Icon(FluentIcons.info_24_regular), + icon: const Icon(FluentIcons.info_24_regular), ), ]; - var rotationTransition = RotationTransition( - turns: AlwaysStoppedAnimation(Tween(begin: 0.0, end: 24.0) - .animate(CurvedAnimation( - parent: widget.iconAnimationController!, - curve: Curves.fastOutSlowIn)) - .value / - 360), + final rotationTransition = RotationTransition( + turns: AlwaysStoppedAnimation( + Tween(begin: 0.0, end: 24.0) + .animate( + CurvedAnimation( + parent: widget.iconAnimationController!, + curve: Curves.fastOutSlowIn, + ), + ) + .value / + 360, + ), ); - var scaleTransition = ScaleTransition( + final scaleTransition = ScaleTransition( scale: AlwaysStoppedAnimation( - 1.0 - (widget.iconAnimationController!.value) * 0.2), + 1.0 - (widget.iconAnimationController!.value) * 0.2, + ), child: rotationTransition, ); - var animatedBuilder = AnimatedBuilder( + final animatedBuilder = AnimatedBuilder( animation: widget.iconAnimationController!, builder: (BuildContext context, Widget? child) { return scaleTransition; }, ); - var animatedTextsColors = [ + final animatedTextsColors = [ Color(Config.drawerTextColor), Colors.black, Colors.blue, @@ -157,7 +163,7 @@ class _HomeDrawerState extends State { Color(Config.drawerHighlightItemColor), ]; - var animatedTextKit = AnimatedTextKit( + final animatedTextKit = AnimatedTextKit( animatedTexts: [ ColorizeAnimatedText( S.of(context).appName, @@ -166,8 +172,7 @@ class _HomeDrawerState extends State { fontWeight: FontWeight.w600, ), colors: animatedTextsColors, - textAlign: TextAlign.start, - speed: const Duration(milliseconds: 3000), + speed: const Duration(seconds: 3), ), ], pause: const Duration(milliseconds: 30000), @@ -186,19 +191,17 @@ class _HomeDrawerState extends State { } }); - var drawerHeader = Container( + final drawerHeader = Container( width: double.infinity, - padding: const EdgeInsets.only(top: 0.0), + padding: EdgeInsets.zero, child: Container( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, children: [ animatedBuilder, Padding( - padding: - EdgeInsets.only(top: (isLargeScreen() ? 30 : 8), left: 4), + padding: EdgeInsets.only(top: isLargeScreen() ? 30 : 8, left: 4), child: ExcludeSemantics(child: animatedTextKit), ), ], @@ -240,11 +243,10 @@ class _HomeDrawerState extends State { ); */ - var scaffold = Scaffold( + final scaffold = Scaffold( backgroundColor: Color(Config.drawerBackgroundColor), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.start, children: [ drawerHeader, const SizedBox(height: 4), @@ -252,7 +254,7 @@ class _HomeDrawerState extends State { Expanded( child: ListView.builder( physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.all(0.0), + padding: EdgeInsets.zero, itemCount: drawerList.length, itemBuilder: (BuildContext context, int index) { return buildInkwell(drawerList[index]); @@ -273,25 +275,27 @@ class _HomeDrawerState extends State { } Widget buildInkwell(DrawerListItem listItem) { - bool ltr = getBidirectionality(context) == Bidirectionality.leftToRight; - double radius = 28.0; - var animatedBuilder = AnimatedBuilder( + final bool ltr = + getBidirectionality(context) == Bidirectionality.leftToRight; + const double radius = 28.0; + final animatedBuilder = AnimatedBuilder( animation: widget.iconAnimationController!, builder: (BuildContext context, Widget? child) { return Transform( transform: Matrix4.translationValues( - (MediaQuery.of(context).size.width * 0.75 - 64) * - (1.0 - widget.iconAnimationController!.value - 1.0), - 0.0, - 0.0), + (MediaQuery.of(context).size.width * 0.75 - 64) * + (1.0 - widget.iconAnimationController!.value - 1.0), + 0.0, + 0.0, + ), child: Padding( - padding: EdgeInsets.only(top: 8, bottom: 8), + padding: const EdgeInsets.only(top: 8, bottom: 8), child: Container( width: MediaQuery.of(context).size.width * 0.75 - 64, height: 46, decoration: BoxDecoration( color: Color(Config.drawerHighlightItemColor), - borderRadius: new BorderRadius.only( + borderRadius: BorderRadius.only( topLeft: Radius.circular(ltr ? 0 : radius), topRight: Radius.circular(ltr ? radius : 0), bottomLeft: Radius.circular(ltr ? 0 : radius), @@ -304,21 +308,20 @@ class _HomeDrawerState extends State { }, ); - var listItemIcon = Icon(listItem.icon!.icon, - color: widget.screenIndex == listItem.index - ? Color(Config.drawerTextColor) // TODO: drawerHighlightTextColor - : Color(Config.drawerTextColor)); + final listItemIcon = Icon( + listItem.icon!.icon, + color: widget.screenIndex == listItem.index + ? Color(Config.drawerTextColor) // TODO: drawerHighlightTextColor + : Color(Config.drawerTextColor), + ); - var stack = Stack( + final stack = Stack( children: [ Container( padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), child: Row( children: [ - Container( - width: 6.0, - height: 46.0, - ), + const SizedBox(width: 6.0, height: 46.0), const Padding( padding: EdgeInsets.all(4.0), ), @@ -334,17 +337,19 @@ class _HomeDrawerState extends State { : FontWeight.w500, fontSize: Config.fontSize, color: widget.screenIndex == listItem.index - ? Color(Config - .drawerTextColor) // TODO: drawerHighlightTextColor + ? Color( + Config.drawerTextColor, + ) // TODO: drawerHighlightTextColor : Color(Config.drawerTextColor), ), ), ], ), ), - widget.screenIndex == listItem.index - ? animatedBuilder - : const SizedBox() + if (widget.screenIndex == listItem.index) + animatedBuilder + else + const SizedBox() ], ); diff --git a/src/ui/flutter_app/lib/widgets/license_page.dart b/src/ui/flutter_app/lib/widgets/license_page.dart index c6117898..5d5d482e 100644 --- a/src/ui/flutter_app/lib/widgets/license_page.dart +++ b/src/ui/flutter_app/lib/widgets/license_page.dart @@ -46,13 +46,18 @@ class _LicenseAgreementPageState extends State { body: ListView( children: [ Container( - padding: const EdgeInsets.only( - top: 16, left: 16, right: 16, bottom: 16), - child: Text( - _data != "" ? _data : 'Nothing to show', - style: TextStyle(fontFamily: 'Monospace', fontSize: 12), - textAlign: TextAlign.left, - )) + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 16, + ), + child: Text( + _data != "" ? _data : 'Nothing to show', + style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), + textAlign: TextAlign.left, + ), + ), ], ), ); diff --git a/src/ui/flutter_app/lib/widgets/list_item_divider.dart b/src/ui/flutter_app/lib/widgets/list_item_divider.dart index ede01300..f0c6760b 100644 --- a/src/ui/flutter_app/lib/widgets/list_item_divider.dart +++ b/src/ui/flutter_app/lib/widgets/list_item_divider.dart @@ -19,6 +19,7 @@ import 'package:flutter/material.dart'; import 'package:sanmill/style/app_theme.dart'; +// TODO: replace with Divider(); class ListItemDivider extends StatelessWidget { const ListItemDivider({ Key? key, diff --git a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart b/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart index 868cea09..69bcf160 100644 --- a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart @@ -52,7 +52,7 @@ class _NavigationHomeScreenState extends State { @override void initState() { drawerIndex = DrawerIndex.humanVsAi; - screenView = GamePage(EngineType.humanVsAi); + screenView = const GamePage(EngineType.humanVsAi); super.initState(); } @@ -87,7 +87,7 @@ class _NavigationHomeScreenState extends State { return; } - var drawerMap = { + final drawerMap = { DrawerIndex.humanVsAi: EngineType.humanVsAi, DrawerIndex.humanVsHuman: EngineType.humanVsHuman, DrawerIndex.aiVsAi: EngineType.aiVsAi, @@ -95,7 +95,7 @@ class _NavigationHomeScreenState extends State { drawerIndex = index; - var engineType = drawerMap[drawerIndex!]; + final engineType = drawerMap[drawerIndex!]; if (engineType != null) { setState(() { Game.instance.setWhoIsAi(engineType); @@ -124,17 +124,16 @@ class _NavigationHomeScreenState extends State { final screenshotFilePath = await writeImageToStorage(feedback.screenshot); final packageInfo = await PackageInfo.fromPlatform(); - var _version = + final _version = '${packageInfo.version} (${packageInfo.buildNumber})'; final Email email = Email( body: feedback.text, subject: Constants.feedbackSubjectPrefix + - "$_version" + + _version + Constants.feedbackSubjectSuffix, recipients: [Constants.recipients], attachmentPaths: [screenshotFilePath], - isHTML: false, ); await FlutterEmailSender.send(email); }); diff --git a/src/ui/flutter_app/lib/widgets/oss_license_page.dart b/src/ui/flutter_app/lib/widgets/oss_license_page.dart index faad7492..2851e07f 100644 --- a/src/ui/flutter_app/lib/widgets/oss_license_page.dart +++ b/src/ui/flutter_app/lib/widgets/oss_license_page.dart @@ -23,8 +23,11 @@ import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/generated/oss_licenses.dart'; import 'package:url_launcher/url_launcher.dart'; +// TODO: use flutters build in viewLicense function class FlutterLicense extends LicenseEntry { + @override final List packages; + @override final List paragraphs; FlutterLicense(this.packages, this.paragraphs); @@ -37,8 +40,10 @@ class OssLicensesPage extends StatelessWidget { yield FlutterLicense([ 'Sound Effects' ], [ - LicenseParagraph( - 'CC-0\nhttps://freesound.org/people/unfa/sounds/243749/', 0) + const LicenseParagraph( + 'CC-0\nhttps://freesound.org/people/unfa/sounds/243749/', + 0, + ) ]); } @@ -47,8 +52,8 @@ class OssLicensesPage extends StatelessWidget { // merging non-dart based dependency list using LicenseRegistry. final ossKeys = ossLicenses.keys.toList(); final lm = >{}; - await for (var l in LicenseRegistry.licenses) { - for (var p in l.packages) { + await for (final l in LicenseRegistry.licenses) { + for (final p in l.packages) { if (!ossKeys.contains(p)) { final lp = lm.putIfAbsent(p, () => []); lp.addAll(l.paragraphs.map((p) => p.text)); @@ -56,7 +61,7 @@ class OssLicensesPage extends StatelessWidget { } } } - for (var key in lm.keys) { + for (final key in lm.keys) { ossLicenses[key] = {'license': lm[key]!.join('\n')}; } return ossKeys..sort(); @@ -66,80 +71,104 @@ class OssLicensesPage extends StatelessWidget { @override Widget build(BuildContext context) => Scaffold( - appBar: AppBar( - title: Text(S.of(context).ossLicenses), - ), - body: FutureBuilder>( + appBar: AppBar( + title: Text(S.of(context).ossLicenses), + ), + body: FutureBuilder>( future: _licenses, builder: (context, snapshot) => ListView.separated( - padding: const EdgeInsets.all(0), - itemCount: snapshot.data?.length ?? 0, - itemBuilder: (context, index) { - final key = snapshot.data![index]; - final ossl = ossLicenses[key]; - final version = ossl['version']; - final desc = ossl['description']; - return ListTile( - title: Text('$key ${version ?? ''}'), - subtitle: desc != null ? Text(desc) : null, - trailing: Icon(FluentIcons.chevron_right_24_regular), - onTap: () => Navigator.of(context).push(MaterialPageRoute( - builder: (context) => - MiscOssLicenseSingle(name: key, json: ossl)))); - }, - separatorBuilder: (context, index) => const Divider()))); + padding: EdgeInsets.zero, + itemCount: snapshot.data?.length ?? 0, + itemBuilder: (context, index) { + final key = snapshot.data![index]; + final ossl = ossLicenses[key] as Map; + final version = ossl['version']; + final desc = ossl['description'] as String?; + return ListTile( + title: Text('$key ${version ?? ''}'), + subtitle: desc != null ? Text(desc) : null, + trailing: const Icon(FluentIcons.chevron_right_24_regular), + onTap: () => Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + MiscOssLicenseSingle(name: key, json: ossl), + ), + ), + ); + }, + separatorBuilder: (context, index) => const Divider(), + ), + ), + ); } class MiscOssLicenseSingle extends StatelessWidget { final String name; final Map json; - String get version => json['version'] == null ? "" : json['version']; - String? get description => json['description']; - String get licenseText => json['license']; - String? get homepage => json['homepage']; + String get version => json['version'] as String? ?? ""; + String? get description => json['description'] as String?; + String get licenseText => json['license'] as String; + String? get homepage => json['homepage'] as String?; - MiscOssLicenseSingle({required this.name, required this.json}); + const MiscOssLicenseSingle({required this.name, required this.json}); String _bodyText() => licenseText.split('\n').map((line) { if (line.startsWith('//')) line = line.substring(2); - line = line.trim(); - return line; + return line.trim(); }).join('\n'); @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: Text('$name $version')), body: Container( - color: Theme.of(context).canvasColor, - child: ListView(children: [ + color: Theme.of(context).canvasColor, + child: ListView( + children: [ if (description != null) Padding( - padding: const EdgeInsets.only( - top: 12.0, left: 12.0, right: 12.0), - child: Text(description!, - style: Theme.of(context) - .textTheme - .bodyText2! - .copyWith(fontWeight: FontWeight.bold))), + padding: const EdgeInsets.only( + top: 12.0, + left: 12.0, + right: 12.0, + ), + child: Text( + description!, + style: Theme.of(context) + .textTheme + .bodyText2! + .copyWith(fontWeight: FontWeight.bold), + ), + ), if (homepage != null) Padding( - padding: const EdgeInsets.only( - top: 12.0, left: 12.0, right: 12.0), - child: InkWell( - child: Text(homepage!, - style: const TextStyle( - color: Colors.blue, - decoration: TextDecoration.underline)), - onTap: () => launch(homepage!), - )), + padding: const EdgeInsets.only( + top: 12.0, + left: 12.0, + right: 12.0, + ), + child: InkWell( + child: Text( + homepage!, + style: const TextStyle( + color: Colors.blue, + decoration: TextDecoration.underline, + ), + ), + onTap: () => launch(homepage!), + ), + ), if (description != null || homepage != null) const Divider(), Padding( padding: const EdgeInsets.only(top: 12.0, left: 12.0, right: 12.0), - child: Text(_bodyText(), - style: Theme.of(context).textTheme.bodyText2), + child: Text( + _bodyText(), + style: Theme.of(context).textTheme.bodyText2, + ), ), - ])), + ], + ), + ), ); } diff --git a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart index e2c2d8df..a11247d8 100644 --- a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart @@ -38,8 +38,8 @@ class PersonalizationSettingsPage extends StatefulWidget { class _PersonalizationSettingsPageState extends State { // create some values - Color pickerColor = Color(0xFF808080); - Color currentColor = Color(0xFF808080); + Color pickerColor = const Color(0xFF808080); + Color currentColor = const Color(0xFF808080); @override void initState() { @@ -51,8 +51,8 @@ class _PersonalizationSettingsPageState setState(() => pickerColor = color); } - showColorDialog(String colorString) async { - Map colorStrToVal = { + Future showColorDialog(String colorString) async { + final Map colorStrToVal = { S.of(context).boardColor: Config.boardBackgroundColor, S.of(context).backgroundColor: Config.darkBackgroundColor, S.of(context).lineColor: Config.boardLineColor, @@ -73,9 +73,9 @@ class _PersonalizationSettingsPageState Config.navigationToolbarIconColor, }; - AlertDialog alert = AlertDialog( + final AlertDialog alert = AlertDialog( title: Text( - S.of(context).pick + " " + colorString, + "${S.of(context).pick} $colorString", style: TextStyle( fontSize: Config.fontSize + 4, ), @@ -84,7 +84,6 @@ class _PersonalizationSettingsPageState child: ColorPicker( pickerColor: Color(colorStrToVal[colorString]!), onColorChanged: changeColor, - showLabel: true, ), ), actions: [ @@ -162,14 +161,16 @@ class _PersonalizationSettingsPageState ); } - SliderTheme _boardBorderLineWidthSliderTheme(context, setState) { + SliderTheme _boardBorderLineWidthSliderTheme( + BuildContext context, + Function setState, + ) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).boardBorderLineWidth, child: Slider( - value: Config.boardBorderLineWidth.toDouble(), - min: 0.0, + value: Config.boardBorderLineWidth, max: 20.0, divisions: 200, label: Config.boardBorderLineWidth.toStringAsFixed(1), @@ -185,25 +186,25 @@ class _PersonalizationSettingsPageState ); } - setBoardBorderLineWidth() async { + Future setBoardBorderLineWidth() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _boardBorderLineWidthSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _boardBorderLineWidthSliderTheme, ), ); } - SliderTheme _boardInnerLineWidthSliderTheme(context, setState) { + SliderTheme _boardInnerLineWidthSliderTheme( + BuildContext context, + Function setState, + ) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).boardInnerLineWidth, child: Slider( - value: Config.boardInnerLineWidth.toDouble(), - min: 0.0, + value: Config.boardInnerLineWidth, max: 20.0, divisions: 200, label: Config.boardInnerLineWidth.toStringAsFixed(1), @@ -219,26 +220,23 @@ class _PersonalizationSettingsPageState ); } - setBoardInnerLineWidth() async { + Future setBoardInnerLineWidth() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _boardInnerLineWidthSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _boardInnerLineWidthSliderTheme, ), ); } - SliderTheme _pieceWidthSliderTheme(context, setState) { + SliderTheme _pieceWidthSliderTheme(BuildContext context, Function setState) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).pieceWidth, child: Slider( - value: Config.pieceWidth.toDouble(), + value: Config.pieceWidth, min: 0.5, - max: 1.0, divisions: 50, label: Config.pieceWidth.toStringAsFixed(1), onChanged: (value) { @@ -253,24 +251,22 @@ class _PersonalizationSettingsPageState ); } - setPieceWidth() async { + Future setPieceWidth() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _pieceWidthSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _pieceWidthSliderTheme, ), ); } - SliderTheme _fontSizeSliderTheme(context, setState) { + SliderTheme _fontSizeSliderTheme(BuildContext context, Function setState) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).fontSize, child: Slider( - value: Config.fontSize.toDouble(), + value: Config.fontSize, min: 16, max: 32, divisions: 16, @@ -287,25 +283,22 @@ class _PersonalizationSettingsPageState ); } - setFontSize() async { + Future setFontSize() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _fontSizeSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _fontSizeSliderTheme, ), ); } - SliderTheme _boardTopSliderTheme(context, setState) { + SliderTheme _boardTopSliderTheme(BuildContext context, Function setState) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).boardTop, child: Slider( - value: Config.boardTop.toDouble(), - min: 0.0, + value: Config.boardTop, max: 288.0, divisions: 288, label: Config.boardTop.toStringAsFixed(1), @@ -321,25 +314,25 @@ class _PersonalizationSettingsPageState ); } - setBoardTop() async { + Future setBoardTop() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _boardTopSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _boardTopSliderTheme, ), ); } - SliderTheme _animationDurationSliderTheme(context, setState) { + SliderTheme _animationDurationSliderTheme( + BuildContext context, + Function setState, + ) { return SliderTheme( data: AppTheme.sliderThemeData, child: Semantics( label: S.of(context).animationDuration, child: Slider( - value: Config.animationDuration.toDouble(), - min: 0.0, + value: Config.animationDuration, max: 5.0, divisions: 50, label: Config.animationDuration.toStringAsFixed(1), @@ -355,13 +348,11 @@ class _PersonalizationSettingsPageState ); } - setAnimationDuration() async { + Future setAnimationDuration() async { showModalBottomSheet( context: context, - builder: (BuildContext context) => StatefulBuilder( - builder: (context, setState) { - return _animationDurationSliderTheme(context, setState); - }, + builder: (_) => StatefulBuilder( + builder: _animationDurationSliderTheme, ), ); } @@ -385,7 +376,7 @@ class _PersonalizationSettingsPageState } List children(BuildContext context) { - langCallback(var langCode) async { + Future langCallback([String? langCode]) async { debugPrint("[config] languageCode = $langCode"); Navigator.of(context).pop(); @@ -411,67 +402,67 @@ class _PersonalizationSettingsPageState trailingString: Config.languageCode == Constants.defaultLanguageCodeName ? "" - : languageCodeToStrings[Config.languageCode.toString()]! - .languageName, + : languageCodeToStrings[Config.languageCode]!.languageName, onTap: () => setLanguage(context, langCallback), ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isPieceCountInHandShown, onChanged: setIsPieceCountInHandShown, titleString: S.of(context).isPieceCountInHandShown, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isNotationsShown, onChanged: setIsNotationsShown, titleString: S.of(context).isNotationsShown, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isHistoryNavigationToolbarShown, onChanged: setIsHistoryNavigationToolbarShown, titleString: S.of(context).isHistoryNavigationToolbarShown, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( - context: context, - titleString: S.of(context).boardBorderLineWidth, - onTap: setBoardBorderLineWidth), - ListItemDivider(), + context: context, + titleString: S.of(context).boardBorderLineWidth, + onTap: setBoardBorderLineWidth, + ), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).boardInnerLineWidth, onTap: setBoardInnerLineWidth, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).pieceWidth, onTap: setPieceWidth, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).fontSize, onTap: setFontSize, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).boardTop, onTap: setBoardTop, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).animationDuration, onTap: setAnimationDuration, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.standardNotationEnabled, @@ -480,7 +471,7 @@ class _PersonalizationSettingsPageState ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).color, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -491,70 +482,70 @@ class _PersonalizationSettingsPageState trailingColor: Config.boardBackgroundColor, onTap: () => showColorDialog(S.of(context).boardColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).backgroundColor, trailingColor: Config.darkBackgroundColor, onTap: () => showColorDialog(S.of(context).backgroundColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).lineColor, trailingColor: Config.boardLineColor, onTap: () => showColorDialog(S.of(context).lineColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).whitePieceColor, trailingColor: Config.whitePieceColor, onTap: () => showColorDialog(S.of(context).whitePieceColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).blackPieceColor, trailingColor: Config.blackPieceColor, onTap: () => showColorDialog(S.of(context).blackPieceColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).pieceHighlightColor, trailingColor: Config.pieceHighlightColor, onTap: () => showColorDialog(S.of(context).pieceHighlightColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).messageColor, trailingColor: Config.messageColor, onTap: () => showColorDialog(S.of(context).messageColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).drawerColor, trailingColor: Config.drawerColor, onTap: () => showColorDialog(S.of(context).drawerColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).drawerBackgroundColor, trailingColor: Config.drawerBackgroundColor, onTap: () => showColorDialog(S.of(context).drawerBackgroundColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).drawerTextColor, trailingColor: Config.drawerTextColor, onTap: () => showColorDialog(S.of(context).drawerTextColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).drawerHighlightItemColor, @@ -562,7 +553,7 @@ class _PersonalizationSettingsPageState onTap: () => showColorDialog(S.of(context).drawerHighlightItemColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).mainToolbarBackgroundColor, @@ -570,14 +561,14 @@ class _PersonalizationSettingsPageState onTap: () => showColorDialog(S.of(context).mainToolbarBackgroundColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).mainToolbarIconColor, trailingColor: Config.mainToolbarIconColor, onTap: () => showColorDialog(S.of(context).mainToolbarIconColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).navigationToolbarBackgroundColor, @@ -585,7 +576,7 @@ class _PersonalizationSettingsPageState onTap: () => showColorDialog(S.of(context).navigationToolbarBackgroundColor), ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).navigationToolbarIconColor, @@ -600,7 +591,7 @@ class _PersonalizationSettingsPageState // Display - setIsPieceCountInHandShown(bool value) async { + Future setIsPieceCountInHandShown(bool value) async { setState(() { Config.isPieceCountInHandShown = value; }); @@ -608,7 +599,7 @@ class _PersonalizationSettingsPageState Config.save(); } - setIsNotationsShown(bool value) async { + Future setIsNotationsShown(bool value) async { setState(() { Config.isNotationsShown = value; }); @@ -616,7 +607,7 @@ class _PersonalizationSettingsPageState Config.save(); } - setIsHistoryNavigationToolbarShown(bool value) async { + Future setIsHistoryNavigationToolbarShown(bool value) async { setState(() { Config.isHistoryNavigationToolbarShown = value; }); @@ -624,7 +615,7 @@ class _PersonalizationSettingsPageState Config.save(); } - setStandardNotationEnabled(bool value) async { + Future setStandardNotationEnabled(bool value) async { setState(() { Config.standardNotationEnabled = value; }); diff --git a/src/ui/flutter_app/lib/widgets/picker.dart b/src/ui/flutter_app/lib/widgets/picker.dart index b952b71d..b528035c 100644 --- a/src/ui/flutter_app/lib/widgets/picker.dart +++ b/src/ui/flutter_app/lib/widgets/picker.dart @@ -22,52 +22,60 @@ import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/style/app_theme.dart'; -Future showPickerNumber(BuildContext context, int begin, int end, - int initValue, String suffixString) async { +Future showPickerNumber( + BuildContext context, + int begin, + int end, + int initValue, + String suffixString, +) async { int selectValue = 0; await Picker( - adapter: NumberPickerAdapter( - data: [ - NumberPickerColumn( - begin: begin, - end: end, - initValue: initValue, - suffix: Text( - suffixString, - style: TextStyle( - fontSize: Config.fontSize, - ), + adapter: NumberPickerAdapter( + data: [ + NumberPickerColumn( + begin: begin, + end: end, + initValue: initValue, + suffix: Text( + suffixString, + style: TextStyle( + fontSize: Config.fontSize, ), ), - ], - ), - hideHeader: true, - title: Text(S.of(context).pleaseSelect, - style: TextStyle( - color: AppTheme.appPrimaryColor, - fontSize: Config.fontSize + 4.0, - )), - textStyle: TextStyle( - color: Colors.black, - fontSize: Config.fontSize, - ), - selectedTextStyle: TextStyle(color: AppTheme.appPrimaryColor), - cancelText: S.of(context).cancel, - cancelTextStyle: TextStyle( + ), + ], + ), + hideHeader: true, + title: Text( + S.of(context).pleaseSelect, + style: TextStyle( color: AppTheme.appPrimaryColor, - fontSize: Config.fontSize, + fontSize: Config.fontSize + 4.0, ), - confirmText: S.of(context).confirm, - confirmTextStyle: TextStyle( - color: AppTheme.appPrimaryColor, - fontSize: Config.fontSize, - ), - onConfirm: (Picker picker, List value) async { - debugPrint(value.toString()); - var selectValues = picker.getSelectedValues(); - debugPrint(selectValues.toString()); - selectValue = selectValues[0]; - }).showDialog(context); + ), + textStyle: TextStyle( + color: Colors.black, + fontSize: Config.fontSize, + ), + selectedTextStyle: const TextStyle(color: AppTheme.appPrimaryColor), + cancelText: S.of(context).cancel, + cancelTextStyle: TextStyle( + color: AppTheme.appPrimaryColor, + fontSize: Config.fontSize, + ), + confirmText: S.of(context).confirm, + confirmTextStyle: TextStyle( + color: AppTheme.appPrimaryColor, + fontSize: Config.fontSize, + ), + onConfirm: (Picker picker, List value) async { + debugPrint(value.toString()); + final selectValues = picker.getSelectedValues(); + debugPrint(selectValues.toString()); + selectValue = selectValues[0]; + }, + ).showDialog(context); return selectValue; } diff --git a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart b/src/ui/flutter_app/lib/widgets/rule_settings_page.dart index 8fb6ecdd..3683fd31 100644 --- a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/rule_settings_page.dart @@ -69,7 +69,7 @@ class _RuleSettingsPageState extends State { trailingString: Config.piecesCount.toString(), onTap: setNTotalPiecesEachSide, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.hasDiagonalLines, @@ -77,7 +77,7 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).hasDiagonalLines, subtitleString: S.of(context).hasDiagonalLines_Detail, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).nMoveRule, @@ -85,7 +85,7 @@ class _RuleSettingsPageState extends State { trailingString: Config.nMoveRule.toString(), onTap: setNMoveRule, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).endgameNMoveRule, @@ -93,7 +93,7 @@ class _RuleSettingsPageState extends State { trailingString: Config.endgameNMoveRule.toString(), onTap: setEndgameNMoveRule, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.threefoldRepetitionRule, @@ -101,10 +101,10 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).threefoldRepetitionRule, subtitleString: S.of(context).threefoldRepetitionRule_Detail, ), - ListItemDivider(), + const ListItemDivider(), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).placing, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -116,7 +116,7 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).hasBannedLocations, subtitleString: S.of(context).hasBannedLocations_Detail, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isWhiteLoseButNotDrawWhenBoardFull, @@ -125,7 +125,7 @@ class _RuleSettingsPageState extends State { subtitleString: S.of(context).isWhiteLoseButNotDrawWhenBoardFull_Detail, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.mayOnlyRemoveUnplacedPieceInPlacingPhase, @@ -135,21 +135,25 @@ class _RuleSettingsPageState extends State { ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).moving, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, children: [ - Config.experimentsEnabled - ? SettingsSwitchListTile( - context: context, - value: Config.mayMoveInPlacingPhase, - onChanged: setMayMoveInPlacingPhase, - titleString: S.of(context).mayMoveInPlacingPhase, - subtitleString: S.of(context).mayMoveInPlacingPhase_Detail, - ) - : SizedBox(height: 1), - Config.experimentsEnabled ? ListItemDivider() : SizedBox(height: 1), + if (Config.experimentsEnabled) + SettingsSwitchListTile( + context: context, + value: Config.mayMoveInPlacingPhase, + onChanged: setMayMoveInPlacingPhase, + titleString: S.of(context).mayMoveInPlacingPhase, + subtitleString: S.of(context).mayMoveInPlacingPhase_Detail, + ) + else + const SizedBox(height: 1), + if (Config.experimentsEnabled) + const ListItemDivider() + else + const SizedBox(height: 1), SettingsSwitchListTile( context: context, value: Config.isDefenderMoveFirst, @@ -157,7 +161,7 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).isDefenderMoveFirst, subtitleString: S.of(context).isDefenderMoveFirst_Detail, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isLoseButNotChangeSideWhenNoWay, @@ -168,7 +172,7 @@ class _RuleSettingsPageState extends State { ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).mayFly, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -180,7 +184,7 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).mayFly, subtitleString: S.of(context).mayFly_Detail, ), - ListItemDivider(), + const ListItemDivider(), SettingsListTile( context: context, titleString: S.of(context).flyPieceCount, @@ -190,7 +194,7 @@ class _RuleSettingsPageState extends State { ), ], ), - SizedBox(height: AppTheme.sizedBoxHeight), + const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).removing, style: AppTheme.settingsHeaderStyle), SettingsCard( context: context, @@ -202,7 +206,7 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).mayRemoveFromMillsAlways, subtitleString: S.of(context).mayRemoveFromMillsAlways_Detail, ), - ListItemDivider(), + const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.mayRemoveMultiple, @@ -210,7 +214,7 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).mayRemoveMultiple, subtitleString: S.of(context).mayRemoveMultiple_Detail, ), - ListItemDivider(), + const ListItemDivider(), ], ), ]; @@ -218,8 +222,8 @@ class _RuleSettingsPageState extends State { // General - setNTotalPiecesEachSide() { - callback(int? piecesCount) async { + void setNTotalPiecesEachSide() { + Future callback(int? piecesCount) async { debugPrint("[config] piecesCount = $piecesCount"); Navigator.of(context).pop(); @@ -243,44 +247,44 @@ class _RuleSettingsPageState extends State { children: [ RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('9'), + title: const Text('9'), groupValue: Config.piecesCount, value: 9, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('10'), + title: const Text('10'), groupValue: Config.piecesCount, value: 10, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('11'), + title: const Text('11'), groupValue: Config.piecesCount, value: 11, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('12'), + title: const Text('12'), groupValue: Config.piecesCount, value: 12, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), ], ), ), ); } - setNMoveRule() { - callback(int? nMoveRule) async { + void setNMoveRule() { + Future callback(int? nMoveRule) async { debugPrint("[config] nMoveRule = $nMoveRule"); Navigator.of(context).pop(); @@ -303,52 +307,52 @@ class _RuleSettingsPageState extends State { children: [ RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('30'), + title: const Text('30'), groupValue: Config.nMoveRule, value: 30, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('50'), + title: const Text('50'), groupValue: Config.nMoveRule, value: 50, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('60'), + title: const Text('60'), groupValue: Config.nMoveRule, value: 60, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('100'), + title: const Text('100'), groupValue: Config.nMoveRule, value: 100, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('200'), + title: const Text('200'), groupValue: Config.nMoveRule, value: 200, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), ], ), ), ); } - setEndgameNMoveRule() { - callback(int? endgameNMoveRule) async { + void setEndgameNMoveRule() { + Future callback(int? endgameNMoveRule) async { debugPrint("[config] endgameNMoveRule = $endgameNMoveRule"); Navigator.of(context).pop(); @@ -372,76 +376,76 @@ class _RuleSettingsPageState extends State { children: [ RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('5'), + title: const Text('5'), groupValue: Config.endgameNMoveRule, value: 5, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('10'), + title: const Text('10'), groupValue: Config.endgameNMoveRule, value: 10, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('20'), + title: const Text('20'), groupValue: Config.endgameNMoveRule, value: 20, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('30'), + title: const Text('30'), groupValue: Config.endgameNMoveRule, value: 30, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('50'), + title: const Text('50'), groupValue: Config.endgameNMoveRule, value: 50, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('60'), + title: const Text('60'), groupValue: Config.endgameNMoveRule, value: 60, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('100'), + title: const Text('100'), groupValue: Config.endgameNMoveRule, value: 100, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('200'), + title: const Text('200'), groupValue: Config.endgameNMoveRule, value: 200, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), ], ), ), ); } - setFlyPieceCount() { - callback(int? flyPieceCount) async { + void setFlyPieceCount() { + Future callback(int? flyPieceCount) async { debugPrint("[config] flyPieceCount = $flyPieceCount"); Navigator.of(context).pop(); @@ -464,27 +468,27 @@ class _RuleSettingsPageState extends State { children: [ RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('3'), + title: const Text('3'), groupValue: Config.flyPieceCount, value: 3, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, - title: Text('4'), + title: const Text('4'), groupValue: Config.flyPieceCount, value: 4, onChanged: callback, ), - ListItemDivider(), + const ListItemDivider(), ], ), ), ); } - setHasDiagonalLines(bool value) async { + Future setHasDiagonalLines(bool value) async { setState(() { rule.hasDiagonalLines = Config.hasDiagonalLines = value; }); @@ -494,7 +498,7 @@ class _RuleSettingsPageState extends State { Config.save(); } - setAllowFlyingAllowed(bool value) async { + Future setAllowFlyingAllowed(bool value) async { setState(() { rule.mayFly = Config.mayFly = value; }); @@ -504,7 +508,7 @@ class _RuleSettingsPageState extends State { Config.save(); } - setThreefoldRepetitionRule(bool value) async { + Future setThreefoldRepetitionRule(bool value) async { setState(() { rule.threefoldRepetitionRule = Config.threefoldRepetitionRule = value; }); @@ -516,7 +520,7 @@ class _RuleSettingsPageState extends State { // Placing - setHasBannedLocations(bool value) async { + Future setHasBannedLocations(bool value) async { setState(() { rule.hasBannedLocations = Config.hasBannedLocations = value; }); @@ -526,7 +530,7 @@ class _RuleSettingsPageState extends State { Config.save(); } - setIsWhiteLoseButNotDrawWhenBoardFull(bool value) async { + Future setIsWhiteLoseButNotDrawWhenBoardFull(bool value) async { setState(() { rule.isWhiteLoseButNotDrawWhenBoardFull = Config.isWhiteLoseButNotDrawWhenBoardFull = value; @@ -537,7 +541,7 @@ class _RuleSettingsPageState extends State { Config.save(); } - setMayOnlyRemoveUnplacedPieceInPlacingPhase(bool value) async { + Future setMayOnlyRemoveUnplacedPieceInPlacingPhase(bool value) async { setState(() { rule.mayOnlyRemoveUnplacedPieceInPlacingPhase = Config.mayOnlyRemoveUnplacedPieceInPlacingPhase = value; @@ -551,7 +555,7 @@ class _RuleSettingsPageState extends State { // Moving - setMayMoveInPlacingPhase(bool value) async { + Future setMayMoveInPlacingPhase(bool value) async { setState(() { rule.mayMoveInPlacingPhase = Config.mayMoveInPlacingPhase = value; }); @@ -566,7 +570,7 @@ class _RuleSettingsPageState extends State { } } - setIsDefenderMoveFirst(bool value) async { + Future setIsDefenderMoveFirst(bool value) async { setState(() { rule.isDefenderMoveFirst = Config.isDefenderMoveFirst = value; }); @@ -576,7 +580,7 @@ class _RuleSettingsPageState extends State { Config.save(); } - setIsLoseButNotChangeSideWhenNoWay(bool value) async { + Future setIsLoseButNotChangeSideWhenNoWay(bool value) async { setState(() { rule.isLoseButNotChangeSideWhenNoWay = Config.isLoseButNotChangeSideWhenNoWay = value; @@ -589,7 +593,7 @@ class _RuleSettingsPageState extends State { // Removing - setAllowRemovePieceInMill(bool value) async { + Future setAllowRemovePieceInMill(bool value) async { setState(() { rule.mayRemoveFromMillsAlways = Config.mayRemoveFromMillsAlways = value; }); @@ -599,7 +603,7 @@ class _RuleSettingsPageState extends State { Config.save(); } - setAllowRemoveMultiPiecesWhenCloseMultiMill(bool value) async { + Future setAllowRemoveMultiPiecesWhenCloseMultiMill(bool value) async { setState(() { rule.mayRemoveMultiple = Config.mayRemoveMultiple = value; }); @@ -611,7 +615,7 @@ class _RuleSettingsPageState extends State { // Unused - setNPiecesAtLeast(int value) async { + Future setNPiecesAtLeast(int value) async { setState(() { rule.piecesAtLeastCount = Config.piecesAtLeastCount = value; }); diff --git a/src/ui/flutter_app/lib/widgets/settings_card.dart b/src/ui/flutter_app/lib/widgets/settings_card.dart index 985fcf76..4afd5f89 100644 --- a/src/ui/flutter_app/lib/widgets/settings_card.dart +++ b/src/ui/flutter_app/lib/widgets/settings_card.dart @@ -27,7 +27,7 @@ class SettingsCard extends StatelessWidget { }) : super(key: key); final BuildContext context; - final children; + final List children; @override Widget build(BuildContext context) { diff --git a/src/ui/flutter_app/lib/widgets/settings_list_tile.dart b/src/ui/flutter_app/lib/widgets/settings_list_tile.dart index f245d53c..36b78bbd 100644 --- a/src/ui/flutter_app/lib/widgets/settings_list_tile.dart +++ b/src/ui/flutter_app/lib/widgets/settings_list_tile.dart @@ -42,7 +42,8 @@ class SettingsListTile extends StatelessWidget { @override Widget build(BuildContext context) { - bool ltr = getBidirectionality(context) == Bidirectionality.leftToRight; + final bool ltr = + getBidirectionality(context) == Bidirectionality.leftToRight; return ListTile( title: Text( titleString, @@ -74,10 +75,11 @@ class SettingsListTile extends StatelessWidget { ), ), Icon( - ltr - ? FluentIcons.chevron_right_24_regular - : FluentIcons.chevron_left_24_regular, - color: AppTheme.listTileSubtitleColor) + ltr + ? FluentIcons.chevron_right_24_regular + : FluentIcons.chevron_left_24_regular, + color: AppTheme.listTileSubtitleColor, + ) ], ), onTap: onTap, diff --git a/src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart b/src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart index 58599264..01ab23a3 100644 --- a/src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart +++ b/src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart @@ -31,10 +31,10 @@ class SettingsSwitchListTile extends StatelessWidget { }) : super(key: key); final BuildContext context; - final value; + final bool value; final String titleString; final String? subtitleString; - final onChanged; + final ValueChanged? onChanged; @override Widget build(BuildContext context) { diff --git a/src/ui/flutter_app/lib/widgets/snack_bar.dart b/src/ui/flutter_app/lib/widgets/snack_bar.dart index 30cffd43..c818be5f 100644 --- a/src/ui/flutter_app/lib/widgets/snack_bar.dart +++ b/src/ui/flutter_app/lib/widgets/snack_bar.dart @@ -19,19 +19,24 @@ import 'package:flutter/material.dart'; import 'package:sanmill/common/config.dart'; -void showSnackBar(BuildContext context, String message, - {Duration duration = const Duration(milliseconds: 4000)}) { +void showSnackBar( + BuildContext context, + String message, { + Duration duration = const Duration(milliseconds: 4000), +}) { if (!Config.screenReaderSupport) { ScaffoldMessenger.of(context).hideCurrentSnackBar(); } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - message, - style: TextStyle( - fontSize: Config.fontSize, + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + message, + style: TextStyle( + fontSize: Config.fontSize, + ), ), + duration: duration, ), - duration: duration, - )); + ); } diff --git a/src/ui/flutter_app/test/widget_test.dart b/src/ui/flutter_app/test/widget_test.dart index 43073f5b..bca4a244 100644 --- a/src/ui/flutter_app/test/widget_test.dart +++ b/src/ui/flutter_app/test/widget_test.dart @@ -38,11 +38,13 @@ void main() { } testWidgets('Widget', (WidgetTester tester) async { - NavigationHomeScreen screen = NavigationHomeScreen(); - await tester.pumpWidget(makeTestableWidget( - child: screen, - locale: const Locale('en'), - )); + final NavigationHomeScreen screen = NavigationHomeScreen(); + await tester.pumpWidget( + makeTestableWidget( + child: screen, + locale: const Locale('en'), + ), + ); await tester.pump(); expect(find.text(S.current.appName), findsOneWidget); }); From 26b7f49a8e13a459c6a318515f14612cb763187f Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:07:45 +0200 Subject: [PATCH 05/13] cleanup code Also makes some Widgets stateless (resulting in performance improvements) --- src/ui/flutter_app/lib/main.dart | 22 +--- src/ui/flutter_app/lib/services/audios.dart | 1 + .../flutter_app/lib/widgets/about_page.dart | 95 ++++++++--------- .../lib/widgets/drawer_user_controller.dart | 6 +- src/ui/flutter_app/lib/widgets/env_page.dart | 72 ++++++------- src/ui/flutter_app/lib/widgets/game_page.dart | 38 ++++--- .../lib/widgets/game_settings_page.dart | 29 ++--- .../flutter_app/lib/widgets/help_screen.dart | 76 ++++--------- .../flutter_app/lib/widgets/home_drawer.dart | 100 ++++++++---------- .../flutter_app/lib/widgets/license_page.dart | 65 ++++++------ .../personalization_settings_page.dart | 27 ----- .../lib/widgets/rule_settings_page.dart | 12 +-- .../lib/widgets/settings_list_tile.dart | 4 +- 13 files changed, 217 insertions(+), 330 deletions(-) diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index d1a32443..318e72d5 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -115,27 +115,13 @@ Future main() async { RouteObserver routeObserver = RouteObserver(); -final globalScaffoldKey = GlobalKey(); - -class SanmillApp extends StatefulWidget { - @override - _SanmillAppState createState() => _SanmillAppState(); -} - -class _SanmillAppState extends State { - @override - void initState() { - super.initState(); - if (Platform.isWindows) { - print("[audio] Audio Player is not support Windows."); - return; - } else { - Audios.loadSounds(); - } - } +class SanmillApp extends StatelessWidget { + final globalScaffoldKey = GlobalKey(); @override Widget build(BuildContext context) { + Audios.loadSounds(); + setSpecialCountryAndRegion(context); return MaterialApp( diff --git a/src/ui/flutter_app/lib/services/audios.dart b/src/ui/flutter_app/lib/services/audios.dart index 35fd3a1a..8c7fd8ab 100644 --- a/src/ui/flutter_app/lib/services/audios.dart +++ b/src/ui/flutter_app/lib/services/audios.dart @@ -44,6 +44,7 @@ class Audios { static Future loadSounds() async { if (Platform.isWindows) { + debugPrint("[audio] Audio Player does not support Windows."); return; } diff --git a/src/ui/flutter_app/lib/widgets/about_page.dart b/src/ui/flutter_app/lib/widgets/about_page.dart index 7746bd75..3ee56e6e 100644 --- a/src/ui/flutter_app/lib/widgets/about_page.dart +++ b/src/ui/flutter_app/lib/widgets/about_page.dart @@ -33,21 +33,10 @@ import 'license_page.dart'; import 'list_item_divider.dart'; import 'oss_license_page.dart'; -class AboutPage extends StatefulWidget { - @override - _AboutPageState createState() => _AboutPageState(); -} - -class _AboutPageState extends State { - String _version = ""; +class AboutPage extends StatelessWidget { + // String _version = ""; final String tag = "[about] "; - @override - void initState() { - _loadVersionInfo(); - super.initState(); - } - String getMode() { late String ret; if (kDebugMode) { @@ -84,21 +73,35 @@ class _AboutPageState extends State { List children(BuildContext context, String mode) { return [ - SettingsListTile( - context: context, - titleString: S.of(context).versionInfo, - subtitleString: "${Constants.projectName} $_version $mode", - onTap: _showVersionInfo, + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: (_, data) { + late final String _version; + if (!data.hasData) { + _version = ''; + } else { + final packageInfo = data.data!; + if (Platform.isWindows) { + _version = packageInfo.version; // TODO + + } else { + _version = '${packageInfo.version} (${packageInfo.buildNumber})'; + } + } + return SettingsListTile( + titleString: S.of(context).versionInfo, + subtitleString: "${Constants.projectName} $_version $mode", + onTap: () => _showVersionInfo(context, _version), + ); + }, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).feedback, onTap: _launchFeedback, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).eula, onTap: () { _launchEULA(); @@ -106,7 +109,6 @@ class _AboutPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).license, onTap: () { Navigator.push( @@ -119,7 +121,6 @@ class _AboutPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).sourceCode, onTap: () { _launchSourceCode(); @@ -127,7 +128,6 @@ class _AboutPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).privacyPolicy, onTap: () { _launchPrivacyPolicy(); @@ -135,15 +135,13 @@ class _AboutPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).ossLicenses, onTap: () { - _launchThirdPartyNotices(); + _launchThirdPartyNotices(context); }, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).helpImproveTranslate, onTap: () { _launchHelpImproveTranslate(); @@ -151,7 +149,6 @@ class _AboutPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).thanks, onTap: () { _launchThanks(); @@ -161,20 +158,6 @@ class _AboutPageState extends State { ]; } - Future _loadVersionInfo() async { - final packageInfo = await PackageInfo.fromPlatform(); - - if (Platform.isWindows) { - setState(() { - _version = packageInfo.version; // TODO - }); - } else { - setState(() { - _version = '${packageInfo.version} (${packageInfo.buildNumber})'; - }); - } - } - Future _launchURL(String url) async { await launch(url); } @@ -224,7 +207,7 @@ class _AboutPageState extends State { } } - Future _launchThirdPartyNotices() async { + Future _launchThirdPartyNotices(BuildContext context) async { Navigator.push( context, MaterialPageRoute( @@ -292,15 +275,27 @@ class _AboutPageState extends State { } } - void _showVersionInfo() { + void _showVersionInfo(BuildContext context, String version) { showDialog( context: context, barrierDismissible: true, - builder: (context) => versionDialog(context), + builder: (_) => _VersionDialog( + version: version, + ), ); } +} - AlertDialog versionDialog(BuildContext context) { +class _VersionDialog extends StatelessWidget { + const _VersionDialog({ + Key? key, + required this.version, + }) : super(key: key); + + final String version; + + @override + Widget build(BuildContext context) { return AlertDialog( title: Text( S.of(context).appName, @@ -310,7 +305,7 @@ class _AboutPageState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("${S.of(context).version}: $_version"), + Text("${S.of(context).version}: $version"), const SizedBox(height: AppTheme.sizedBoxHeight), const SizedBox(height: AppTheme.sizedBoxHeight), Text( @@ -324,7 +319,7 @@ class _AboutPageState extends State { actions: [ TextButton( child: Text(S.of(context).more), - onPressed: () => _showFlutterVersionInfo(), + onPressed: () => _showFlutterVersionInfo(context), ), TextButton( child: Text(S.of(context).ok), @@ -334,17 +329,17 @@ class _AboutPageState extends State { ); } - void _showFlutterVersionInfo() { + void _showFlutterVersionInfo(BuildContext context) { Navigator.of(context).pop(); showDialog( context: context, barrierDismissible: true, - builder: (context) => flutterVersionDialog(context), + builder: (context) => _flutterVersionDialog(context), ); } - AlertDialog flutterVersionDialog(BuildContext context) { + AlertDialog _flutterVersionDialog(BuildContext context) { return AlertDialog( title: Text( S.of(context).more, diff --git a/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart b/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart index 1856a075..b78f9f99 100644 --- a/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart +++ b/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart @@ -49,9 +49,9 @@ class DrawerUserController extends StatefulWidget { class _DrawerUserControllerState extends State with TickerProviderStateMixin { - late ScrollController scrollController; - late AnimationController iconAnimationController; - late AnimationController animationController; + late final ScrollController scrollController; + late final AnimationController iconAnimationController; + late final AnimationController animationController; double scrollOffset = 0.0; diff --git a/src/ui/flutter_app/lib/widgets/env_page.dart b/src/ui/flutter_app/lib/widgets/env_page.dart index 4b5694a8..bd94d8ff 100644 --- a/src/ui/flutter_app/lib/widgets/env_page.dart +++ b/src/ui/flutter_app/lib/widgets/env_page.dart @@ -21,49 +21,43 @@ import 'package:flutter/services.dart' show rootBundle; import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; -class EnvironmentVariablesPage extends StatefulWidget { - @override - _EnvironmentVariablesPageState createState() => - _EnvironmentVariablesPageState(); -} - -class _EnvironmentVariablesPageState extends State { - String _data = ""; - - Future _loadData() async { - final _loadedData = - await rootBundle.loadString(Constants.environmentVariablesFilename); - setState(() { - _data = _loadedData; - }); - } - +class EnvironmentVariablesPage extends StatelessWidget { @override Widget build(BuildContext context) { - _loadData(); + return FutureBuilder( + future: rootBundle.loadString(Constants.environmentVariablesFilename), + builder: (context, data) { + late final String _data; + if (!data.hasData) { + _data = 'Nothing to show'; + } else { + _data = data.data!; + } - return Scaffold( - appBar: AppBar( - title: Text(S.of(context).environmentVariables), - centerTitle: true, - ), - body: ListView( - children: [ - Container( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 16, - ), - child: Text( - _data != "" ? _data : 'Nothing to show', - style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), - textAlign: TextAlign.left, - ), + return Scaffold( + appBar: AppBar( + title: Text(S.of(context).environmentVariables), + centerTitle: true, ), - ], - ), + body: ListView( + children: [ + Container( + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 16, + ), + child: Text( + _data, + style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), + textAlign: TextAlign.left, + ), + ), + ], + ), + ); + }, ); } } diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/widgets/game_page.dart index 9e11196e..91751a8a 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_page.dart @@ -53,9 +53,8 @@ class GamePage extends StatefulWidget { static double screenPaddingH = AppTheme.boardScreenPaddingH; final EngineType engineType; - final Engine engine; - GamePage(this.engineType) : engine = NativeEngine(); + const GamePage(this.engineType); @override _GamePageState createState() => _GamePageState(); @@ -63,6 +62,8 @@ class GamePage extends StatefulWidget { class _GamePageState extends State with RouteAware, SingleTickerProviderStateMixin { + final Engine _engine = NativeEngine(); + String? _tip = ''; bool isReady = false; bool isGoingToHistory = false; @@ -87,7 +88,7 @@ class _GamePageState extends State super.initState(); Game.instance.init(); - widget.engine.startup(); + _engine.startup(); timer = Timer.periodic(const Duration(microseconds: 100), (Timer t) { _setReadyState(); @@ -421,7 +422,8 @@ class _GamePageState extends State case -2: Audios.playTone(Audios.illegalSoundId); debugPrint( - "[tap] removePiece: Cannot Remove our pieces, skip [$sq]"); + "[tap] removePiece: Cannot Remove our pieces, skip [$sq]", + ); if (mounted) { showTip(S.of(context).tipSelectOpponentsPiece); if (Config.screenReaderSupport) { @@ -574,10 +576,10 @@ class _GamePageState extends State if (!isMoveNow) { debugPrint("[engineToGo] Searching..."); - response = await widget.engine.search(Game.instance.position); + response = await _engine.search(Game.instance.position); } else { debugPrint("[engineToGo] Get search result now..."); - response = await widget.engine.search(null); + response = await _engine.search(null); isMoveNow = false; } @@ -1005,8 +1007,10 @@ class _GamePageState extends State ); } - Future onGotoHistoryButtonsPressed(Future func, - {bool pop = true}) async { + Future onGotoHistoryButtonsPressed( + Future func, { + bool pop = true, + }) async { if (pop == true) { Navigator.of(context).pop(); } @@ -1017,7 +1021,8 @@ class _GamePageState extends State if (isGoingToHistory) { debugPrint( - "[TakeBack] Is going to history, ignore Take Back button press."); + "[TakeBack] Is going to history, ignore Take Back button press.", + ); return; } @@ -1245,7 +1250,8 @@ class _GamePageState extends State }; debugPrint( - "$tag Game over reason: ${Game.instance.position.gameOverReason}"); + "$tag Game over reason: ${Game.instance.position.gameOverReason}", + ); String? loseReasonStr = reasonMap[Game.instance.position.gameOverReason]; @@ -1363,8 +1369,8 @@ class _GamePageState extends State onPressed: () async { if (!isTopLevel) Config.skillLevel++; Config.save(); - await widget.engine.setOptions(context); - print("[config] skillLevel: ${Config.skillLevel}"); + await _engine.setOptions(context); + debugPrint("[config] skillLevel: ${Config.skillLevel}"); Navigator.of(context).pop(); }, ), @@ -1891,7 +1897,7 @@ class _GamePageState extends State void dispose() { debugPrint("$tag dispose"); disposed = true; - widget.engine.shutdown(); + _engine.shutdown(); _animationController.dispose(); super.dispose(); routeObserver.unsubscribe(this); @@ -1901,7 +1907,7 @@ class _GamePageState extends State Future didPush() async { final route = ModalRoute.of(context)!.settings.name; debugPrint('$tag Game Page didPush route: $route'); - await widget.engine.setOptions(context); + await _engine.setOptions(context); if (Config.languageCode != Constants.defaultLanguageCodeName) { S.load(Locale(Config.languageCode)); setState(() {}); @@ -1912,7 +1918,7 @@ class _GamePageState extends State Future didPopNext() async { final route = ModalRoute.of(context)!.settings.name; debugPrint('$tag Game Page didPopNext route: $route'); - await widget.engine.setOptions(context); + await _engine.setOptions(context); if (Config.languageCode != Constants.defaultLanguageCodeName) { S.load(Locale(Config.languageCode)); } @@ -1922,7 +1928,7 @@ class _GamePageState extends State Future didPushNext() async { final route = ModalRoute.of(context)!.settings.name; debugPrint('$tag Game Page didPushNext route: $route'); - await widget.engine.setOptions(context); + await _engine.setOptions(context); if (Config.languageCode != Constants.defaultLanguageCodeName) { S.load(Locale(Config.languageCode)); } diff --git a/src/ui/flutter_app/lib/widgets/game_settings_page.dart b/src/ui/flutter_app/lib/widgets/game_settings_page.dart index 6ed88c53..11e833ba 100644 --- a/src/ui/flutter_app/lib/widgets/game_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_settings_page.dart @@ -75,13 +75,11 @@ class _GameSettingsPageState extends State { max: 30, divisions: 29, label: Config.skillLevel.toString(), - onChanged: (value) { - setState(() { - debugPrint("[config] Slider value: $value"); - Config.skillLevel = value.toInt(); - Config.save(); - }); - }, + onChanged: (value) => setState(() { + debugPrint("[config] Slider value: $value"); + Config.skillLevel = value.toInt(); + Config.save(); + }), ), ), ); @@ -97,13 +95,11 @@ class _GameSettingsPageState extends State { max: 60, divisions: 60, label: Config.moveTime.toString(), - onChanged: (value) { - setState(() { - debugPrint("[config] Slider value: $value"); - Config.moveTime = value.toInt(); - Config.save(); - }); - }, + onChanged: (value) => setState(() { + debugPrint("[config] Slider value: $value"); + Config.moveTime = value.toInt(); + Config.save(); + }), ), ), ); @@ -216,14 +212,12 @@ class _GameSettingsPageState extends State { context: context, children: [ SettingsListTile( - context: context, titleString: S.of(context).skillLevel, //trailingString: "L" + Config.skillLevel.toString(), onTap: setSkillLevel, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).moveTime, onTap: setMoveTime, ), @@ -235,7 +229,6 @@ class _GameSettingsPageState extends State { context: context, children: [ SettingsListTile( - context: context, titleString: S.of(context).algorithm, trailingString: algorithmNames[Config.algorithm], onTap: setAlgorithm, @@ -318,7 +311,6 @@ class _GameSettingsPageState extends State { context: context, children: [ SettingsListTile( - context: context, titleString: S.of(context).restoreDefaultSettings, onTap: restoreFactoryDefaultSettings, ), @@ -359,7 +351,6 @@ class _GameSettingsPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).environmentVariables, onTap: () { Navigator.push( diff --git a/src/ui/flutter_app/lib/widgets/help_screen.dart b/src/ui/flutter_app/lib/widgets/help_screen.dart index d0b2f967..18c31386 100644 --- a/src/ui/flutter_app/lib/widgets/help_screen.dart +++ b/src/ui/flutter_app/lib/widgets/help_screen.dart @@ -2,62 +2,32 @@ import 'package:flutter/material.dart'; import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/style/colors.dart'; - -class HelpScreen extends StatefulWidget { - @override - _HelpScreenState createState() => _HelpScreenState(); -} - -class _HelpScreenState extends State { - @override - void initState() { - super.initState(); - } +class HelpScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - color: UIColors.nearlyWhite, - child: SafeArea( - top: false, - child: Scaffold( - backgroundColor: Color(Config.darkBackgroundColor), - body: ListView( - children: [ - const SizedBox(height: AppTheme.sizedBoxHeight), - Container( - padding: const EdgeInsets.only( - top: 48, - left: 16, - right: 16, - bottom: 16, - ), - child: Text( - S.of(context).howToPlay, - style: TextStyle( - fontSize: Config.fontSize + 4, - fontWeight: FontWeight.bold, - color: AppTheme.helpTextColor, - ), - ), - ), - Container( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 16, - ), - child: Text( - S.of(context).helpContent, - style: TextStyle( - fontSize: Config.fontSize, - color: AppTheme.helpTextColor, - ), - ), - ), - ], + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + S.of(context).howToPlay, + style: TextStyle( + fontSize: Config.fontSize + 4, + fontWeight: FontWeight.bold, + color: AppTheme.helpTextColor, + ), + ), + ), + backgroundColor: Color(Config.darkBackgroundColor), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Text( + S.of(context).helpContent, + style: TextStyle( + fontSize: Config.fontSize, + color: AppTheme.helpTextColor, + ), ), ), ), diff --git a/src/ui/flutter_app/lib/widgets/home_drawer.dart b/src/ui/flutter_app/lib/widgets/home_drawer.dart index 58c668b4..5877ba52 100644 --- a/src/ui/flutter_app/lib/widgets/home_drawer.dart +++ b/src/ui/flutter_app/lib/widgets/home_drawer.dart @@ -48,7 +48,7 @@ class DrawerListItem { Icon? icon; } -class HomeDrawer extends StatefulWidget { +class HomeDrawer extends StatelessWidget { const HomeDrawer({ Key? key, this.screenIndex, @@ -60,22 +60,10 @@ class HomeDrawer extends StatefulWidget { final DrawerIndex? screenIndex; final Function(DrawerIndex?)? callBackIndex; - @override - _HomeDrawerState createState() => _HomeDrawerState(); -} - -class _HomeDrawerState extends State { - DateTime? lastTapTime; - - final String tag = "[home_drawer]"; - - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { + const String tag = "[home_drawer]"; + final List drawerList = [ DrawerListItem( index: DrawerIndex.humanVsAi, @@ -129,7 +117,7 @@ class _HomeDrawerState extends State { Tween(begin: 0.0, end: 24.0) .animate( CurvedAnimation( - parent: widget.iconAnimationController!, + parent: iconAnimationController!, curve: Curves.fastOutSlowIn, ), ) @@ -140,13 +128,13 @@ class _HomeDrawerState extends State { final scaleTransition = ScaleTransition( scale: AlwaysStoppedAnimation( - 1.0 - (widget.iconAnimationController!.value) * 0.2, + 1.0 - (iconAnimationController!.value) * 0.2, ), child: rotationTransition, ); final animatedBuilder = AnimatedBuilder( - animation: widget.iconAnimationController!, + animation: iconAnimationController!, builder: (BuildContext context, Widget? child) { return scaleTransition; }, @@ -164,32 +152,34 @@ class _HomeDrawerState extends State { ]; final animatedTextKit = AnimatedTextKit( - animatedTexts: [ - ColorizeAnimatedText( - S.of(context).appName, - textStyle: TextStyle( - fontSize: Config.fontSize + 16, - fontWeight: FontWeight.w600, - ), - colors: animatedTextsColors, - speed: const Duration(seconds: 3), + animatedTexts: [ + ColorizeAnimatedText( + S.of(context).appName, + textStyle: TextStyle( + fontSize: Config.fontSize + 16, + fontWeight: FontWeight.w600, ), - ], - pause: const Duration(milliseconds: 30000), - repeatForever: true, - stopPauseOnTap: true, - onTap: () { - if (lastTapTime == null || - DateTime.now().difference(lastTapTime!) > Duration(seconds: 1)) { - lastTapTime = DateTime.now(); - debugPrint( - "$tag Tap again in one second to enable developer mode."); - } else { - lastTapTime = DateTime.now(); - Developer.developerModeEnabled = true; - debugPrint("$tag Developer mode enabled."); - } - }); + colors: animatedTextsColors, + speed: const Duration(seconds: 3), + ), + ], + pause: const Duration(milliseconds: 30000), + repeatForever: true, + stopPauseOnTap: true, + onTap: () { + DateTime? lastTapTime; + if (lastTapTime == null || + DateTime.now().difference(lastTapTime) > + const Duration(seconds: 1)) { + lastTapTime = DateTime.now(); + debugPrint("$tag Tap again in one second to enable developer mode."); + } else { + lastTapTime = DateTime.now(); + Developer.developerModeEnabled = true; + debugPrint("$tag Developer mode enabled."); + } + }, + ); final drawerHeader = Container( width: double.infinity, @@ -256,9 +246,8 @@ class _HomeDrawerState extends State { physics: const BouncingScrollPhysics(), padding: EdgeInsets.zero, itemCount: drawerList.length, - itemBuilder: (BuildContext context, int index) { - return buildInkwell(drawerList[index]); - }, + itemBuilder: (BuildContext context, int index) => + buildInkwell(context, drawerList[index]), ), ), Divider(height: 1, color: AppTheme.drawerDividerColor), @@ -271,20 +260,20 @@ class _HomeDrawerState extends State { } Future navigationToScreen(DrawerIndex? index) async { - widget.callBackIndex!(index); + callBackIndex!(index); } - Widget buildInkwell(DrawerListItem listItem) { + Widget buildInkwell(BuildContext context, DrawerListItem listItem) { final bool ltr = getBidirectionality(context) == Bidirectionality.leftToRight; const double radius = 28.0; final animatedBuilder = AnimatedBuilder( - animation: widget.iconAnimationController!, + animation: iconAnimationController!, builder: (BuildContext context, Widget? child) { return Transform( transform: Matrix4.translationValues( (MediaQuery.of(context).size.width * 0.75 - 64) * - (1.0 - widget.iconAnimationController!.value - 1.0), + (1.0 - iconAnimationController!.value - 1.0), 0.0, 0.0, ), @@ -310,7 +299,7 @@ class _HomeDrawerState extends State { final listItemIcon = Icon( listItem.icon!.icon, - color: widget.screenIndex == listItem.index + color: screenIndex == listItem.index ? Color(Config.drawerTextColor) // TODO: drawerHighlightTextColor : Color(Config.drawerTextColor), ); @@ -332,11 +321,11 @@ class _HomeDrawerState extends State { Text( listItem.title, style: TextStyle( - fontWeight: widget.screenIndex == listItem.index + fontWeight: screenIndex == listItem.index ? FontWeight.w700 : FontWeight.w500, fontSize: Config.fontSize, - color: widget.screenIndex == listItem.index + color: screenIndex == listItem.index ? Color( Config.drawerTextColor, ) // TODO: drawerHighlightTextColor @@ -346,10 +335,7 @@ class _HomeDrawerState extends State { ], ), ), - if (widget.screenIndex == listItem.index) - animatedBuilder - else - const SizedBox() + if (screenIndex == listItem.index) animatedBuilder else const SizedBox() ], ); diff --git a/src/ui/flutter_app/lib/widgets/license_page.dart b/src/ui/flutter_app/lib/widgets/license_page.dart index 5d5d482e..5900e530 100644 --- a/src/ui/flutter_app/lib/widgets/license_page.dart +++ b/src/ui/flutter_app/lib/widgets/license_page.dart @@ -21,45 +21,40 @@ import 'package:flutter/services.dart' show rootBundle; import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; -class LicenseAgreementPage extends StatefulWidget { - @override - _LicenseAgreementPageState createState() => _LicenseAgreementPageState(); -} - -class _LicenseAgreementPageState extends State { - String _data = ""; - - Future _loadData() async { - final _loadedData = - await rootBundle.loadString(Constants.gplLicenseFilename); - setState(() { - _data = _loadedData; - }); - } - +class LicenseAgreementPage extends StatelessWidget { @override Widget build(BuildContext context) { - _loadData(); + return FutureBuilder( + future: rootBundle.loadString(Constants.gplLicenseFilename), + builder: (context, data) { + late final String _data; + if (!data.hasData) { + _data = 'Nothing to show'; + } else { + _data = data.data!; + } - return Scaffold( - appBar: AppBar(title: Text(S.of(context).license), centerTitle: true), - body: ListView( - children: [ - Container( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 16, - ), - child: Text( - _data != "" ? _data : 'Nothing to show', - style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), - textAlign: TextAlign.left, - ), + return Scaffold( + appBar: AppBar(title: Text(S.of(context).license), centerTitle: true), + body: ListView( + children: [ + Container( + padding: const EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: 16, + ), + child: Text( + _data, + style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), + textAlign: TextAlign.left, + ), + ), + ], ), - ], - ), + ); + }, ); } } diff --git a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart index a11247d8..6c8e4ea0 100644 --- a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart @@ -41,11 +41,6 @@ class _PersonalizationSettingsPageState Color pickerColor = const Color(0xFF808080); Color currentColor = const Color(0xFF808080); - @override - void initState() { - super.initState(); - } - // ValueChanged callback void changeColor(Color color) { setState(() => pickerColor = color); @@ -397,7 +392,6 @@ class _PersonalizationSettingsPageState context: context, children: [ SettingsListTile( - context: context, titleString: S.of(context).language, trailingString: Config.languageCode == Constants.defaultLanguageCodeName @@ -428,37 +422,31 @@ class _PersonalizationSettingsPageState ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).boardBorderLineWidth, onTap: setBoardBorderLineWidth, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).boardInnerLineWidth, onTap: setBoardInnerLineWidth, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).pieceWidth, onTap: setPieceWidth, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).fontSize, onTap: setFontSize, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).boardTop, onTap: setBoardTop, ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).animationDuration, onTap: setAnimationDuration, ), @@ -477,77 +465,66 @@ class _PersonalizationSettingsPageState context: context, children: [ SettingsListTile( - context: context, titleString: S.of(context).boardColor, trailingColor: Config.boardBackgroundColor, onTap: () => showColorDialog(S.of(context).boardColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).backgroundColor, trailingColor: Config.darkBackgroundColor, onTap: () => showColorDialog(S.of(context).backgroundColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).lineColor, trailingColor: Config.boardLineColor, onTap: () => showColorDialog(S.of(context).lineColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).whitePieceColor, trailingColor: Config.whitePieceColor, onTap: () => showColorDialog(S.of(context).whitePieceColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).blackPieceColor, trailingColor: Config.blackPieceColor, onTap: () => showColorDialog(S.of(context).blackPieceColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).pieceHighlightColor, trailingColor: Config.pieceHighlightColor, onTap: () => showColorDialog(S.of(context).pieceHighlightColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).messageColor, trailingColor: Config.messageColor, onTap: () => showColorDialog(S.of(context).messageColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).drawerColor, trailingColor: Config.drawerColor, onTap: () => showColorDialog(S.of(context).drawerColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).drawerBackgroundColor, trailingColor: Config.drawerBackgroundColor, onTap: () => showColorDialog(S.of(context).drawerBackgroundColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).drawerTextColor, trailingColor: Config.drawerTextColor, onTap: () => showColorDialog(S.of(context).drawerTextColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).drawerHighlightItemColor, trailingColor: Config.drawerHighlightItemColor, onTap: () => @@ -555,7 +532,6 @@ class _PersonalizationSettingsPageState ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).mainToolbarBackgroundColor, trailingColor: Config.mainToolbarBackgroundColor, onTap: () => @@ -563,14 +539,12 @@ class _PersonalizationSettingsPageState ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).mainToolbarIconColor, trailingColor: Config.mainToolbarIconColor, onTap: () => showColorDialog(S.of(context).mainToolbarIconColor), ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).navigationToolbarBackgroundColor, trailingColor: Config.navigationToolbarBackgroundColor, onTap: () => @@ -578,7 +552,6 @@ class _PersonalizationSettingsPageState ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).navigationToolbarIconColor, trailingColor: Config.navigationToolbarIconColor, onTap: () => diff --git a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart b/src/ui/flutter_app/lib/widgets/rule_settings_page.dart index 3683fd31..0a4f17b7 100644 --- a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/widgets/rule_settings_page.dart @@ -35,11 +35,6 @@ class RuleSettingsPage extends StatefulWidget { } class _RuleSettingsPageState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { return Scaffold( @@ -63,7 +58,6 @@ class _RuleSettingsPageState extends State { context: context, children: [ SettingsListTile( - context: context, titleString: S.of(context).piecesCount, subtitleString: S.of(context).piecesCount_Detail, trailingString: Config.piecesCount.toString(), @@ -79,7 +73,6 @@ class _RuleSettingsPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).nMoveRule, subtitleString: S.of(context).nMoveRule_Detail, trailingString: Config.nMoveRule.toString(), @@ -87,7 +80,6 @@ class _RuleSettingsPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).endgameNMoveRule, subtitleString: S.of(context).endgameNMoveRule_Detail, trailingString: Config.endgameNMoveRule.toString(), @@ -186,7 +178,6 @@ class _RuleSettingsPageState extends State { ), const ListItemDivider(), SettingsListTile( - context: context, titleString: S.of(context).flyPieceCount, subtitleString: S.of(context).flyPieceCount_Detail, trailingString: Config.flyPieceCount.toString(), @@ -548,7 +539,8 @@ class _RuleSettingsPageState extends State { }); debugPrint( - "[config] rule.mayOnlyRemoveUnplacedPieceInPlacingPhase: $value"); + "[config] rule.mayOnlyRemoveUnplacedPieceInPlacingPhase: $value", + ); Config.save(); } diff --git a/src/ui/flutter_app/lib/widgets/settings_list_tile.dart b/src/ui/flutter_app/lib/widgets/settings_list_tile.dart index 36b78bbd..a2401c57 100644 --- a/src/ui/flutter_app/lib/widgets/settings_list_tile.dart +++ b/src/ui/flutter_app/lib/widgets/settings_list_tile.dart @@ -25,7 +25,6 @@ import 'package:sanmill/style/app_theme.dart'; class SettingsListTile extends StatelessWidget { const SettingsListTile({ Key? key, - required this.context, required this.titleString, this.subtitleString, this.trailingString, @@ -33,12 +32,11 @@ class SettingsListTile extends StatelessWidget { required this.onTap, }) : super(key: key); - final BuildContext context; final String titleString; final String? subtitleString; final String? trailingString; final int? trailingColor; - final onTap; + final VoidCallback onTap; @override Widget build(BuildContext context) { From ef6c7a2176f55884495ba3360c201776249482fc Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sat, 9 Oct 2021 18:34:51 +0200 Subject: [PATCH 06/13] cleanup widget tree removes some redundant widgets that aren't displayed or diplicated --- src/ui/flutter_app/lib/l10n/resources.dart | 8 +- .../flutter_app/lib/widgets/about_page.dart | 79 ++++------- src/ui/flutter_app/lib/widgets/board.dart | 67 ++++++---- src/ui/flutter_app/lib/widgets/env_page.dart | 23 +--- src/ui/flutter_app/lib/widgets/game_page.dart | 2 +- .../flutter_app/lib/widgets/help_screen.dart | 14 +- .../flutter_app/lib/widgets/home_drawer.dart | 45 +++---- .../flutter_app/lib/widgets/license_page.dart | 28 ++-- .../lib/widgets/list_item_divider.dart | 9 +- .../lib/widgets/navigation_home_screen.dart | 35 ++--- .../lib/widgets/oss_license_page.dart | 125 +++++++++--------- 11 files changed, 194 insertions(+), 241 deletions(-) diff --git a/src/ui/flutter_app/lib/l10n/resources.dart b/src/ui/flutter_app/lib/l10n/resources.dart index 9ff69dff..b53def7a 100644 --- a/src/ui/flutter_app/lib/l10n/resources.dart +++ b/src/ui/flutter_app/lib/l10n/resources.dart @@ -520,7 +520,9 @@ class Resources { } Future setLanguage( - BuildContext context, Function(String?)? callback) async { + BuildContext context, + Function(String?)? callback, +) async { final languageColumn = Column( mainAxisSize: MainAxisSize.min, children: [ @@ -570,7 +572,7 @@ Bidirectionality getBidirectionality(BuildContext context) { currentLocale.languageCode == "he" || currentLocale.languageCode == "ps" || currentLocale.languageCode == "ur") { - print("bidirectionality: RTL"); + debugPrint("bidirectionality: RTL"); return Bidirectionality.rightToLeft; } else { return Bidirectionality.leftToRight; @@ -591,5 +593,5 @@ void setSpecialCountryAndRegion(BuildContext context) { break; } - print("Set Special Country and Region to $specialCountryAndRegion."); + debugPrint("Set Special Country and Region to $specialCountryAndRegion."); } diff --git a/src/ui/flutter_app/lib/widgets/about_page.dart b/src/ui/flutter_app/lib/widgets/about_page.dart index 3ee56e6e..e6d7fea0 100644 --- a/src/ui/flutter_app/lib/widgets/about_page.dart +++ b/src/ui/flutter_app/lib/widgets/about_page.dart @@ -37,42 +37,21 @@ class AboutPage extends StatelessWidget { // String _version = ""; final String tag = "[about] "; - String getMode() { - late String ret; + String get mode { if (kDebugMode) { - ret = "- debug"; + return "- debug"; } else if (kProfileMode) { - ret = "- profile"; + return "- profile"; } else if (kReleaseMode) { - ret = ""; + return ""; } else { - ret = "-test"; + return "-test"; } - - return ret; } @override Widget build(BuildContext context) { - final String mode = getMode(); - - return Scaffold( - backgroundColor: AppTheme.aboutPageBackgroundColor, - appBar: AppBar( - centerTitle: true, - title: Text("${S.of(context).about} ${S.of(context).appName}"), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - children: children(context, mode), - ), - ), - ); - } - - List children(BuildContext context, String mode) { - return [ + final List _children = [ FutureBuilder( future: PackageInfo.fromPlatform(), builder: (_, data) { @@ -95,19 +74,14 @@ class AboutPage extends StatelessWidget { ); }, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).feedback, onTap: _launchFeedback, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).eula, - onTap: () { - _launchEULA(); - }, + onTap: _launchEULA, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).license, onTap: () { @@ -119,43 +93,40 @@ class AboutPage extends StatelessWidget { ); }, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).sourceCode, - onTap: () { - _launchSourceCode(); - }, + onTap: _launchSourceCode, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).privacyPolicy, - onTap: () { - _launchPrivacyPolicy(); - }, + onTap: _launchPrivacyPolicy, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).ossLicenses, - onTap: () { - _launchThirdPartyNotices(context); - }, + onTap: () => _launchThirdPartyNotices(context), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).helpImproveTranslate, - onTap: () { - _launchHelpImproveTranslate(); - }, + onTap: _launchHelpImproveTranslate, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).thanks, - onTap: () { - _launchThanks(); - }, + onTap: _launchThanks, ), - const ListItemDivider(), ]; + + return Scaffold( + backgroundColor: AppTheme.aboutPageBackgroundColor, + appBar: AppBar( + centerTitle: true, + title: Text("${S.of(context).about} ${S.of(context).appName}"), + ), + body: ListView.separated( + itemBuilder: (_, index) => _children[index], + separatorBuilder: (_, __) => const ListItemDivider(), + itemCount: _children.length, + ), + ); } Future _launchURL(String url) async { diff --git a/src/ui/flutter_app/lib/widgets/board.dart b/src/ui/flutter_app/lib/widgets/board.dart index 4ecbff9f..58c7c86e 100644 --- a/src/ui/flutter_app/lib/widgets/board.dart +++ b/src/ui/flutter_app/lib/widgets/board.dart @@ -46,24 +46,22 @@ class Board extends StatelessWidget { buildSquareDescription(context); - final container = Container( - margin: EdgeInsets.zero, - child: GridView( - scrollDirection: Axis.horizontal, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 7, - ), - children: List.generate(7 * 7, (index) { - return Center( - child: Text( - squareDesc[index], - style: TextStyle( - fontSize: Config.fontSize, - color: Config.developerMode ? Colors.red : Colors.transparent, - ), + final grid = GridView( + scrollDirection: Axis.horizontal, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, + ), + children: List.generate( + 7 * 7, + (index) => Center( + child: Text( + squareDesc[index], + style: TextStyle( + fontSize: Config.fontSize, + color: Config.developerMode ? Colors.red : Colors.transparent, ), - ); - }), + ), + ), ), ); @@ -76,7 +74,7 @@ class Board extends StatelessWidget { blurIndex: Game.instance.blurIndex, animationValue: animationValue, ), - child: container, + child: grid, ); final boardContainer = Container( @@ -128,7 +126,7 @@ class Board extends StatelessWidget { final List coordinates = []; final List pieceDesc = []; - final map = [ + const map = [ /* 1 */ 1, 8, @@ -187,7 +185,7 @@ class Board extends StatelessWidget { 49 ]; - final checkPoints = [ + const checkPoints = [ /* 1 */ 1, 0, @@ -266,14 +264,27 @@ class Board extends StatelessWidget { for (var i = 0; i < 7 * 7; i++) { if (checkPoints[i] == 0) { pieceDesc.add(S.of(context).noPoint); - } else if (Game.instance.position.pieceOnGrid(i) == PieceColor.white) { - pieceDesc.add(S.of(context).whitePiece); - } else if (Game.instance.position.pieceOnGrid(i) == PieceColor.black) { - pieceDesc.add(S.of(context).blackPiece); - } else if (Game.instance.position.pieceOnGrid(i) == PieceColor.ban) { - pieceDesc.add(S.of(context).banPoint); - } else if (Game.instance.position.pieceOnGrid(i) == PieceColor.none) { - pieceDesc.add(S.of(context).emptyPoint); + } else { + switch (Game.instance.position.pieceOnGrid(i)) { + case PieceColor.white: + pieceDesc.add(S.of(context).whitePiece); + + break; + case PieceColor.black: + pieceDesc.add(S.of(context).blackPiece); + + break; + case PieceColor.ban: + pieceDesc.add(S.of(context).banPoint); + + break; + case PieceColor.none: + pieceDesc.add(S.of(context).emptyPoint); + + break; + + default: + } } } diff --git a/src/ui/flutter_app/lib/widgets/env_page.dart b/src/ui/flutter_app/lib/widgets/env_page.dart index bd94d8ff..78eca778 100644 --- a/src/ui/flutter_app/lib/widgets/env_page.dart +++ b/src/ui/flutter_app/lib/widgets/env_page.dart @@ -39,22 +39,13 @@ class EnvironmentVariablesPage extends StatelessWidget { title: Text(S.of(context).environmentVariables), centerTitle: true, ), - body: ListView( - children: [ - Container( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 16, - ), - child: Text( - _data, - style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), - textAlign: TextAlign.left, - ), - ), - ], + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Text( + _data, + style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), + textAlign: TextAlign.left, + ), ), ); }, diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/widgets/game_page.dart index 91751a8a..a170d2a8 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_page.dart @@ -1515,7 +1515,7 @@ class _GamePageState extends State borderRadius: BorderRadius.circular(2), ), ), - Container( + Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( _tip!, diff --git a/src/ui/flutter_app/lib/widgets/help_screen.dart b/src/ui/flutter_app/lib/widgets/help_screen.dart index 18c31386..19e3c3b4 100644 --- a/src/ui/flutter_app/lib/widgets/help_screen.dart +++ b/src/ui/flutter_app/lib/widgets/help_screen.dart @@ -20,14 +20,12 @@ class HelpScreen extends StatelessWidget { ), backgroundColor: Color(Config.darkBackgroundColor), body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16), - child: Text( - S.of(context).helpContent, - style: TextStyle( - fontSize: Config.fontSize, - color: AppTheme.helpTextColor, - ), + padding: const EdgeInsets.all(16), + child: Text( + S.of(context).helpContent, + style: TextStyle( + fontSize: Config.fontSize, + color: AppTheme.helpTextColor, ), ), ), diff --git a/src/ui/flutter_app/lib/widgets/home_drawer.dart b/src/ui/flutter_app/lib/widgets/home_drawer.dart index 5877ba52..4777cf20 100644 --- a/src/ui/flutter_app/lib/widgets/home_drawer.dart +++ b/src/ui/flutter_app/lib/widgets/home_drawer.dart @@ -135,9 +135,7 @@ class HomeDrawer extends StatelessWidget { final animatedBuilder = AnimatedBuilder( animation: iconAnimationController!, - builder: (BuildContext context, Widget? child) { - return scaleTransition; - }, + builder: (_, __) => scaleTransition, ); final animatedTextsColors = [ @@ -181,21 +179,17 @@ class HomeDrawer extends StatelessWidget { }, ); - final drawerHeader = Container( - width: double.infinity, - padding: EdgeInsets.zero, - child: Container( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - animatedBuilder, - Padding( - padding: EdgeInsets.only(top: isLargeScreen() ? 30 : 8, left: 4), - child: ExcludeSemantics(child: animatedTextKit), - ), - ], - ), + final drawerHeader = Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + animatedBuilder, + Padding( + padding: EdgeInsets.only(top: isLargeScreen() ? 30 : 8, left: 4), + child: ExcludeSemantics(child: animatedTextKit), + ), + ], ), ); @@ -233,9 +227,9 @@ class HomeDrawer extends StatelessWidget { ); */ - final scaffold = Scaffold( - backgroundColor: Color(Config.drawerBackgroundColor), - body: Column( + final drawer = Material( + color: Color(Config.drawerBackgroundColor), + child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ drawerHeader, @@ -244,7 +238,6 @@ class HomeDrawer extends StatelessWidget { Expanded( child: ListView.builder( physics: const BouncingScrollPhysics(), - padding: EdgeInsets.zero, itemCount: drawerList.length, itemBuilder: (BuildContext context, int index) => buildInkwell(context, drawerList[index]), @@ -256,7 +249,7 @@ class HomeDrawer extends StatelessWidget { ), ); - return scaffold; + return drawer; } Future navigationToScreen(DrawerIndex? index) async { @@ -278,7 +271,7 @@ class HomeDrawer extends StatelessWidget { 0.0, ), child: Padding( - padding: const EdgeInsets.only(top: 8, bottom: 8), + padding: const EdgeInsets.symmetric(horizontal: 8), child: Container( width: MediaQuery.of(context).size.width * 0.75 - 64, height: 46, @@ -306,8 +299,8 @@ class HomeDrawer extends StatelessWidget { final stack = Stack( children: [ - Container( - padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Row( children: [ const SizedBox(width: 6.0, height: 46.0), diff --git a/src/ui/flutter_app/lib/widgets/license_page.dart b/src/ui/flutter_app/lib/widgets/license_page.dart index 5900e530..9c5a89e1 100644 --- a/src/ui/flutter_app/lib/widgets/license_page.dart +++ b/src/ui/flutter_app/lib/widgets/license_page.dart @@ -35,23 +35,17 @@ class LicenseAgreementPage extends StatelessWidget { } return Scaffold( - appBar: AppBar(title: Text(S.of(context).license), centerTitle: true), - body: ListView( - children: [ - Container( - padding: const EdgeInsets.only( - top: 16, - left: 16, - right: 16, - bottom: 16, - ), - child: Text( - _data, - style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), - textAlign: TextAlign.left, - ), - ), - ], + appBar: AppBar( + title: Text(S.of(context).license), + centerTitle: true, + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Text( + _data, + style: const TextStyle(fontFamily: 'Monospace', fontSize: 12), + textAlign: TextAlign.left, + ), ), ); }, diff --git a/src/ui/flutter_app/lib/widgets/list_item_divider.dart b/src/ui/flutter_app/lib/widgets/list_item_divider.dart index f0c6760b..50f7c6ea 100644 --- a/src/ui/flutter_app/lib/widgets/list_item_divider.dart +++ b/src/ui/flutter_app/lib/widgets/list_item_divider.dart @@ -19,7 +19,6 @@ import 'package:flutter/material.dart'; import 'package:sanmill/style/app_theme.dart'; -// TODO: replace with Divider(); class ListItemDivider extends StatelessWidget { const ListItemDivider({ Key? key, @@ -27,10 +26,10 @@ class ListItemDivider extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( - margin: const EdgeInsets.symmetric(horizontal: 16), - width: double.infinity, - height: 1.0, + return const Divider( + indent: 16, + endIndent: 16, + thickness: 1.0, color: AppTheme.listItemDividerColor, ); } diff --git a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart b/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart index 69bcf160..50ae5961 100644 --- a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart @@ -29,7 +29,6 @@ import 'package:sanmill/common/constants.dart'; import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/style/colors.dart'; import 'package:sanmill/widgets/about_page.dart'; import 'package:sanmill/widgets/drawer_user_controller.dart'; import 'package:sanmill/widgets/help_screen.dart'; @@ -58,26 +57,19 @@ class _NavigationHomeScreenState extends State { @override Widget build(BuildContext context) { - return Container( - color: UIColors.nearlyWhite, - child: SafeArea( - top: false, - bottom: false, - child: Scaffold( - backgroundColor: AppTheme.navigationHomeScreenBackgroundColor, - body: DrawerUserController( - screenIndex: drawerIndex, - drawerWidth: MediaQuery.of(context).size.width * 0.75, - onDrawerCall: (DrawerIndex index) { - // callback from drawer for replace screen - // as user need with passing DrawerIndex (Enum index) - changeIndex(index); - }, - // we replace screen view as - // we need on navigate starting screens - screenView: screenView, - ), - ), + return Material( + color: AppTheme.navigationHomeScreenBackgroundColor, + child: DrawerUserController( + screenIndex: drawerIndex, + drawerWidth: MediaQuery.of(context).size.width * 0.75, + onDrawerCall: (DrawerIndex index) { + // callback from drawer for replace screen + // as user need with passing DrawerIndex (Enum index) + changeIndex(index); + }, + // we replace screen view as + // we need on navigate starting screens + screenView: screenView, ), ); } @@ -95,6 +87,7 @@ class _NavigationHomeScreenState extends State { drawerIndex = index; + // TODO: use switch case final engineType = drawerMap[drawerIndex!]; if (engineType != null) { setState(() { diff --git a/src/ui/flutter_app/lib/widgets/oss_license_page.dart b/src/ui/flutter_app/lib/widgets/oss_license_page.dart index 2851e07f..fdf6b315 100644 --- a/src/ui/flutter_app/lib/widgets/oss_license_page.dart +++ b/src/ui/flutter_app/lib/widgets/oss_license_page.dart @@ -37,14 +37,15 @@ class FlutterLicense extends LicenseEntry { class OssLicensesPage extends StatelessWidget { static Future> loadLicenses() async { Stream licenses() async* { - yield FlutterLicense([ - 'Sound Effects' - ], [ - const LicenseParagraph( - 'CC-0\nhttps://freesound.org/people/unfa/sounds/243749/', - 0, - ) - ]); + yield FlutterLicense( + ['Sound Effects'], + [ + const LicenseParagraph( + 'CC-0\nhttps://freesound.org/people/unfa/sounds/243749/', + 0, + ), + ], + ); } LicenseRegistry.addLicense(licenses); @@ -67,17 +68,14 @@ class OssLicensesPage extends StatelessWidget { return ossKeys..sort(); } - static final _licenses = loadLicenses(); - @override Widget build(BuildContext context) => Scaffold( appBar: AppBar( title: Text(S.of(context).ossLicenses), ), body: FutureBuilder>( - future: _licenses, + future: loadLicenses(), builder: (context, snapshot) => ListView.separated( - padding: EdgeInsets.zero, itemCount: snapshot.data?.length ?? 0, itemBuilder: (context, index) { final key = snapshot.data![index]; @@ -85,13 +83,12 @@ class OssLicensesPage extends StatelessWidget { final version = ossl['version']; final desc = ossl['description'] as String?; return ListTile( - title: Text('$key ${version ?? ''}'), + title: Text('$key $version'), subtitle: desc != null ? Text(desc) : null, trailing: const Icon(FluentIcons.chevron_right_24_regular), onTap: () => Navigator.of(context).push( MaterialPageRoute( - builder: (context) => - MiscOssLicenseSingle(name: key, json: ossl), + builder: (_) => MiscOssLicenseSingle(name: key, json: ossl), ), ), ); @@ -106,14 +103,17 @@ class MiscOssLicenseSingle extends StatelessWidget { final String name; final Map json; + const MiscOssLicenseSingle({ + required this.name, + required this.json, + }); + String get version => json['version'] as String? ?? ""; String? get description => json['description'] as String?; String get licenseText => json['license'] as String; String? get homepage => json['homepage'] as String?; - const MiscOssLicenseSingle({required this.name, required this.json}); - - String _bodyText() => licenseText.split('\n').map((line) { + String get _bodyText => licenseText.split('\n').map((line) { if (line.startsWith('//')) line = line.substring(2); return line.trim(); }).join('\n'); @@ -121,54 +121,55 @@ class MiscOssLicenseSingle extends StatelessWidget { @override Widget build(BuildContext context) => Scaffold( appBar: AppBar(title: Text('$name $version')), - body: Container( - color: Theme.of(context).canvasColor, - child: ListView( - children: [ - if (description != null) - Padding( - padding: const EdgeInsets.only( - top: 12.0, - left: 12.0, - right: 12.0, - ), - child: Text( - description!, - style: Theme.of(context) - .textTheme - .bodyText2! - .copyWith(fontWeight: FontWeight.bold), - ), - ), - if (homepage != null) - Padding( - padding: const EdgeInsets.only( - top: 12.0, - left: 12.0, - right: 12.0, - ), - child: InkWell( - child: Text( - homepage!, - style: const TextStyle( - color: Colors.blue, - decoration: TextDecoration.underline, - ), - ), - onTap: () => launch(homepage!), - ), - ), - if (description != null || homepage != null) const Divider(), + backgroundColor: Theme.of(context).canvasColor, + body: ListView( + children: [ + if (description != null) Padding( - padding: - const EdgeInsets.only(top: 12.0, left: 12.0, right: 12.0), + padding: const EdgeInsets.only( + top: 12.0, + left: 12.0, + right: 12.0, + ), child: Text( - _bodyText(), - style: Theme.of(context).textTheme.bodyText2, + description!, + style: Theme.of(context) + .textTheme + .bodyText2! + .copyWith(fontWeight: FontWeight.bold), ), ), - ], - ), + if (homepage != null) + Padding( + padding: const EdgeInsets.only( + top: 12.0, + left: 12.0, + right: 12.0, + ), + child: InkWell( + child: Text( + homepage!, + style: const TextStyle( + color: Colors.blue, + decoration: TextDecoration.underline, + ), + ), + onTap: () => launch(homepage!), + ), + ), + if (description != null || homepage != null) const Divider(), + Padding( + padding: const EdgeInsets.only( + top: 12.0, + left: 12.0, + right: 12.0, + ), + child: Text( + _bodyText, + style: Theme.of(context).textTheme.bodyText2, + ), + ), + ], ), ); } From ab97c71188a46565ef7188456c07e73eb30d9d71 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:08:45 +0200 Subject: [PATCH 07/13] restructure files and renable theming - change file structure - fixes the personalication/theme to not be static anymore --- .../flutter_app/lib/engine/native_engine.dart | 2 +- src/ui/flutter_app/lib/l10n/resources.dart | 8 +- src/ui/flutter_app/lib/main.dart | 6 +- src/ui/flutter_app/lib/mill/game.dart | 2 +- src/ui/flutter_app/lib/mill/position.dart | 8 +- src/ui/flutter_app/lib/mill/recorder.dart | 2 +- src/ui/flutter_app/lib/mill/zobrist.dart | 4 +- .../lib/{widgets => screens}/about_page.dart | 6 +- .../lib/{widgets => screens}/board.dart | 14 +- .../drawer_user_controller.dart | 6 +- .../lib/{widgets => screens}/env_page.dart | 2 +- .../lib/{widgets => screens}/game_page.dart | 20 +-- .../game_settings_page.dart | 14 +- .../lib/{widgets => screens}/help_screen.dart | 4 +- .../lib/{widgets => screens}/home_drawer.dart | 16 +- .../{widgets => screens}/license_page.dart | 2 +- .../list_item_divider.dart | 4 +- .../navigation_home_screen.dart | 14 +- .../oss_license_page.dart | 0 .../personalization_settings_page.dart | 12 +- .../rule_settings_page.dart | 12 +- .../settings}/settings_card.dart | 2 +- .../settings}/settings_list_tile.dart | 4 +- .../settings}/settings_switch_list_tile.dart | 4 +- src/ui/flutter_app/lib/services/audios.dart | 2 +- .../lib/{ => shared}/common/config.dart | 4 +- .../lib/{ => shared}/common/constants.dart | 0 .../lib/{ => shared}/common/settings.dart | 2 +- .../lib/{widgets => shared}/dialog.dart | 4 +- .../painters}/board_painter.dart | 10 +- .../painters}/painter_base.dart | 2 +- .../painters}/pieces_painter.dart | 4 +- .../lib/{widgets => shared}/picker.dart | 4 +- .../lib/{widgets => shared}/snack_bar.dart | 2 +- .../lib/shared/theme/app_theme.dart | 142 ++++++++++++++++++ .../flutter_app/lib/shared/theme/colors.dart | 46 ++++++ src/ui/flutter_app/lib/style/app_theme.dart | 139 ----------------- src/ui/flutter_app/lib/style/colors.dart | 45 ------ src/ui/flutter_app/test/widget_test.dart | 2 +- 39 files changed, 289 insertions(+), 287 deletions(-) rename src/ui/flutter_app/lib/{widgets => screens}/about_page.dart (98%) rename src/ui/flutter_app/lib/{widgets => screens}/board.dart (94%) rename src/ui/flutter_app/lib/{widgets => screens}/drawer_user_controller.dart (98%) rename src/ui/flutter_app/lib/{widgets => screens}/env_page.dart (96%) rename src/ui/flutter_app/lib/{widgets => screens}/game_page.dart (99%) rename src/ui/flutter_app/lib/{widgets => screens}/game_settings_page.dart (97%) rename src/ui/flutter_app/lib/{widgets => screens}/help_screen.dart (88%) rename src/ui/flutter_app/lib/{widgets => screens}/home_drawer.dart (96%) rename src/ui/flutter_app/lib/{widgets => screens}/license_page.dart (96%) rename src/ui/flutter_app/lib/{widgets => screens}/list_item_divider.dart (93%) rename src/ui/flutter_app/lib/{widgets => screens}/navigation_home_screen.dart (93%) rename src/ui/flutter_app/lib/{widgets => screens}/oss_license_page.dart (100%) rename src/ui/flutter_app/lib/{widgets => screens}/personalization_settings_page.dart (98%) rename src/ui/flutter_app/lib/{widgets => screens}/rule_settings_page.dart (98%) rename src/ui/flutter_app/lib/{widgets => screens/settings}/settings_card.dart (95%) rename src/ui/flutter_app/lib/{widgets => screens/settings}/settings_list_tile.dart (96%) rename src/ui/flutter_app/lib/{widgets => screens/settings}/settings_switch_list_tile.dart (94%) rename src/ui/flutter_app/lib/{ => shared}/common/config.dart (99%) rename src/ui/flutter_app/lib/{ => shared}/common/constants.dart (100%) rename src/ui/flutter_app/lib/{ => shared}/common/settings.dart (97%) rename src/ui/flutter_app/lib/{widgets => shared}/dialog.dart (98%) rename src/ui/flutter_app/lib/{painting => shared/painters}/board_painter.dart (97%) rename src/ui/flutter_app/lib/{painting => shared/painters}/painter_base.dart (95%) rename src/ui/flutter_app/lib/{painting => shared/painters}/pieces_painter.dart (98%) rename src/ui/flutter_app/lib/{widgets => shared}/picker.dart (95%) rename src/ui/flutter_app/lib/{widgets => shared}/snack_bar.dart (95%) create mode 100644 src/ui/flutter_app/lib/shared/theme/app_theme.dart create mode 100644 src/ui/flutter_app/lib/shared/theme/colors.dart delete mode 100644 src/ui/flutter_app/lib/style/app_theme.dart delete mode 100644 src/ui/flutter_app/lib/style/colors.dart diff --git a/src/ui/flutter_app/lib/engine/native_engine.dart b/src/ui/flutter_app/lib/engine/native_engine.dart index f4459297..dec820c6 100644 --- a/src/ui/flutter_app/lib/engine/native_engine.dart +++ b/src/ui/flutter_app/lib/engine/native_engine.dart @@ -20,9 +20,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/types.dart'; +import 'package:sanmill/shared/common/config.dart'; import 'engine.dart'; diff --git a/src/ui/flutter_app/lib/l10n/resources.dart b/src/ui/flutter_app/lib/l10n/resources.dart index b53def7a..c5f0bcdd 100644 --- a/src/ui/flutter_app/lib/l10n/resources.dart +++ b/src/ui/flutter_app/lib/l10n/resources.dart @@ -19,11 +19,11 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/list_item_divider.dart'; +import 'package:sanmill/screens/list_item_divider.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; Map languageCodeToStrings = { "ar": ArabicStrings(), diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index 318e72d5..4712d02c 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -27,12 +27,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; +import 'package:sanmill/screens/navigation_home_screen.dart'; import 'package:sanmill/services/audios.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/navigation_home_screen.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'services/audios.dart'; diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index 2804caf4..b9b0e3b0 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -17,8 +17,8 @@ */ import 'package:flutter/foundation.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/engine/engine.dart'; +import 'package:sanmill/shared/common/config.dart'; import 'position.dart'; import 'types.dart'; diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index 122b07dc..7a2e5fb2 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -982,15 +982,13 @@ class Position { return false; } - int? moveSquare; - for (int s = sqBegin; s < sqEnd; s++) { if (!(sideToMove() == colorOn(s))) { continue; } for (int d = moveDirectionBegin; d < moveDirectionNumber; d++) { - moveSquare = adjacentSquares[s][d]; + final int moveSquare = adjacentSquares[s][d]; if (moveSquare != 0 && board[moveSquare] == Piece.noPiece) { return false; } @@ -1010,7 +1008,7 @@ class Position { /////////////////////////////////////////////////////////////////////////////// - int getNPiecesInHand() { + int get nPiecesInHand { pieceInHandCount[PieceColor.white] = rule.piecesCount - pieceOnBoardCount[PieceColor.white]!; pieceInHandCount[PieceColor.black] = @@ -1051,7 +1049,7 @@ class Position { return -1; } - getNPiecesInHand(); + nPiecesInHand; pieceToRemoveCount = 0; winner = PieceColor.nobody; diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index 6dec910d..42940b0f 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -17,7 +17,7 @@ */ import 'package:flutter/foundation.dart'; -import 'package:sanmill/common/config.dart'; +import 'package:sanmill/shared/common/config.dart'; import 'position.dart'; import 'types.dart'; diff --git a/src/ui/flutter_app/lib/mill/zobrist.dart b/src/ui/flutter_app/lib/mill/zobrist.dart index 390cb2b5..ed320ba4 100644 --- a/src/ui/flutter_app/lib/mill/zobrist.dart +++ b/src/ui/flutter_app/lib/mill/zobrist.dart @@ -20,7 +20,7 @@ class Zobrist { const Zobrist._(); static const int KEY_MISC_BIT = 2; - static List> psq = [ + static const List> psq = [ [ 0x4E421A, 0x3962FF, @@ -191,5 +191,5 @@ class Zobrist { ] ]; - static int side = 0x201906; + static const int side = 0x201906; } diff --git a/src/ui/flutter_app/lib/widgets/about_page.dart b/src/ui/flutter_app/lib/screens/about_page.dart similarity index 98% rename from src/ui/flutter_app/lib/widgets/about_page.dart rename to src/ui/flutter_app/lib/screens/about_page.dart index e6d7fea0..42ed09c3 100644 --- a/src/ui/flutter_app/lib/widgets/about_page.dart +++ b/src/ui/flutter_app/lib/screens/about_page.dart @@ -22,11 +22,11 @@ import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/flutter_version.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/settings_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_list_tile.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'package:url_launcher/url_launcher.dart'; import 'license_page.dart'; diff --git a/src/ui/flutter_app/lib/widgets/board.dart b/src/ui/flutter_app/lib/screens/board.dart similarity index 94% rename from src/ui/flutter_app/lib/widgets/board.dart rename to src/ui/flutter_app/lib/screens/board.dart index 58c7c86e..6be66aa1 100644 --- a/src/ui/flutter_app/lib/widgets/board.dart +++ b/src/ui/flutter_app/lib/screens/board.dart @@ -17,19 +17,21 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/painting/board_painter.dart'; -import 'package:sanmill/painting/pieces_painter.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/painters/board_painter.dart'; +import 'package:sanmill/shared/painters/pieces_painter.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; + +typedef BoardTapCallback = void Function(int index); class Board extends StatelessWidget { final double width; final double height; - final Function(BuildContext, int) onBoardTap; + final BoardTapCallback onBoardTap; final double animationValue; final List squareDesc = []; final String tag = "[board]"; @@ -117,7 +119,7 @@ class Board extends StatelessWidget { debugPrint("$tag Tap on ($row, $column) <$index>"); - onBoardTap(context, index); + onBoardTap(index); }, ); } diff --git a/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart b/src/ui/flutter_app/lib/screens/drawer_user_controller.dart similarity index 98% rename from src/ui/flutter_app/lib/widgets/drawer_user_controller.dart rename to src/ui/flutter_app/lib/screens/drawer_user_controller.dart index b78f9f99..b5052125 100644 --- a/src/ui/flutter_app/lib/widgets/drawer_user_controller.dart +++ b/src/ui/flutter_app/lib/screens/drawer_user_controller.dart @@ -17,11 +17,11 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/home_drawer.dart'; +import 'package:sanmill/screens/home_drawer.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; class DrawerUserController extends StatefulWidget { const DrawerUserController({ diff --git a/src/ui/flutter_app/lib/widgets/env_page.dart b/src/ui/flutter_app/lib/screens/env_page.dart similarity index 96% rename from src/ui/flutter_app/lib/widgets/env_page.dart rename to src/ui/flutter_app/lib/screens/env_page.dart index 78eca778..0fa381ee 100644 --- a/src/ui/flutter_app/lib/widgets/env_page.dart +++ b/src/ui/flutter_app/lib/screens/env_page.dart @@ -18,8 +18,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; +import 'package:sanmill/shared/common/constants.dart'; class EnvironmentVariablesPage extends StatelessWidget { @override diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/screens/game_page.dart similarity index 99% rename from src/ui/flutter_app/lib/widgets/game_page.dart rename to src/ui/flutter_app/lib/screens/game_page.dart index a170d2a8..6ed876b3 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/screens/game_page.dart @@ -23,8 +23,6 @@ import 'dart:async'; import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/engine/native_engine.dart'; import 'package:sanmill/generated/l10n.dart'; @@ -34,17 +32,19 @@ import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/rule.dart'; import 'package:sanmill/mill/types.dart'; +import 'package:sanmill/screens/game_settings_page.dart'; import 'package:sanmill/services/audios.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/game_settings_page.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; //import 'package:screen_recorder/screen_recorder.dart'; import 'package:stack_trace/stack_trace.dart'; +import '../shared/dialog.dart'; +import '../shared/picker.dart'; +import '../shared/snack_bar.dart'; import 'board.dart'; -import 'dialog.dart'; import 'game_settings_page.dart'; -import 'picker.dart'; -import 'snack_bar.dart'; double boardWidth = 0.0; @@ -188,7 +188,7 @@ class _GamePageState extends State } } - dynamic onBoardTap(BuildContext context, int index) { + dynamic onBoardTap(int index) { if (!isReady) { debugPrint("[tap] Not ready, ignore tapping."); return false; @@ -1189,7 +1189,7 @@ class _GamePageState extends State } void onInfoButtonPressed() { - final analyzeText = getInfoText(); + final analyzeText = infoText; showDialog( context: context, barrierDismissible: true, @@ -1584,7 +1584,7 @@ class _GamePageState extends State ); } - String getInfoText() { + String get infoText { String phase = ""; final String period = Config.screenReaderSupport ? "." : ""; final String comma = Config.screenReaderSupport ? "," : ""; diff --git a/src/ui/flutter_app/lib/widgets/game_settings_page.dart b/src/ui/flutter_app/lib/screens/game_settings_page.dart similarity index 97% rename from src/ui/flutter_app/lib/widgets/game_settings_page.dart rename to src/ui/flutter_app/lib/screens/game_settings_page.dart index 11e833ba..5d734ac8 100644 --- a/src/ui/flutter_app/lib/widgets/game_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/game_settings_page.dart @@ -20,15 +20,15 @@ import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/settings.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/settings_card.dart'; -import 'package:sanmill/widgets/settings_list_tile.dart'; -import 'package:sanmill/widgets/settings_switch_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_card.dart'; +import 'package:sanmill/screens/settings/settings_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_switch_list_tile.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/settings.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; -import 'dialog.dart'; +import '../shared/dialog.dart'; import 'env_page.dart'; import 'list_item_divider.dart'; diff --git a/src/ui/flutter_app/lib/widgets/help_screen.dart b/src/ui/flutter_app/lib/screens/help_screen.dart similarity index 88% rename from src/ui/flutter_app/lib/widgets/help_screen.dart rename to src/ui/flutter_app/lib/screens/help_screen.dart index 19e3c3b4..0130e7ee 100644 --- a/src/ui/flutter_app/lib/widgets/help_screen.dart +++ b/src/ui/flutter_app/lib/screens/help_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; class HelpScreen extends StatelessWidget { @override diff --git a/src/ui/flutter_app/lib/widgets/home_drawer.dart b/src/ui/flutter_app/lib/screens/home_drawer.dart similarity index 96% rename from src/ui/flutter_app/lib/widgets/home_drawer.dart rename to src/ui/flutter_app/lib/screens/home_drawer.dart index 4777cf20..9334a960 100644 --- a/src/ui/flutter_app/lib/widgets/home_drawer.dart +++ b/src/ui/flutter_app/lib/screens/home_drawer.dart @@ -21,12 +21,12 @@ import 'dart:async'; import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/game_settings_page.dart'; +import 'package:sanmill/screens/game_settings_page.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; enum DrawerIndex { humanVsAi, @@ -227,7 +227,7 @@ class HomeDrawer extends StatelessWidget { ); */ - final drawer = Material( + return Material( color: Color(Config.drawerBackgroundColor), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -248,8 +248,6 @@ class HomeDrawer extends StatelessWidget { ], ), ); - - return drawer; } Future navigationToScreen(DrawerIndex? index) async { @@ -271,7 +269,7 @@ class HomeDrawer extends StatelessWidget { 0.0, ), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), + padding: const EdgeInsets.symmetric(vertical: 8), child: Container( width: MediaQuery.of(context).size.width * 0.75 - 64, height: 46, @@ -300,7 +298,7 @@ class HomeDrawer extends StatelessWidget { final stack = Stack( children: [ Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), + padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ const SizedBox(width: 6.0, height: 46.0), diff --git a/src/ui/flutter_app/lib/widgets/license_page.dart b/src/ui/flutter_app/lib/screens/license_page.dart similarity index 96% rename from src/ui/flutter_app/lib/widgets/license_page.dart rename to src/ui/flutter_app/lib/screens/license_page.dart index 9c5a89e1..3d580251 100644 --- a/src/ui/flutter_app/lib/widgets/license_page.dart +++ b/src/ui/flutter_app/lib/screens/license_page.dart @@ -18,8 +18,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; +import 'package:sanmill/shared/common/constants.dart'; class LicenseAgreementPage extends StatelessWidget { @override diff --git a/src/ui/flutter_app/lib/widgets/list_item_divider.dart b/src/ui/flutter_app/lib/screens/list_item_divider.dart similarity index 93% rename from src/ui/flutter_app/lib/widgets/list_item_divider.dart rename to src/ui/flutter_app/lib/screens/list_item_divider.dart index 50f7c6ea..3b80df82 100644 --- a/src/ui/flutter_app/lib/widgets/list_item_divider.dart +++ b/src/ui/flutter_app/lib/screens/list_item_divider.dart @@ -17,7 +17,7 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; class ListItemDivider extends StatelessWidget { const ListItemDivider({ @@ -26,7 +26,7 @@ class ListItemDivider extends StatelessWidget { @override Widget build(BuildContext context) { - return const Divider( + return Divider( indent: 16, endIndent: 16, thickness: 1.0, diff --git a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart similarity index 93% rename from src/ui/flutter_app/lib/widgets/navigation_home_screen.dart rename to src/ui/flutter_app/lib/screens/navigation_home_screen.dart index 50ae5961..917e3c91 100644 --- a/src/ui/flutter_app/lib/widgets/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart @@ -24,15 +24,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/mill/game.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/about_page.dart'; -import 'package:sanmill/widgets/drawer_user_controller.dart'; -import 'package:sanmill/widgets/help_screen.dart'; -import 'package:sanmill/widgets/home_drawer.dart'; +import 'package:sanmill/screens/about_page.dart'; +import 'package:sanmill/screens/drawer_user_controller.dart'; +import 'package:sanmill/screens/help_screen.dart'; +import 'package:sanmill/screens/home_drawer.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'game_page.dart'; import 'game_settings_page.dart'; diff --git a/src/ui/flutter_app/lib/widgets/oss_license_page.dart b/src/ui/flutter_app/lib/screens/oss_license_page.dart similarity index 100% rename from src/ui/flutter_app/lib/widgets/oss_license_page.dart rename to src/ui/flutter_app/lib/screens/oss_license_page.dart diff --git a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart similarity index 98% rename from src/ui/flutter_app/lib/widgets/personalization_settings_page.dart rename to src/ui/flutter_app/lib/screens/personalization_settings_page.dart index 6c8e4ea0..5b8c7299 100644 --- a/src/ui/flutter_app/lib/widgets/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart @@ -18,14 +18,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/settings_card.dart'; -import 'package:sanmill/widgets/settings_list_tile.dart'; -import 'package:sanmill/widgets/settings_switch_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_card.dart'; +import 'package:sanmill/screens/settings/settings_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_switch_list_tile.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'list_item_divider.dart'; diff --git a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart b/src/ui/flutter_app/lib/screens/rule_settings_page.dart similarity index 98% rename from src/ui/flutter_app/lib/widgets/rule_settings_page.dart rename to src/ui/flutter_app/lib/screens/rule_settings_page.dart index 0a4f17b7..4e3ecc29 100644 --- a/src/ui/flutter_app/lib/widgets/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/rule_settings_page.dart @@ -17,17 +17,17 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/mill/rule.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/settings_card.dart'; -import 'package:sanmill/widgets/settings_list_tile.dart'; -import 'package:sanmill/widgets/settings_switch_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_card.dart'; +import 'package:sanmill/screens/settings/settings_list_tile.dart'; +import 'package:sanmill/screens/settings/settings_switch_list_tile.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; +import '../shared/snack_bar.dart'; import 'list_item_divider.dart'; -import 'snack_bar.dart'; class RuleSettingsPage extends StatefulWidget { @override diff --git a/src/ui/flutter_app/lib/widgets/settings_card.dart b/src/ui/flutter_app/lib/screens/settings/settings_card.dart similarity index 95% rename from src/ui/flutter_app/lib/widgets/settings_card.dart rename to src/ui/flutter_app/lib/screens/settings/settings_card.dart index 4afd5f89..078d3764 100644 --- a/src/ui/flutter_app/lib/widgets/settings_card.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_card.dart @@ -17,7 +17,7 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsCard extends StatelessWidget { const SettingsCard({ diff --git a/src/ui/flutter_app/lib/widgets/settings_list_tile.dart b/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart similarity index 96% rename from src/ui/flutter_app/lib/widgets/settings_list_tile.dart rename to src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart index a2401c57..acc419db 100644 --- a/src/ui/flutter_app/lib/widgets/settings_list_tile.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart @@ -18,9 +18,9 @@ import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsListTile extends StatelessWidget { const SettingsListTile({ diff --git a/src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart b/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart similarity index 94% rename from src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart rename to src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart index 01ab23a3..34afbbcd 100644 --- a/src/ui/flutter_app/lib/widgets/settings_switch_list_tile.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart @@ -17,8 +17,8 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsSwitchListTile extends StatelessWidget { const SettingsSwitchListTile({ diff --git a/src/ui/flutter_app/lib/services/audios.dart b/src/ui/flutter_app/lib/services/audios.dart index 8c7fd8ab..1c7dabbc 100644 --- a/src/ui/flutter_app/lib/services/audios.dart +++ b/src/ui/flutter_app/lib/services/audios.dart @@ -20,7 +20,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -import 'package:sanmill/common/config.dart'; +import 'package:sanmill/shared/common/config.dart'; import 'package:soundpool/soundpool.dart'; import 'package:stack_trace/stack_trace.dart'; diff --git a/src/ui/flutter_app/lib/common/config.dart b/src/ui/flutter_app/lib/shared/common/config.dart similarity index 99% rename from src/ui/flutter_app/lib/common/config.dart rename to src/ui/flutter_app/lib/shared/common/config.dart index 8891fda7..437b1038 100644 --- a/src/ui/flutter_app/lib/common/config.dart +++ b/src/ui/flutter_app/lib/shared/common/config.dart @@ -17,10 +17,10 @@ */ import 'package:flutter/foundation.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/mill/rule.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'settings.dart'; diff --git a/src/ui/flutter_app/lib/common/constants.dart b/src/ui/flutter_app/lib/shared/common/constants.dart similarity index 100% rename from src/ui/flutter_app/lib/common/constants.dart rename to src/ui/flutter_app/lib/shared/common/constants.dart diff --git a/src/ui/flutter_app/lib/common/settings.dart b/src/ui/flutter_app/lib/shared/common/settings.dart similarity index 97% rename from src/ui/flutter_app/lib/common/settings.dart rename to src/ui/flutter_app/lib/shared/common/settings.dart index 9d115aec..b7c8d710 100644 --- a/src/ui/flutter_app/lib/common/settings.dart +++ b/src/ui/flutter_app/lib/shared/common/settings.dart @@ -21,7 +21,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:sanmill/common/constants.dart'; +import 'package:sanmill/shared/common/constants.dart'; class Settings { static final settingsFileName = Constants.settingsFilename; diff --git a/src/ui/flutter_app/lib/widgets/dialog.dart b/src/ui/flutter_app/lib/shared/dialog.dart similarity index 98% rename from src/ui/flutter_app/lib/widgets/dialog.dart rename to src/ui/flutter_app/lib/shared/dialog.dart index b20ef006..bdabcd83 100644 --- a/src/ui/flutter_app/lib/widgets/dialog.dart +++ b/src/ui/flutter_app/lib/shared/dialog.dart @@ -23,9 +23,9 @@ import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; import 'package:sanmill/generated/l10n.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; import 'package:url_launcher/url_launcher.dart'; int _counter = 0; diff --git a/src/ui/flutter_app/lib/painting/board_painter.dart b/src/ui/flutter_app/lib/shared/painters/board_painter.dart similarity index 97% rename from src/ui/flutter_app/lib/painting/board_painter.dart rename to src/ui/flutter_app/lib/shared/painters/board_painter.dart index 3b72c7c0..e72f1b15 100644 --- a/src/ui/flutter_app/lib/painting/board_painter.dart +++ b/src/ui/flutter_app/lib/shared/painters/board_painter.dart @@ -17,11 +17,11 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/style/app_theme.dart'; -import 'package:sanmill/widgets/game_page.dart'; +import 'package:sanmill/screens/game_page.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'painter_base.dart'; @@ -112,7 +112,7 @@ class BoardPainter extends PiecesBasePainter { notationH = horizontalNotations[i]; final TextSpan notationSpanV = TextSpan( - style: const TextStyle( + style: TextStyle( fontSize: 20, color: AppTheme.boardLineColor, ), // TODO @@ -120,7 +120,7 @@ class BoardPainter extends PiecesBasePainter { ); final TextSpan notationSpanH = TextSpan( - style: const TextStyle( + style: TextStyle( fontSize: 20, color: AppTheme.boardLineColor, ), // TODO diff --git a/src/ui/flutter_app/lib/painting/painter_base.dart b/src/ui/flutter_app/lib/shared/painters/painter_base.dart similarity index 95% rename from src/ui/flutter_app/lib/painting/painter_base.dart rename to src/ui/flutter_app/lib/shared/painters/painter_base.dart index fe4898e3..c661c4db 100644 --- a/src/ui/flutter_app/lib/painting/painter_base.dart +++ b/src/ui/flutter_app/lib/shared/painters/painter_base.dart @@ -17,7 +17,7 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; abstract class PiecesBasePainter extends CustomPainter { final double width; diff --git a/src/ui/flutter_app/lib/painting/pieces_painter.dart b/src/ui/flutter_app/lib/shared/painters/pieces_painter.dart similarity index 98% rename from src/ui/flutter_app/lib/painting/pieces_painter.dart rename to src/ui/flutter_app/lib/shared/painters/pieces_painter.dart index c7b40149..63542751 100644 --- a/src/ui/flutter_app/lib/painting/pieces_painter.dart +++ b/src/ui/flutter_app/lib/shared/painters/pieces_painter.dart @@ -17,10 +17,10 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; import 'painter_base.dart'; diff --git a/src/ui/flutter_app/lib/widgets/picker.dart b/src/ui/flutter_app/lib/shared/picker.dart similarity index 95% rename from src/ui/flutter_app/lib/widgets/picker.dart rename to src/ui/flutter_app/lib/shared/picker.dart index b528035c..3a9ac9a6 100644 --- a/src/ui/flutter_app/lib/widgets/picker.dart +++ b/src/ui/flutter_app/lib/shared/picker.dart @@ -18,9 +18,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_picker/flutter_picker.dart'; -import 'package:sanmill/common/config.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/style/app_theme.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/theme/app_theme.dart'; Future showPickerNumber( BuildContext context, diff --git a/src/ui/flutter_app/lib/widgets/snack_bar.dart b/src/ui/flutter_app/lib/shared/snack_bar.dart similarity index 95% rename from src/ui/flutter_app/lib/widgets/snack_bar.dart rename to src/ui/flutter_app/lib/shared/snack_bar.dart index c818be5f..3b18874f 100644 --- a/src/ui/flutter_app/lib/widgets/snack_bar.dart +++ b/src/ui/flutter_app/lib/shared/snack_bar.dart @@ -17,7 +17,7 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; +import 'package:sanmill/shared/common/config.dart'; void showSnackBar( BuildContext context, diff --git a/src/ui/flutter_app/lib/shared/theme/app_theme.dart b/src/ui/flutter_app/lib/shared/theme/app_theme.dart new file mode 100644 index 00000000..921c3581 --- /dev/null +++ b/src/ui/flutter_app/lib/shared/theme/app_theme.dart @@ -0,0 +1,142 @@ +import 'package:flutter/material.dart'; +import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/theme/colors.dart'; + +class AppTheme { + AppTheme._(); + + // Theme data + static final lightThemeData = ThemeData( + primarySwatch: AppTheme.appPrimaryColor, + brightness: Brightness.light, + ); + + static final darkThemeData = ThemeData( + primarySwatch: AppTheme.appPrimaryColor, + brightness: Brightness.dark, + ); + + // Color + static const appPrimaryColor = Colors.green; // Appbar & Dialog button + static const dialogTitleColor = appPrimaryColor; + + /// Game page + static Color boardBackgroundColor = UIColors.burlyWood; + static Color mainToolbarBackgroundColor = UIColors.burlyWood; + static Color navigationToolbarBackgroundColor = UIColors.burlyWood; + static Color boardLineColor = const Color(0x996D000D); + static Color whitePieceColor = const Color.fromARGB(0xFF, 0xFF, 0xFF, 0xFF); + static Color whitePieceBorderColor = + const Color.fromARGB(0xFF, 0x66, 0x00, 0x00); + static Color blackPieceColor = const Color.fromARGB(0xFF, 0x00, 0x00, 0x00); + static Color blackPieceBorderColor = + const Color.fromARGB(0xFF, 0x22, 0x22, 0x22); + static Color pieceHighlightColor = Colors.red; + static Color messageColor = Colors.white; + static Color banColor = + const Color.fromARGB(0xFF, 0xFF, 0x00, 0x00); // unused + static Color banBorderColor = + const Color.fromARGB(0x80, 0xFF, 0x00, 0x00); // unused + static Color mainToolbarIconColor = listTileSubtitleColor; + static Color navigationToolbarIconColor = listTileSubtitleColor; + static Color toolbarTextColor = mainToolbarIconColor; + static Color moveHistoryTextColor = Colors.yellow; + static Color moveHistoryDialogBackgroundColor = Colors.transparent; + static Color infoDialogBackgroundColor = moveHistoryDialogBackgroundColor; + static Color infoTextColor = moveHistoryTextColor; + static Color simpleDialogOptionTextColor = Colors.yellow; + + /// Settings page + static Color darkBackgroundColor = UIColors.crusoe; + static Color lightBackgroundColor = UIColors.papayaWhip; + static Color listTileSubtitleColor = const Color(0x99461220); + static Color listItemDividerColor = const Color(0x336D000D); + static Color switchListTileActiveColor = dialogTitleColor; + static Color switchListTileTitleColor = UIColors.crusoe; + static Color cardColor = UIColors.floralWhite; + static Color settingsHeaderTextColor = UIColors.crusoe; + + /// Help page + static Color helpBackgroundColor = boardBackgroundColor; + static Color helpTextColor = boardBackgroundColor; + + /// About + static Color aboutPageBackgroundColor = lightBackgroundColor; + + /// Drawer + static Color drawerColor = Colors.white; + static Color drawerBackgroundColor = + UIColors.notWhite.withOpacity(0.5); // TODO + static Color drawerHighlightItemColor = + UIColors.freeSpeechGreen.withOpacity(0.2); + static Color drawerDividerColor = UIColors.grey.withOpacity(0.6); + static Color drawerBoxerShadowColor = UIColors.grey.withOpacity(0.6); + static Color drawerTextColor = UIColors.nearlyBlack; + static Color drawerHighlightTextColor = UIColors.nearlyBlack; + static Color exitTextColor = UIColors.nearlyBlack; + static Color drawerIconColor = drawerTextColor; + static Color drawerHighlightIconColor = drawerHighlightTextColor; + static Color drawerAnimationIconColor = Colors.white; + static Color exitIconColor = Colors.red; + static Color drawerSplashColor = + Colors.grey.withOpacity(0.1); // TODO: no use? + static Color drawerHighlightColor = Colors.transparent; // TODO: no use? + static Color navigationHomeScreenBackgroundColor = + UIColors.nearlyWhite; // TODO: no use? + + // Theme + + static const sliderThemeData = SliderThemeData( + trackHeight: 20, + activeTrackColor: Colors.green, + inactiveTrackColor: Colors.grey, + disabledActiveTrackColor: Colors.yellow, + disabledInactiveTrackColor: Colors.cyan, + activeTickMarkColor: Colors.black, + inactiveTickMarkColor: Colors.green, + //overlayColor: Colors.yellow, + overlappingShapeStrokeColor: Colors.black, + //overlayShape: RoundSliderOverlayShape(), + valueIndicatorColor: Colors.green, + showValueIndicator: ShowValueIndicator.always, + minThumbSeparation: 100, + thumbShape: RoundSliderThumbShape( + enabledThumbRadius: 2.0, + disabledThumbRadius: 1.0, + ), + rangeTrackShape: RoundedRectRangeSliderTrackShape(), + tickMarkShape: RoundSliderTickMarkShape(tickMarkRadius: 2.0), + valueIndicatorTextStyle: TextStyle(fontSize: 24), + ); + + static TextStyle simpleDialogOptionTextStyle = TextStyle( + fontSize: Config.fontSize + 4.0, + color: AppTheme.simpleDialogOptionTextColor, + ); + + static TextStyle moveHistoryTextStyle = TextStyle( + fontSize: Config.fontSize + 2.0, + height: 1.5, + color: moveHistoryTextColor, + ); + + static double boardTop = isLargeScreen() ? 75.0 : 36.0; + static double boardMargin = 10.0; + static double boardScreenPaddingH = 10.0; + static double boardBorderRadius = 5.0; + static double boardPadding = 5.0; + + static TextStyle settingsHeaderStyle = + TextStyle(color: settingsHeaderTextColor, fontSize: Config.fontSize + 4); + + static TextStyle settingsTextStyle = TextStyle(fontSize: Config.fontSize); + + static const cardMargin = EdgeInsets.symmetric(vertical: 4.0); + + static const double drawerWidth = 250.0; + + static const double sizedBoxHeight = 16.0; + + static double copyrightFontSize = 12; +} diff --git a/src/ui/flutter_app/lib/shared/theme/colors.dart b/src/ui/flutter_app/lib/shared/theme/colors.dart new file mode 100644 index 00000000..0aa66843 --- /dev/null +++ b/src/ui/flutter_app/lib/shared/theme/colors.dart @@ -0,0 +1,46 @@ +/* + 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 . +*/ + +import 'package:flutter/material.dart'; + +class UIColors { + // https://www.htmlcsscolor.com + const UIColors._(); + + static const Color white = Color(0xFFFFFFFF); + static const Color notWhite = Color(0xFFEDF0F2); + static const Color nearlyWhite = Color(0xFFFEFEFE); + static const Color floralWhite = Color(0xFFFFFAF0); + + static const Color nearlyBlack = Color(0xFF213333); + + static const Color grey = Color(0xFF3A5160); + static const Color darkGrey = Color(0xFF313A44); + + static const Color burlyWood = Color(0xFFDEB887); + static const Color cottonCandy = Color.fromARGB(0xFF, 255, 189, 219); + static const Color turkishRose = Color.fromARGB(0xFF, 163, 109, 173); + static const Color crusoe = Color(0xFF165B31); + static const Color forestGreen = Color(0xFF228B22); + static const Color freeSpeechGreen = Color(0xFF09F911); + static const Color oasis = Color.fromARGB(0xFF, 253, 239, 194); + static const Color papayaWhip = Color(0xFFFFEFD5); + static const Color stormGrey = Color.fromARGB(0xFF, 119, 121, 131); + static const Color turmeric = Color.fromARGB(0xFF, 186, 202, 68); + static const Color LavenderBlush = Color.fromARGB(0xFF, 255, 240, 246); +} diff --git a/src/ui/flutter_app/lib/style/app_theme.dart b/src/ui/flutter_app/lib/style/app_theme.dart deleted file mode 100644 index 5ffbd998..00000000 --- a/src/ui/flutter_app/lib/style/app_theme.dart +++ /dev/null @@ -1,139 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:sanmill/common/config.dart'; -import 'package:sanmill/common/constants.dart'; -import 'package:sanmill/style/colors.dart'; - -class AppTheme { - AppTheme._(); - - // Theme data - static final lightThemeData = ThemeData( - primarySwatch: AppTheme.appPrimaryColor, - brightness: Brightness.light, - ); - - static final darkThemeData = ThemeData( - primarySwatch: AppTheme.appPrimaryColor, - brightness: Brightness.dark, - ); - - // Color - static const appPrimaryColor = Colors.green; // Appbar & Dialog button - static const dialogTitleColor = appPrimaryColor; - - /// Game page - static const boardBackgroundColor = UIColors.burlyWood; - static const mainToolbarBackgroundColor = UIColors.burlyWood; - static const navigationToolbarBackgroundColor = UIColors.burlyWood; - static const boardLineColor = Color(0x996D000D); - static const whitePieceColor = Color.fromARGB(0xFF, 0xFF, 0xFF, 0xFF); - static const whitePieceBorderColor = Color.fromARGB(0xFF, 0x66, 0x00, 0x00); - static const blackPieceColor = Color.fromARGB(0xFF, 0x00, 0x00, 0x00); - static const blackPieceBorderColor = Color.fromARGB(0xFF, 0x22, 0x22, 0x22); - static const pieceHighlightColor = Colors.red; - static const messageColor = Colors.white; - static const banColor = Color.fromARGB(0xFF, 0xFF, 0x00, 0x00); // unused - static const banBorderColor = - Color.fromARGB(0x80, 0xFF, 0x00, 0x00); // unused - static const mainToolbarIconColor = listTileSubtitleColor; - static const navigationToolbarIconColor = listTileSubtitleColor; - static const toolbarTextColor = mainToolbarIconColor; - static const moveHistoryTextColor = Colors.yellow; - static const moveHistoryDialogBackgroundColor = Colors.transparent; - static const infoDialogBackgroundColor = moveHistoryDialogBackgroundColor; - static const infoTextColor = moveHistoryTextColor; - static const simpleDialogOptionTextColor = Colors.yellow; - - /// Settings page - static const darkBackgroundColor = UIColors.crusoe; - static const lightBackgroundColor = UIColors.papayaWhip; - static const listTileSubtitleColor = Color(0x99461220); - static const listItemDividerColor = Color(0x336D000D); - static const switchListTileActiveColor = dialogTitleColor; - static const switchListTileTitleColor = UIColors.crusoe; - static const cardColor = UIColors.floralWhite; - static const settingsHeaderTextColor = UIColors.crusoe; - - /// Help page - static const helpBackgroundColor = boardBackgroundColor; - static const helpTextColor = boardBackgroundColor; - - /// About - static const aboutPageBackgroundColor = lightBackgroundColor; - - /// Drawer - static const drawerColor = Colors.white; - static final drawerBackgroundColor = - UIColors.notWhite.withOpacity(0.5); // TODO - static final drawerHighlightItemColor = - UIColors.freeSpeechGreen.withOpacity(0.2); - static final drawerDividerColor = UIColors.grey.withOpacity(0.6); - static final drawerBoxerShadowColor = UIColors.grey.withOpacity(0.6); - static const drawerTextColor = UIColors.nearlyBlack; - static const drawerHighlightTextColor = UIColors.nearlyBlack; - static const exitTextColor = UIColors.nearlyBlack; - static const drawerIconColor = drawerTextColor; - static const drawerHighlightIconColor = drawerHighlightTextColor; - static const drawerAnimationIconColor = Colors.white; - static const exitIconColor = Colors.red; - static final drawerSplashColor = - Colors.grey.withOpacity(0.1); // TODO: no use? - static const drawerHighlightColor = Colors.transparent; // TODO: no use? - static const navigationHomeScreenBackgroundColor = - UIColors.nearlyWhite; // TODO: no use? - - // Theme - - static const sliderThemeData = SliderThemeData( - trackHeight: 20, - activeTrackColor: Colors.green, - inactiveTrackColor: Colors.grey, - disabledActiveTrackColor: Colors.yellow, - disabledInactiveTrackColor: Colors.cyan, - activeTickMarkColor: Colors.black, - inactiveTickMarkColor: Colors.green, - //overlayColor: Colors.yellow, - overlappingShapeStrokeColor: Colors.black, - //overlayShape: RoundSliderOverlayShape(), - valueIndicatorColor: Colors.green, - showValueIndicator: ShowValueIndicator.always, - minThumbSeparation: 100, - thumbShape: RoundSliderThumbShape( - enabledThumbRadius: 2.0, - disabledThumbRadius: 1.0, - ), - rangeTrackShape: RoundedRectRangeSliderTrackShape(), - tickMarkShape: RoundSliderTickMarkShape(tickMarkRadius: 2.0), - valueIndicatorTextStyle: TextStyle(fontSize: 24), - ); - - static TextStyle simpleDialogOptionTextStyle = TextStyle( - fontSize: Config.fontSize + 4.0, - color: AppTheme.simpleDialogOptionTextColor, - ); - - static TextStyle moveHistoryTextStyle = TextStyle( - fontSize: Config.fontSize + 2.0, - height: 1.5, - color: moveHistoryTextColor, - ); - - static double boardTop = isLargeScreen() ? 75.0 : 36.0; - static double boardMargin = 10.0; - static double boardScreenPaddingH = 10.0; - static double boardBorderRadius = 5.0; - static double boardPadding = 5.0; - - static TextStyle settingsHeaderStyle = - TextStyle(color: settingsHeaderTextColor, fontSize: Config.fontSize + 4); - - static TextStyle settingsTextStyle = TextStyle(fontSize: Config.fontSize); - - static const cardMargin = EdgeInsets.symmetric(vertical: 4.0); - - static const double drawerWidth = 250.0; - - static const double sizedBoxHeight = 16.0; - - static double copyrightFontSize = 12; -} diff --git a/src/ui/flutter_app/lib/style/colors.dart b/src/ui/flutter_app/lib/style/colors.dart deleted file mode 100644 index 0494f9ed..00000000 --- a/src/ui/flutter_app/lib/style/colors.dart +++ /dev/null @@ -1,45 +0,0 @@ -/* - 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 . -*/ - -import 'package:flutter/material.dart'; - -class UIColors { - // https://www.htmlcsscolor.com - - static const white = Color(0xFFFFFFFF); - static const notWhite = Color(0xFFEDF0F2); - static const nearlyWhite = Color(0xFFFEFEFE); - static const floralWhite = Color(0xFFFFFAF0); - - static const nearlyBlack = Color(0xFF213333); - - static const grey = Color(0xFF3A5160); - static const darkGrey = Color(0xFF313A44); - - static const burlyWood = Color(0xFFDEB887); - static const cottonCandy = Color.fromARGB(0xFF, 255, 189, 219); - static const turkishRose = Color.fromARGB(0xFF, 163, 109, 173); - static const crusoe = Color(0xFF165B31); - static const forestGreen = Color(0xFF228B22); - static const freeSpeechGreen = Color(0xFF09F911); - static const oasis = Color.fromARGB(0xFF, 253, 239, 194); - static const papayaWhip = Color(0xFFFFEFD5); - static const stormGrey = Color.fromARGB(0xFF, 119, 121, 131); - static const turmeric = Color.fromARGB(0xFF, 186, 202, 68); - static const LavenderBlush = Color.fromARGB(0xFF, 255, 240, 246); -} diff --git a/src/ui/flutter_app/test/widget_test.dart b/src/ui/flutter_app/test/widget_test.dart index bca4a244..e459b6ba 100644 --- a/src/ui/flutter_app/test/widget_test.dart +++ b/src/ui/flutter_app/test/widget_test.dart @@ -20,7 +20,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/widgets/navigation_home_screen.dart'; +import 'package:sanmill/screens/navigation_home_screen.dart'; void main() { Widget makeTestableWidget({required Widget child, required Locale locale}) { From 418d1cfb4440e496eb85b6661353282b2b7937dc Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:09:29 +0200 Subject: [PATCH 08/13] cleanup boilerplate code --- src/ui/flutter_app/analysis_options.yaml | 1 - src/ui/flutter_app/lib/mill/game.dart | 13 +- src/ui/flutter_app/lib/mill/position.dart | 61 +++-- .../flutter_app/lib/screens/about_page.dart | 6 +- src/ui/flutter_app/lib/screens/board.dart | 10 +- src/ui/flutter_app/lib/screens/game_page.dart | 228 ++++++++---------- .../lib/screens/game_settings_page.dart | 112 ++------- .../flutter_app/lib/screens/home_drawer.dart | 2 +- .../lib/screens/navigation_home_screen.dart | 38 +-- .../lib/screens/oss_license_page.dart | 3 +- .../personalization_settings_page.dart | 54 +---- .../lib/screens/rule_settings_page.dart | 156 +++++------- .../lib/screens/settings/settings_card.dart | 9 +- src/ui/flutter_app/lib/shared/dialog.dart | 4 +- .../lib/shared/painters/board_painter.dart | 8 +- 15 files changed, 266 insertions(+), 439 deletions(-) diff --git a/src/ui/flutter_app/analysis_options.yaml b/src/ui/flutter_app/analysis_options.yaml index d1a1d79b..5ce91844 100644 --- a/src/ui/flutter_app/analysis_options.yaml +++ b/src/ui/flutter_app/analysis_options.yaml @@ -1,6 +1,5 @@ include: package:lint/analysis_options.yaml - linter: rules: avoid_positional_boolean_parameters: false diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index b9b0e3b0..eb28357d 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -26,14 +26,11 @@ import 'types.dart'; enum PlayerType { human, AI } Map isAi = {PieceColor.white: false, PieceColor.black: true}; -class Game { - static Game? _instance; - final String tag = "[game]"; +// TODO: add constructor +Game gameInstance = Game(); - // TODO: use constructor - static Game get instance { - return _instance ??= Game(); - } +class Game { + final String tag = "[game]"; void init() { _position = Position(); @@ -131,7 +128,7 @@ class Game { moveHistory.add(move); - sideToMove = position.sideToMove() ?? PieceColor.nobody; + sideToMove = position.sideToMove; printStat(); diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index 7a2e5fb2..8cd06f69 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -133,11 +133,9 @@ class Position { bool empty(int sq) => pieceOn(sq) == Piece.noPiece; - String sideToMove() => _sideToMove; + String get sideToMove => _sideToMove; - String movedPiece(int move) { - return pieceOn(fromSq(move)); - } + String movedPiece(int move) => pieceOn(fromSq(move)); bool movePiece(int from, int to) { if (selectPiece(from) == 0) { @@ -477,7 +475,7 @@ class Position { } if (phase == Phase.placing) { - piece = sideToMove(); + piece = sideToMove; if (pieceInHandCount[us] != null) { pieceInHandCount[us] = pieceInHandCount[us]! - 1; } @@ -526,7 +524,7 @@ class Position { } else { changeSideToMove(); } - Game.instance.focusIndex = squareToIndex[s] ?? invalidIndex; + gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex; Audios.playTone(Audios.placeSoundId); } else { pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1; @@ -562,7 +560,7 @@ class Position { action = Act.remove; } - Game.instance.focusIndex = squareToIndex[s] ?? invalidIndex; + gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex; Audios.playTone(Audios.millSoundId); } } else if (phase == Phase.moving) { @@ -571,8 +569,7 @@ class Position { } // if illegal - if (pieceOnBoardCount[sideToMove()]! > rule.flyPieceCount || - !rule.mayFly) { + if (pieceOnBoardCount[sideToMove]! > rule.flyPieceCount || !rule.mayFly) { int md; for (md = 0; md < moveDirectionNumber; md++) { @@ -611,14 +608,14 @@ class Position { if (checkIfGameIsOver()) { return true; } else { - Game.instance.focusIndex = squareToIndex[s] ?? invalidIndex; + gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex; Audios.playTone(Audios.placeSoundId); } } else { pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1; updateKeyMisc(); action = Act.remove; - Game.instance.focusIndex = squareToIndex[s] ?? invalidIndex; + gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex; Audios.playTone(Audios.millSoundId); } } else { @@ -636,11 +633,11 @@ class Position { if (pieceToRemoveCount <= 0) return -1; // if piece is not their - if (!(PieceColor.opponent(sideToMove()) == board[s])) return -2; + if (!(PieceColor.opponent(sideToMove) == board[s])) return -2; if (!rule.mayRemoveFromMillsAlways && potentialMillsCount(s, PieceColor.nobody) > 0 && - !isAllInMills(PieceColor.opponent(sideToMove()))) { + !isAllInMills(PieceColor.opponent(sideToMove))) { return -3; } @@ -666,7 +663,7 @@ class Position { if (pieceOnBoardCount[them]! + pieceInHandCount[them]! < rule.piecesAtLeastCount) { - setGameOver(sideToMove(), GameOverReason.loseReasonlessThanThree); + setGameOver(sideToMove, GameOverReason.loseReasonlessThanThree); return 0; } @@ -715,13 +712,13 @@ class Position { return -3; } - if (!(board[sq] == sideToMove())) { + if (!(board[sq] == sideToMove)) { return -4; } currentSquare = sq; action = Act.place; - Game.instance.blurIndex = squareToIndex[sq]!; + gameInstance.blurIndex = squareToIndex[sq]!; return 0; } @@ -808,7 +805,7 @@ class Position { if (phase == Phase.moving && action == Act.select && isAllSurrounded()) { if (rule.isLoseButNotChangeSideWhenNoWay) { setGameOver( - PieceColor.opponent(sideToMove()), + PieceColor.opponent(sideToMove), GameOverReason.loseReasonNoWay, ); return true; @@ -864,9 +861,7 @@ class Position { int updateKey(int s) { final String pieceType = colorOn(s); - st.key ^= Zobrist.psq[pieceColorIndex[pieceType]!][s]; - - return st.key; + return st.key ^= Zobrist.psq[pieceColorIndex[pieceType]!][s]; } int revertKey(int s) { @@ -890,11 +885,12 @@ class Position { int potentialMillsCount(int to, String c, {int from = 0}) { int n = 0; String locbak = Piece.noPiece; + String _c = c; assert(0 <= from && from < sqNumber); - if (c == PieceColor.nobody) { - c = colorOn(to); + if (_c == PieceColor.nobody) { + _c = colorOn(to); } if (from != 0 && from >= sqBegin && from < sqEnd) { @@ -903,7 +899,8 @@ class Position { } for (int l = 0; l < lineDirectionNumber; l++) { - if (c == board[millTable[to][l][0]] && c == board[millTable[to][l][1]]) { + if (_c == board[millTable[to][l][0]] && + _c == board[millTable[to][l][1]]) { n++; } } @@ -978,12 +975,12 @@ class Position { } // Can fly - if (pieceOnBoardCount[sideToMove()]! <= rule.flyPieceCount && rule.mayFly) { + if (pieceOnBoardCount[sideToMove]! <= rule.flyPieceCount && rule.mayFly) { return false; } for (int s = sqBegin; s < sqEnd; s++) { - if (!(sideToMove() == colorOn(s))) { + if (!(sideToMove == colorOn(s))) { continue; } @@ -1112,21 +1109,21 @@ class Position { } // Backup context - final engineTypeBackup = Game.instance.engineType; + final engineTypeBackup = gameInstance.engineType; - Game.instance.engineType = EngineType.humanVsHuman; - Game.instance.setWhoIsAi(EngineType.humanVsHuman); + gameInstance.engineType = EngineType.humanVsHuman; + gameInstance.setWhoIsAi(EngineType.humanVsHuman); final historyBack = history; - Game.instance.newGame(); + gameInstance.newGame(); if (moveIndex == -1) { errString = ""; } for (var i = 0; i <= moveIndex; i++) { - if (Game.instance.doMove(history[i].move!) == false) { + if (gameInstance.doMove(history[i].move!) == false) { errString = history[i].move!; break; } @@ -1136,8 +1133,8 @@ class Position { } // Restore context - Game.instance.engineType = engineTypeBackup; - Game.instance.setWhoIsAi(engineTypeBackup); + gameInstance.engineType = engineTypeBackup; + gameInstance.setWhoIsAi(engineTypeBackup); recorder!.history = historyBack; recorder!.cur = moveIndex; diff --git a/src/ui/flutter_app/lib/screens/about_page.dart b/src/ui/flutter_app/lib/screens/about_page.dart index 42ed09c3..905f6c65 100644 --- a/src/ui/flutter_app/lib/screens/about_page.dart +++ b/src/ui/flutter_app/lib/screens/about_page.dart @@ -294,14 +294,14 @@ class _VersionDialog extends StatelessWidget { ), TextButton( child: Text(S.of(context).ok), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ); } void _showFlutterVersionInfo(BuildContext context) { - Navigator.of(context).pop(); + Navigator.pop(context); showDialog( context: context, @@ -332,7 +332,7 @@ class _VersionDialog extends StatelessWidget { actions: [ TextButton( child: Text(S.of(context).ok), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ); diff --git a/src/ui/flutter_app/lib/screens/board.dart b/src/ui/flutter_app/lib/screens/board.dart index 6be66aa1..b01ab97c 100644 --- a/src/ui/flutter_app/lib/screens/board.dart +++ b/src/ui/flutter_app/lib/screens/board.dart @@ -26,7 +26,7 @@ import 'package:sanmill/shared/painters/board_painter.dart'; import 'package:sanmill/shared/painters/pieces_painter.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; -typedef BoardTapCallback = void Function(int index); +typedef BoardTapCallback = dynamic Function(int index); class Board extends StatelessWidget { final double width; @@ -71,9 +71,9 @@ class Board extends StatelessWidget { painter: BoardPainter(width: width), foregroundPainter: PiecesPainter( width: width, - position: Game.instance.position, - focusIndex: Game.instance.focusIndex, - blurIndex: Game.instance.blurIndex, + position: gameInstance.position, + focusIndex: gameInstance.focusIndex, + blurIndex: gameInstance.blurIndex, animationValue: animationValue, ), child: grid, @@ -267,7 +267,7 @@ class Board extends StatelessWidget { if (checkPoints[i] == 0) { pieceDesc.add(S.of(context).noPoint); } else { - switch (Game.instance.position.pieceOnGrid(i)) { + switch (gameInstance.position.pieceOnGrid(i)) { case PieceColor.white: pieceDesc.add(S.of(context).whitePiece); diff --git a/src/ui/flutter_app/lib/screens/game_page.dart b/src/ui/flutter_app/lib/screens/game_page.dart index 6ed876b3..eb6ced0c 100644 --- a/src/ui/flutter_app/lib/screens/game_page.dart +++ b/src/ui/flutter_app/lib/screens/game_page.dart @@ -84,10 +84,10 @@ class _GamePageState extends State void initState() { debugPrint("$tag Engine type: ${widget.engineType}"); - Game.instance.setWhoIsAi(widget.engineType); + gameInstance.setWhoIsAi(widget.engineType); super.initState(); - Game.instance.init(); + gameInstance.init(); _engine.startup(); timer = Timer.periodic(const Duration(microseconds: 100), (Timer t) { @@ -159,7 +159,7 @@ class _GamePageState extends State return; } - final winner = Game.instance.position.winner; + final winner = gameInstance.position.winner; final Map colorWinStrings = { PieceColor.white: S.of(context).whiteWin, @@ -168,11 +168,11 @@ class _GamePageState extends State }; if (winner == PieceColor.nobody) { - if (Game.instance.position.phase == Phase.placing) { + if (gameInstance.position.phase == Phase.placing) { if (mounted) { showTip(S.of(context).tipPlace); } - } else if (Game.instance.position.phase == Phase.moving) { + } else if (gameInstance.position.phase == Phase.moving) { if (mounted) { showTip(S.of(context).tipMove); } @@ -199,13 +199,13 @@ class _GamePageState extends State Duration(milliseconds: (Config.animationDuration * 1000).toInt()); _animationController.reset(); - if (Game.instance.engineType == EngineType.aiVsAi || - Game.instance.engineType == EngineType.testViaLAN) { + if (gameInstance.engineType == EngineType.aiVsAi || + gameInstance.engineType == EngineType.testViaLAN) { debugPrint("$tag Engine type is no human, ignore tapping."); return false; } - final position = Game.instance.position; + final position = gameInstance.position; final int? sq = indexToSquare[index]; @@ -221,10 +221,10 @@ class _GamePageState extends State if (position.phase == Phase.placing && position.pieceOnBoardCount[PieceColor.white] == 0 && position.pieceOnBoardCount[PieceColor.black] == 0) { - Game.instance.newGame(); + gameInstance.newGame(); - if (Game.instance.isAiToMove()!) { - if (Game.instance.aiIsSearching()) { + if (gameInstance.isAiToMove()!) { + if (gameInstance.aiIsSearching()) { debugPrint("$tag AI is thinking, skip tapping."); return false; } else { @@ -235,13 +235,13 @@ class _GamePageState extends State } } - if (Game.instance.isAiToMove()! || Game.instance.aiIsSearching()) { + if (gameInstance.isAiToMove()! || gameInstance.aiIsSearching()) { debugPrint("[tap] AI's turn, skip tapping."); return false; } if (position.phase == Phase.ready) { - Game.instance.start(); + gameInstance.start(); } // Human to go @@ -261,7 +261,7 @@ class _GamePageState extends State } } else { //Audios.playTone(Audios.placeSoundId); - if (Game.instance.engineType == EngineType.humanVsAi && mounted) { + if (gameInstance.engineType == EngineType.humanVsAi && mounted) { if (rule.mayOnlyRemoveUnplacedPieceInPlacingPhase) { showTip(S.of(context).continueToMakeMove); } else { @@ -273,7 +273,7 @@ class _GamePageState extends State S.of(context).tipPlaced, ); // TODO: HumanVsHuman - Change tip } else { - final side = Game.instance.sideToMove == PieceColor.white + final side = gameInstance.sideToMove == PieceColor.white ? S.of(context).black : S.of(context).white; showTip(side + S.of(context).tipToMove); @@ -313,16 +313,16 @@ class _GamePageState extends State switch (selectRet) { case 0: Audios.playTone(Audios.selectSoundId); - Game.instance.select(index); + gameInstance.select(index); ret = true; debugPrint("[tap] selectPiece: [$sq]"); - final us = Game.instance.sideToMove; + final us = gameInstance.sideToMove; if (position.phase == Phase.moving && rule.mayFly && - (Game.instance.position.pieceOnBoardCount[us] == + (gameInstance.position.pieceOnBoardCount[us] == Config.flyPieceCount || - Game.instance.position.pieceOnBoardCount[us] == 3)) { + gameInstance.position.pieceOnBoardCount[us] == 3)) { debugPrint("[tap] May fly."); if (mounted) { showTip(S.of(context).tipCanMoveToAnyPoint); @@ -395,7 +395,7 @@ class _GamePageState extends State //Audios.playTone(Audios.removeSoundId); ret = true; debugPrint("[tap] removePiece: [$sq]"); - if (Game.instance.position.pieceToRemoveCount >= 1) { + if (gameInstance.position.pieceToRemoveCount >= 1) { if (mounted) { showTip(S.of(context).tipContinueMill); if (Config.screenReaderSupport) { @@ -403,13 +403,13 @@ class _GamePageState extends State } } } else { - if (Game.instance.engineType == EngineType.humanVsAi) { + if (gameInstance.engineType == EngineType.humanVsAi) { if (mounted) { showTip(S.of(context).tipRemoved); } } else { if (mounted) { - final them = Game.instance.sideToMove == PieceColor.white + final them = gameInstance.sideToMove == PieceColor.white ? S.of(context).black : S.of(context).white; if (mounted) { @@ -466,8 +466,8 @@ class _GamePageState extends State } if (ret) { - Game.instance.sideToMove = position.sideToMove() ?? PieceColor.nobody; - Game.instance.moveHistory.add(position.record!); + gameInstance.sideToMove = position.sideToMove; + gameInstance.moveHistory.add(position.record!); // TODO: Need Others? // Increment ply counters. In particular, @@ -514,7 +514,7 @@ class _GamePageState extends State } } - Game.instance.sideToMove = position.sideToMove() ?? PieceColor.nobody; + gameInstance.sideToMove = position.sideToMove; setState(() {}); }); // Chain.capture @@ -523,6 +523,8 @@ class _GamePageState extends State } Future engineToGo(bool isMoveNow) async { + bool _isMoveNow = isMoveNow; + if (!mounted) { debugPrint("[engineToGo] !mounted, skip engineToGo."); return; @@ -531,14 +533,14 @@ class _GamePageState extends State // TODO debugPrint("[engineToGo] engine type is ${widget.engineType}"); - if (isMoveNow == true) { - if (!Game.instance.isAiToMove()!) { + if (_isMoveNow) { + if (!gameInstance.isAiToMove()!) { debugPrint("[engineToGo] Human to Move. Cannot get search result now."); ScaffoldMessenger.of(context).clearSnackBars(); showSnackBar(context, S.of(context).notAIsTurn); return; } - if (!Game.instance.position.recorder!.isClean()) { + if (!gameInstance.position.recorder!.isClean()) { debugPrint( "[engineToGo] History is not clean. Cannot get search result now.", ); @@ -549,22 +551,22 @@ class _GamePageState extends State } while ((Config.isAutoRestart == true || - Game.instance.position.winner == PieceColor.nobody) && - Game.instance.isAiToMove()! && + gameInstance.position.winner == PieceColor.nobody) && + gameInstance.isAiToMove()! && mounted) { if (widget.engineType == EngineType.aiVsAi) { final String score = - "${Game.instance.position.score[PieceColor.white]} : ${Game.instance.position.score[PieceColor.black]} : ${Game.instance.position.score[PieceColor.draw]}"; + "${gameInstance.position.score[PieceColor.white]} : ${gameInstance.position.score[PieceColor.black]} : ${gameInstance.position.score[PieceColor.draw]}"; showTip(score); } else { if (mounted) { showTip(S.of(context).thinking); - final Move? m = Game.instance.position.recorder!.lastMove; + final Move? m = gameInstance.position.recorder!.lastMove; if (Config.screenReaderSupport && - Game.instance.position.action != Act.remove && + gameInstance.position.action != Act.remove && m != null && m.notation != null) { showSnackBar(context, "${S.of(context).human}: ${m.notation!}"); @@ -574,13 +576,13 @@ class _GamePageState extends State late EngineResponse response; - if (!isMoveNow) { + if (!_isMoveNow) { debugPrint("[engineToGo] Searching..."); - response = await _engine.search(Game.instance.position); + response = await _engine.search(gameInstance.position); } else { debugPrint("[engineToGo] Get search result now..."); response = await _engine.search(null); - isMoveNow = false; + _isMoveNow = false; } debugPrint("[engineToGo] Engine response type: ${response.type}"); @@ -601,7 +603,7 @@ class _GamePageState extends State ); } - Game.instance.doMove(move.move!); + gameInstance.doMove(move.move!); showTips(); if (Config.screenReaderSupport && move.notation != null) { showSnackBar(context, "${S.of(context).ai}: ${move.notation!}"); @@ -625,22 +627,22 @@ class _GamePageState extends State } if (Config.isAutoRestart == true && - Game.instance.position.winner != PieceColor.nobody) { - Game.instance.newGame(); + gameInstance.position.winner != PieceColor.nobody) { + gameInstance.newGame(); } } } Future onStartNewGameButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); - if (Game.instance.isAiToMove()!) { + if (gameInstance.isAiToMove()!) { // TODO: Move now //debugPrint("$tag New game, AI to move, move now."); //await engineToGo(true); } - Game.instance.newGame(); + gameInstance.newGame(); if (mounted) { showTip(S.of(context).gameStarted); @@ -650,14 +652,14 @@ class _GamePageState extends State } } - if (Game.instance.isAiToMove()!) { + if (gameInstance.isAiToMove()!) { debugPrint("$tag New game, AI to move."); engineToGo(false); } } Future onImportGameButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); ScaffoldMessenger.of(context).clearSnackBars(); final ClipboardData? data = await Clipboard.getData(Clipboard.kTextPlain); @@ -672,8 +674,8 @@ class _GamePageState extends State debugPrint(text); await onTakeBackAllButtonPressed(pop: false); - Game.instance.position.recorder!.clear(); - final importFailedStr = Game.instance.position.recorder!.import(text); + gameInstance.position.recorder!.clear(); + final importFailedStr = gameInstance.position.recorder!.import(text); if (importFailedStr != "") { showTip("${S.of(context).cannotImport} $importFailedStr"); @@ -694,9 +696,9 @@ class _GamePageState extends State } Future onExportGameButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); - final moveHistoryText = Game.instance.position.moveHistoryText; + final moveHistoryText = gameInstance.position.moveHistoryText; Clipboard.setData(ClipboardData(text: moveHistoryText)).then((_) { showSnackBar(context, S.of(context).moveHistoryCopied); @@ -705,7 +707,7 @@ class _GamePageState extends State /* onStartRecordingButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); showDialog( context: context, barrierDismissible: true, @@ -737,7 +739,7 @@ class _GamePageState extends State fontSize: Config.fontSize, ), ), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ), @@ -751,7 +753,7 @@ class _GamePageState extends State } onStopRecordingButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); screenRecorderController.stop(); showSnackBar( S.of(context).stopRecording, @@ -760,7 +762,7 @@ class _GamePageState extends State } onShowRecordingButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); showSnackBar( S.of(context).pleaseWait, duration: Duration(seconds: 1 << 31), @@ -786,7 +788,7 @@ class _GamePageState extends State */ Future onAutoReplayButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); await onTakeBackAllButtonPressed(pop: false); await onStepForwardAllButtonPressed(pop: false); @@ -836,10 +838,8 @@ class _GamePageState extends State style: AppTheme.simpleDialogOptionTextStyle, textAlign: TextAlign.center, ), - onPressed: () => Navigator.of(context).pop(), - ) - else - const SizedBox(height: 1), + onPressed: () => Navigator.pop(context), + ), /* SizedBox(height: AppTheme.sizedBoxHeight), Config.experimentsEnabled @@ -912,9 +912,7 @@ class _GamePageState extends State child: SimpleDialog( backgroundColor: Colors.transparent, children: [ - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) SimpleDialogOption( onPressed: onTakeBackButtonPressed, child: Text( @@ -923,13 +921,9 @@ class _GamePageState extends State textAlign: TextAlign.center, ), ), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) const SizedBox(height: AppTheme.sizedBoxHeight), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) SimpleDialogOption( onPressed: onStepForwardButtonPressed, child: Text( @@ -938,13 +932,9 @@ class _GamePageState extends State textAlign: TextAlign.center, ), ), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) const SizedBox(height: AppTheme.sizedBoxHeight), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) SimpleDialogOption( onPressed: onTakeBackAllButtonPressed, child: Text( @@ -953,13 +943,9 @@ class _GamePageState extends State textAlign: TextAlign.center, ), ), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) const SizedBox(height: AppTheme.sizedBoxHeight), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) SimpleDialogOption( onPressed: onStepForwardAllButtonPressed, child: Text( @@ -968,9 +954,7 @@ class _GamePageState extends State textAlign: TextAlign.center, ), ), - if (Config.isHistoryNavigationToolbarShown) - const SizedBox(height: 1) - else + if (!Config.isHistoryNavigationToolbarShown) const SizedBox(height: AppTheme.sizedBoxHeight), SimpleDialogOption( onPressed: onMoveListButtonPressed, @@ -997,10 +981,8 @@ class _GamePageState extends State style: AppTheme.simpleDialogOptionTextStyle, textAlign: TextAlign.center, ), - onPressed: () => Navigator.of(context).pop(), - ) - else - const SizedBox(height: 1), + onPressed: () => Navigator.pop(context), + ), ], ), ), @@ -1012,7 +994,7 @@ class _GamePageState extends State bool pop = true, }) async { if (pop == true) { - Navigator.of(context).pop(); + Navigator.pop(context); } if (mounted) { @@ -1053,7 +1035,7 @@ class _GamePageState extends State if (mounted) { String text = ""; - final pos = Game.instance.position; + final pos = gameInstance.position; /* String us = ""; @@ -1084,32 +1066,32 @@ class _GamePageState extends State } Future onTakeBackButtonPressed({bool pop = true}) async { - onGotoHistoryButtonsPressed(Game.instance.position.takeBack(), pop: pop); + onGotoHistoryButtonsPressed(gameInstance.position.takeBack(), pop: pop); } Future onStepForwardButtonPressed({bool pop = true}) async { - onGotoHistoryButtonsPressed(Game.instance.position.stepForward(), pop: pop); + onGotoHistoryButtonsPressed(gameInstance.position.stepForward(), pop: pop); } Future onTakeBackAllButtonPressed({bool pop = true}) async { - onGotoHistoryButtonsPressed(Game.instance.position.takeBackAll(), pop: pop); + onGotoHistoryButtonsPressed(gameInstance.position.takeBackAll(), pop: pop); } Future onStepForwardAllButtonPressed({bool pop = true}) async { onGotoHistoryButtonsPressed( - Game.instance.position.stepForwardAll(), + gameInstance.position.stepForwardAll(), pop: pop, ); } Future onTakeBackNButtonPressed(int n, {bool pop = true}) async { - onGotoHistoryButtonsPressed(Game.instance.position.takeBackN(n), pop: pop); + onGotoHistoryButtonsPressed(gameInstance.position.takeBackN(n), pop: pop); } void onMoveListButtonPressed() { - final moveHistoryText = Game.instance.position.moveHistoryText; - final end = Game.instance.moveHistory.length - 1; - Navigator.of(context).pop(); + final moveHistoryText = gameInstance.position.moveHistoryText; + final end = gameInstance.moveHistory.length - 1; + Navigator.pop(context); ScaffoldMessenger.of(context).clearSnackBars(); showDialog( @@ -1156,7 +1138,7 @@ class _GamePageState extends State else TextButton( child: const Text(""), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), TextButton( child: Text( @@ -1175,7 +1157,7 @@ class _GamePageState extends State S.of(context).cancel, style: AppTheme.moveHistoryTextStyle, ), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ); @@ -1184,7 +1166,7 @@ class _GamePageState extends State } Future onMoveNowButtonPressed() async { - Navigator.of(context).pop(); + Navigator.pop(context); await engineToGo(true); } @@ -1203,7 +1185,7 @@ class _GamePageState extends State TextButton( child: Text(S.of(context).ok, style: AppTheme.moveHistoryTextStyle), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ); @@ -1212,9 +1194,7 @@ class _GamePageState extends State } Future setPrivacyPolicyAccepted(bool value) async { - setState(() { - Config.isPrivacyPolicyAccepted = value; - }); + setState(() => Config.isPrivacyPolicyAccepted = value); debugPrint("[config] isPrivacyPolicyAccepted: $value"); @@ -1250,10 +1230,10 @@ class _GamePageState extends State }; debugPrint( - "$tag Game over reason: ${Game.instance.position.gameOverReason}", + "$tag Game over reason: ${gameInstance.position.gameOverReason}", ); - String? loseReasonStr = reasonMap[Game.instance.position.gameOverReason]; + String? loseReasonStr = reasonMap[gameInstance.position.gameOverReason]; if (loseReasonStr == null) { loseReasonStr = S.of(context).gameOverUnknownReason; @@ -1296,7 +1276,7 @@ class _GamePageState extends State void showGameResult(String winner) { final GameResult result = getGameResult(winner); - Game.instance.position.result = result; + gameInstance.position.result = result; switch (result) { case GameResult.win: @@ -1312,7 +1292,7 @@ class _GamePageState extends State } final Map retMap = { - GameResult.win: Game.instance.engineType == EngineType.humanVsAi + GameResult.win: gameInstance.engineType == EngineType.humanVsAi ? S.of(context).youWin : S.of(context).gameOver, GameResult.lose: S.of(context).gameOver, @@ -1329,10 +1309,10 @@ class _GamePageState extends State if (result == GameResult.win && !isTopLevel && - Game.instance.engineType == EngineType.humanVsAi) { + gameInstance.engineType == EngineType.humanVsAi) { var contentStr = getGameOverReasonString( - Game.instance.position.gameOverReason, - Game.instance.position.winner, + gameInstance.position.gameOverReason, + gameInstance.position.winner, ); if (!isTopLevel) { @@ -1371,7 +1351,7 @@ class _GamePageState extends State Config.save(); await _engine.setOptions(context); debugPrint("[config] skillLevel: ${Config.skillLevel}"); - Navigator.of(context).pop(); + Navigator.pop(context); }, ), TextButton( @@ -1381,7 +1361,7 @@ class _GamePageState extends State fontSize: Config.fontSize, ), ), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ); @@ -1402,8 +1382,8 @@ class _GamePageState extends State ), content: Text( getGameOverReasonString( - Game.instance.position.gameOverReason, - Game.instance.position.winner, + gameInstance.position.gameOverReason, + gameInstance.position.winner, ), style: TextStyle( fontSize: Config.fontSize, @@ -1418,8 +1398,8 @@ class _GamePageState extends State ), ), onPressed: () { - Navigator.of(context).pop(); - Game.instance.newGame(); + Navigator.pop(context); + gameInstance.newGame(); if (mounted) { showTip(S.of(context).gameStarted); if (Config.screenReaderSupport) { @@ -1428,7 +1408,7 @@ class _GamePageState extends State } } - if (Game.instance.isAiToMove()!) { + if (gameInstance.isAiToMove()!) { debugPrint("$tag New game, AI to move."); engineToGo(false); } @@ -1441,7 +1421,7 @@ class _GamePageState extends State fontSize: Config.fontSize, ), ), - onPressed: () => Navigator.of(context).pop(), + onPressed: () => Navigator.pop(context), ), ], ); @@ -1534,8 +1514,8 @@ class _GamePageState extends State IconData getIconArrow() { IconData iconArrow = FluentIcons.code_24_regular; - if (Game.instance.position.phase == Phase.gameOver) { - switch (Game.instance.position.winner) { + if (gameInstance.position.phase == Phase.gameOver) { + switch (gameInstance.position.winner) { case PieceColor.white: iconArrow = ltr ? FluentIcons.toggle_left_24_regular @@ -1551,7 +1531,7 @@ class _GamePageState extends State break; } } else { - switch (Game.instance.sideToMove) { + switch (gameInstance.sideToMove) { case PieceColor.white: iconArrow = FluentIcons.chevron_left_24_regular; break; @@ -1589,7 +1569,7 @@ class _GamePageState extends State final String period = Config.screenReaderSupport ? "." : ""; final String comma = Config.screenReaderSupport ? "," : ""; - final pos = Game.instance.position; + final pos = gameInstance.position; switch (pos.phase) { case Phase.placing: @@ -1870,11 +1850,7 @@ class _GamePageState extends State children: [ BlockSemantics(child: header), board, - if (Config.isHistoryNavigationToolbarShown) - historyNavToolbar - else - const SizedBox(height: 0), - const SizedBox(height: 1), + if (Config.isHistoryNavigationToolbarShown) historyNavToolbar, toolbar, ], ), diff --git a/src/ui/flutter_app/lib/screens/game_settings_page.dart b/src/ui/flutter_app/lib/screens/game_settings_page.dart index 5d734ac8..0092b4e2 100644 --- a/src/ui/flutter_app/lib/screens/game_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/game_settings_page.dart @@ -30,7 +30,6 @@ import 'package:sanmill/shared/theme/app_theme.dart'; import '../shared/dialog.dart'; import 'env_page.dart'; -import 'list_item_divider.dart'; class Developer { const Developer._(); @@ -109,7 +108,7 @@ class _GameSettingsPageState extends State { Future restoreFactoryDefaultSettings() async { Future confirm() async { - Navigator.of(context).pop(); + Navigator.pop(context); if (Platform.isAndroid) { showCountdownDialog(context, 10, _events, _restore); } else { @@ -121,7 +120,7 @@ class _GameSettingsPageState extends State { } } - void cancel() => Navigator.of(context).pop(); + void cancel() => Navigator.pop(context); var prompt = ""; @@ -216,7 +215,6 @@ class _GameSettingsPageState extends State { //trailingString: "L" + Config.skillLevel.toString(), onTap: setSkillLevel, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).moveTime, onTap: setMoveTime, @@ -233,28 +231,24 @@ class _GameSettingsPageState extends State { trailingString: algorithmNames[Config.algorithm], onTap: setAlgorithm, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.drawOnHumanExperience, onChanged: setDrawOnHumanExperience, titleString: S.of(context).drawOnHumanExperience, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.considerMobility, onChanged: setConsiderMobility, titleString: S.of(context).considerMobility, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.aiIsLazy, onChanged: setAiIsLazy, titleString: S.of(context).passive, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.shufflingEnabled, @@ -281,7 +275,6 @@ class _GameSettingsPageState extends State { onChanged: setTone, titleString: S.of(context).playSoundsInTheGame, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.keepMuteWhenTakingBack, @@ -314,7 +307,6 @@ class _GameSettingsPageState extends State { titleString: S.of(context).restoreDefaultSettings, onTap: restoreFactoryDefaultSettings, ), - const ListItemDivider(), ], ), const SizedBox(height: AppTheme.sizedBoxHeight), @@ -322,9 +314,7 @@ class _GameSettingsPageState extends State { Text( S.of(context).forDevelopers, style: AppTheme.settingsHeaderStyle, - ) - else - const SizedBox(height: 1), + ), if (Developer.developerModeEnabled) SettingsCard( context: context, @@ -335,21 +325,18 @@ class _GameSettingsPageState extends State { onChanged: setDeveloperMode, titleString: S.of(context).developerMode, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.experimentsEnabled, onChanged: setExperimentsEnabled, titleString: S.of(context).experiments, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isAutoRestart, onChanged: setIsAutoRestart, titleString: S.of(context).isAutoRestart, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).environmentVariables, onTap: () { @@ -362,9 +349,7 @@ class _GameSettingsPageState extends State { }, ), ], - ) - else - const SizedBox(height: 1), + ), ]; } @@ -387,9 +372,7 @@ class _GameSettingsPageState extends State { } Future setWhoMovesFirst(bool value) async { - setState(() { - Config.aiMovesFirst = !value; - }); + setState(() => Config.aiMovesFirst = !value); debugPrint("[config] aiMovesFirst: ${Config.aiMovesFirst}"); @@ -397,9 +380,7 @@ class _GameSettingsPageState extends State { } Future setAiIsLazy(bool value) async { - setState(() { - Config.aiIsLazy = value; - }); + setState(() => Config.aiIsLazy = value); debugPrint("[config] aiMovesFirst: $value"); @@ -410,11 +391,9 @@ class _GameSettingsPageState extends State { Future callback(int? algorithm) async { debugPrint("[config] algorithm = $algorithm"); - Navigator.of(context).pop(); + Navigator.pop(context); - setState(() { - Config.algorithm = algorithm ?? 2; - }); + setState(() => Config.algorithm = algorithm ?? 2); debugPrint("[config] Config.algorithm: ${Config.algorithm}"); @@ -435,7 +414,6 @@ class _GameSettingsPageState extends State { value: 0, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('PVS'), @@ -443,7 +421,6 @@ class _GameSettingsPageState extends State { value: 1, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('MTD(f)'), @@ -451,7 +428,6 @@ class _GameSettingsPageState extends State { value: 2, onChanged: callback, ), - const ListItemDivider(), ], ), ), @@ -459,9 +435,7 @@ class _GameSettingsPageState extends State { } Future setDrawOnHumanExperience(bool value) async { - setState(() { - Config.drawOnHumanExperience = value; - }); + setState(() => Config.drawOnHumanExperience = value); debugPrint("[config] drawOnHumanExperience: $value"); @@ -469,9 +443,7 @@ class _GameSettingsPageState extends State { } Future setConsiderMobility(bool value) async { - setState(() { - Config.considerMobility = value; - }); + setState(() => Config.considerMobility = value); debugPrint("[config] considerMobility: $value"); @@ -479,9 +451,7 @@ class _GameSettingsPageState extends State { } Future setIsAutoRestart(bool value) async { - setState(() { - Config.isAutoRestart = value; - }); + setState(() => Config.isAutoRestart = value); debugPrint("[config] isAutoRestart: $value"); @@ -489,9 +459,7 @@ class _GameSettingsPageState extends State { } Future setIsAutoChangeFirstMove(bool value) async { - setState(() { - Config.isAutoChangeFirstMove = value; - }); + setState(() => Config.isAutoChangeFirstMove = value); debugPrint("[config] isAutoChangeFirstMove: $value"); @@ -499,9 +467,7 @@ class _GameSettingsPageState extends State { } Future setResignIfMostLose(bool value) async { - setState(() { - Config.resignIfMostLose = value; - }); + setState(() => Config.resignIfMostLose = value); debugPrint("[config] resignIfMostLose: $value"); @@ -509,9 +475,7 @@ class _GameSettingsPageState extends State { } Future setShufflingEnabled(bool value) async { - setState(() { - Config.shufflingEnabled = value; - }); + setState(() => Config.shufflingEnabled = value); debugPrint("[config] shufflingEnabled: $value"); @@ -519,9 +483,7 @@ class _GameSettingsPageState extends State { } Future setLearnEndgame(bool value) async { - setState(() { - Config.learnEndgame = value; - }); + setState(() => Config.learnEndgame = value); debugPrint("[config] learnEndgame: $value"); @@ -529,9 +491,7 @@ class _GameSettingsPageState extends State { } Future setOpeningBook(bool value) async { - setState(() { - Config.openingBook = value; - }); + setState(() => Config.openingBook = value); debugPrint("[config] openingBook: $value"); @@ -539,9 +499,7 @@ class _GameSettingsPageState extends State { } Future setTone(bool value) async { - setState(() { - Config.toneEnabled = value; - }); + setState(() => Config.toneEnabled = value); debugPrint("[config] toneEnabled: $value"); @@ -549,9 +507,7 @@ class _GameSettingsPageState extends State { } Future setKeepMuteWhenTakingBack(bool value) async { - setState(() { - Config.keepMuteWhenTakingBack = value; - }); + setState(() => Config.keepMuteWhenTakingBack = value); debugPrint("[config] keepMuteWhenTakingBack: $value"); @@ -559,9 +515,7 @@ class _GameSettingsPageState extends State { } Future setScreenReaderSupport(bool value) async { - setState(() { - Config.screenReaderSupport = value; - }); + setState(() => Config.screenReaderSupport = value); debugPrint("[config] screenReaderSupport: $value"); @@ -569,9 +523,7 @@ class _GameSettingsPageState extends State { } Future setDeveloperMode(bool value) async { - setState(() { - Config.developerMode = value; - }); + setState(() => Config.developerMode = value); debugPrint("[config] developerMode: $value"); @@ -579,9 +531,7 @@ class _GameSettingsPageState extends State { } Future setExperimentsEnabled(bool value) async { - setState(() { - Config.experimentsEnabled = value; - }); + setState(() => Config.experimentsEnabled = value); debugPrint("[config] experimentsEnabled: $value"); @@ -591,9 +541,7 @@ class _GameSettingsPageState extends State { // Display Future setLanguage(String value) async { - setState(() { - Config.languageCode = value; - }); + setState(() => Config.languageCode = value); debugPrint("[config] languageCode: $value"); @@ -601,9 +549,7 @@ class _GameSettingsPageState extends State { } Future setIsPieceCountInHandShown(bool value) async { - setState(() { - Config.isPieceCountInHandShown = value; - }); + setState(() => Config.isPieceCountInHandShown = value); debugPrint("[config] isPieceCountInHandShown: $value"); @@ -611,9 +557,7 @@ class _GameSettingsPageState extends State { } Future setIsNotationsShown(bool value) async { - setState(() { - Config.isNotationsShown = value; - }); + setState(() => Config.isNotationsShown = value); debugPrint("[config] isNotationsShown: $value"); @@ -621,9 +565,7 @@ class _GameSettingsPageState extends State { } Future setIsHistoryNavigationToolbarShown(bool value) async { - setState(() { - Config.isHistoryNavigationToolbarShown = value; - }); + setState(() => Config.isHistoryNavigationToolbarShown = value); debugPrint("[config] isHistoryNavigationToolbarShown: $value"); @@ -631,9 +573,7 @@ class _GameSettingsPageState extends State { } Future setStandardNotationEnabled(bool value) async { - setState(() { - Config.standardNotationEnabled = value; - }); + setState(() => Config.standardNotationEnabled = value); debugPrint("[config] standardNotationEnabled: $value"); diff --git a/src/ui/flutter_app/lib/screens/home_drawer.dart b/src/ui/flutter_app/lib/screens/home_drawer.dart index 9334a960..4c3fecdf 100644 --- a/src/ui/flutter_app/lib/screens/home_drawer.dart +++ b/src/ui/flutter_app/lib/screens/home_drawer.dart @@ -301,7 +301,7 @@ class HomeDrawer extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ - const SizedBox(width: 6.0, height: 46.0), + const SizedBox(height: 46.0, width: 6.0), const Padding( padding: EdgeInsets.all(4.0), ), 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 917e3c91..242225b3 100644 --- a/src/ui/flutter_app/lib/screens/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart @@ -89,25 +89,17 @@ class _NavigationHomeScreenState extends State { // TODO: use switch case final engineType = drawerMap[drawerIndex!]; - if (engineType != null) { - setState(() { - Game.instance.setWhoIsAi(engineType); + setState(() { + if (engineType != null) { + gameInstance.setWhoIsAi(engineType); screenView = GamePage(engineType); - }); - } else if (drawerIndex == DrawerIndex.preferences) { - setState(() { + } else if (drawerIndex == DrawerIndex.preferences) { screenView = GameSettingsPage(); - }); - } else if (drawerIndex == DrawerIndex.ruleSettings) { - setState(() { + } else if (drawerIndex == DrawerIndex.ruleSettings) { screenView = RuleSettingsPage(); - }); - } else if (drawerIndex == DrawerIndex.personalization) { - setState(() { + } else if (drawerIndex == DrawerIndex.personalization) { screenView = PersonalizationSettingsPage(); - }); - } else if (drawerIndex == DrawerIndex.feedback && !Config.developerMode) { - setState(() { + } else if (drawerIndex == DrawerIndex.feedback && !Config.developerMode) { if (Platform.isWindows) { debugPrint("flutter_email_sender does not support Windows."); //_launchFeedback(); @@ -131,18 +123,14 @@ class _NavigationHomeScreenState extends State { await FlutterEmailSender.send(email); }); } - }); - } else if (drawerIndex == DrawerIndex.Help && !Config.developerMode) { - setState(() { + } else if (drawerIndex == DrawerIndex.Help && !Config.developerMode) { screenView = HelpScreen(); - }); - } else if (drawerIndex == DrawerIndex.About && !Config.developerMode) { - setState(() { + } else if (drawerIndex == DrawerIndex.About && !Config.developerMode) { screenView = AboutPage(); - }); - } else { - //do in your way...... - } + } else { + //do in your way...... + } + }); } Future writeImageToStorage(Uint8List feedbackScreenshot) async { diff --git a/src/ui/flutter_app/lib/screens/oss_license_page.dart b/src/ui/flutter_app/lib/screens/oss_license_page.dart index fdf6b315..101b105b 100644 --- a/src/ui/flutter_app/lib/screens/oss_license_page.dart +++ b/src/ui/flutter_app/lib/screens/oss_license_page.dart @@ -86,7 +86,8 @@ class OssLicensesPage extends StatelessWidget { title: Text('$key $version'), subtitle: desc != null ? Text(desc) : null, trailing: const Icon(FluentIcons.chevron_right_24_regular), - onTap: () => Navigator.of(context).push( + onTap: () => Navigator.push( + context, MaterialPageRoute( builder: (_) => MiscOssLicenseSingle(name: key, json: ossl), ), diff --git a/src/ui/flutter_app/lib/screens/personalization_settings_page.dart b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart index 5b8c7299..b5e289a9 100644 --- a/src/ui/flutter_app/lib/screens/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart @@ -27,8 +27,6 @@ import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; -import 'list_item_divider.dart'; - class PersonalizationSettingsPage extends StatefulWidget { @override _PersonalizationSettingsPageState createState() => @@ -130,7 +128,7 @@ class _PersonalizationSettingsPageState } Config.save(); - Navigator.of(context).pop(); + Navigator.pop(context); }, ), TextButton( @@ -141,7 +139,7 @@ class _PersonalizationSettingsPageState ), ), onPressed: () { - Navigator.of(context).pop(); + Navigator.pop(context); }, ), ], @@ -374,7 +372,7 @@ class _PersonalizationSettingsPageState Future langCallback([String? langCode]) async { debugPrint("[config] languageCode = $langCode"); - Navigator.of(context).pop(); + Navigator.pop(context); setState(() { Config.languageCode = langCode ?? Constants.defaultLanguageCodeName; @@ -394,63 +392,53 @@ class _PersonalizationSettingsPageState SettingsListTile( titleString: S.of(context).language, trailingString: - Config.languageCode == Constants.defaultLanguageCodeName - ? "" - : languageCodeToStrings[Config.languageCode]!.languageName, + Config.languageCode != Constants.defaultLanguageCodeName + ? languageCodeToStrings[Config.languageCode]!.languageName + : "", onTap: () => setLanguage(context, langCallback), ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isPieceCountInHandShown, onChanged: setIsPieceCountInHandShown, titleString: S.of(context).isPieceCountInHandShown, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isNotationsShown, onChanged: setIsNotationsShown, titleString: S.of(context).isNotationsShown, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isHistoryNavigationToolbarShown, onChanged: setIsHistoryNavigationToolbarShown, titleString: S.of(context).isHistoryNavigationToolbarShown, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).boardBorderLineWidth, onTap: setBoardBorderLineWidth, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).boardInnerLineWidth, onTap: setBoardInnerLineWidth, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).pieceWidth, onTap: setPieceWidth, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).fontSize, onTap: setFontSize, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).boardTop, onTap: setBoardTop, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).animationDuration, onTap: setAnimationDuration, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.standardNotationEnabled, @@ -469,88 +457,74 @@ class _PersonalizationSettingsPageState trailingColor: Config.boardBackgroundColor, onTap: () => showColorDialog(S.of(context).boardColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).backgroundColor, trailingColor: Config.darkBackgroundColor, onTap: () => showColorDialog(S.of(context).backgroundColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).lineColor, trailingColor: Config.boardLineColor, onTap: () => showColorDialog(S.of(context).lineColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).whitePieceColor, trailingColor: Config.whitePieceColor, onTap: () => showColorDialog(S.of(context).whitePieceColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).blackPieceColor, trailingColor: Config.blackPieceColor, onTap: () => showColorDialog(S.of(context).blackPieceColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).pieceHighlightColor, trailingColor: Config.pieceHighlightColor, onTap: () => showColorDialog(S.of(context).pieceHighlightColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).messageColor, trailingColor: Config.messageColor, onTap: () => showColorDialog(S.of(context).messageColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).drawerColor, trailingColor: Config.drawerColor, onTap: () => showColorDialog(S.of(context).drawerColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).drawerBackgroundColor, trailingColor: Config.drawerBackgroundColor, onTap: () => showColorDialog(S.of(context).drawerBackgroundColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).drawerTextColor, trailingColor: Config.drawerTextColor, onTap: () => showColorDialog(S.of(context).drawerTextColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).drawerHighlightItemColor, trailingColor: Config.drawerHighlightItemColor, onTap: () => showColorDialog(S.of(context).drawerHighlightItemColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).mainToolbarBackgroundColor, trailingColor: Config.mainToolbarBackgroundColor, onTap: () => showColorDialog(S.of(context).mainToolbarBackgroundColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).mainToolbarIconColor, trailingColor: Config.mainToolbarIconColor, onTap: () => showColorDialog(S.of(context).mainToolbarIconColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).navigationToolbarBackgroundColor, trailingColor: Config.navigationToolbarBackgroundColor, onTap: () => showColorDialog(S.of(context).navigationToolbarBackgroundColor), ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).navigationToolbarIconColor, trailingColor: Config.navigationToolbarIconColor, @@ -565,33 +539,25 @@ class _PersonalizationSettingsPageState // Display Future setIsPieceCountInHandShown(bool value) async { - setState(() { - Config.isPieceCountInHandShown = value; - }); + setState(() => Config.isPieceCountInHandShown = value); Config.save(); } Future setIsNotationsShown(bool value) async { - setState(() { - Config.isNotationsShown = value; - }); + setState(() => Config.isNotationsShown = value); Config.save(); } Future setIsHistoryNavigationToolbarShown(bool value) async { - setState(() { - Config.isHistoryNavigationToolbarShown = value; - }); + setState(() => Config.isHistoryNavigationToolbarShown = value); Config.save(); } Future setStandardNotationEnabled(bool value) async { - setState(() { - Config.standardNotationEnabled = value; - }); + setState(() => Config.standardNotationEnabled = value); debugPrint("[config] standardNotationEnabled: $value"); diff --git a/src/ui/flutter_app/lib/screens/rule_settings_page.dart b/src/ui/flutter_app/lib/screens/rule_settings_page.dart index 4e3ecc29..05e25d10 100644 --- a/src/ui/flutter_app/lib/screens/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/rule_settings_page.dart @@ -27,7 +27,6 @@ import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; import '../shared/snack_bar.dart'; -import 'list_item_divider.dart'; class RuleSettingsPage extends StatefulWidget { @override @@ -63,7 +62,6 @@ class _RuleSettingsPageState extends State { trailingString: Config.piecesCount.toString(), onTap: setNTotalPiecesEachSide, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.hasDiagonalLines, @@ -71,21 +69,18 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).hasDiagonalLines, subtitleString: S.of(context).hasDiagonalLines_Detail, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).nMoveRule, subtitleString: S.of(context).nMoveRule_Detail, trailingString: Config.nMoveRule.toString(), onTap: setNMoveRule, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).endgameNMoveRule, subtitleString: S.of(context).endgameNMoveRule_Detail, trailingString: Config.endgameNMoveRule.toString(), onTap: setEndgameNMoveRule, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.threefoldRepetitionRule, @@ -93,7 +88,6 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).threefoldRepetitionRule, subtitleString: S.of(context).threefoldRepetitionRule_Detail, ), - const ListItemDivider(), ], ), const SizedBox(height: AppTheme.sizedBoxHeight), @@ -108,7 +102,6 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).hasBannedLocations, subtitleString: S.of(context).hasBannedLocations_Detail, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.isWhiteLoseButNotDrawWhenBoardFull, @@ -117,7 +110,6 @@ class _RuleSettingsPageState extends State { subtitleString: S.of(context).isWhiteLoseButNotDrawWhenBoardFull_Detail, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.mayOnlyRemoveUnplacedPieceInPlacingPhase, @@ -141,19 +133,13 @@ class _RuleSettingsPageState extends State { subtitleString: S.of(context).mayMoveInPlacingPhase_Detail, ) else - const SizedBox(height: 1), - if (Config.experimentsEnabled) - const ListItemDivider() - else - const SizedBox(height: 1), - SettingsSwitchListTile( - context: context, - value: Config.isDefenderMoveFirst, - onChanged: setIsDefenderMoveFirst, - titleString: S.of(context).isDefenderMoveFirst, - subtitleString: S.of(context).isDefenderMoveFirst_Detail, - ), - const ListItemDivider(), + SettingsSwitchListTile( + context: context, + value: Config.isDefenderMoveFirst, + onChanged: setIsDefenderMoveFirst, + titleString: S.of(context).isDefenderMoveFirst, + subtitleString: S.of(context).isDefenderMoveFirst_Detail, + ), SettingsSwitchListTile( context: context, value: Config.isLoseButNotChangeSideWhenNoWay, @@ -176,7 +162,6 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).mayFly, subtitleString: S.of(context).mayFly_Detail, ), - const ListItemDivider(), SettingsListTile( titleString: S.of(context).flyPieceCount, subtitleString: S.of(context).flyPieceCount_Detail, @@ -197,7 +182,6 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).mayRemoveFromMillsAlways, subtitleString: S.of(context).mayRemoveFromMillsAlways_Detail, ), - const ListItemDivider(), SettingsSwitchListTile( context: context, value: Config.mayRemoveMultiple, @@ -205,7 +189,6 @@ class _RuleSettingsPageState extends State { titleString: S.of(context).mayRemoveMultiple, subtitleString: S.of(context).mayRemoveMultiple_Detail, ), - const ListItemDivider(), ], ), ]; @@ -217,12 +200,12 @@ class _RuleSettingsPageState extends State { Future callback(int? piecesCount) async { debugPrint("[config] piecesCount = $piecesCount"); - Navigator.of(context).pop(); + Navigator.pop(context); - setState(() { - rule.piecesCount = Config.piecesCount = - piecesCount ?? (specialCountryAndRegion == "Iran" ? 12 : 9); - }); + setState( + () => rule.piecesCount = Config.piecesCount = + piecesCount ?? (specialCountryAndRegion == "Iran" ? 12 : 9), + ); debugPrint("[config] rule.piecesCount: ${rule.piecesCount}"); @@ -243,7 +226,6 @@ class _RuleSettingsPageState extends State { value: 9, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('10'), @@ -251,7 +233,6 @@ class _RuleSettingsPageState extends State { value: 10, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('11'), @@ -259,7 +240,6 @@ class _RuleSettingsPageState extends State { value: 11, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('12'), @@ -267,7 +247,6 @@ class _RuleSettingsPageState extends State { value: 12, onChanged: callback, ), - const ListItemDivider(), ], ), ), @@ -278,11 +257,9 @@ class _RuleSettingsPageState extends State { Future callback(int? nMoveRule) async { debugPrint("[config] nMoveRule = $nMoveRule"); - Navigator.of(context).pop(); + Navigator.pop(context); - setState(() { - rule.nMoveRule = Config.nMoveRule = nMoveRule ?? 100; - }); + setState(() => rule.nMoveRule = Config.nMoveRule = nMoveRule ?? 100); debugPrint("[config] rule.nMoveRule: ${rule.nMoveRule}"); @@ -303,7 +280,6 @@ class _RuleSettingsPageState extends State { value: 30, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('50'), @@ -311,7 +287,6 @@ class _RuleSettingsPageState extends State { value: 50, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('60'), @@ -319,7 +294,6 @@ class _RuleSettingsPageState extends State { value: 60, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('100'), @@ -327,7 +301,6 @@ class _RuleSettingsPageState extends State { value: 100, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('200'), @@ -335,7 +308,6 @@ class _RuleSettingsPageState extends State { value: 200, onChanged: callback, ), - const ListItemDivider(), ], ), ), @@ -346,12 +318,12 @@ class _RuleSettingsPageState extends State { Future callback(int? endgameNMoveRule) async { debugPrint("[config] endgameNMoveRule = $endgameNMoveRule"); - Navigator.of(context).pop(); + Navigator.pop(context); - setState(() { - rule.endgameNMoveRule = - Config.endgameNMoveRule = endgameNMoveRule ?? 100; - }); + setState( + () => rule.endgameNMoveRule = + Config.endgameNMoveRule = endgameNMoveRule ?? 100, + ); debugPrint("[config] rule.endgameNMoveRule: ${rule.endgameNMoveRule}"); @@ -372,7 +344,6 @@ class _RuleSettingsPageState extends State { value: 5, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('10'), @@ -380,7 +351,6 @@ class _RuleSettingsPageState extends State { value: 10, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('20'), @@ -388,7 +358,6 @@ class _RuleSettingsPageState extends State { value: 20, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('30'), @@ -396,7 +365,6 @@ class _RuleSettingsPageState extends State { value: 30, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('50'), @@ -404,7 +372,6 @@ class _RuleSettingsPageState extends State { value: 50, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('60'), @@ -412,7 +379,6 @@ class _RuleSettingsPageState extends State { value: 60, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('100'), @@ -420,7 +386,6 @@ class _RuleSettingsPageState extends State { value: 100, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('200'), @@ -428,7 +393,6 @@ class _RuleSettingsPageState extends State { value: 200, onChanged: callback, ), - const ListItemDivider(), ], ), ), @@ -439,11 +403,11 @@ class _RuleSettingsPageState extends State { Future callback(int? flyPieceCount) async { debugPrint("[config] flyPieceCount = $flyPieceCount"); - Navigator.of(context).pop(); + Navigator.pop(context); - setState(() { - rule.flyPieceCount = Config.flyPieceCount = flyPieceCount ?? 3; - }); + setState( + () => rule.flyPieceCount = Config.flyPieceCount = flyPieceCount ?? 3, + ); debugPrint("[config] rule.flyPieceCount: ${rule.flyPieceCount}"); @@ -464,7 +428,6 @@ class _RuleSettingsPageState extends State { value: 3, onChanged: callback, ), - const ListItemDivider(), RadioListTile( activeColor: AppTheme.switchListTileActiveColor, title: const Text('4'), @@ -472,7 +435,6 @@ class _RuleSettingsPageState extends State { value: 4, onChanged: callback, ), - const ListItemDivider(), ], ), ), @@ -480,9 +442,7 @@ class _RuleSettingsPageState extends State { } Future setHasDiagonalLines(bool value) async { - setState(() { - rule.hasDiagonalLines = Config.hasDiagonalLines = value; - }); + setState(() => rule.hasDiagonalLines = Config.hasDiagonalLines = value); debugPrint("[config] rule.hasDiagonalLines: $value"); @@ -490,9 +450,7 @@ class _RuleSettingsPageState extends State { } Future setAllowFlyingAllowed(bool value) async { - setState(() { - rule.mayFly = Config.mayFly = value; - }); + setState(() => rule.mayFly = Config.mayFly = value); debugPrint("[config] rule.mayFly: $value"); @@ -500,9 +458,10 @@ class _RuleSettingsPageState extends State { } Future setThreefoldRepetitionRule(bool value) async { - setState(() { - rule.threefoldRepetitionRule = Config.threefoldRepetitionRule = value; - }); + setState( + () => + rule.threefoldRepetitionRule = Config.threefoldRepetitionRule = value, + ); debugPrint("[config] rule.threefoldRepetitionRule: $value"); @@ -512,9 +471,7 @@ class _RuleSettingsPageState extends State { // Placing Future setHasBannedLocations(bool value) async { - setState(() { - rule.hasBannedLocations = Config.hasBannedLocations = value; - }); + setState(() => rule.hasBannedLocations = Config.hasBannedLocations = value); debugPrint("[config] rule.hasBannedLocations: $value"); @@ -522,10 +479,10 @@ class _RuleSettingsPageState extends State { } Future setIsWhiteLoseButNotDrawWhenBoardFull(bool value) async { - setState(() { - rule.isWhiteLoseButNotDrawWhenBoardFull = - Config.isWhiteLoseButNotDrawWhenBoardFull = value; - }); + setState( + () => rule.isWhiteLoseButNotDrawWhenBoardFull = + Config.isWhiteLoseButNotDrawWhenBoardFull = value, + ); debugPrint("[config] rule.isWhiteLoseButNotDrawWhenBoardFull: $value"); @@ -533,10 +490,10 @@ class _RuleSettingsPageState extends State { } Future setMayOnlyRemoveUnplacedPieceInPlacingPhase(bool value) async { - setState(() { - rule.mayOnlyRemoveUnplacedPieceInPlacingPhase = - Config.mayOnlyRemoveUnplacedPieceInPlacingPhase = value; - }); + setState( + () => rule.mayOnlyRemoveUnplacedPieceInPlacingPhase = + Config.mayOnlyRemoveUnplacedPieceInPlacingPhase = value, + ); debugPrint( "[config] rule.mayOnlyRemoveUnplacedPieceInPlacingPhase: $value", @@ -548,9 +505,9 @@ class _RuleSettingsPageState extends State { // Moving Future setMayMoveInPlacingPhase(bool value) async { - setState(() { - rule.mayMoveInPlacingPhase = Config.mayMoveInPlacingPhase = value; - }); + setState( + () => rule.mayMoveInPlacingPhase = Config.mayMoveInPlacingPhase = value, + ); debugPrint("[config] rule.mayMoveInPlacingPhase: $value"); @@ -563,9 +520,9 @@ class _RuleSettingsPageState extends State { } Future setIsDefenderMoveFirst(bool value) async { - setState(() { - rule.isDefenderMoveFirst = Config.isDefenderMoveFirst = value; - }); + setState( + () => rule.isDefenderMoveFirst = Config.isDefenderMoveFirst = value, + ); debugPrint("[config] rule.isDefenderMoveFirst: $value"); @@ -573,10 +530,10 @@ class _RuleSettingsPageState extends State { } Future setIsLoseButNotChangeSideWhenNoWay(bool value) async { - setState(() { - rule.isLoseButNotChangeSideWhenNoWay = - Config.isLoseButNotChangeSideWhenNoWay = value; - }); + setState( + () => rule.isLoseButNotChangeSideWhenNoWay = + Config.isLoseButNotChangeSideWhenNoWay = value, + ); debugPrint("[config] rule.isLoseButNotChangeSideWhenNoWay: $value"); @@ -586,9 +543,10 @@ class _RuleSettingsPageState extends State { // Removing Future setAllowRemovePieceInMill(bool value) async { - setState(() { - rule.mayRemoveFromMillsAlways = Config.mayRemoveFromMillsAlways = value; - }); + setState( + () => rule.mayRemoveFromMillsAlways = + Config.mayRemoveFromMillsAlways = value, + ); debugPrint("[config] rule.mayRemoveFromMillsAlways: $value"); @@ -596,9 +554,9 @@ class _RuleSettingsPageState extends State { } Future setAllowRemoveMultiPiecesWhenCloseMultiMill(bool value) async { - setState(() { - rule.mayRemoveMultiple = Config.mayRemoveMultiple = value; - }); + setState( + () => rule.mayRemoveMultiple = Config.mayRemoveMultiple = value, + ); debugPrint("[config] rule.mayRemoveMultiple: $value"); @@ -608,9 +566,7 @@ class _RuleSettingsPageState extends State { // Unused Future setNPiecesAtLeast(int value) async { - setState(() { - rule.piecesAtLeastCount = Config.piecesAtLeastCount = value; - }); + setState(() => rule.piecesAtLeastCount = Config.piecesAtLeastCount = value); debugPrint("[config] rule.piecesAtLeastCount: $value"); diff --git a/src/ui/flutter_app/lib/screens/settings/settings_card.dart b/src/ui/flutter_app/lib/screens/settings/settings_card.dart index 078d3764..efae523f 100644 --- a/src/ui/flutter_app/lib/screens/settings/settings_card.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_card.dart @@ -17,6 +17,7 @@ */ import 'package:flutter/material.dart'; +import 'package:sanmill/screens/list_item_divider.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsCard extends StatelessWidget { @@ -34,7 +35,13 @@ class SettingsCard extends StatelessWidget { return Card( color: AppTheme.cardColor, margin: AppTheme.cardMargin, - child: Column(children: children), + child: ListView.separated( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (_, index) => children[index], + separatorBuilder: (_, __) => const ListItemDivider(), + itemCount: children.length, + ), ); } } diff --git a/src/ui/flutter_app/lib/shared/dialog.dart b/src/ui/flutter_app/lib/shared/dialog.dart index bdabcd83..9380567a 100644 --- a/src/ui/flutter_app/lib/shared/dialog.dart +++ b/src/ui/flutter_app/lib/shared/dialog.dart @@ -72,7 +72,7 @@ void showCountdownDialog( const SizedBox(height: 20), InkWell( onTap: () { - Navigator.of(context).pop(); + Navigator.pop(context); }, child: Center( child: Text( @@ -179,7 +179,7 @@ Future showPrivacyDialog( child: Text(S.of(context).accept), onPressed: () { setPrivacyPolicyAccepted(true); - Navigator.of(context).pop(); + Navigator.pop(context); }, ), if (Platform.isAndroid) diff --git a/src/ui/flutter_app/lib/shared/painters/board_painter.dart b/src/ui/flutter_app/lib/shared/painters/board_painter.dart index e72f1b15..90d364c3 100644 --- a/src/ui/flutter_app/lib/shared/painters/board_painter.dart +++ b/src/ui/flutter_app/lib/shared/painters/board_painter.dart @@ -63,16 +63,16 @@ class BoardPainter extends PiecesBasePainter { if (Config.isPieceCountInHandShown) { var pieceInHandCount = - Game.instance.position.pieceInHandCount[PieceColor.black]; + gameInstance.position.pieceInHandCount[PieceColor.black]; - if (Game.instance.position.pieceOnBoardCount[PieceColor.white] == 0 && - Game.instance.position.pieceOnBoardCount[PieceColor.black] == 0) { + if (gameInstance.position.pieceOnBoardCount[PieceColor.white] == 0 && + gameInstance.position.pieceOnBoardCount[PieceColor.black] == 0) { pieceInHandCount = Config.piecesCount; } var pieceInHandCountStr = ""; - if (Game.instance.position.phase == Phase.placing) { + if (gameInstance.position.phase == Phase.placing) { pieceInHandCountStr = pieceInHandCount.toString(); } From 961aa6241b18bfc56b6b28d7b93edf2528461df7 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:16:01 +0200 Subject: [PATCH 09/13] fix some stuff - remove unnecessary containers - bump linting version in pubspec.yml - make `isLargeScreen` and `isSmallScreen` a geter - add decimal points to double values - remove unused SizedBox - use const constructor where possible - remove residual code - fix help_screen AppBar - Fix historyNavToolbar padding fix styling of drawer - fix the padding of the drawer elements. cleanup settings - removes unused properties - fixes ListItemDivider height --- src/ui/flutter_app/lib/main.dart | 4 +- .../flutter_app/lib/screens/about_page.dart | 1 - src/ui/flutter_app/lib/screens/game_page.dart | 276 ++++++++---------- .../lib/screens/game_settings_page.dart | 31 +- .../flutter_app/lib/screens/help_screen.dart | 4 +- .../flutter_app/lib/screens/home_drawer.dart | 12 +- .../lib/screens/list_item_divider.dart | 1 + .../personalization_settings_page.dart | 6 - .../lib/screens/rule_settings_page.dart | 16 - .../lib/screens/settings/settings_card.dart | 2 - .../screens/settings/settings_list_tile.dart | 4 +- .../settings/settings_switch_list_tile.dart | 2 - .../flutter_app/lib/shared/common/config.dart | 10 +- .../lib/shared/common/constants.dart | 8 +- src/ui/flutter_app/lib/shared/dialog.dart | 4 +- .../lib/shared/theme/app_theme.dart | 5 +- src/ui/flutter_app/pubspec.yaml | 2 +- 17 files changed, 142 insertions(+), 246 deletions(-) diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index 4712d02c..9a1b9e52 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -96,7 +96,7 @@ Future main() async { [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown], ); - if (Platform.isAndroid && isLargeScreen()) { + if (Platform.isAndroid && isLargeScreen) { SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( statusBarColor: Colors.transparent, @@ -108,7 +108,7 @@ Future main() async { ); } - if (isSmallScreen()) { + if (isSmallScreen) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); } } diff --git a/src/ui/flutter_app/lib/screens/about_page.dart b/src/ui/flutter_app/lib/screens/about_page.dart index 905f6c65..8b2ad500 100644 --- a/src/ui/flutter_app/lib/screens/about_page.dart +++ b/src/ui/flutter_app/lib/screens/about_page.dart @@ -34,7 +34,6 @@ import 'list_item_divider.dart'; import 'oss_license_page.dart'; class AboutPage extends StatelessWidget { - // String _version = ""; final String tag = "[about] "; String get mode { diff --git a/src/ui/flutter_app/lib/screens/game_page.dart b/src/ui/flutter_app/lib/screens/game_page.dart index eb6ced0c..3151c60e 100644 --- a/src/ui/flutter_app/lib/screens/game_page.dart +++ b/src/ui/flutter_app/lib/screens/game_page.dart @@ -49,12 +49,9 @@ import 'game_settings_page.dart'; double boardWidth = 0.0; class GamePage extends StatefulWidget { - static double boardMargin = AppTheme.boardMargin; - static double screenPaddingH = AppTheme.boardScreenPaddingH; - final EngineType engineType; - const GamePage(this.engineType); + const GamePage(this.engineType, {Key? key}) : super(key: key); @override _GamePageState createState() => _GamePageState(); @@ -64,6 +61,9 @@ class _GamePageState extends State with RouteAware, SingleTickerProviderStateMixin { final Engine _engine = NativeEngine(); + double screenPaddingH = AppTheme.boardScreenPaddingH; + final double boardMargin = AppTheme.boardMargin; + String? _tip = ''; bool isReady = false; bool isGoingToHistory = false; @@ -77,26 +77,9 @@ class _GamePageState extends State late AnimationController _animationController; late Animation animation; bool disposed = false; - bool ltr = true; + late final bool ltr; final String tag = "[game_page]"; - @override - void initState() { - debugPrint("$tag Engine type: ${widget.engineType}"); - - gameInstance.setWhoIsAi(widget.engineType); - - super.initState(); - gameInstance.init(); - _engine.startup(); - - timer = Timer.periodic(const Duration(microseconds: 100), (Timer t) { - _setReadyState(); - }); - - _initAnimation(); - } - Future _setReadyState() async { debugPrint("$tag Check if need to set Ready state..."); if (!isReady && mounted && Config.settingsLoaded) { @@ -124,9 +107,7 @@ class _GamePageState extends State begin: 1.27, // sqrt(1.618) = 1.272 end: 1.0, ).animate(_animationController) - ..addListener(() { - setState(() {}); - }); + ..addListener(() => setState(() {})); _animationController.addStatusListener((state) { if (state == AnimationStatus.completed || @@ -904,6 +885,44 @@ class _GamePageState extends State } void onMoveButtonPressed() { + final List _historyNavigation = [ + SimpleDialogOption( + onPressed: onTakeBackButtonPressed, + child: Text( + S.of(context).takeBack, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onStepForwardButtonPressed, + child: Text( + S.of(context).stepForward, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onTakeBackAllButtonPressed, + child: Text( + S.of(context).takeBackAll, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + onPressed: onStepForwardAllButtonPressed, + child: Text( + S.of(context).stepForwardAll, + style: AppTheme.simpleDialogOptionTextStyle, + textAlign: TextAlign.center, + ), + ), + const SizedBox(height: AppTheme.sizedBoxHeight), + ]; showModalBottomSheet( context: context, backgroundColor: Colors.transparent, @@ -912,50 +931,7 @@ class _GamePageState extends State child: SimpleDialog( backgroundColor: Colors.transparent, children: [ - if (!Config.isHistoryNavigationToolbarShown) - SimpleDialogOption( - onPressed: onTakeBackButtonPressed, - child: Text( - S.of(context).takeBack, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - ), - if (!Config.isHistoryNavigationToolbarShown) - const SizedBox(height: AppTheme.sizedBoxHeight), - if (!Config.isHistoryNavigationToolbarShown) - SimpleDialogOption( - onPressed: onStepForwardButtonPressed, - child: Text( - S.of(context).stepForward, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - ), - if (!Config.isHistoryNavigationToolbarShown) - const SizedBox(height: AppTheme.sizedBoxHeight), - if (!Config.isHistoryNavigationToolbarShown) - SimpleDialogOption( - onPressed: onTakeBackAllButtonPressed, - child: Text( - S.of(context).takeBackAll, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - ), - if (!Config.isHistoryNavigationToolbarShown) - const SizedBox(height: AppTheme.sizedBoxHeight), - if (!Config.isHistoryNavigationToolbarShown) - SimpleDialogOption( - onPressed: onStepForwardAllButtonPressed, - child: Text( - S.of(context).stepForwardAll, - style: AppTheme.simpleDialogOptionTextStyle, - textAlign: TextAlign.center, - ), - ), - if (!Config.isHistoryNavigationToolbarShown) - const SizedBox(height: AppTheme.sizedBoxHeight), + if (!Config.isHistoryNavigationToolbarShown) ..._historyNavigation, SimpleDialogOption( onPressed: onMoveListButtonPressed, child: Text( @@ -1430,21 +1406,23 @@ class _GamePageState extends State } } - void calcScreenPaddingH() { + double get _screenPaddingH { // // when screen's height/width rate is less than 16/9, limit width of board final windowSize = MediaQuery.of(context).size; final double height = windowSize.height; double width = windowSize.width; + // TODO: maybe use windowSize.aspectratio if (height / width < 16.0 / 9.0) { width = height * 9 / 16; - GamePage.screenPaddingH = - (windowSize.width - width) / 2 - AppTheme.boardMargin; + return (windowSize.width - width) / 2 - AppTheme.boardMargin; + } else { + return AppTheme.boardScreenPaddingH; } } - Widget createPageHeader() { + Widget get header { final Map engineTypeToIconLeft = { EngineType.humanVsAi: Config.aiMovesFirst ? FluentIcons.bot_24_filled @@ -1467,17 +1445,14 @@ class _GamePageState extends State EngineType.testViaLAN: FluentIcons.wifi_1_24_filled, }; - final IconData iconArrow = getIconArrow(); - final iconColor = Color(Config.messageColor); final iconRow = Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - const Expanded(child: SizedBox()), Icon(engineTypeToIconLeft[widget.engineType], color: iconColor), Icon(iconArrow, color: iconColor), Icon(engineTypeToIconRight[widget.engineType], color: iconColor), - const Expanded(child: SizedBox()), ], ); @@ -1511,7 +1486,7 @@ class _GamePageState extends State ); } - IconData getIconArrow() { + IconData get iconArrow { IconData iconArrow = FluentIcons.code_24_regular; if (gameInstance.position.phase == Phase.gameOver) { @@ -1547,15 +1522,11 @@ class _GamePageState extends State return iconArrow; } - Widget createBoard() { - boardWidth = - MediaQuery.of(context).size.width - GamePage.screenPaddingH * 2; + Widget get board { + boardWidth = MediaQuery.of(context).size.width - screenPaddingH * 2; return Container( - margin: EdgeInsets.symmetric( - horizontal: GamePage.screenPaddingH, - vertical: GamePage.boardMargin, - ), + margin: EdgeInsets.symmetric(vertical: boardMargin), child: Board( width: boardWidth, onBoardTap: onBoardTap, @@ -1630,7 +1601,7 @@ class _GamePageState extends State return ret; } - Widget createToolbar() { + Widget get toolbar { final gameButton = TextButton( onPressed: onGameButtonPressed, child: Column( @@ -1704,94 +1675,70 @@ class _GamePageState extends State borderRadius: BorderRadius.circular(5), color: Color(Config.mainToolbarBackgroundColor), ), - margin: EdgeInsets.symmetric(horizontal: GamePage.screenPaddingH), + margin: EdgeInsets.symmetric(horizontal: screenPaddingH), padding: const EdgeInsets.symmetric(vertical: 2), child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, textDirection: TextDirection.ltr, children: [ - const Expanded(child: SizedBox()), gameButton, - const Expanded(child: SizedBox()), optionsButton, - const Expanded(child: SizedBox()), moveButton, - const Expanded(child: SizedBox()), //dashboard_outlined infoButton, - const Expanded(child: SizedBox()), ], ), ); } - Widget createHistoryNavigationToolbar() { + Widget get historyNavToolbar { final takeBackAllButton = TextButton( - child: Column( - // Replace with a Row for horizontal icon + text - children: [ - Semantics( - label: S.of(context).takeBackAll, - child: Icon( - ltr - ? FluentIcons.arrow_previous_24_regular - : FluentIcons.arrow_next_24_regular, - color: Color(Config.navigationToolbarIconColor), - ), - ), - ], + child: Semantics( + label: S.of(context).takeBackAll, + child: Icon( + ltr + ? FluentIcons.arrow_previous_24_regular + : FluentIcons.arrow_next_24_regular, + color: Color(Config.navigationToolbarIconColor), + ), ), onPressed: () => onTakeBackAllButtonPressed(pop: false), ); final takeBackButton = TextButton( - child: Column( - // Replace with a Row for horizontal icon + text - children: [ - Semantics( - label: S.of(context).takeBack, - child: Icon( - ltr - ? FluentIcons.chevron_left_24_regular - : FluentIcons.chevron_right_24_regular, - color: Color(Config.navigationToolbarIconColor), - ), - ), - ], + child: Semantics( + label: S.of(context).takeBack, + child: Icon( + ltr + ? FluentIcons.chevron_left_24_regular + : FluentIcons.chevron_right_24_regular, + color: Color(Config.navigationToolbarIconColor), + ), ), onPressed: () => onTakeBackButtonPressed(pop: false), ); final stepForwardButton = TextButton( - child: Column( - // Replace with a Row for horizontal icon + text - children: [ - Semantics( - label: S.of(context).stepForward, - child: Icon( - ltr - ? FluentIcons.chevron_right_24_regular - : FluentIcons.chevron_left_24_regular, - color: Color(Config.navigationToolbarIconColor), - ), - ), - ], + child: Semantics( + label: S.of(context).stepForward, + child: Icon( + ltr + ? FluentIcons.chevron_right_24_regular + : FluentIcons.chevron_left_24_regular, + color: Color(Config.navigationToolbarIconColor), + ), ), onPressed: () => onStepForwardButtonPressed(pop: false), ); final stepForwardAllButton = TextButton( - child: Column( - // Replace with a Row for horizontal icon + text - children: [ - Semantics( - label: S.of(context).stepForwardAll, - child: Icon( - ltr - ? FluentIcons.arrow_next_24_regular - : FluentIcons.arrow_previous_24_regular, - color: Color(Config.navigationToolbarIconColor), - ), - ), - ], + child: Semantics( + label: S.of(context).stepForwardAll, + child: Icon( + ltr + ? FluentIcons.arrow_next_24_regular + : FluentIcons.arrow_previous_24_regular, + color: Color(Config.navigationToolbarIconColor), + ), ), onPressed: () => onStepForwardAllButtonPressed(pop: false), ); @@ -1801,25 +1748,41 @@ class _GamePageState extends State borderRadius: BorderRadius.circular(5), color: Color(Config.navigationToolbarBackgroundColor), ), - margin: EdgeInsets.symmetric(horizontal: GamePage.screenPaddingH), + margin: EdgeInsets.symmetric( + horizontal: screenPaddingH, + vertical: 1, + ), padding: const EdgeInsets.symmetric(vertical: 2), child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, textDirection: TextDirection.ltr, children: [ - const Expanded(child: SizedBox()), takeBackAllButton, - const Expanded(child: SizedBox()), takeBackButton, - const Expanded(child: SizedBox()), stepForwardButton, - const Expanded(child: SizedBox()), //dashboard_outlined stepForwardAllButton, - const Expanded(child: SizedBox()), ], ), ); } + @override + void initState() { + debugPrint("$tag Engine type: ${widget.engineType}"); + + gameInstance.setWhoIsAi(widget.engineType); + + super.initState(); + gameInstance.init(); + _engine.startup(); + + timer = Timer.periodic(const Duration(microseconds: 100), (Timer t) { + _setReadyState(); + }); + + _initAnimation(); + } + @override void didChangeDependencies() { super.didChangeDependencies(); @@ -1827,23 +1790,16 @@ class _GamePageState extends State this, ModalRoute.of(context)! as PageRoute, ); + screenPaddingH = _screenPaddingH; + ltr = getBidirectionality(context) == Bidirectionality.leftToRight; } @override Widget build(BuildContext context) { - ltr = getBidirectionality(context) == Bidirectionality.leftToRight; - if (_tip == '') { _tip = S.of(context).welcome; } - calcScreenPaddingH(); - - final header = createPageHeader(); - final board = createBoard(); - final toolbar = createToolbar(); - final historyNavToolbar = createHistoryNavigationToolbar(); - return Scaffold( backgroundColor: Color(Config.darkBackgroundColor), body: Column( diff --git a/src/ui/flutter_app/lib/screens/game_settings_page.dart b/src/ui/flutter_app/lib/screens/game_settings_page.dart index 0092b4e2..b78aaa09 100644 --- a/src/ui/flutter_app/lib/screens/game_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/game_settings_page.dart @@ -194,10 +194,8 @@ class _GameSettingsPageState extends State { return [ Text(S.of(context).whoMovesFirst, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: !Config.aiMovesFirst, onChanged: setWhoMovesFirst, titleString: @@ -208,7 +206,6 @@ class _GameSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).difficulty, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsListTile( titleString: S.of(context).skillLevel, @@ -224,7 +221,6 @@ class _GameSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).aisPlayStyle, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsListTile( titleString: S.of(context).algorithm, @@ -232,66 +228,50 @@ class _GameSettingsPageState extends State { onTap: setAlgorithm, ), SettingsSwitchListTile( - context: context, value: Config.drawOnHumanExperience, onChanged: setDrawOnHumanExperience, titleString: S.of(context).drawOnHumanExperience, ), SettingsSwitchListTile( - context: context, value: Config.considerMobility, onChanged: setConsiderMobility, titleString: S.of(context).considerMobility, ), SettingsSwitchListTile( - context: context, value: Config.aiIsLazy, onChanged: setAiIsLazy, titleString: S.of(context).passive, ), SettingsSwitchListTile( - context: context, value: Config.shufflingEnabled, onChanged: setShufflingEnabled, titleString: S.of(context).shufflingEnabled, ), ], ), + if (!Platform.isWindows) const SizedBox(height: AppTheme.sizedBoxHeight), if (!Platform.isWindows) - const SizedBox(height: AppTheme.sizedBoxHeight) - else - const SizedBox(height: 0.0, width: 0.0), - if (!Platform.isWindows) - Text(S.of(context).playSounds, style: AppTheme.settingsHeaderStyle) - else - const SizedBox(height: 0.0, width: 0.0), + Text(S.of(context).playSounds, style: AppTheme.settingsHeaderStyle), if (!Platform.isWindows) SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: Config.toneEnabled, onChanged: setTone, titleString: S.of(context).playSoundsInTheGame, ), SettingsSwitchListTile( - context: context, value: Config.keepMuteWhenTakingBack, onChanged: setKeepMuteWhenTakingBack, titleString: S.of(context).keepMuteWhenTakingBack, ), ], - ) - else - const SizedBox(height: 0.0, width: 0.0), + ), const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).accessibility, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: Config.screenReaderSupport, onChanged: setScreenReaderSupport, titleString: S.of(context).screenReaderSupport, @@ -301,7 +281,6 @@ class _GameSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).restore, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsListTile( titleString: S.of(context).restoreDefaultSettings, @@ -317,22 +296,18 @@ class _GameSettingsPageState extends State { ), if (Developer.developerModeEnabled) SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: Config.developerMode, onChanged: setDeveloperMode, titleString: S.of(context).developerMode, ), SettingsSwitchListTile( - context: context, value: Config.experimentsEnabled, onChanged: setExperimentsEnabled, titleString: S.of(context).experiments, ), SettingsSwitchListTile( - context: context, value: Config.isAutoRestart, onChanged: setIsAutoRestart, titleString: S.of(context).isAutoRestart, diff --git a/src/ui/flutter_app/lib/screens/help_screen.dart b/src/ui/flutter_app/lib/screens/help_screen.dart index 0130e7ee..de170302 100644 --- a/src/ui/flutter_app/lib/screens/help_screen.dart +++ b/src/ui/flutter_app/lib/screens/help_screen.dart @@ -8,12 +8,12 @@ class HelpScreen extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( + elevation: 0.0, + backgroundColor: Color(Config.darkBackgroundColor), centerTitle: true, title: Text( S.of(context).howToPlay, style: TextStyle( - fontSize: Config.fontSize + 4, - fontWeight: FontWeight.bold, color: AppTheme.helpTextColor, ), ), diff --git a/src/ui/flutter_app/lib/screens/home_drawer.dart b/src/ui/flutter_app/lib/screens/home_drawer.dart index 4c3fecdf..347b9f8e 100644 --- a/src/ui/flutter_app/lib/screens/home_drawer.dart +++ b/src/ui/flutter_app/lib/screens/home_drawer.dart @@ -186,7 +186,7 @@ class HomeDrawer extends StatelessWidget { children: [ animatedBuilder, Padding( - padding: EdgeInsets.only(top: isLargeScreen() ? 30 : 8, left: 4), + padding: EdgeInsets.only(top: isLargeScreen ? 30 : 8, left: 4), child: ExcludeSemantics(child: animatedTextKit), ), ], @@ -269,7 +269,7 @@ class HomeDrawer extends StatelessWidget { 0.0, ), child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), + padding: const EdgeInsets.symmetric(horizontal: 8), child: Container( width: MediaQuery.of(context).size.width * 0.75 - 64, height: 46, @@ -298,7 +298,7 @@ class HomeDrawer extends StatelessWidget { final stack = Stack( children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), + padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Row( children: [ const SizedBox(height: 46.0, width: 6.0), @@ -326,7 +326,7 @@ class HomeDrawer extends StatelessWidget { ], ), ), - if (screenIndex == listItem.index) animatedBuilder else const SizedBox() + if (screenIndex == listItem.index) animatedBuilder, ], ); @@ -336,9 +336,7 @@ class HomeDrawer extends StatelessWidget { child: InkWell( splashColor: AppTheme.drawerSplashColor, highlightColor: AppTheme.drawerHighlightColor, - onTap: () { - navigationToScreen(listItem.index); - }, + onTap: () => navigationToScreen(listItem.index), child: stack, ), ); diff --git a/src/ui/flutter_app/lib/screens/list_item_divider.dart b/src/ui/flutter_app/lib/screens/list_item_divider.dart index 3b80df82..55a22ff5 100644 --- a/src/ui/flutter_app/lib/screens/list_item_divider.dart +++ b/src/ui/flutter_app/lib/screens/list_item_divider.dart @@ -29,6 +29,7 @@ class ListItemDivider extends StatelessWidget { return Divider( indent: 16, endIndent: 16, + height: 1.0, thickness: 1.0, color: AppTheme.listItemDividerColor, ); diff --git a/src/ui/flutter_app/lib/screens/personalization_settings_page.dart b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart index b5e289a9..330df6ec 100644 --- a/src/ui/flutter_app/lib/screens/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart @@ -387,7 +387,6 @@ class _PersonalizationSettingsPageState return [ Text(S.of(context).display, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsListTile( titleString: S.of(context).language, @@ -398,19 +397,16 @@ class _PersonalizationSettingsPageState onTap: () => setLanguage(context, langCallback), ), SettingsSwitchListTile( - context: context, value: Config.isPieceCountInHandShown, onChanged: setIsPieceCountInHandShown, titleString: S.of(context).isPieceCountInHandShown, ), SettingsSwitchListTile( - context: context, value: Config.isNotationsShown, onChanged: setIsNotationsShown, titleString: S.of(context).isNotationsShown, ), SettingsSwitchListTile( - context: context, value: Config.isHistoryNavigationToolbarShown, onChanged: setIsHistoryNavigationToolbarShown, titleString: S.of(context).isHistoryNavigationToolbarShown, @@ -440,7 +436,6 @@ class _PersonalizationSettingsPageState onTap: setAnimationDuration, ), SettingsSwitchListTile( - context: context, value: Config.standardNotationEnabled, onChanged: setStandardNotationEnabled, titleString: S.of(context).standardNotation, @@ -450,7 +445,6 @@ class _PersonalizationSettingsPageState const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).color, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsListTile( titleString: S.of(context).boardColor, diff --git a/src/ui/flutter_app/lib/screens/rule_settings_page.dart b/src/ui/flutter_app/lib/screens/rule_settings_page.dart index 05e25d10..ec2589c2 100644 --- a/src/ui/flutter_app/lib/screens/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/rule_settings_page.dart @@ -54,7 +54,6 @@ class _RuleSettingsPageState extends State { return [ Text(S.of(context).general, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsListTile( titleString: S.of(context).piecesCount, @@ -63,7 +62,6 @@ class _RuleSettingsPageState extends State { onTap: setNTotalPiecesEachSide, ), SettingsSwitchListTile( - context: context, value: Config.hasDiagonalLines, onChanged: setHasDiagonalLines, titleString: S.of(context).hasDiagonalLines, @@ -82,7 +80,6 @@ class _RuleSettingsPageState extends State { onTap: setEndgameNMoveRule, ), SettingsSwitchListTile( - context: context, value: Config.threefoldRepetitionRule, onChanged: setThreefoldRepetitionRule, titleString: S.of(context).threefoldRepetitionRule, @@ -93,17 +90,14 @@ class _RuleSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).placing, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: Config.hasBannedLocations, onChanged: setHasBannedLocations, titleString: S.of(context).hasBannedLocations, subtitleString: S.of(context).hasBannedLocations_Detail, ), SettingsSwitchListTile( - context: context, value: Config.isWhiteLoseButNotDrawWhenBoardFull, onChanged: setIsWhiteLoseButNotDrawWhenBoardFull, titleString: S.of(context).isWhiteLoseButNotDrawWhenBoardFull, @@ -111,7 +105,6 @@ class _RuleSettingsPageState extends State { S.of(context).isWhiteLoseButNotDrawWhenBoardFull_Detail, ), SettingsSwitchListTile( - context: context, value: Config.mayOnlyRemoveUnplacedPieceInPlacingPhase, onChanged: setMayOnlyRemoveUnplacedPieceInPlacingPhase, titleString: S.of(context).removeUnplacedPiece, @@ -122,11 +115,9 @@ class _RuleSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).moving, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ if (Config.experimentsEnabled) SettingsSwitchListTile( - context: context, value: Config.mayMoveInPlacingPhase, onChanged: setMayMoveInPlacingPhase, titleString: S.of(context).mayMoveInPlacingPhase, @@ -134,14 +125,12 @@ class _RuleSettingsPageState extends State { ) else SettingsSwitchListTile( - context: context, value: Config.isDefenderMoveFirst, onChanged: setIsDefenderMoveFirst, titleString: S.of(context).isDefenderMoveFirst, subtitleString: S.of(context).isDefenderMoveFirst_Detail, ), SettingsSwitchListTile( - context: context, value: Config.isLoseButNotChangeSideWhenNoWay, onChanged: setIsLoseButNotChangeSideWhenNoWay, titleString: S.of(context).isLoseButNotChangeSideWhenNoWay, @@ -153,10 +142,8 @@ class _RuleSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).mayFly, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: Config.mayFly, onChanged: setAllowFlyingAllowed, titleString: S.of(context).mayFly, @@ -173,17 +160,14 @@ class _RuleSettingsPageState extends State { const SizedBox(height: AppTheme.sizedBoxHeight), Text(S.of(context).removing, style: AppTheme.settingsHeaderStyle), SettingsCard( - context: context, children: [ SettingsSwitchListTile( - context: context, value: Config.mayRemoveFromMillsAlways, onChanged: setAllowRemovePieceInMill, titleString: S.of(context).mayRemoveFromMillsAlways, subtitleString: S.of(context).mayRemoveFromMillsAlways_Detail, ), SettingsSwitchListTile( - context: context, value: Config.mayRemoveMultiple, onChanged: setAllowRemoveMultiPiecesWhenCloseMultiMill, titleString: S.of(context).mayRemoveMultiple, diff --git a/src/ui/flutter_app/lib/screens/settings/settings_card.dart b/src/ui/flutter_app/lib/screens/settings/settings_card.dart index efae523f..0debe7a1 100644 --- a/src/ui/flutter_app/lib/screens/settings/settings_card.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_card.dart @@ -23,11 +23,9 @@ import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsCard extends StatelessWidget { const SettingsCard({ Key? key, - required this.context, required this.children, }) : super(key: key); - final BuildContext context; final List children; @override diff --git a/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart b/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart index acc419db..cf1d2c11 100644 --- a/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart @@ -63,9 +63,7 @@ class SettingsListTile extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Text( - trailingColor == null - ? (trailingString == null ? "" : trailingString!) - : trailingColor!.toRadixString(16), + trailingColor?.toRadixString(16) ?? trailingString ?? '', style: TextStyle( fontSize: Config.fontSize, backgroundColor: diff --git a/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart b/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart index 34afbbcd..f4e58750 100644 --- a/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart +++ b/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart @@ -23,14 +23,12 @@ import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsSwitchListTile extends StatelessWidget { const SettingsSwitchListTile({ Key? key, - required this.context, required this.value, required this.onChanged, required this.titleString, this.subtitleString, }) : super(key: key); - final BuildContext context; final bool value; final String titleString; final String? subtitleString; diff --git a/src/ui/flutter_app/lib/shared/common/config.dart b/src/ui/flutter_app/lib/shared/common/config.dart index 437b1038..c5a1b4f6 100644 --- a/src/ui/flutter_app/lib/shared/common/config.dart +++ b/src/ui/flutter_app/lib/shared/common/config.dart @@ -60,7 +60,7 @@ class Config { static double boardInnerLineWidth = 2.0; static double pieceWidth = 0.9; static double fontSize = 16.0; - static double boardTop = isLargeScreen() ? 75.0 : 36.0; + static double boardTop = isLargeScreen ? 75.0 : 36.0; static double animationDuration = 0.0; // Color @@ -146,14 +146,14 @@ class Config { Config.isHistoryNavigationToolbarShown = settings['IsHistoryNavigationToolbarShown'] as bool? ?? false; Config.boardBorderLineWidth = - settings['BoardBorderLineWidth'] as double? ?? 2; + settings['BoardBorderLineWidth'] as double? ?? 2.0; Config.boardInnerLineWidth = - settings['BoardInnerLineWidth'] as double? ?? 2; + settings['BoardInnerLineWidth'] as double? ?? 2.0; Config.pieceWidth = settings['PieceWidth'] as double? ?? 0.9; Config.fontSize = settings['FontSize'] as double? ?? 16.0; Config.boardTop = - settings['BoardTop'] as double? ?? (isLargeScreen() ? 75 : 36); - Config.animationDuration = settings['AnimationDuration'] as double? ?? 0; + settings['BoardTop'] as double? ?? (isLargeScreen ? 75.0 : 36.0); + Config.animationDuration = settings['AnimationDuration'] as double? ?? 0.0; // Color Config.boardLineColor = diff --git a/src/ui/flutter_app/lib/shared/common/constants.dart b/src/ui/flutter_app/lib/shared/common/constants.dart index 5f094e5a..5b1ef46a 100644 --- a/src/ui/flutter_app/lib/shared/common/constants.dart +++ b/src/ui/flutter_app/lib/shared/common/constants.dart @@ -78,10 +78,6 @@ class Constants { static final windowAspectRatio = windowHeight / windowWidth; } -bool isSmallScreen() { - return Constants.windowHeight <= 800; -} +bool get isSmallScreen => Constants.windowHeight <= 800; -bool isLargeScreen() { - return !isSmallScreen(); -} +bool get isLargeScreen => !isSmallScreen; diff --git a/src/ui/flutter_app/lib/shared/dialog.dart b/src/ui/flutter_app/lib/shared/dialog.dart index 9380567a..cb7b8c7a 100644 --- a/src/ui/flutter_app/lib/shared/dialog.dart +++ b/src/ui/flutter_app/lib/shared/dialog.dart @@ -189,9 +189,7 @@ Future showPrivacyDialog( setPrivacyPolicyAccepted(false); SystemChannels.platform.invokeMethod('SystemNavigator.pop'); }, - ) - else - const SizedBox(height: 0.0, width: 0.0), + ), ], ), ); diff --git a/src/ui/flutter_app/lib/shared/theme/app_theme.dart b/src/ui/flutter_app/lib/shared/theme/app_theme.dart index 921c3581..990a19dd 100644 --- a/src/ui/flutter_app/lib/shared/theme/app_theme.dart +++ b/src/ui/flutter_app/lib/shared/theme/app_theme.dart @@ -4,7 +4,8 @@ import 'package:sanmill/shared/common/constants.dart'; import 'package:sanmill/shared/theme/colors.dart'; class AppTheme { - AppTheme._(); + const AppTheme._(); + // TODO: restructure theming. Some theme Elements should be accessed via Theme.of(context) // Theme data static final lightThemeData = ThemeData( @@ -121,7 +122,7 @@ class AppTheme { color: moveHistoryTextColor, ); - static double boardTop = isLargeScreen() ? 75.0 : 36.0; + static double boardTop = isLargeScreen ? 75.0 : 36.0; static double boardMargin = 10.0; static double boardScreenPaddingH = 10.0; static double boardBorderRadius = 5.0; diff --git a/src/ui/flutter_app/pubspec.yaml b/src/ui/flutter_app/pubspec.yaml index 0e1ded96..ec34c62d 100644 --- a/src/ui/flutter_app/pubspec.yaml +++ b/src/ui/flutter_app/pubspec.yaml @@ -39,7 +39,7 @@ dev_dependencies: flutter_oss_licenses: ^1.0.1 flutter_test: sdk: flutter - lint: ^1.0.0 + lint: ^1.7.2 msix: ^2.1.3 flutter: From 53ddb55b046490adfa99fde33d766fbddef4a66a Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:47:59 +0200 Subject: [PATCH 10/13] restructure drawer cleanup the drawer code. - fixes the drawer design Home drawer performance improvements As the child doesn't depend on the transformation we shouldn't repaint it => better performance --- .../lib/screens/drawer_user_controller.dart | 87 +++- .../flutter_app/lib/screens/home_drawer.dart | 450 ++++++++---------- .../lib/screens/navigation_home_screen.dart | 14 +- 3 files changed, 261 insertions(+), 290 deletions(-) diff --git a/src/ui/flutter_app/lib/screens/drawer_user_controller.dart b/src/ui/flutter_app/lib/screens/drawer_user_controller.dart index b5052125..d19f387e 100644 --- a/src/ui/flutter_app/lib/screens/drawer_user_controller.dart +++ b/src/ui/flutter_app/lib/screens/drawer_user_controller.dart @@ -16,6 +16,7 @@ along with this program. If not, see . */ +import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; @@ -27,21 +28,21 @@ class DrawerUserController extends StatefulWidget { const DrawerUserController({ Key? key, this.drawerWidth = AppTheme.drawerWidth, - this.onDrawerCall, - this.screenView, + required this.onDrawerCall, + required this.screenView, this.animatedIconData = AnimatedIcons.arrow_menu, this.menuView, this.drawerIsOpen, - this.screenIndex, + required this.screenIndex, }) : super(key: key); final double drawerWidth; - final Function(DrawerIndex)? onDrawerCall; - final Widget? screenView; + final Function(DrawerIndex) onDrawerCall; + final Widget screenView; final Function(bool)? drawerIsOpen; final AnimatedIconData animatedIconData; final Widget? menuView; - final DrawerIndex? screenIndex; + final DrawerIndex screenIndex; @override _DrawerUserControllerState createState() => _DrawerUserControllerState(); @@ -58,7 +59,7 @@ class _DrawerUserControllerState extends State @override void initState() { animationController = AnimationController( - duration: const Duration(milliseconds: 2000), + duration: const Duration(seconds: 2), vsync: this, ); @@ -89,8 +90,7 @@ class _DrawerUserControllerState extends State duration: Duration.zero, curve: Curves.fastOutSlowIn, ); - } else if (scrollController.offset > 0 && - scrollController.offset < widget.drawerWidth.floor()) { + } else if (scrollController.offset < widget.drawerWidth.floor()) { iconAnimationController.animateTo( (scrollController.offset * 100 / (widget.drawerWidth)) / 100, duration: Duration.zero, @@ -150,6 +150,54 @@ class _DrawerUserControllerState extends State }, ); + final List drawerItems = [ + DrawerListItem( + index: DrawerIndex.humanVsAi, + title: S.of(context).humanVsAi, + icon: const Icon(FluentIcons.person_24_regular), + ), + DrawerListItem( + index: DrawerIndex.humanVsHuman, + title: S.of(context).humanVsHuman, + icon: const Icon(FluentIcons.people_24_regular), + ), + DrawerListItem( + index: DrawerIndex.aiVsAi, + title: S.of(context).aiVsAi, + icon: const Icon(FluentIcons.bot_24_regular), + ), + DrawerListItem( + index: DrawerIndex.preferences, + title: S.of(context).preferences, + icon: const Icon(FluentIcons.options_24_regular), + ), + DrawerListItem( + index: DrawerIndex.ruleSettings, + title: S.of(context).ruleSettings, + icon: const Icon(FluentIcons.task_list_ltr_24_regular), + ), + DrawerListItem( + index: DrawerIndex.personalization, + title: S.of(context).personalization, + icon: const Icon(FluentIcons.design_ideas_24_regular), + ), + DrawerListItem( + index: DrawerIndex.feedback, + title: S.of(context).feedback, + icon: const Icon(FluentIcons.chat_warning_24_regular), + ), + DrawerListItem( + index: DrawerIndex.Help, + title: S.of(context).help, + icon: const Icon(FluentIcons.question_circle_24_regular), + ), + DrawerListItem( + index: DrawerIndex.About, + title: S.of(context).about, + icon: const Icon(FluentIcons.info_24_regular), + ), + ]; + final animatedBuilder = AnimatedBuilder( animation: iconAnimationController, builder: (BuildContext context, Widget? child) { @@ -159,14 +207,15 @@ class _DrawerUserControllerState extends State transform: Matrix4.translationValues(scrollController.offset, 0.0, 0.0), child: HomeDrawer( - screenIndex: widget.screenIndex ?? DrawerIndex.humanVsAi, + screenIndex: widget.screenIndex, iconAnimationController: iconAnimationController, - callBackIndex: (DrawerIndex? indexType) { + callBackIndex: (DrawerIndex indexType) { onDrawerClick(); try { - widget.onDrawerCall!(indexType!); + widget.onDrawerCall(indexType); } catch (_) {} }, + items: drawerItems, ), ); }, @@ -192,17 +241,15 @@ class _DrawerUserControllerState extends State // tap on a few home screen area and close the drawer if (scrollOffset == 1.0) InkWell( - onTap: () { - onDrawerClick(); - }, + onTap: onDrawerClick, ), Padding( padding: EdgeInsets.only( top: MediaQuery.of(context).padding.top + tapOffset, ), child: SizedBox( - width: AppBar().preferredSize.height, - height: AppBar().preferredSize.height, + width: kToolbarHeight, + height: kToolbarHeight, child: Material( color: Colors.transparent, child: inkWell, @@ -242,9 +289,9 @@ class _DrawerUserControllerState extends State ], ); - return Scaffold( - backgroundColor: Color(Config.drawerColor), - body: SingleChildScrollView( + return Material( + color: Color(Config.drawerColor), + child: SingleChildScrollView( controller: scrollController, scrollDirection: Axis.horizontal, physics: const PageScrollPhysics(parent: ClampingScrollPhysics()), diff --git a/src/ui/flutter_app/lib/screens/home_drawer.dart b/src/ui/flutter_app/lib/screens/home_drawer.dart index 347b9f8e..4c38bc3b 100644 --- a/src/ui/flutter_app/lib/screens/home_drawer.dart +++ b/src/ui/flutter_app/lib/screens/home_drawer.dart @@ -19,7 +19,6 @@ import 'dart:async'; import 'package:animated_text_kit/animated_text_kit.dart'; -import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; @@ -41,104 +40,158 @@ enum DrawerIndex { } class DrawerListItem { - DrawerListItem({this.index, this.title = '', this.icon}); + const DrawerListItem({ + required this.index, + required this.title, + required this.icon, + }); - DrawerIndex? index; - String title; - Icon? icon; + final DrawerIndex index; + final String title; + final Icon icon; } class HomeDrawer extends StatelessWidget { const HomeDrawer({ Key? key, - this.screenIndex, - this.iconAnimationController, - this.callBackIndex, + required this.screenIndex, + required this.iconAnimationController, + required this.callBackIndex, + required this.items, }) : super(key: key); - final AnimationController? iconAnimationController; - final DrawerIndex? screenIndex; - final Function(DrawerIndex?)? callBackIndex; + final AnimationController iconAnimationController; + final DrawerIndex screenIndex; + final Function(DrawerIndex) callBackIndex; + final List items; + + @override + Widget build(BuildContext context) { + return Material( + color: Color(Config.drawerBackgroundColor), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _DrawerHeader( + iconAnimationController: iconAnimationController, + ), + Divider(height: 1, color: AppTheme.drawerDividerColor), + ListView.builder( + padding: const EdgeInsets.only(top: 4.0), + physics: const BouncingScrollPhysics(), + shrinkWrap: true, + itemCount: items.length, + itemBuilder: _buildChildren, + ), + //drawFooter, + ], + ), + ); + } + + Future navigationToScreen(DrawerIndex index) async { + callBackIndex(index); + } + + Widget _buildChildren(BuildContext context, int index) { + final listItem = items[index]; + final bool isSelected = screenIndex == listItem.index; + + final bool ltr = + getBidirectionality(context) == Bidirectionality.leftToRight; + const double radius = 28.0; + final animatedBuilder = AnimatedBuilder( + animation: iconAnimationController, + builder: (BuildContext context, Widget? child) { + return Transform( + transform: Matrix4.translationValues( + (MediaQuery.of(context).size.width * 0.75 - 64) * + (1.0 - iconAnimationController.value - 1.0), + 0.0, + 0.0, + ), + child: child, + ); + }, + child: Container( + width: MediaQuery.of(context).size.width * 0.75 - 64, + height: 46, + decoration: BoxDecoration( + color: Color(Config.drawerHighlightItemColor), + borderRadius: BorderRadius.only( + topLeft: Radius.circular(ltr ? 0 : radius), + topRight: Radius.circular(ltr ? radius : 0), + bottomLeft: Radius.circular(ltr ? 0 : radius), + bottomRight: Radius.circular(ltr ? radius : 0), + ), + ), + ), + ); + + final listItemIcon = Icon( + listItem.icon.icon, + color: isSelected + ? Color(Config.drawerTextColor) // TODO: drawerHighlightTextColor + : Color(Config.drawerTextColor), + ); + + final child = Row( + children: [ + const SizedBox(height: 46.0, width: 6.0), + const Padding( + padding: EdgeInsets.all(4.0), + ), + listItemIcon, + const Padding( + padding: EdgeInsets.all(4.0), + ), + Text( + listItem.title, + style: TextStyle( + fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500, + fontSize: Config.fontSize, + color: isSelected + ? Color( + Config.drawerTextColor, + ) // TODO: drawerHighlightTextColor + : Color(Config.drawerTextColor), + ), + ), + ], + ); + + return InkWell( + splashColor: AppTheme.drawerSplashColor, + highlightColor: AppTheme.drawerHighlightColor, + onTap: () => navigationToScreen(listItem.index), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: isSelected + ? Stack( + children: [ + child, + animatedBuilder, + ], + ) + : child, + ), + ); + } +} + +class _DrawerHeader extends StatelessWidget { + const _DrawerHeader({ + Key? key, + required this.iconAnimationController, + }) : super(key: key); + + final AnimationController iconAnimationController; @override Widget build(BuildContext context) { const String tag = "[home_drawer]"; - final List drawerList = [ - DrawerListItem( - index: DrawerIndex.humanVsAi, - title: S.of(context).humanVsAi, - icon: const Icon(FluentIcons.person_24_regular), - ), - DrawerListItem( - index: DrawerIndex.humanVsHuman, - title: S.of(context).humanVsHuman, - icon: const Icon(FluentIcons.people_24_regular), - ), - DrawerListItem( - index: DrawerIndex.aiVsAi, - title: S.of(context).aiVsAi, - icon: const Icon(FluentIcons.bot_24_regular), - ), - DrawerListItem( - index: DrawerIndex.preferences, - title: S.of(context).preferences, - icon: const Icon(FluentIcons.options_24_regular), - ), - DrawerListItem( - index: DrawerIndex.ruleSettings, - title: S.of(context).ruleSettings, - icon: const Icon(FluentIcons.task_list_ltr_24_regular), - ), - DrawerListItem( - index: DrawerIndex.personalization, - title: S.of(context).personalization, - icon: const Icon(FluentIcons.design_ideas_24_regular), - ), - DrawerListItem( - index: DrawerIndex.feedback, - title: S.of(context).feedback, - icon: const Icon(FluentIcons.chat_warning_24_regular), - ), - DrawerListItem( - index: DrawerIndex.Help, - title: S.of(context).help, - icon: const Icon(FluentIcons.question_circle_24_regular), - ), - DrawerListItem( - index: DrawerIndex.About, - title: S.of(context).about, - icon: const Icon(FluentIcons.info_24_regular), - ), - ]; - - final rotationTransition = RotationTransition( - turns: AlwaysStoppedAnimation( - Tween(begin: 0.0, end: 24.0) - .animate( - CurvedAnimation( - parent: iconAnimationController!, - curve: Curves.fastOutSlowIn, - ), - ) - .value / - 360, - ), - ); - - final scaleTransition = ScaleTransition( - scale: AlwaysStoppedAnimation( - 1.0 - (iconAnimationController!.value) * 0.2, - ), - child: rotationTransition, - ); - - final animatedBuilder = AnimatedBuilder( - animation: iconAnimationController!, - builder: (_, __) => scaleTransition, - ); - - final animatedTextsColors = [ + final List animatedTextsColors = [ Color(Config.drawerTextColor), Colors.black, Colors.blue, @@ -149,196 +202,69 @@ class HomeDrawer extends StatelessWidget { Color(Config.drawerHighlightItemColor), ]; - final animatedTextKit = AnimatedTextKit( - animatedTexts: [ - ColorizeAnimatedText( - S.of(context).appName, - textStyle: TextStyle( - fontSize: Config.fontSize + 16, - fontWeight: FontWeight.w600, + final rotationTransition = RotationTransition( + turns: AlwaysStoppedAnimation( + Tween(begin: 0.0, end: 24.0) + .animate( + CurvedAnimation( + parent: iconAnimationController, + curve: Curves.fastOutSlowIn, + ), + ) + .value / + 360, + ), + ); + + final scaleTransition = ScaleTransition( + scale: AlwaysStoppedAnimation( + 1.0 - (iconAnimationController.value) * 0.2, + ), + child: rotationTransition, + ); + + final animatedBuilder = AnimatedBuilder( + animation: iconAnimationController, + builder: (_, __) => scaleTransition, + ); + + final animation = GestureDetector( + child: AnimatedTextKit( + animatedTexts: [ + ColorizeAnimatedText( + S.of(context).appName, + textStyle: TextStyle( + fontSize: Config.fontSize + 16, + fontWeight: FontWeight.w600, + ), + colors: animatedTextsColors, + speed: const Duration(seconds: 3), ), - colors: animatedTextsColors, - speed: const Duration(seconds: 3), - ), - ], - pause: const Duration(milliseconds: 30000), - repeatForever: true, - stopPauseOnTap: true, - onTap: () { - DateTime? lastTapTime; - if (lastTapTime == null || - DateTime.now().difference(lastTapTime) > - const Duration(seconds: 1)) { - lastTapTime = DateTime.now(); - debugPrint("$tag Tap again in one second to enable developer mode."); - } else { - lastTapTime = DateTime.now(); - Developer.developerModeEnabled = true; - debugPrint("$tag Developer mode enabled."); - } + ], + pause: const Duration(seconds: 3), + repeatForever: true, + stopPauseOnTap: true, + onTap: () => debugPrint("$tag DoubleTap to enable developer mode."), + ), + onDoubleTap: () { + Developer.developerModeEnabled = true; + debugPrint("$tag Developer mode enabled."); }, ); - final drawerHeader = Padding( + return Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // TODO: can animatedBuilder be removed? does not appear in the widget tree animatedBuilder, Padding( padding: EdgeInsets.only(top: isLargeScreen ? 30 : 8, left: 4), - child: ExcludeSemantics(child: animatedTextKit), + child: ExcludeSemantics(child: animation), ), ], ), ); - - /* - var exitListTile = ListTile( - title: Text( - S.of(context).exit, - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 16, - color: AppTheme.exitTextColor, - ), - textAlign: TextAlign.left, - ), - trailing: Icon( - FluentIcons.power_24_regular, - color: AppTheme.exitIconColor, - ), - onTap: () async { - if (Config.developerMode) { - return; - } - - await SystemChannels.platform.invokeMethod('SystemNavigator.pop'); - }, - ); - */ - - /* - var drawFooter = Column( - children: [ - exitListTile, - SizedBox(height: MediaQuery.of(context).padding.bottom) - ], - ); - */ - - return Material( - color: Color(Config.drawerBackgroundColor), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - drawerHeader, - const SizedBox(height: 4), - Divider(height: 1, color: AppTheme.drawerDividerColor), - Expanded( - child: ListView.builder( - physics: const BouncingScrollPhysics(), - itemCount: drawerList.length, - itemBuilder: (BuildContext context, int index) => - buildInkwell(context, drawerList[index]), - ), - ), - Divider(height: 1, color: AppTheme.drawerDividerColor), - //drawFooter, - ], - ), - ); - } - - Future navigationToScreen(DrawerIndex? index) async { - callBackIndex!(index); - } - - Widget buildInkwell(BuildContext context, DrawerListItem listItem) { - final bool ltr = - getBidirectionality(context) == Bidirectionality.leftToRight; - const double radius = 28.0; - final animatedBuilder = AnimatedBuilder( - animation: iconAnimationController!, - builder: (BuildContext context, Widget? child) { - return Transform( - transform: Matrix4.translationValues( - (MediaQuery.of(context).size.width * 0.75 - 64) * - (1.0 - iconAnimationController!.value - 1.0), - 0.0, - 0.0, - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 8), - child: Container( - width: MediaQuery.of(context).size.width * 0.75 - 64, - height: 46, - decoration: BoxDecoration( - color: Color(Config.drawerHighlightItemColor), - borderRadius: BorderRadius.only( - topLeft: Radius.circular(ltr ? 0 : radius), - topRight: Radius.circular(ltr ? radius : 0), - bottomLeft: Radius.circular(ltr ? 0 : radius), - bottomRight: Radius.circular(ltr ? radius : 0), - ), - ), - ), - ), - ); - }, - ); - - final listItemIcon = Icon( - listItem.icon!.icon, - color: screenIndex == listItem.index - ? Color(Config.drawerTextColor) // TODO: drawerHighlightTextColor - : Color(Config.drawerTextColor), - ); - - final stack = Stack( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Row( - children: [ - const SizedBox(height: 46.0, width: 6.0), - const Padding( - padding: EdgeInsets.all(4.0), - ), - listItemIcon, - const Padding( - padding: EdgeInsets.all(4.0), - ), - Text( - listItem.title, - style: TextStyle( - fontWeight: screenIndex == listItem.index - ? FontWeight.w700 - : FontWeight.w500, - fontSize: Config.fontSize, - color: screenIndex == listItem.index - ? Color( - Config.drawerTextColor, - ) // TODO: drawerHighlightTextColor - : Color(Config.drawerTextColor), - ), - ), - ], - ), - ), - if (screenIndex == listItem.index) animatedBuilder, - ], - ); - - return Material( - // Semantics: Main menu item - color: Colors.transparent, - child: InkWell( - splashColor: AppTheme.drawerSplashColor, - highlightColor: AppTheme.drawerHighlightColor, - onTap: () => navigationToScreen(listItem.index), - child: stack, - ), - ); } } 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 242225b3..2893be22 100644 --- a/src/ui/flutter_app/lib/screens/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart @@ -45,8 +45,8 @@ class NavigationHomeScreen extends StatefulWidget { } class _NavigationHomeScreenState extends State { - Widget? screenView; - DrawerIndex? drawerIndex; + late Widget screenView; + late DrawerIndex drawerIndex; @override void initState() { @@ -62,11 +62,7 @@ class _NavigationHomeScreenState extends State { child: DrawerUserController( screenIndex: drawerIndex, drawerWidth: MediaQuery.of(context).size.width * 0.75, - onDrawerCall: (DrawerIndex index) { - // callback from drawer for replace screen - // as user need with passing DrawerIndex (Enum index) - changeIndex(index); - }, + onDrawerCall: changeIndex, // we replace screen view as // we need on navigate starting screens screenView: screenView, @@ -74,6 +70,8 @@ class _NavigationHomeScreenState extends State { ); } + /// callback from drawer for replace screen + /// as user need with passing DrawerIndex (Enum index) void changeIndex(DrawerIndex index) { if (drawerIndex == index && drawerIndex != DrawerIndex.feedback) { return; @@ -88,7 +86,7 @@ class _NavigationHomeScreenState extends State { drawerIndex = index; // TODO: use switch case - final engineType = drawerMap[drawerIndex!]; + final engineType = drawerMap[drawerIndex]; setState(() { if (engineType != null) { gameInstance.setWhoIsAi(engineType); From 339af395791d628f36227b1567f8f16e7aa6b9a9 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 11:54:29 +0200 Subject: [PATCH 11/13] Externalize GamePageToolBar widget --- .../screens/{ => game_page}/game_page.dart | 78 +++++++------------ .../screens/game_page/game_page_tool_bar.dart | 44 +++++++++++ .../lib/screens/navigation_home_screen.dart | 10 +-- .../lib/shared/painters/board_painter.dart | 2 +- 4 files changed, 79 insertions(+), 55 deletions(-) rename src/ui/flutter_app/lib/screens/{ => game_page}/game_page.dart (97%) create mode 100644 src/ui/flutter_app/lib/screens/game_page/game_page_tool_bar.dart diff --git a/src/ui/flutter_app/lib/screens/game_page.dart b/src/ui/flutter_app/lib/screens/game_page/game_page.dart similarity index 97% rename from src/ui/flutter_app/lib/screens/game_page.dart rename to src/ui/flutter_app/lib/screens/game_page/game_page.dart index 3151c60e..5c187224 100644 --- a/src/ui/flutter_app/lib/screens/game_page.dart +++ b/src/ui/flutter_app/lib/screens/game_page/game_page.dart @@ -32,19 +32,19 @@ import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/rule.dart'; import 'package:sanmill/mill/types.dart'; +import 'package:sanmill/screens/board.dart'; import 'package:sanmill/screens/game_settings_page.dart'; import 'package:sanmill/services/audios.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/dialog.dart'; +import 'package:sanmill/shared/picker.dart'; +import 'package:sanmill/shared/snack_bar.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; //import 'package:screen_recorder/screen_recorder.dart'; import 'package:stack_trace/stack_trace.dart'; -import '../shared/dialog.dart'; -import '../shared/picker.dart'; -import '../shared/snack_bar.dart'; -import 'board.dart'; -import 'game_settings_page.dart'; +part 'package:sanmill/screens/game_page/game_page_tool_bar.dart'; double boardWidth = 0.0; @@ -1670,23 +1670,13 @@ class _GamePageState extends State ), ); - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Color(Config.mainToolbarBackgroundColor), - ), - margin: EdgeInsets.symmetric(horizontal: screenPaddingH), - padding: const EdgeInsets.symmetric(vertical: 2), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - textDirection: TextDirection.ltr, - children: [ - gameButton, - optionsButton, - moveButton, - infoButton, - ], - ), + return GamePageToolBar( + children: [ + gameButton, + optionsButton, + moveButton, + infoButton, + ], ); } @@ -1743,26 +1733,13 @@ class _GamePageState extends State onPressed: () => onStepForwardAllButtonPressed(pop: false), ); - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), - color: Color(Config.navigationToolbarBackgroundColor), - ), - margin: EdgeInsets.symmetric( - horizontal: screenPaddingH, - vertical: 1, - ), - padding: const EdgeInsets.symmetric(vertical: 2), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - textDirection: TextDirection.ltr, - children: [ - takeBackAllButton, - takeBackButton, - stepForwardButton, - stepForwardAllButton, - ], - ), + return GamePageToolBar( + children: [ + takeBackAllButton, + takeBackButton, + stepForwardButton, + stepForwardAllButton, + ], ); } @@ -1802,13 +1779,16 @@ class _GamePageState extends State return Scaffold( backgroundColor: Color(Config.darkBackgroundColor), - body: Column( - children: [ - BlockSemantics(child: header), - board, - if (Config.isHistoryNavigationToolbarShown) historyNavToolbar, - toolbar, - ], + body: Padding( + padding: EdgeInsets.symmetric(horizontal: screenPaddingH), + child: Column( + children: [ + BlockSemantics(child: header), + board, + if (Config.isHistoryNavigationToolbarShown) historyNavToolbar, + toolbar, + ], + ), ), /* body: Column(children: [ diff --git a/src/ui/flutter_app/lib/screens/game_page/game_page_tool_bar.dart b/src/ui/flutter_app/lib/screens/game_page/game_page_tool_bar.dart new file mode 100644 index 00000000..a65fc4ed --- /dev/null +++ b/src/ui/flutter_app/lib/screens/game_page/game_page_tool_bar.dart @@ -0,0 +1,44 @@ +/* + 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/screens/game_page/game_page.dart'; + +class GamePageToolBar extends StatelessWidget { + final List children; + const GamePageToolBar({ + Key? key, + required this.children, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(5), + color: Color(Config.navigationToolbarBackgroundColor), + ), + margin: const EdgeInsets.symmetric(vertical: 0.5), + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + textDirection: TextDirection.ltr, + children: children, + ), + ); + } +} 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 2893be22..7b0477a7 100644 --- a/src/ui/flutter_app/lib/screens/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart @@ -28,17 +28,17 @@ import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/screens/about_page.dart'; import 'package:sanmill/screens/drawer_user_controller.dart'; +import 'package:sanmill/screens/game_page/game_page.dart'; +import 'package:sanmill/screens/game_settings_page.dart'; import 'package:sanmill/screens/help_screen.dart'; import 'package:sanmill/screens/home_drawer.dart'; +import 'package:sanmill/screens/personalization_settings_page.dart'; +import 'package:sanmill/screens/rule_settings_page.dart'; +import 'package:sanmill/services/engine/engine.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; -import 'game_page.dart'; -import 'game_settings_page.dart'; -import 'personalization_settings_page.dart'; -import 'rule_settings_page.dart'; - class NavigationHomeScreen extends StatefulWidget { @override _NavigationHomeScreenState createState() => _NavigationHomeScreenState(); diff --git a/src/ui/flutter_app/lib/shared/painters/board_painter.dart b/src/ui/flutter_app/lib/shared/painters/board_painter.dart index 90d364c3..a5951f5e 100644 --- a/src/ui/flutter_app/lib/shared/painters/board_painter.dart +++ b/src/ui/flutter_app/lib/shared/painters/board_painter.dart @@ -19,7 +19,7 @@ import 'package:flutter/material.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/screens/game_page.dart'; +import 'package:sanmill/screens/game_page/game_page.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; From 8727dc2a87a45e5f8e0e81563ef17b9d47451103 Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Fri, 8 Oct 2021 19:14:33 +0200 Subject: [PATCH 12/13] restructure - move list_item_divider into lib/shared - move lib/engine into lib/services/engine unify Import style - I've unified the way files are imported. We now use absolute imports everywhere. This is not a must but I find it more usefull. cleanup imports - prefer using part files where needed --- src/ui/flutter_app/lib/l10n/resources.dart | 12 +++++------- src/ui/flutter_app/lib/main.dart | 3 --- src/ui/flutter_app/lib/mill/game.dart | 7 +++---- src/ui/flutter_app/lib/mill/mills.dart | 4 ++-- src/ui/flutter_app/lib/mill/position.dart | 8 +++----- src/ui/flutter_app/lib/mill/recorder.dart | 5 ++--- src/ui/flutter_app/lib/screens/about_page.dart | 9 ++++----- .../lib/screens/{ => game_page}/board.dart | 10 +--------- .../lib/screens/game_page/game_page.dart | 13 ++++++++----- .../lib/screens/game_settings_page.dart | 11 +++++------ src/ui/flutter_app/lib/screens/home_drawer.dart | 11 +---------- .../lib/screens/navigation_home_screen.dart | 12 ++++++++---- .../screens/personalization_settings_page.dart | 6 +++--- .../lib/screens/rule_settings_page.dart | 9 ++++----- .../lib/{ => services}/engine/engine.dart | 0 .../lib/{ => services}/engine/native_engine.dart | 12 ++++++++---- .../drawer_controller.dart} | 16 +++++----------- .../{screens => shared}/list_item_divider.dart | 0 .../lib/shared/painters/board_painter.dart | 9 +-------- .../lib/shared/painters/painter_base.dart | 3 +-- .../lib/shared/painters/pieces_painter.dart | 8 +------- .../settings/settings_card.dart | 2 +- .../settings/settings_list_tile.dart | 0 .../settings/settings_switch_list_tile.dart | 0 24 files changed, 66 insertions(+), 104 deletions(-) rename src/ui/flutter_app/lib/screens/{ => game_page}/board.dart (93%) rename src/ui/flutter_app/lib/{ => services}/engine/engine.dart (100%) rename src/ui/flutter_app/lib/{ => services}/engine/native_engine.dart (95%) rename src/ui/flutter_app/lib/{screens/drawer_user_controller.dart => shared/drawer_controller.dart} (94%) rename src/ui/flutter_app/lib/{screens => shared}/list_item_divider.dart (100%) rename src/ui/flutter_app/lib/{screens => shared}/settings/settings_card.dart (96%) rename src/ui/flutter_app/lib/{screens => shared}/settings/settings_list_tile.dart (100%) rename src/ui/flutter_app/lib/{screens => shared}/settings/settings_switch_list_tile.dart (100%) diff --git a/src/ui/flutter_app/lib/l10n/resources.dart b/src/ui/flutter_app/lib/l10n/resources.dart index c5f0bcdd..d021a442 100644 --- a/src/ui/flutter_app/lib/l10n/resources.dart +++ b/src/ui/flutter_app/lib/l10n/resources.dart @@ -19,10 +19,10 @@ import 'dart:io'; import 'package:flutter/material.dart'; -import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/screens/list_item_divider.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/generated/l10n.dart'; +import 'package:sanmill/shared/list_item_divider.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; Map languageCodeToStrings = { @@ -520,9 +520,7 @@ class Resources { } Future setLanguage( - BuildContext context, - Function(String?)? callback, -) async { + BuildContext context, Function(String?)? callback) async { final languageColumn = Column( mainAxisSize: MainAxisSize.min, children: [ @@ -572,7 +570,7 @@ Bidirectionality getBidirectionality(BuildContext context) { currentLocale.languageCode == "he" || currentLocale.languageCode == "ps" || currentLocale.languageCode == "ur") { - debugPrint("bidirectionality: RTL"); + print("bidirectionality: RTL"); return Bidirectionality.rightToLeft; } else { return Bidirectionality.leftToRight; @@ -593,5 +591,5 @@ void setSpecialCountryAndRegion(BuildContext context) { break; } - debugPrint("Set Special Country and Region to $specialCountryAndRegion."); + print("Set Special Country and Region to $specialCountryAndRegion."); } diff --git a/src/ui/flutter_app/lib/main.dart b/src/ui/flutter_app/lib/main.dart index 9a1b9e52..d480f51b 100644 --- a/src/ui/flutter_app/lib/main.dart +++ b/src/ui/flutter_app/lib/main.dart @@ -16,7 +16,6 @@ along with this program. If not, see . */ -import 'dart:async'; import 'dart:io'; import 'dart:ui'; @@ -34,8 +33,6 @@ import 'package:sanmill/services/audios.dart'; import 'package:sanmill/shared/common/constants.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; -import 'services/audios.dart'; - Future main() async { final catcher = Catcher( rootWidget: BetterFeedback( diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index eb28357d..18b91007 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -17,12 +17,11 @@ */ import 'package:flutter/foundation.dart'; -import 'package:sanmill/engine/engine.dart'; +import 'package:sanmill/mill/position.dart'; +import 'package:sanmill/mill/types.dart'; +import 'package:sanmill/services/engine/engine.dart'; import 'package:sanmill/shared/common/config.dart'; -import 'position.dart'; -import 'types.dart'; - enum PlayerType { human, AI } Map isAi = {PieceColor.white: false, PieceColor.black: true}; diff --git a/src/ui/flutter_app/lib/mill/mills.dart b/src/ui/flutter_app/lib/mill/mills.dart index 19cbee5e..03f7940c 100644 --- a/src/ui/flutter_app/lib/mill/mills.dart +++ b/src/ui/flutter_app/lib/mill/mills.dart @@ -16,8 +16,8 @@ along with this program. If not, see . */ -import 'position.dart'; -import 'rule.dart'; +import 'package:sanmill/mill/position.dart'; +import 'package:sanmill/mill/rule.dart'; class Mills { const Mills._(); diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index 8cd06f69..a219e540 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -17,16 +17,14 @@ */ import 'package:flutter/foundation.dart'; -import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/mill/game.dart'; +import 'package:sanmill/mill/mills.dart'; import 'package:sanmill/mill/recorder.dart'; import 'package:sanmill/mill/rule.dart'; import 'package:sanmill/mill/types.dart'; +import 'package:sanmill/mill/zobrist.dart'; import 'package:sanmill/services/audios.dart'; - -import 'mills.dart'; -import 'types.dart'; -import 'zobrist.dart'; +import 'package:sanmill/services/engine/engine.dart'; List posKeyHistory = []; diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index 42940b0f..a7cd1472 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -17,11 +17,10 @@ */ import 'package:flutter/foundation.dart'; +import 'package:sanmill/mill/position.dart'; +import 'package:sanmill/mill/types.dart'; import 'package:sanmill/shared/common/config.dart'; -import 'position.dart'; -import 'types.dart'; - // TODO class GameRecorder { int cur = -1; diff --git a/src/ui/flutter_app/lib/screens/about_page.dart b/src/ui/flutter_app/lib/screens/about_page.dart index 8b2ad500..e003c0bb 100644 --- a/src/ui/flutter_app/lib/screens/about_page.dart +++ b/src/ui/flutter_app/lib/screens/about_page.dart @@ -24,15 +24,14 @@ import 'package:flutter/material.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sanmill/generated/flutter_version.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/screens/settings/settings_list_tile.dart'; +import 'package:sanmill/screens/license_page.dart'; +import 'package:sanmill/screens/oss_license_page.dart'; import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/list_item_divider.dart'; +import 'package:sanmill/shared/settings/settings_list_tile.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'license_page.dart'; -import 'list_item_divider.dart'; -import 'oss_license_page.dart'; - class AboutPage extends StatelessWidget { final String tag = "[about] "; diff --git a/src/ui/flutter_app/lib/screens/board.dart b/src/ui/flutter_app/lib/screens/game_page/board.dart similarity index 93% rename from src/ui/flutter_app/lib/screens/board.dart rename to src/ui/flutter_app/lib/screens/game_page/board.dart index b01ab97c..e544adbc 100644 --- a/src/ui/flutter_app/lib/screens/board.dart +++ b/src/ui/flutter_app/lib/screens/game_page/board.dart @@ -16,15 +16,7 @@ along with this program. If not, see . */ -import 'package:flutter/material.dart'; -import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/mill/game.dart'; -import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/shared/common/config.dart'; -import 'package:sanmill/shared/painters/board_painter.dart'; -import 'package:sanmill/shared/painters/pieces_painter.dart'; -import 'package:sanmill/shared/theme/app_theme.dart'; +part of 'package:sanmill/screens/game_page/game_page.dart'; typedef BoardTapCallback = dynamic Function(int index); diff --git a/src/ui/flutter_app/lib/screens/game_page/game_page.dart b/src/ui/flutter_app/lib/screens/game_page/game_page.dart index 5c187224..d599a1b9 100644 --- a/src/ui/flutter_app/lib/screens/game_page/game_page.dart +++ b/src/ui/flutter_app/lib/screens/game_page/game_page.dart @@ -16,15 +16,13 @@ along with this program. If not, see . */ -import 'dart:async'; - //import 'dart:typed_data'; +import 'dart:async'; + import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:sanmill/engine/engine.dart'; -import 'package:sanmill/engine/native_engine.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/main.dart'; @@ -32,9 +30,10 @@ import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/rule.dart'; import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/screens/board.dart'; import 'package:sanmill/screens/game_settings_page.dart'; import 'package:sanmill/services/audios.dart'; +import 'package:sanmill/services/engine/engine.dart'; +import 'package:sanmill/services/engine/native_engine.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; import 'package:sanmill/shared/dialog.dart'; @@ -45,6 +44,10 @@ import 'package:sanmill/shared/theme/app_theme.dart'; import 'package:stack_trace/stack_trace.dart'; part 'package:sanmill/screens/game_page/game_page_tool_bar.dart'; +part 'package:sanmill/screens/game_page/board.dart'; +part 'package:sanmill/shared/painters/board_painter.dart'; +part 'package:sanmill/shared/painters/pieces_painter.dart'; +part 'package:sanmill/shared/painters/painter_base.dart'; double boardWidth = 0.0; diff --git a/src/ui/flutter_app/lib/screens/game_settings_page.dart b/src/ui/flutter_app/lib/screens/game_settings_page.dart index b78aaa09..43a8fa2d 100644 --- a/src/ui/flutter_app/lib/screens/game_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/game_settings_page.dart @@ -21,16 +21,15 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/screens/settings/settings_card.dart'; -import 'package:sanmill/screens/settings/settings_list_tile.dart'; -import 'package:sanmill/screens/settings/settings_switch_list_tile.dart'; +import 'package:sanmill/screens/env_page.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/settings.dart'; +import 'package:sanmill/shared/dialog.dart'; +import 'package:sanmill/shared/settings/settings_card.dart'; +import 'package:sanmill/shared/settings/settings_list_tile.dart'; +import 'package:sanmill/shared/settings/settings_switch_list_tile.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; -import '../shared/dialog.dart'; -import 'env_page.dart'; - class Developer { const Developer._(); static bool developerModeEnabled = false; diff --git a/src/ui/flutter_app/lib/screens/home_drawer.dart b/src/ui/flutter_app/lib/screens/home_drawer.dart index 4c38bc3b..b6c3af0e 100644 --- a/src/ui/flutter_app/lib/screens/home_drawer.dart +++ b/src/ui/flutter_app/lib/screens/home_drawer.dart @@ -16,16 +16,7 @@ along with this program. If not, see . */ -import 'dart:async'; - -import 'package:animated_text_kit/animated_text_kit.dart'; -import 'package:flutter/material.dart'; -import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/screens/game_settings_page.dart'; -import 'package:sanmill/shared/common/config.dart'; -import 'package:sanmill/shared/common/constants.dart'; -import 'package:sanmill/shared/theme/app_theme.dart'; +part of 'package:sanmill/screens/navigation_home_screen.dart'; enum DrawerIndex { humanVsAi, 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 7b0477a7..473e3a55 100644 --- a/src/ui/flutter_app/lib/screens/navigation_home_screen.dart +++ b/src/ui/flutter_app/lib/screens/navigation_home_screen.dart @@ -19,19 +19,20 @@ import 'dart:io'; import 'dart:typed_data'; +import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:feedback/feedback.dart'; +import 'package:fluentui_system_icons/fluentui_system_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_email_sender/flutter_email_sender.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:sanmill/engine/engine.dart'; +import 'package:sanmill/generated/l10n.dart'; +import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/screens/about_page.dart'; -import 'package:sanmill/screens/drawer_user_controller.dart'; import 'package:sanmill/screens/game_page/game_page.dart'; import 'package:sanmill/screens/game_settings_page.dart'; import 'package:sanmill/screens/help_screen.dart'; -import 'package:sanmill/screens/home_drawer.dart'; import 'package:sanmill/screens/personalization_settings_page.dart'; import 'package:sanmill/screens/rule_settings_page.dart'; import 'package:sanmill/services/engine/engine.dart'; @@ -39,6 +40,9 @@ import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; +part 'package:sanmill/screens/home_drawer.dart'; +part 'package:sanmill/shared/drawer_controller.dart'; + class NavigationHomeScreen extends StatefulWidget { @override _NavigationHomeScreenState createState() => _NavigationHomeScreenState(); @@ -59,7 +63,7 @@ class _NavigationHomeScreenState extends State { Widget build(BuildContext context) { return Material( color: AppTheme.navigationHomeScreenBackgroundColor, - child: DrawerUserController( + child: DrawerController( screenIndex: drawerIndex, drawerWidth: MediaQuery.of(context).size.width * 0.75, onDrawerCall: changeIndex, diff --git a/src/ui/flutter_app/lib/screens/personalization_settings_page.dart b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart index 330df6ec..c94e7415 100644 --- a/src/ui/flutter_app/lib/screens/personalization_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/personalization_settings_page.dart @@ -20,11 +20,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/screens/settings/settings_card.dart'; -import 'package:sanmill/screens/settings/settings_list_tile.dart'; -import 'package:sanmill/screens/settings/settings_switch_list_tile.dart'; import 'package:sanmill/shared/common/config.dart'; import 'package:sanmill/shared/common/constants.dart'; +import 'package:sanmill/shared/settings/settings_card.dart'; +import 'package:sanmill/shared/settings/settings_list_tile.dart'; +import 'package:sanmill/shared/settings/settings_switch_list_tile.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; class PersonalizationSettingsPage extends StatefulWidget { diff --git a/src/ui/flutter_app/lib/screens/rule_settings_page.dart b/src/ui/flutter_app/lib/screens/rule_settings_page.dart index ec2589c2..acd11b2f 100644 --- a/src/ui/flutter_app/lib/screens/rule_settings_page.dart +++ b/src/ui/flutter_app/lib/screens/rule_settings_page.dart @@ -20,14 +20,13 @@ import 'package:flutter/material.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/l10n/resources.dart'; import 'package:sanmill/mill/rule.dart'; -import 'package:sanmill/screens/settings/settings_card.dart'; -import 'package:sanmill/screens/settings/settings_list_tile.dart'; -import 'package:sanmill/screens/settings/settings_switch_list_tile.dart'; import 'package:sanmill/shared/common/config.dart'; +import 'package:sanmill/shared/settings/settings_card.dart'; +import 'package:sanmill/shared/settings/settings_list_tile.dart'; +import 'package:sanmill/shared/settings/settings_switch_list_tile.dart'; +import 'package:sanmill/shared/snack_bar.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; -import '../shared/snack_bar.dart'; - class RuleSettingsPage extends StatefulWidget { @override _RuleSettingsPageState createState() => _RuleSettingsPageState(); diff --git a/src/ui/flutter_app/lib/engine/engine.dart b/src/ui/flutter_app/lib/services/engine/engine.dart similarity index 100% rename from src/ui/flutter_app/lib/engine/engine.dart rename to src/ui/flutter_app/lib/services/engine/engine.dart diff --git a/src/ui/flutter_app/lib/engine/native_engine.dart b/src/ui/flutter_app/lib/services/engine/native_engine.dart similarity index 95% rename from src/ui/flutter_app/lib/engine/native_engine.dart rename to src/ui/flutter_app/lib/services/engine/native_engine.dart index dec820c6..4a02e349 100644 --- a/src/ui/flutter_app/lib/engine/native_engine.dart +++ b/src/ui/flutter_app/lib/services/engine/native_engine.dart @@ -22,10 +22,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/types.dart'; +import 'package:sanmill/services/engine/engine.dart'; import 'package:sanmill/shared/common/config.dart'; -import 'engine.dart'; - class NativeEngine extends Engine { static const platform = MethodChannel('com.calcitem.sanmill/engine'); bool isActive = false; @@ -55,8 +54,13 @@ class NativeEngine extends Engine { return platform.invokeMethod('isReady'); } - Future isThinking() async { - return platform.invokeMethod('isThinking') as Future; + FutureOr isThinking() async { + final _isThinking = await platform.invokeMethod('isThinking'); + if (_isThinking is bool) { + return _isThinking; + } else { + throw 'Invalid platform response. Expected a value of type bool'; + } } @override diff --git a/src/ui/flutter_app/lib/screens/drawer_user_controller.dart b/src/ui/flutter_app/lib/shared/drawer_controller.dart similarity index 94% rename from src/ui/flutter_app/lib/screens/drawer_user_controller.dart rename to src/ui/flutter_app/lib/shared/drawer_controller.dart index d19f387e..94a14dfe 100644 --- a/src/ui/flutter_app/lib/screens/drawer_user_controller.dart +++ b/src/ui/flutter_app/lib/shared/drawer_controller.dart @@ -16,16 +16,10 @@ along with this program. If not, see . */ -import 'package:fluentui_system_icons/fluentui_system_icons.dart'; -import 'package:flutter/material.dart'; -import 'package:sanmill/generated/l10n.dart'; -import 'package:sanmill/l10n/resources.dart'; -import 'package:sanmill/screens/home_drawer.dart'; -import 'package:sanmill/shared/common/config.dart'; -import 'package:sanmill/shared/theme/app_theme.dart'; +part of 'package:sanmill/screens/navigation_home_screen.dart'; -class DrawerUserController extends StatefulWidget { - const DrawerUserController({ +class DrawerController extends StatefulWidget { + const DrawerController({ Key? key, this.drawerWidth = AppTheme.drawerWidth, required this.onDrawerCall, @@ -45,10 +39,10 @@ class DrawerUserController extends StatefulWidget { final DrawerIndex screenIndex; @override - _DrawerUserControllerState createState() => _DrawerUserControllerState(); + _DrawerControllerState createState() => _DrawerControllerState(); } -class _DrawerUserControllerState extends State +class _DrawerControllerState extends State with TickerProviderStateMixin { late final ScrollController scrollController; late final AnimationController iconAnimationController; diff --git a/src/ui/flutter_app/lib/screens/list_item_divider.dart b/src/ui/flutter_app/lib/shared/list_item_divider.dart similarity index 100% rename from src/ui/flutter_app/lib/screens/list_item_divider.dart rename to src/ui/flutter_app/lib/shared/list_item_divider.dart diff --git a/src/ui/flutter_app/lib/shared/painters/board_painter.dart b/src/ui/flutter_app/lib/shared/painters/board_painter.dart index a5951f5e..fa3cbb5a 100644 --- a/src/ui/flutter_app/lib/shared/painters/board_painter.dart +++ b/src/ui/flutter_app/lib/shared/painters/board_painter.dart @@ -16,14 +16,7 @@ along with this program. If not, see . */ -import 'package:flutter/material.dart'; -import 'package:sanmill/mill/game.dart'; -import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/screens/game_page/game_page.dart'; -import 'package:sanmill/shared/common/config.dart'; -import 'package:sanmill/shared/theme/app_theme.dart'; - -import 'painter_base.dart'; +part of 'package:sanmill/screens/game_page/game_page.dart'; class BoardPainter extends PiecesBasePainter { BoardPainter({required double width}) : super(width: width); diff --git a/src/ui/flutter_app/lib/shared/painters/painter_base.dart b/src/ui/flutter_app/lib/shared/painters/painter_base.dart index c661c4db..b8c62b3e 100644 --- a/src/ui/flutter_app/lib/shared/painters/painter_base.dart +++ b/src/ui/flutter_app/lib/shared/painters/painter_base.dart @@ -16,8 +16,7 @@ along with this program. If not, see . */ -import 'package:flutter/material.dart'; -import 'package:sanmill/shared/theme/app_theme.dart'; +part of 'package:sanmill/screens/game_page/game_page.dart'; abstract class PiecesBasePainter extends CustomPainter { final double width; diff --git a/src/ui/flutter_app/lib/shared/painters/pieces_painter.dart b/src/ui/flutter_app/lib/shared/painters/pieces_painter.dart index 63542751..1ae305bd 100644 --- a/src/ui/flutter_app/lib/shared/painters/pieces_painter.dart +++ b/src/ui/flutter_app/lib/shared/painters/pieces_painter.dart @@ -16,13 +16,7 @@ along with this program. If not, see . */ -import 'package:flutter/material.dart'; -import 'package:sanmill/mill/position.dart'; -import 'package:sanmill/mill/types.dart'; -import 'package:sanmill/shared/common/config.dart'; -import 'package:sanmill/shared/theme/app_theme.dart'; - -import 'painter_base.dart'; +part of 'package:sanmill/screens/game_page/game_page.dart'; class PiecePaintParam { final String piece; diff --git a/src/ui/flutter_app/lib/screens/settings/settings_card.dart b/src/ui/flutter_app/lib/shared/settings/settings_card.dart similarity index 96% rename from src/ui/flutter_app/lib/screens/settings/settings_card.dart rename to src/ui/flutter_app/lib/shared/settings/settings_card.dart index 0debe7a1..5b16e8f0 100644 --- a/src/ui/flutter_app/lib/screens/settings/settings_card.dart +++ b/src/ui/flutter_app/lib/shared/settings/settings_card.dart @@ -17,7 +17,7 @@ */ import 'package:flutter/material.dart'; -import 'package:sanmill/screens/list_item_divider.dart'; +import 'package:sanmill/shared/list_item_divider.dart'; import 'package:sanmill/shared/theme/app_theme.dart'; class SettingsCard extends StatelessWidget { diff --git a/src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart b/src/ui/flutter_app/lib/shared/settings/settings_list_tile.dart similarity index 100% rename from src/ui/flutter_app/lib/screens/settings/settings_list_tile.dart rename to src/ui/flutter_app/lib/shared/settings/settings_list_tile.dart diff --git a/src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart b/src/ui/flutter_app/lib/shared/settings/settings_switch_list_tile.dart similarity index 100% rename from src/ui/flutter_app/lib/screens/settings/settings_switch_list_tile.dart rename to src/ui/flutter_app/lib/shared/settings/settings_switch_list_tile.dart From c029bf39d088e4d3a195721f1d1cbc93b82bafca Mon Sep 17 00:00:00 2001 From: Leptopoda Date: Sun, 10 Oct 2021 12:05:05 +0200 Subject: [PATCH 13/13] game board cleanup removes some unneded code and better utilizes null safety --- src/ui/flutter_app/lib/mill/game.dart | 5 +++-- src/ui/flutter_app/lib/mill/types.dart | 14 ++++++++++---- .../lib/screens/game_page/game_page.dart | 16 ++++++++-------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index 18b91007..d8b497fb 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -53,8 +53,9 @@ class Game { String sideToMove = PieceColor.white; - bool? isAiToMove() { - return isAi[sideToMove]; + bool get isAiToMove { + assert(sideToMove == PieceColor.white || sideToMove == PieceColor.black); + return isAi[sideToMove]!; } List moveHistory = [""]; diff --git a/src/ui/flutter_app/lib/mill/types.dart b/src/ui/flutter_app/lib/mill/types.dart index c26c7444..84d78b94 100644 --- a/src/ui/flutter_app/lib/mill/types.dart +++ b/src/ui/flutter_app/lib/mill/types.dart @@ -147,10 +147,16 @@ class PieceColor { static const draw = '='; static String of(String piece) { - if (white.contains(piece)) return white; - if (black.contains(piece)) return black; - if (ban.contains(piece)) return ban; - return nobody; + switch (piece) { + case white: + return white; + case black: + return black; + case ban: + return ban; + default: + return nobody; + } } static bool isSameColor(String p1, String p2) => of(p1) == of(p2); diff --git a/src/ui/flutter_app/lib/screens/game_page/game_page.dart b/src/ui/flutter_app/lib/screens/game_page/game_page.dart index d599a1b9..8375a3d1 100644 --- a/src/ui/flutter_app/lib/screens/game_page/game_page.dart +++ b/src/ui/flutter_app/lib/screens/game_page/game_page.dart @@ -80,7 +80,7 @@ class _GamePageState extends State late AnimationController _animationController; late Animation animation; bool disposed = false; - late final bool ltr; + late bool ltr; final String tag = "[game_page]"; Future _setReadyState() async { @@ -207,7 +207,7 @@ class _GamePageState extends State position.pieceOnBoardCount[PieceColor.black] == 0) { gameInstance.newGame(); - if (gameInstance.isAiToMove()!) { + if (gameInstance.isAiToMove) { if (gameInstance.aiIsSearching()) { debugPrint("$tag AI is thinking, skip tapping."); return false; @@ -219,7 +219,7 @@ class _GamePageState extends State } } - if (gameInstance.isAiToMove()! || gameInstance.aiIsSearching()) { + if (gameInstance.isAiToMove || gameInstance.aiIsSearching()) { debugPrint("[tap] AI's turn, skip tapping."); return false; } @@ -518,7 +518,7 @@ class _GamePageState extends State debugPrint("[engineToGo] engine type is ${widget.engineType}"); if (_isMoveNow) { - if (!gameInstance.isAiToMove()!) { + if (!gameInstance.isAiToMove) { debugPrint("[engineToGo] Human to Move. Cannot get search result now."); ScaffoldMessenger.of(context).clearSnackBars(); showSnackBar(context, S.of(context).notAIsTurn); @@ -536,7 +536,7 @@ class _GamePageState extends State while ((Config.isAutoRestart == true || gameInstance.position.winner == PieceColor.nobody) && - gameInstance.isAiToMove()! && + gameInstance.isAiToMove && mounted) { if (widget.engineType == EngineType.aiVsAi) { final String score = @@ -620,7 +620,7 @@ class _GamePageState extends State Future onStartNewGameButtonPressed() async { Navigator.pop(context); - if (gameInstance.isAiToMove()!) { + if (gameInstance.isAiToMove) { // TODO: Move now //debugPrint("$tag New game, AI to move, move now."); //await engineToGo(true); @@ -636,7 +636,7 @@ class _GamePageState extends State } } - if (gameInstance.isAiToMove()!) { + if (gameInstance.isAiToMove) { debugPrint("$tag New game, AI to move."); engineToGo(false); } @@ -1387,7 +1387,7 @@ class _GamePageState extends State } } - if (gameInstance.isAiToMove()!) { + if (gameInstance.isAiToMove) { debugPrint("$tag New game, AI to move."); engineToGo(false); }