From 4a70a4de847172cdacb8890cf235f035aa6fc875 Mon Sep 17 00:00:00 2001 From: EkaterinaMarkina-1 Date: Wed, 21 May 2025 13:38:20 +0600 Subject: [PATCH 1/7] =?UTF-8?q?fix:=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=80=D0=B0=D0=B7=D0=B1=D0=B8=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=B8=D0=B4=D0=B6=D0=B5=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B7=D0=BD=D0=BE?= =?UTF-8?q?=D0=B9=20=D1=88=D0=B8=D1=80=D0=B8=D0=BD=D1=8B=20=D1=8D=D0=BA?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setting_view/game_settings_mobile.dart | 122 ++++++++++++++++ .../setting_view/game_settings_tablet.dart | 119 +++++++++++++++ .../setting_view/game_settings_view.dart | 138 +++++++----------- 3 files changed, 290 insertions(+), 89 deletions(-) create mode 100644 frontend/lib/views/setting_view/game_settings_mobile.dart create mode 100644 frontend/lib/views/setting_view/game_settings_tablet.dart diff --git a/frontend/lib/views/setting_view/game_settings_mobile.dart b/frontend/lib/views/setting_view/game_settings_mobile.dart new file mode 100644 index 0000000..d847757 --- /dev/null +++ b/frontend/lib/views/setting_view/game_settings_mobile.dart @@ -0,0 +1,122 @@ +part of 'game_settings_view.dart'; + +class GameSettingsMobile extends StatelessWidget { + final GameModel gameModel; + final bool withoutTime; + final int durationOfGame; + final int addingOfMove; + final bool isMoveBack; + final bool isThreats; + final bool isHints; + final void Function(int) setIsTime; + final void Function(int) setMinutes; + final void Function(int) setSeconds; + final void Function(bool) setIsMoveBack; + final void Function(bool) setIsThreats; + final void Function(bool) setIsHints; + final VoidCallback onStartGame; + + const GameSettingsMobile({ + super.key, + required this.gameModel, + required this.withoutTime, + required this.durationOfGame, + required this.addingOfMove, + required this.isMoveBack, + required this.isThreats, + required this.isHints, + required this.setIsTime, + required this.setMinutes, + required this.setSeconds, + required this.setIsMoveBack, + required this.setIsThreats, + required this.setIsHints, + required this.onStartGame, + }); + + @override + Widget build(BuildContext context) { + final scheme = Theme.of(context).colorScheme; + return DefaultTabController( + length: 2, + child: Scaffold( + backgroundColor: scheme.background, + body: SafeArea( + child: Stack( + children: [ + SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: MediaQuery.of(context).size.width, + minHeight: MediaQuery.of(context).size.height, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.only(left: 24, right: 24, top: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings(label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, + ], + isSettingsPage: true, + onTap: (dynamic index) => setIsTime(index as int), + ), + if (!withoutTime) ...[ + SetTimeSection( + minutesStartValue: durationOfGame, + minutesOnChanged: (dynamic value) => setMinutes(value as int), + secondsStartValue: addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : addingOfMove, + secondsOnChanged: (dynamic value) => setSeconds(value as int), + ) + ], + SettingsRowsSection( + choseMoveBack: isMoveBack, + moveBackOnChanged: setIsMoveBack, + choseThreats: isThreats, + threatsOnChanged: setIsThreats, + choseHints: isHints, + hintsOnChanged: setIsHints, + ), + const SizedBox(height: 100), + ], + ), + ), + ), + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Container( + color: scheme.background, + child: Padding( + padding: const EdgeInsets.only( + top: 15, + bottom: 23, + left: 23, + right: 23, + ), + child: NextPageButton( + text: GameSettingConsts.startGameText, + textColor: ColorsConst.primaryColor0, + buttonColor: scheme.secondaryContainer, + isClickable: true, + onTap: onStartGame, + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/lib/views/setting_view/game_settings_tablet.dart b/frontend/lib/views/setting_view/game_settings_tablet.dart new file mode 100644 index 0000000..8cec27e --- /dev/null +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -0,0 +1,119 @@ +part of 'game_settings_view.dart'; + +class GameSettingsTablet extends StatelessWidget { + final GameModel gameModel; + final bool withoutTime; + final int durationOfGame; + final int addingOfMove; + final bool isMoveBack; + final bool isThreats; + final bool isHints; + final void Function(int) setIsTime; + final void Function(int) setMinutes; + final void Function(int) setSeconds; + final void Function(bool) setIsMoveBack; + final void Function(bool) setIsThreats; + final void Function(bool) setIsHints; + final VoidCallback onStartGame; + + const GameSettingsTablet({ + super.key, + required this.gameModel, + required this.withoutTime, + required this.durationOfGame, + required this.addingOfMove, + required this.isMoveBack, + required this.isThreats, + required this.isHints, + required this.setIsTime, + required this.setMinutes, + required this.setSeconds, + required this.setIsMoveBack, + required this.setIsThreats, + required this.setIsHints, + required this.onStartGame, + }); + + @override + Widget build(BuildContext context) { + final scheme = Theme.of(context).colorScheme; + return DefaultTabController( + length: 2, + child: Scaffold( + backgroundColor: scheme.background, + body: SafeArea( + child: Stack( + children: [ + SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: MediaQuery.of(context).size.height, + ), + child: Padding( + padding: const EdgeInsets.only(left: 24, right: 24, top: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings(label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, + ], + isSettingsPage: true, + onTap: (dynamic index) => setIsTime(index as int), + ), + if (!withoutTime) ...[ + SetTimeSection( + minutesStartValue: durationOfGame, + minutesOnChanged: (dynamic value) => setMinutes(value as int), + secondsStartValue: addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : addingOfMove, + secondsOnChanged: (dynamic value) => setSeconds(value as int), + ) + ], + SettingsRowsSection( + choseMoveBack: isMoveBack, + moveBackOnChanged: setIsMoveBack, + choseThreats: isThreats, + threatsOnChanged: setIsThreats, + choseHints: isHints, + hintsOnChanged: setIsHints, + ), + const SizedBox(height: 100), + ], + ), + ), + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Container( + color: scheme.background, + child: Padding( + padding: const EdgeInsets.only( + top: 15, + bottom: 23, + left: 23, + right: 23, + ), + child: NextPageButton( + text: GameSettingConsts.startGameText, + textColor: ColorsConst.primaryColor0, + buttonColor: scheme.secondaryContainer, + isClickable: true, + onTap: onStartGame, + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/frontend/lib/views/setting_view/game_settings_view.dart b/frontend/lib/views/setting_view/game_settings_view.dart index 4ec8b3f..00cf54d 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -1,8 +1,10 @@ import "package:flutter/material.dart"; import "package:go_router/go_router.dart"; import "package:sqflite/sqflite.dart"; -import "package:flutter_gen/gen_l10n/app_localizations.dart"; + import "../../exports.dart"; +part 'game_settings_mobile.dart'; +part 'game_settings_tablet.dart'; class GameSettingsView extends StatefulWidget { const GameSettingsView(this.gameModel, {super.key}); @@ -135,6 +137,13 @@ class _GameSettingsViewState extends State await database.close(); } + Future _handleStartGame(BuildContext context) async { + if (isSettingsEdited) await setSettings(); + if (!context.mounted) return; + widget.gameModel.newGame(context, notify: false); + context.go(RouteLocations.gameScreen, extra: widget.gameModel); +} + void onInit() async { var databasesPath = await getDatabasesPath(); String p = "$databasesPath/settings.db"; @@ -156,93 +165,44 @@ class _GameSettingsViewState extends State @override Widget build(BuildContext context) { - final scheme = Theme.of(context).colorScheme; - final l10n = AppLocalizations.of(context)!; - return isLoading - ? const LoadingWidget() - : DefaultTabController( - length: countOfTabs, - child: Scaffold( - backgroundColor: scheme.background, - body: SafeArea( - child: Stack( - children: [ - SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: MediaQuery.of(context).size.width, - minHeight: MediaQuery.of(context).size.height), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.only( - left: 24, right: 24, top: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AppBarSettings(label: l10n.settings), - CustomTabBar( - initialIndex: withoutTime ? 0 : 1, - header: l10n.time, - subTitles: [ - l10n.withoutTimer, - l10n.withTimer, - ], - isSettingsPage: true, - onTap: setIsTime, - ), - if (!withoutTime) ...[ - SetTimeSection( - minutesStartValue: durationOfGame, - minutesOnChanged: setMinutes, - secondsStartValue: addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : addingOfMove, - secondsOnChanged: setSeconds) - ], - SettingsRowsSection( - choseMoveBack: isMoveBack, - moveBackOnChanged: setIsMoveBack, - choseThreats: isThreats, - threatsOnChanged: setIsThreats, - choseHints: isHints, - hintsOnChanged: setIsHints, - ), - const SizedBox(height: 100), - ], - ), - ), - ), - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - color: scheme.background, - child: Padding( - padding: const EdgeInsets.only( - top: 15, bottom: 23, left: 23, right: 23), - child: NextPageButton( - text: l10n.startGame, - textColor: ColorsConst.primaryColor0, - buttonColor: scheme.secondaryContainer, - isClickable: true, - onTap: () async { - if (isSettingsEdited) { - await setSettings(); - } - if (!context.mounted) return; - widget.gameModel.newGame(context, notify: false); - context.go(RouteLocations.gameScreen, - extra: widget.gameModel); - }, - ), - ), - ), - ), - ], - ), - ), - ), - ); + if (isLoading) return const LoadingWidget(); + return LayoutBuilder( + builder: (context, constraints) { + final isTablet = constraints.maxWidth >= 640; + return isTablet + ? GameSettingsTablet( + gameModel: widget.gameModel, + withoutTime: withoutTime, + durationOfGame: durationOfGame, + addingOfMove: addingOfMove, + isMoveBack: isMoveBack, + isThreats: isThreats, + isHints: isHints, + setIsTime: setIsTime, + setMinutes: setMinutes, + setSeconds: setSeconds, + setIsMoveBack: setIsMoveBack, + setIsThreats: setIsThreats, + setIsHints: setIsHints, + onStartGame: () => _handleStartGame(context), + ) + : GameSettingsMobile( + gameModel: widget.gameModel, + withoutTime: withoutTime, + durationOfGame: durationOfGame, + addingOfMove: addingOfMove, + isMoveBack: isMoveBack, + isThreats: isThreats, + isHints: isHints, + setIsTime: setIsTime, + setMinutes: setMinutes, + setSeconds: setSeconds, + setIsMoveBack: setIsMoveBack, + setIsThreats: setIsThreats, + setIsHints: setIsHints, + onStartGame: () => _handleStartGame(context), + ); + }, + ); } } From 8a6abed2e29472fedc333131a85ea9f23dd56611 Mon Sep 17 00:00:00 2001 From: EkaterinaMarkina-1 Date: Wed, 21 May 2025 14:00:38 +0600 Subject: [PATCH 2/7] =?UTF-8?q?fix:=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B9=D0=BA=D0=B0=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=82=D0=B5=D0=BA=D1=81=D0=B0=20=D0=B8=20=D0=BA=D0=BD?= =?UTF-8?q?=D0=BE=D0=BF=D0=BE=D0=BA;=20=D1=80=D0=B0=D0=B7=D0=B1=D0=B8?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B9=D0=BA=D0=B8=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B2=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=20=D0=BE=D1=82=20=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=82=D0=B0=20=D1=83=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setting_view/game_settings_mobile.dart | 2 - .../setting_view/game_settings_tablet.dart | 77 +++++++++---------- .../setting_view/game_settings_view.dart | 2 - 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/frontend/lib/views/setting_view/game_settings_mobile.dart b/frontend/lib/views/setting_view/game_settings_mobile.dart index d847757..b67262c 100644 --- a/frontend/lib/views/setting_view/game_settings_mobile.dart +++ b/frontend/lib/views/setting_view/game_settings_mobile.dart @@ -1,7 +1,6 @@ part of 'game_settings_view.dart'; class GameSettingsMobile extends StatelessWidget { - final GameModel gameModel; final bool withoutTime; final int durationOfGame; final int addingOfMove; @@ -18,7 +17,6 @@ class GameSettingsMobile extends StatelessWidget { const GameSettingsMobile({ super.key, - required this.gameModel, required this.withoutTime, required this.durationOfGame, required this.addingOfMove, diff --git a/frontend/lib/views/setting_view/game_settings_tablet.dart b/frontend/lib/views/setting_view/game_settings_tablet.dart index 8cec27e..06d3e8a 100644 --- a/frontend/lib/views/setting_view/game_settings_tablet.dart +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -1,7 +1,5 @@ part of 'game_settings_view.dart'; - class GameSettingsTablet extends StatelessWidget { - final GameModel gameModel; final bool withoutTime; final int durationOfGame; final int addingOfMove; @@ -15,10 +13,8 @@ class GameSettingsTablet extends StatelessWidget { final void Function(bool) setIsThreats; final void Function(bool) setIsHints; final VoidCallback onStartGame; - const GameSettingsTablet({ super.key, - required this.gameModel, required this.withoutTime, required this.durationOfGame, required this.addingOfMove, @@ -33,7 +29,6 @@ class GameSettingsTablet extends StatelessWidget { required this.setIsHints, required this.onStartGame, }); - @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; @@ -49,46 +44,48 @@ class GameSettingsTablet extends StatelessWidget { constraints: BoxConstraints( minHeight: MediaQuery.of(context).size.height, ), - child: Padding( - padding: const EdgeInsets.only(left: 24, right: 24, top: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AppBarSettings(label: GameSettingConsts.appBarLabel), - CustomTabBar( - initialIndex: withoutTime ? 0 : 1, - header: GameSettingConsts.timeText, - subTitles: [ - GameSettingConsts.gameWithoutTimeText, - GameSettingConsts.gameWithTimeText, + child: Padding( + padding: const EdgeInsets.only(left: 24, right: 24, top: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings(label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, + ], + isSettingsPage: true, + onTap: (dynamic index) => setIsTime(index as int), + ), + if (!withoutTime) ...[ + const SizedBox(height: 70), + SetTimeSection( + minutesStartValue: durationOfGame, + minutesOnChanged: (dynamic value) => setMinutes(value as int), + secondsStartValue: addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : addingOfMove, + secondsOnChanged: (dynamic value) => setSeconds(value as int), + ) ], - isSettingsPage: true, - onTap: (dynamic index) => setIsTime(index as int), - ), - if (!withoutTime) ...[ - SetTimeSection( - minutesStartValue: durationOfGame, - minutesOnChanged: (dynamic value) => setMinutes(value as int), - secondsStartValue: addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : addingOfMove, - secondsOnChanged: (dynamic value) => setSeconds(value as int), - ) + const SizedBox(height: 120), + SettingsRowsSection( + choseMoveBack: isMoveBack, + moveBackOnChanged: setIsMoveBack, + choseThreats: isThreats, + threatsOnChanged: setIsThreats, + choseHints: isHints, + hintsOnChanged: setIsHints, + ), + const SizedBox(height: 100), ], - SettingsRowsSection( - choseMoveBack: isMoveBack, - moveBackOnChanged: setIsMoveBack, - choseThreats: isThreats, - threatsOnChanged: setIsThreats, - choseHints: isHints, - hintsOnChanged: setIsHints, - ), - const SizedBox(height: 100), - ], + ), ), ), ), - ), Align( alignment: Alignment.bottomCenter, child: Container( diff --git a/frontend/lib/views/setting_view/game_settings_view.dart b/frontend/lib/views/setting_view/game_settings_view.dart index 00cf54d..c463e89 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -171,7 +171,6 @@ class _GameSettingsViewState extends State final isTablet = constraints.maxWidth >= 640; return isTablet ? GameSettingsTablet( - gameModel: widget.gameModel, withoutTime: withoutTime, durationOfGame: durationOfGame, addingOfMove: addingOfMove, @@ -187,7 +186,6 @@ class _GameSettingsViewState extends State onStartGame: () => _handleStartGame(context), ) : GameSettingsMobile( - gameModel: widget.gameModel, withoutTime: withoutTime, durationOfGame: durationOfGame, addingOfMove: addingOfMove, From 4080f3f22a6c750227ce1567ced8d929b41f4b84 Mon Sep 17 00:00:00 2001 From: EkaterinaMarkina-1 Date: Wed, 21 May 2025 23:17:27 +0600 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B9=D0=BA=D0=B0=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=20=D1=8D=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D1=8D=D0=BA=D1=80=D0=B0=D0=BD=D0=B5=20=D0=B8?= =?UTF-8?q?=20=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B0=D1=81=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=B5=D0=B6=D0=B4=D1=83=20=D0=BD=D0=B8=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setting_view/components/app_bar_settings.dart | 12 +++++++++--- .../setting_view/components/chose_time_carousel.dart | 1 + .../views/setting_view/components/settings_row.dart | 12 ++++++++++-- .../components/settings_rows_section.dart | 7 +++++++ .../views/setting_view/components/text_heading.dart | 12 +++++++++++- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/frontend/lib/views/setting_view/components/app_bar_settings.dart b/frontend/lib/views/setting_view/components/app_bar_settings.dart index bed9a94..a1687ec 100644 --- a/frontend/lib/views/setting_view/components/app_bar_settings.dart +++ b/frontend/lib/views/setting_view/components/app_bar_settings.dart @@ -6,17 +6,22 @@ class AppBarSettings extends StatelessWidget { const AppBarSettings({super.key, required this.label}); final String label; + bool _isTablet(BuildContext context) { + final shortestSide = MediaQuery.of(context).size.shortestSide; + return shortestSide > 640; + } @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final isTablet = _isTablet(context); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CustomIconButton( iconName: "assets/images/icons/left_big_arrow_icon.svg", color: scheme.onTertiary, - iconSize: 40, + iconSize: isTablet ? 50 : 40, onTap: () { context.go(RouteLocations.homeScreen); }, @@ -25,12 +30,13 @@ class AppBarSettings extends StatelessWidget { label, style: TextStyles.body1.copyWith( color: scheme.primary, + fontSize: isTablet ? 30 : 20, ), ), ButtonToGuide( backGroundColor: scheme.outlineVariant, - height: 40, - width: 40, + height: isTablet ? 50 : 40, + width: isTablet ? 50 : 40, onTap: () { context.push(RouteLocations.guidebookScreen); }, diff --git a/frontend/lib/views/setting_view/components/chose_time_carousel.dart b/frontend/lib/views/setting_view/components/chose_time_carousel.dart index b65b5f3..31d28fb 100644 --- a/frontend/lib/views/setting_view/components/chose_time_carousel.dart +++ b/frontend/lib/views/setting_view/components/chose_time_carousel.dart @@ -47,6 +47,7 @@ class _ChoseTimeCarouselState extends State { textAlign: TextAlign.center, style: TextStyles.header2.copyWith( color: scheme.primary, + fontSize: MediaQuery.of(context).size.width > 640 ? 24 : 16, ), ), Center( diff --git a/frontend/lib/views/setting_view/components/settings_row.dart b/frontend/lib/views/setting_view/components/settings_row.dart index 4ecdaaf..968f007 100644 --- a/frontend/lib/views/setting_view/components/settings_row.dart +++ b/frontend/lib/views/setting_view/components/settings_row.dart @@ -11,6 +11,7 @@ class SettingsRow extends StatelessWidget { required this.modalHeader, this.choseDiffWidget, this.onChanged, + this.forceTabletLayout, }); final bool? chose; @@ -18,11 +19,17 @@ class SettingsRow extends StatelessWidget { final String modalHeader; final Widget? choseDiffWidget; final void Function(bool)? onChanged; + final bool? forceTabletLayout; + + bool _isTablet(BuildContext context) { + return forceTabletLayout ?? MediaQuery.of(context).size.width >= 640; + } @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; final isPro = context.watch().isPro; + final isTablet = _isTablet(context); return Padding( padding: const EdgeInsets.only(bottom: 8), child: SizedBox( @@ -36,10 +43,11 @@ class SettingsRow extends StatelessWidget { text, style: TextStyles.body2.copyWith( color: isPro ? scheme.primary : ColorsConst.disabledColor, + fontSize: isTablet ? 25 : 16, ), ), - const SizedBox( - width: 10, + SizedBox( + width: isTablet ? 16 : 10 ), ProFunctionsTooltip( isPro: isPro, diff --git a/frontend/lib/views/setting_view/components/settings_rows_section.dart b/frontend/lib/views/setting_view/components/settings_rows_section.dart index 1e75714..d27f2a4 100644 --- a/frontend/lib/views/setting_view/components/settings_rows_section.dart +++ b/frontend/lib/views/setting_view/components/settings_rows_section.dart @@ -19,8 +19,14 @@ class SettingsRowsSection extends StatelessWidget { final bool choseHints; final void Function(bool)? hintsOnChanged; + bool _isTablet(BuildContext context) { + final shortestSide = MediaQuery.of(context).size.shortestSide; + return shortestSide >= 640; + } + @override Widget build(BuildContext context) { + final isTablet = _isTablet(context); final l10n = AppLocalizations.of(context)!; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -32,6 +38,7 @@ class SettingsRowsSection extends StatelessWidget { l10n.gameSettings, style: TextStyles.title3.copyWith( color: Theme.of(context).colorScheme.primary, + fontSize: isTablet ? 45 : null, ), ), ), diff --git a/frontend/lib/views/setting_view/components/text_heading.dart b/frontend/lib/views/setting_view/components/text_heading.dart index 724474d..f1be3b7 100644 --- a/frontend/lib/views/setting_view/components/text_heading.dart +++ b/frontend/lib/views/setting_view/components/text_heading.dart @@ -6,21 +6,31 @@ class TextHeading extends StatelessWidget { {super.key, required this.text, required this.topMargin, - required this.bottomMargin}); + required this.bottomMargin, + this.style, + }); final String text; final double topMargin; final double bottomMargin; + final TextStyle? style; + + bool _isTablet(BuildContext context) { + final shortestSide = MediaQuery.of(context).size.shortestSide; + return shortestSide >= 640; + } @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final isTablet = _isTablet(context); return Container( margin: EdgeInsets.only(top: topMargin, bottom: bottomMargin), child: Text( text, style: TextStyles.title3.copyWith( color: scheme.primary, + fontSize: isTablet ? 45 : TextStyles.title3.fontSize, ), ), ); From ed2ebf51d46b8194c8cc46bfc6667572d1b69230 Mon Sep 17 00:00:00 2001 From: EkaterinaMarkina-1 Date: Sat, 24 May 2025 21:29:23 +0600 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=D1=81=D0=BF=D0=BB=D1=8B=D0=B2?= =?UTF-8?q?=D0=B0=D1=8E=D1=89=D0=B5=D0=B3=D0=BE=20=D0=BE=D0=BA=D0=BD=D0=B0?= =?UTF-8?q?=20=D1=81=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B5=D0=B9=20=D0=BE=20pro-=D0=BF=D0=BE=D0=B4=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=B5=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BF=D1=8B=D1=82=D0=BA=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=BE=D0=B2=20=D0=B8=D0=B3=D1=80?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/pro_functions_tooltip.dart | 27 +++++++----- .../setting_view/components/settings_row.dart | 43 +++++++++++++++---- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/frontend/lib/views/components/pro_functions_tooltip.dart b/frontend/lib/views/components/pro_functions_tooltip.dart index fef1d50..2f87e88 100644 --- a/frontend/lib/views/components/pro_functions_tooltip.dart +++ b/frontend/lib/views/components/pro_functions_tooltip.dart @@ -10,18 +10,26 @@ class ProFunctionsTooltip extends StatefulWidget { required this.modalHeader, required this.child, required this.isPro, + this.controller, }); final String modalHeader; final Widget child; final bool isPro; + final SuperTooltipController? controller; @override State createState() => _ProFunctionsTooltipState(); } class _ProFunctionsTooltipState extends State { - final _controller = SuperTooltipController(); + late final SuperTooltipController _controller; + + @override + void initState() { + super.initState(); + _controller = widget.controller ?? SuperTooltipController(); + } @override Widget build(BuildContext context) { @@ -38,7 +46,7 @@ class _ProFunctionsTooltipState extends State { popupDirection: TooltipDirection.up, content: DecoratedBox( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), color: Colors.white), + borderRadius: BorderRadius.circular(16), color: Colors.white), child: Padding( padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 32), child: Column( @@ -62,14 +70,13 @@ class _ProFunctionsTooltipState extends State { ), ), ), - !widget.isPro - ? UpgradeToProButton( - onTap: () { - _controller.hideTooltip(); - context.push(RouteLocations.promoScreen); - }, - ) - : const SizedBox.shrink() + if (!widget.isPro) + UpgradeToProButton( + onTap: () { + _controller.hideTooltip(); + context.push(RouteLocations.promoScreen); + }, + ) ], ), ), diff --git a/frontend/lib/views/setting_view/components/settings_row.dart b/frontend/lib/views/setting_view/components/settings_row.dart index 968f007..efbd94c 100644 --- a/frontend/lib/views/setting_view/components/settings_row.dart +++ b/frontend/lib/views/setting_view/components/settings_row.dart @@ -2,8 +2,9 @@ import "package:flutter/material.dart"; import "package:flutter_svg/flutter_svg.dart"; import "package:frontend/exports.dart"; import "package:provider/provider.dart"; +import "package:super_tooltip/super_tooltip.dart"; -class SettingsRow extends StatelessWidget { +class SettingsRow extends StatefulWidget { const SettingsRow({ super.key, this.chose, @@ -21,8 +22,27 @@ class SettingsRow extends StatelessWidget { final void Function(bool)? onChanged; final bool? forceTabletLayout; + @override + State createState() => _SettingsRowState(); +} + +class _SettingsRowState extends State { + late final SuperTooltipController _tooltipController; + + @override + void initState() { + super.initState(); + _tooltipController = SuperTooltipController(); + } + + @override + void dispose() { + _tooltipController.dispose(); + super.dispose(); + } + bool _isTablet(BuildContext context) { - return forceTabletLayout ?? MediaQuery.of(context).size.width >= 640; + return widget.forceTabletLayout ?? MediaQuery.of(context).size.width >= 640; } @override @@ -40,7 +60,7 @@ class SettingsRow extends StatelessWidget { Row( children: [ Text( - text, + widget.text, style: TextStyles.body2.copyWith( color: isPro ? scheme.primary : ColorsConst.disabledColor, fontSize: isTablet ? 25 : 16, @@ -51,11 +71,12 @@ class SettingsRow extends StatelessWidget { ), ProFunctionsTooltip( isPro: isPro, - modalHeader: modalHeader, + modalHeader: widget.modalHeader, + controller: _tooltipController, child: SvgPicture.asset( "assets/images/icons/question_icon.svg", colorFilter: ColorFilter.mode( - isPro + isPro ? scheme.tertiaryContainer : ColorsConst.disabledColor, BlendMode.srcIn), @@ -67,15 +88,21 @@ class SettingsRow extends StatelessWidget { data: ThemeData(useMaterial3: false), child: Switch( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - value: isPro ? chose! : false, + value: isPro ? widget.chose! : false, inactiveThumbColor: isPro ? scheme.surfaceTint : ColorsConst.disabledColor, inactiveTrackColor: scheme.outline, activeColor: scheme.inversePrimary, activeTrackColor: ColorsConst.primaryColor100, - onChanged: onChanged, + onChanged: (value) { + if (isPro) { + widget.onChanged?.call(value); + } else { + _tooltipController.showTooltip(); + } + }, ), - ) + ), ], ), ), From 027fab575ff44a9449c919095cbef4427f6ab57e Mon Sep 17 00:00:00 2001 From: neekeetuh Date: Mon, 2 Jun 2025 19:17:21 +0600 Subject: [PATCH 5/7] =?UTF-8?q?refactor:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/common/shared_functions.dart | 8 ++ frontend/lib/router/router.dart | 5 +- .../components/pro_functions_tooltip.dart | 12 ++- .../components/app_bar_settings.dart | 7 +- .../setting_view/components/settings_row.dart | 60 ++++------- .../components/settings_rows_section.dart | 40 +++---- .../setting_view/components/text_heading.dart | 28 +++-- .../setting_view/game_settings_mobile.dart | 64 ++++------- .../setting_view/game_settings_tablet.dart | 102 +++++++----------- .../setting_view/game_settings_view.dart | 55 +++------- 10 files changed, 136 insertions(+), 245 deletions(-) create mode 100644 frontend/lib/common/shared_functions.dart diff --git a/frontend/lib/common/shared_functions.dart b/frontend/lib/common/shared_functions.dart new file mode 100644 index 0000000..e516994 --- /dev/null +++ b/frontend/lib/common/shared_functions.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +sealed class SharedFunctions { + static bool isTablet(BuildContext context) { + final shortestSide = MediaQuery.of(context).size.shortestSide; + return shortestSide >= 640; + } +} diff --git a/frontend/lib/router/router.dart b/frontend/lib/router/router.dart index 49715cf..f6d380d 100644 --- a/frontend/lib/router/router.dart +++ b/frontend/lib/router/router.dart @@ -69,7 +69,10 @@ final shellRoutes = [ path: RouteLocations.settingsScreen, parentNavigatorKey: shellNavigatorKey, builder: (BuildContext context, GoRouterState state) { - return GameSettingsView(state.extra as GameModel); + return GameSettingsView( + state.extra as GameModel, + key: gameSettingsViewStateKey, + ); }, ), GoRoute( diff --git a/frontend/lib/views/components/pro_functions_tooltip.dart b/frontend/lib/views/components/pro_functions_tooltip.dart index 2f87e88..64fa7d9 100644 --- a/frontend/lib/views/components/pro_functions_tooltip.dart +++ b/frontend/lib/views/components/pro_functions_tooltip.dart @@ -10,13 +10,11 @@ class ProFunctionsTooltip extends StatefulWidget { required this.modalHeader, required this.child, required this.isPro, - this.controller, }); final String modalHeader; final Widget child; final bool isPro; - final SuperTooltipController? controller; @override State createState() => _ProFunctionsTooltipState(); @@ -28,7 +26,13 @@ class _ProFunctionsTooltipState extends State { @override void initState() { super.initState(); - _controller = widget.controller ?? SuperTooltipController(); + _controller = SuperTooltipController(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); } @override @@ -46,7 +50,7 @@ class _ProFunctionsTooltipState extends State { popupDirection: TooltipDirection.up, content: DecoratedBox( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), color: Colors.white), + borderRadius: BorderRadius.circular(16), color: Colors.white), child: Padding( padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 32), child: Column( diff --git a/frontend/lib/views/setting_view/components/app_bar_settings.dart b/frontend/lib/views/setting_view/components/app_bar_settings.dart index a1687ec..6ed2754 100644 --- a/frontend/lib/views/setting_view/components/app_bar_settings.dart +++ b/frontend/lib/views/setting_view/components/app_bar_settings.dart @@ -1,4 +1,5 @@ import "package:flutter/material.dart"; +import "package:frontend/common/shared_functions.dart"; import "package:go_router/go_router.dart"; import "../../../exports.dart"; @@ -6,15 +7,11 @@ class AppBarSettings extends StatelessWidget { const AppBarSettings({super.key, required this.label}); final String label; - bool _isTablet(BuildContext context) { - final shortestSide = MediaQuery.of(context).size.shortestSide; - return shortestSide > 640; - } @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; - final isTablet = _isTablet(context); + final isTablet = SharedFunctions.isTablet(context); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/frontend/lib/views/setting_view/components/settings_row.dart b/frontend/lib/views/setting_view/components/settings_row.dart index efbd94c..dc7ec97 100644 --- a/frontend/lib/views/setting_view/components/settings_row.dart +++ b/frontend/lib/views/setting_view/components/settings_row.dart @@ -1,8 +1,8 @@ import "package:flutter/material.dart"; import "package:flutter_svg/flutter_svg.dart"; +import "package:frontend/common/shared_functions.dart"; import "package:frontend/exports.dart"; import "package:provider/provider.dart"; -import "package:super_tooltip/super_tooltip.dart"; class SettingsRow extends StatefulWidget { const SettingsRow({ @@ -12,7 +12,6 @@ class SettingsRow extends StatefulWidget { required this.modalHeader, this.choseDiffWidget, this.onChanged, - this.forceTabletLayout, }); final bool? chose; @@ -20,36 +19,17 @@ class SettingsRow extends StatefulWidget { final String modalHeader; final Widget? choseDiffWidget; final void Function(bool)? onChanged; - final bool? forceTabletLayout; @override State createState() => _SettingsRowState(); } class _SettingsRowState extends State { - late final SuperTooltipController _tooltipController; - - @override - void initState() { - super.initState(); - _tooltipController = SuperTooltipController(); - } - - @override - void dispose() { - _tooltipController.dispose(); - super.dispose(); - } - - bool _isTablet(BuildContext context) { - return widget.forceTabletLayout ?? MediaQuery.of(context).size.width >= 640; - } - @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; final isPro = context.watch().isPro; - final isTablet = _isTablet(context); + final isTablet = SharedFunctions.isTablet(context); return Padding( padding: const EdgeInsets.only(bottom: 8), child: SizedBox( @@ -66,17 +46,14 @@ class _SettingsRowState extends State { fontSize: isTablet ? 25 : 16, ), ), - SizedBox( - width: isTablet ? 16 : 10 - ), + SizedBox(width: isTablet ? 16 : 10), ProFunctionsTooltip( isPro: isPro, modalHeader: widget.modalHeader, - controller: _tooltipController, child: SvgPicture.asset( "assets/images/icons/question_icon.svg", colorFilter: ColorFilter.mode( - isPro + isPro ? scheme.tertiaryContainer : ColorsConst.disabledColor, BlendMode.srcIn), @@ -86,21 +63,20 @@ class _SettingsRowState extends State { ), Theme( data: ThemeData(useMaterial3: false), - child: Switch( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - value: isPro ? widget.chose! : false, - inactiveThumbColor: - isPro ? scheme.surfaceTint : ColorsConst.disabledColor, - inactiveTrackColor: scheme.outline, - activeColor: scheme.inversePrimary, - activeTrackColor: ColorsConst.primaryColor100, - onChanged: (value) { - if (isPro) { - widget.onChanged?.call(value); - } else { - _tooltipController.showTooltip(); - } - }, + child: ProFunctionsTooltip( + isPro: isPro, + modalHeader: widget.modalHeader, + child: Switch( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + value: isPro ? widget.chose! : false, + inactiveThumbColor: + isPro ? scheme.surfaceTint : ColorsConst.disabledColor, + inactiveTrackColor: scheme.outline, + activeColor: scheme.inversePrimary, + activeTrackColor: ColorsConst.primaryColor100, + onChanged: + isPro ? (value) => widget.onChanged?.call(value) : null, + ), ), ), ], diff --git a/frontend/lib/views/setting_view/components/settings_rows_section.dart b/frontend/lib/views/setting_view/components/settings_rows_section.dart index d27f2a4..fc1ba5f 100644 --- a/frontend/lib/views/setting_view/components/settings_rows_section.dart +++ b/frontend/lib/views/setting_view/components/settings_rows_section.dart @@ -1,32 +1,16 @@ import 'package:flutter/material.dart'; +import 'package:frontend/common/shared_functions.dart'; import 'package:frontend/exports.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SettingsRowsSection extends StatelessWidget { - const SettingsRowsSection( - {super.key, - required this.choseMoveBack, - required this.moveBackOnChanged, - required this.choseThreats, - required this.threatsOnChanged, - required this.choseHints, - required this.hintsOnChanged}); - - final bool choseMoveBack; - final void Function(bool)? moveBackOnChanged; - final bool choseThreats; - final void Function(bool)? threatsOnChanged; - final bool choseHints; - final void Function(bool)? hintsOnChanged; - - bool _isTablet(BuildContext context) { - final shortestSide = MediaQuery.of(context).size.shortestSide; - return shortestSide >= 640; - } + const SettingsRowsSection({ + super.key, + }); @override Widget build(BuildContext context) { - final isTablet = _isTablet(context); + final settingsState = gameSettingsViewStateKey.currentState; final l10n = AppLocalizations.of(context)!; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -38,7 +22,7 @@ class SettingsRowsSection extends StatelessWidget { l10n.gameSettings, style: TextStyles.title3.copyWith( color: Theme.of(context).colorScheme.primary, - fontSize: isTablet ? 45 : null, + fontSize: SharedFunctions.isTablet(context) ? 45 : null, ), ), ), @@ -46,22 +30,22 @@ class SettingsRowsSection extends StatelessWidget { Column( children: [ SettingsRow( - chose: choseMoveBack, + chose: settingsState?.isMoveBack, text: l10n.undoMoves, modalHeader: l10n.undoMovesDescription, - onChanged: moveBackOnChanged, + onChanged: settingsState?.setIsMoveBack, ), SettingsRow( - chose: choseThreats, + chose: settingsState?.isThreats, text: l10n.threats, modalHeader: l10n.threatsDescription, - onChanged: threatsOnChanged, + onChanged: settingsState?.setIsThreats, ), SettingsRow( - chose: choseHints, + chose: settingsState?.isHints, text: l10n.hints, modalHeader: l10n.hintsDescription, - onChanged: hintsOnChanged, + onChanged: settingsState?.setIsHints, ) ], ), diff --git a/frontend/lib/views/setting_view/components/text_heading.dart b/frontend/lib/views/setting_view/components/text_heading.dart index f1be3b7..4dfa656 100644 --- a/frontend/lib/views/setting_view/components/text_heading.dart +++ b/frontend/lib/views/setting_view/components/text_heading.dart @@ -1,36 +1,32 @@ import "package:flutter/material.dart"; +import "package:frontend/common/shared_functions.dart"; import "package:frontend/exports.dart"; class TextHeading extends StatelessWidget { - const TextHeading( - {super.key, - required this.text, - required this.topMargin, - required this.bottomMargin, - this.style, - }); + const TextHeading({ + super.key, + required this.text, + required this.topMargin, + required this.bottomMargin, + this.style, + }); final String text; final double topMargin; final double bottomMargin; final TextStyle? style; - bool _isTablet(BuildContext context) { - final shortestSide = MediaQuery.of(context).size.shortestSide; - return shortestSide >= 640; - } - @override Widget build(BuildContext context) { - final scheme = Theme.of(context).colorScheme; - final isTablet = _isTablet(context); return Container( margin: EdgeInsets.only(top: topMargin, bottom: bottomMargin), child: Text( text, style: TextStyles.title3.copyWith( - color: scheme.primary, - fontSize: isTablet ? 45 : TextStyles.title3.fontSize, + color: Theme.of(context).colorScheme.primary, + fontSize: SharedFunctions.isTablet(context) + ? 45 + : TextStyles.title3.fontSize, ), ), ); diff --git a/frontend/lib/views/setting_view/game_settings_mobile.dart b/frontend/lib/views/setting_view/game_settings_mobile.dart index b67262c..1d36311 100644 --- a/frontend/lib/views/setting_view/game_settings_mobile.dart +++ b/frontend/lib/views/setting_view/game_settings_mobile.dart @@ -1,40 +1,14 @@ part of 'game_settings_view.dart'; class GameSettingsMobile extends StatelessWidget { - final bool withoutTime; - final int durationOfGame; - final int addingOfMove; - final bool isMoveBack; - final bool isThreats; - final bool isHints; - final void Function(int) setIsTime; - final void Function(int) setMinutes; - final void Function(int) setSeconds; - final void Function(bool) setIsMoveBack; - final void Function(bool) setIsThreats; - final void Function(bool) setIsHints; - final VoidCallback onStartGame; - const GameSettingsMobile({ super.key, - required this.withoutTime, - required this.durationOfGame, - required this.addingOfMove, - required this.isMoveBack, - required this.isThreats, - required this.isHints, - required this.setIsTime, - required this.setMinutes, - required this.setSeconds, - required this.setIsMoveBack, - required this.setIsThreats, - required this.setIsHints, - required this.onStartGame, }); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final settingsState = gameSettingsViewStateKey.currentState; return DefaultTabController( length: 2, child: Scaffold( @@ -50,39 +24,39 @@ class GameSettingsMobile extends StatelessWidget { ), child: IntrinsicHeight( child: Padding( - padding: const EdgeInsets.only(left: 24, right: 24, top: 24), + padding: + const EdgeInsets.only(left: 24, right: 24, top: 24), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ AppBarSettings(label: GameSettingConsts.appBarLabel), CustomTabBar( - initialIndex: withoutTime ? 0 : 1, + initialIndex: settingsState!.withoutTime ? 0 : 1, header: GameSettingConsts.timeText, subTitles: [ GameSettingConsts.gameWithoutTimeText, GameSettingConsts.gameWithTimeText, ], isSettingsPage: true, - onTap: (dynamic index) => setIsTime(index as int), + onTap: (dynamic index) => gameSettingsViewStateKey + .currentState + ?.setIsTime(index as int), ), - if (!withoutTime) ...[ + if (!settingsState.withoutTime) ...[ SetTimeSection( - minutesStartValue: durationOfGame, - minutesOnChanged: (dynamic value) => setMinutes(value as int), - secondsStartValue: addingOfMove == 0 + minutesStartValue: settingsState.durationOfGame, + minutesOnChanged: (dynamic value) => + gameSettingsViewStateKey.currentState + ?.setMinutes(value as int), + secondsStartValue: settingsState.addingOfMove == 0 ? GameSettingConsts.longDashSymbol - : addingOfMove, - secondsOnChanged: (dynamic value) => setSeconds(value as int), + : settingsState.addingOfMove, + secondsOnChanged: (dynamic value) => + gameSettingsViewStateKey.currentState + ?.setSeconds(value as int), ) ], - SettingsRowsSection( - choseMoveBack: isMoveBack, - moveBackOnChanged: setIsMoveBack, - choseThreats: isThreats, - threatsOnChanged: setIsThreats, - choseHints: isHints, - hintsOnChanged: setIsHints, - ), + const SettingsRowsSection(), const SizedBox(height: 100), ], ), @@ -106,7 +80,7 @@ class GameSettingsMobile extends StatelessWidget { textColor: ColorsConst.primaryColor0, buttonColor: scheme.secondaryContainer, isClickable: true, - onTap: onStartGame, + onTap: () => settingsState.handleStartGame(context), ), ), ), diff --git a/frontend/lib/views/setting_view/game_settings_tablet.dart b/frontend/lib/views/setting_view/game_settings_tablet.dart index 06d3e8a..1165c9b 100644 --- a/frontend/lib/views/setting_view/game_settings_tablet.dart +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -1,37 +1,13 @@ part of 'game_settings_view.dart'; + class GameSettingsTablet extends StatelessWidget { - final bool withoutTime; - final int durationOfGame; - final int addingOfMove; - final bool isMoveBack; - final bool isThreats; - final bool isHints; - final void Function(int) setIsTime; - final void Function(int) setMinutes; - final void Function(int) setSeconds; - final void Function(bool) setIsMoveBack; - final void Function(bool) setIsThreats; - final void Function(bool) setIsHints; - final VoidCallback onStartGame; const GameSettingsTablet({ super.key, - required this.withoutTime, - required this.durationOfGame, - required this.addingOfMove, - required this.isMoveBack, - required this.isThreats, - required this.isHints, - required this.setIsTime, - required this.setMinutes, - required this.setSeconds, - required this.setIsMoveBack, - required this.setIsThreats, - required this.setIsHints, - required this.onStartGame, }); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final settingsState = gameSettingsViewStateKey.currentState; return DefaultTabController( length: 2, child: Scaffold( @@ -44,48 +20,46 @@ class GameSettingsTablet extends StatelessWidget { constraints: BoxConstraints( minHeight: MediaQuery.of(context).size.height, ), - child: Padding( - padding: const EdgeInsets.only(left: 24, right: 24, top: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AppBarSettings(label: GameSettingConsts.appBarLabel), - CustomTabBar( - initialIndex: withoutTime ? 0 : 1, - header: GameSettingConsts.timeText, - subTitles: [ - GameSettingConsts.gameWithoutTimeText, - GameSettingConsts.gameWithTimeText, - ], - isSettingsPage: true, - onTap: (dynamic index) => setIsTime(index as int), - ), - if (!withoutTime) ...[ - const SizedBox(height: 70), - SetTimeSection( - minutesStartValue: durationOfGame, - minutesOnChanged: (dynamic value) => setMinutes(value as int), - secondsStartValue: addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : addingOfMove, - secondsOnChanged: (dynamic value) => setSeconds(value as int), - ) + child: Padding( + padding: + const EdgeInsets.only(left: 24, right: 24, top: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings(label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: settingsState!.withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, ], - const SizedBox(height: 120), - SettingsRowsSection( - choseMoveBack: isMoveBack, - moveBackOnChanged: setIsMoveBack, - choseThreats: isThreats, - threatsOnChanged: setIsThreats, - choseHints: isHints, - hintsOnChanged: setIsHints, - ), - const SizedBox(height: 100), + isSettingsPage: true, + onTap: (dynamic index) => gameSettingsViewStateKey + .currentState + ?.setIsTime(index as int), + ), + if (!settingsState.withoutTime) ...[ + const SizedBox(height: 70), + SetTimeSection( + minutesStartValue: settingsState.durationOfGame, + minutesOnChanged: (dynamic value) => + settingsState.setMinutes(value as int), + secondsStartValue: settingsState.addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : settingsState.addingOfMove, + secondsOnChanged: (dynamic value) => + settingsState.setSeconds(value as int), + ) ], - ), + const SizedBox(height: 120), + const SettingsRowsSection(), + const SizedBox(height: 100), + ], ), ), ), + ), Align( alignment: Alignment.bottomCenter, child: Container( @@ -102,7 +76,7 @@ class GameSettingsTablet extends StatelessWidget { textColor: ColorsConst.primaryColor0, buttonColor: scheme.secondaryContainer, isClickable: true, - onTap: onStartGame, + onTap: () => settingsState.handleStartGame(context), ), ), ), diff --git a/frontend/lib/views/setting_view/game_settings_view.dart b/frontend/lib/views/setting_view/game_settings_view.dart index c463e89..15cca91 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -1,4 +1,5 @@ import "package:flutter/material.dart"; +import "package:frontend/common/shared_functions.dart"; import "package:go_router/go_router.dart"; import "package:sqflite/sqflite.dart"; @@ -11,10 +12,13 @@ class GameSettingsView extends StatefulWidget { final GameModel gameModel; @override - State createState() => _GameSettingsViewState(); + State createState() => GameSettingsViewState(); } -class _GameSettingsViewState extends State +GlobalKey gameSettingsViewStateKey = + GlobalKey(); + +class GameSettingsViewState extends State with TickerProviderStateMixin { bool isLoading = true; bool isDBNotEmpty = false; @@ -137,12 +141,12 @@ class _GameSettingsViewState extends State await database.close(); } - Future _handleStartGame(BuildContext context) async { - if (isSettingsEdited) await setSettings(); - if (!context.mounted) return; - widget.gameModel.newGame(context, notify: false); - context.go(RouteLocations.gameScreen, extra: widget.gameModel); -} + Future handleStartGame(BuildContext context) async { + if (isSettingsEdited) await setSettings(); + if (!context.mounted) return; + widget.gameModel.newGame(context, notify: false); + context.go(RouteLocations.gameScreen, extra: widget.gameModel); + } void onInit() async { var databasesPath = await getDatabasesPath(); @@ -168,38 +172,9 @@ class _GameSettingsViewState extends State if (isLoading) return const LoadingWidget(); return LayoutBuilder( builder: (context, constraints) { - final isTablet = constraints.maxWidth >= 640; - return isTablet - ? GameSettingsTablet( - withoutTime: withoutTime, - durationOfGame: durationOfGame, - addingOfMove: addingOfMove, - isMoveBack: isMoveBack, - isThreats: isThreats, - isHints: isHints, - setIsTime: setIsTime, - setMinutes: setMinutes, - setSeconds: setSeconds, - setIsMoveBack: setIsMoveBack, - setIsThreats: setIsThreats, - setIsHints: setIsHints, - onStartGame: () => _handleStartGame(context), - ) - : GameSettingsMobile( - withoutTime: withoutTime, - durationOfGame: durationOfGame, - addingOfMove: addingOfMove, - isMoveBack: isMoveBack, - isThreats: isThreats, - isHints: isHints, - setIsTime: setIsTime, - setMinutes: setMinutes, - setSeconds: setSeconds, - setIsMoveBack: setIsMoveBack, - setIsThreats: setIsThreats, - setIsHints: setIsHints, - onStartGame: () => _handleStartGame(context), - ); + return SharedFunctions.isTablet(context) + ? const GameSettingsTablet() + : const GameSettingsMobile(); }, ); } From a18f0593202d8d68a238cf7aa37656652cd0c8d9 Mon Sep 17 00:00:00 2001 From: neekeetuh Date: Mon, 2 Jun 2025 21:07:26 +0600 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=20stateful=20=D0=B2=D0=B8=D0=B4=D0=B6=D0=B5=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8=20=D0=B8=D0=B3=D1=80=D1=8B=20=D0=BD=D0=B0=20change?= =?UTF-8?q?=20notifier=20=D0=B4=D0=BB=D1=8F=20=D0=B1=D0=BE=D0=BB=D0=B5?= =?UTF-8?q?=D0=B5=20=D1=83=D0=B4=D0=BE=D0=B1=D0=BD=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=B4=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=B0=20=D0=B8=D0=B7=20?= =?UTF-8?q?=D0=BB=D1=8E=D0=B1=D0=BE=D0=B9=20=D1=87=D0=B0=D1=81=D1=82=D0=B8?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B5=D0=B2=D0=B0=20?= =?UTF-8?q?=D0=B2=D0=B8=D0=B4=D0=B6=D0=B5=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/lib/router/router.dart | 3 +- .../components/settings_rows_section.dart | 48 ++--- .../setting_view/game_settings_mobile.dart | 76 ++++---- .../setting_view/game_settings_tablet.dart | 76 ++++---- .../setting_view/game_settings_view.dart | 184 ++---------------- .../providers/game_settings_provider.dart | 142 ++++++++++++++ 6 files changed, 267 insertions(+), 262 deletions(-) create mode 100644 frontend/lib/views/setting_view/providers/game_settings_provider.dart diff --git a/frontend/lib/router/router.dart b/frontend/lib/router/router.dart index f6d380d..c1abb7a 100644 --- a/frontend/lib/router/router.dart +++ b/frontend/lib/router/router.dart @@ -70,8 +70,7 @@ final shellRoutes = [ parentNavigatorKey: shellNavigatorKey, builder: (BuildContext context, GoRouterState state) { return GameSettingsView( - state.extra as GameModel, - key: gameSettingsViewStateKey, + gameModel: state.extra as GameModel, ); }, ), diff --git a/frontend/lib/views/setting_view/components/settings_rows_section.dart b/frontend/lib/views/setting_view/components/settings_rows_section.dart index fc1ba5f..5a9d4f7 100644 --- a/frontend/lib/views/setting_view/components/settings_rows_section.dart +++ b/frontend/lib/views/setting_view/components/settings_rows_section.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:frontend/common/shared_functions.dart'; import 'package:frontend/exports.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:frontend/views/setting_view/providers/game_settings_provider.dart'; +import 'package:provider/provider.dart'; class SettingsRowsSection extends StatelessWidget { const SettingsRowsSection({ @@ -10,7 +12,6 @@ class SettingsRowsSection extends StatelessWidget { @override Widget build(BuildContext context) { - final settingsState = gameSettingsViewStateKey.currentState; final l10n = AppLocalizations.of(context)!; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -27,28 +28,29 @@ class SettingsRowsSection extends StatelessWidget { ), ), ), - Column( - children: [ - SettingsRow( - chose: settingsState?.isMoveBack, - text: l10n.undoMoves, - modalHeader: l10n.undoMovesDescription, - onChanged: settingsState?.setIsMoveBack, - ), - SettingsRow( - chose: settingsState?.isThreats, - text: l10n.threats, - modalHeader: l10n.threatsDescription, - onChanged: settingsState?.setIsThreats, - ), - SettingsRow( - chose: settingsState?.isHints, - text: l10n.hints, - modalHeader: l10n.hintsDescription, - onChanged: settingsState?.setIsHints, - ) - ], - ), + Consumer( + builder: (_, provider, __) => Column( + children: [ + SettingsRow( + chose: provider.isMoveBack, + text: l10n.undoMoves, + modalHeader: l10n.undoMovesDescription, + onChanged: provider.setIsMoveBack, + ), + SettingsRow( + chose: provider.isThreats, + text: l10n.threats, + modalHeader: l10n.threatsDescription, + onChanged: provider.setIsThreats, + ), + SettingsRow( + chose: provider.isHints, + text: l10n.hints, + modalHeader: l10n.hintsDescription, + onChanged: provider.setIsHints, + ) + ], + )), ], ); } diff --git a/frontend/lib/views/setting_view/game_settings_mobile.dart b/frontend/lib/views/setting_view/game_settings_mobile.dart index 1d36311..99c7cc4 100644 --- a/frontend/lib/views/setting_view/game_settings_mobile.dart +++ b/frontend/lib/views/setting_view/game_settings_mobile.dart @@ -8,7 +8,6 @@ class GameSettingsMobile extends StatelessWidget { @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; - final settingsState = gameSettingsViewStateKey.currentState; return DefaultTabController( length: 2, child: Scaffold( @@ -26,40 +25,43 @@ class GameSettingsMobile extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(left: 24, right: 24, top: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AppBarSettings(label: GameSettingConsts.appBarLabel), - CustomTabBar( - initialIndex: settingsState!.withoutTime ? 0 : 1, - header: GameSettingConsts.timeText, - subTitles: [ - GameSettingConsts.gameWithoutTimeText, - GameSettingConsts.gameWithTimeText, - ], - isSettingsPage: true, - onTap: (dynamic index) => gameSettingsViewStateKey - .currentState - ?.setIsTime(index as int), - ), - if (!settingsState.withoutTime) ...[ - SetTimeSection( - minutesStartValue: settingsState.durationOfGame, - minutesOnChanged: (dynamic value) => - gameSettingsViewStateKey.currentState - ?.setMinutes(value as int), - secondsStartValue: settingsState.addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : settingsState.addingOfMove, - secondsOnChanged: (dynamic value) => - gameSettingsViewStateKey.currentState - ?.setSeconds(value as int), - ) - ], - const SettingsRowsSection(), - const SizedBox(height: 100), - ], - ), + child: Consumer( + builder: (_, settingsProvider, __) => Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings( + label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: + settingsProvider.withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, + ], + isSettingsPage: true, + onTap: (dynamic index) => settingsProvider + .setIsTime(index as int), + ), + if (!settingsProvider.withoutTime) ...[ + SetTimeSection( + minutesStartValue: + settingsProvider.durationOfGame, + minutesOnChanged: (dynamic value) => + settingsProvider + .setMinutes(value as int), + secondsStartValue: + settingsProvider.addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : settingsProvider.addingOfMove, + secondsOnChanged: (dynamic value) => + settingsProvider.setSeconds(value), + ) + ], + const SettingsRowsSection(), + const SizedBox(height: 100), + ], + )), ), ), ), @@ -80,7 +82,9 @@ class GameSettingsMobile extends StatelessWidget { textColor: ColorsConst.primaryColor0, buttonColor: scheme.secondaryContainer, isClickable: true, - onTap: () => settingsState.handleStartGame(context), + onTap: () => context + .read() + .handleStartGame(context), ), ), ), diff --git a/frontend/lib/views/setting_view/game_settings_tablet.dart b/frontend/lib/views/setting_view/game_settings_tablet.dart index 1165c9b..0cf3082 100644 --- a/frontend/lib/views/setting_view/game_settings_tablet.dart +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -7,7 +7,6 @@ class GameSettingsTablet extends StatelessWidget { @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; - final settingsState = gameSettingsViewStateKey.currentState; return DefaultTabController( length: 2, child: Scaffold( @@ -23,39 +22,46 @@ class GameSettingsTablet extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(left: 24, right: 24, top: 24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AppBarSettings(label: GameSettingConsts.appBarLabel), - CustomTabBar( - initialIndex: settingsState!.withoutTime ? 0 : 1, - header: GameSettingConsts.timeText, - subTitles: [ - GameSettingConsts.gameWithoutTimeText, - GameSettingConsts.gameWithTimeText, + child: Consumer( + builder: (_, settingsProvider, __) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings( + label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: + settingsProvider.withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, + ], + isSettingsPage: true, + onTap: (dynamic index) => + settingsProvider.setIsTime(index as int), + ), + if (!settingsProvider.withoutTime) ...[ + const SizedBox(height: 70), + SetTimeSection( + minutesStartValue: + settingsProvider.durationOfGame, + minutesOnChanged: (dynamic value) => + settingsProvider.setMinutes(value as int), + secondsStartValue: + settingsProvider.addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : settingsProvider.addingOfMove, + secondsOnChanged: (dynamic value) => + settingsProvider.setSeconds(value as int), + ) + ], + const SizedBox(height: 120), + const SettingsRowsSection(), + const SizedBox(height: 100), ], - isSettingsPage: true, - onTap: (dynamic index) => gameSettingsViewStateKey - .currentState - ?.setIsTime(index as int), - ), - if (!settingsState.withoutTime) ...[ - const SizedBox(height: 70), - SetTimeSection( - minutesStartValue: settingsState.durationOfGame, - minutesOnChanged: (dynamic value) => - settingsState.setMinutes(value as int), - secondsStartValue: settingsState.addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : settingsState.addingOfMove, - secondsOnChanged: (dynamic value) => - settingsState.setSeconds(value as int), - ) - ], - const SizedBox(height: 120), - const SettingsRowsSection(), - const SizedBox(height: 100), - ], + ); + }, ), ), ), @@ -76,7 +82,9 @@ class GameSettingsTablet extends StatelessWidget { textColor: ColorsConst.primaryColor0, buttonColor: scheme.secondaryContainer, isClickable: true, - onTap: () => settingsState.handleStartGame(context), + onTap: () => context + .read() + .handleStartGame(context), ), ), ), diff --git a/frontend/lib/views/setting_view/game_settings_view.dart b/frontend/lib/views/setting_view/game_settings_view.dart index 15cca91..aa5903b 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -1,181 +1,31 @@ import "package:flutter/material.dart"; import "package:frontend/common/shared_functions.dart"; -import "package:go_router/go_router.dart"; -import "package:sqflite/sqflite.dart"; +import "package:frontend/views/setting_view/providers/game_settings_provider.dart"; + +import "package:provider/provider.dart"; import "../../exports.dart"; part 'game_settings_mobile.dart'; part 'game_settings_tablet.dart'; -class GameSettingsView extends StatefulWidget { - const GameSettingsView(this.gameModel, {super.key}); +class GameSettingsView extends StatelessWidget { final GameModel gameModel; - - @override - State createState() => GameSettingsViewState(); -} - -GlobalKey gameSettingsViewStateKey = - GlobalKey(); - -class GameSettingsViewState extends State - with TickerProviderStateMixin { - bool isLoading = true; - bool isDBNotEmpty = false; - bool withoutTime = true; - bool isMoveBack = true; - bool isThreats = false; - bool isHints = false; - int countOfTabs = 2; - int durationOfGame = 15; - int addingOfMove = 0; - bool isSettingsEdited = false; - late String path; - - void setIsTime(int chose) { - setState(() { - isSettingsEdited = true; - withoutTime = chose == 0; - if (withoutTime) { - widget.gameModel.setTimeLimit(0); - } else { - widget.gameModel.setTimeLimit(durationOfGame); - } - }); - } - - void setMinutes(chose) { - setState(() { - if (!withoutTime) { - widget.gameModel.setTimeLimit(chose); - } - isSettingsEdited = true; - durationOfGame = chose; - }); - } - - void setSeconds(chose) { - setState(() { - isSettingsEdited = true; - addingOfMove = chose == GameSettingConsts.longDashSymbol ? 0 : chose; - widget.gameModel.setAddingOnMove(addingOfMove); - }); - } - - void setIsMoveBack(bool chose) { - setState(() { - isSettingsEdited = true; - isMoveBack = chose; - widget.gameModel.setAllowUndoRedo(chose); - }); - } - - void setIsThreats(bool chose) { - setState(() { - isSettingsEdited = true; - isThreats = chose; - widget.gameModel.setIsThreatsPicked(chose); - }); - } - - void setIsHints(bool chose) { - setState(() { - isSettingsEdited = true; - isHints = chose; - widget.gameModel.setShowHint(chose); - }); - } - - Future getSettings() async { - Database database = await openDatabase(path, version: 1, - onCreate: (Database db, int version) async { - await db.execute(GameSettingConsts.dbCreateScript); - }); - List list = - await database.rawQuery(GameSettingConsts.dbGetSettingsScript); - if (list.isNotEmpty) { - Map data = list.first; - setIsTime(data["withoutTime"]); - setMinutes(data["durationGame"]); - setSeconds(data["addingOnMove"]); - setIsMoveBack(data["isMoveBack"] == 0); - setIsThreats(data["isThreats"] == 0); - setIsHints(data["isHints"] == 0); - setState(() { - isDBNotEmpty = true; - }); - } else { - widget.gameModel.setTimeLimit(0); - widget.gameModel.setPlayerCount(1); - widget.gameModel.setAddingOnMove(0); - setIsMoveBack(true); - setIsThreats(false); - setIsHints(false); - } - - await database.close(); - } - - Future setSettings() async { - Database database = await openDatabase(path, version: 1, - onCreate: (Database db, int version) async { - await db.execute(GameSettingConsts.dbCreateScript); - }); - List updatedSettings = [ - withoutTime ? 0 : 1, - durationOfGame, - addingOfMove, - isMoveBack ? 0 : 1, - isThreats ? 0 : 1, - isHints ? 0 : 1 - ]; - - if (isDBNotEmpty) { - await database.rawUpdate( - GameSettingConsts.dbUpdateSettingsScript, updatedSettings); - } else { - await database.rawInsert( - GameSettingConsts.dbSetSettingsScript, updatedSettings); - } - - await database.close(); - } - - Future handleStartGame(BuildContext context) async { - if (isSettingsEdited) await setSettings(); - if (!context.mounted) return; - widget.gameModel.newGame(context, notify: false); - context.go(RouteLocations.gameScreen, extra: widget.gameModel); - } - - void onInit() async { - var databasesPath = await getDatabasesPath(); - String p = "$databasesPath/settings.db"; - setState(() { - path = p; - }); - await getSettings(); - - setState(() { - isLoading = false; - }); - } - - @override - void initState() { - onInit(); - super.initState(); - } + const GameSettingsView({super.key, required this.gameModel}); @override Widget build(BuildContext context) { - if (isLoading) return const LoadingWidget(); - return LayoutBuilder( - builder: (context, constraints) { - return SharedFunctions.isTablet(context) - ? const GameSettingsTablet() - : const GameSettingsMobile(); - }, + return ChangeNotifierProvider( + create: (context) => GameSettingsProvider(gameModel: gameModel), + child: LayoutBuilder( + builder: (context, constraints) { + if (context.watch().isLoading) { + return const LoadingWidget(); + } + return SharedFunctions.isTablet(context) + ? const GameSettingsTablet() + : const GameSettingsMobile(); + }, + ), ); } } diff --git a/frontend/lib/views/setting_view/providers/game_settings_provider.dart b/frontend/lib/views/setting_view/providers/game_settings_provider.dart new file mode 100644 index 0000000..0fc967e --- /dev/null +++ b/frontend/lib/views/setting_view/providers/game_settings_provider.dart @@ -0,0 +1,142 @@ +import 'package:flutter/material.dart'; +import 'package:frontend/exports.dart'; +import 'package:go_router/go_router.dart'; +import 'package:sqflite/sqflite.dart'; + +class GameSettingsProvider extends ChangeNotifier { + final GameModel gameModel; + bool isLoading = true; + bool isDBNotEmpty = false; + bool withoutTime = true; + bool isMoveBack = true; + bool isThreats = false; + bool isHints = false; + int countOfTabs = 2; + int durationOfGame = 15; + int addingOfMove = 0; + bool isSettingsEdited = false; + late String path; + + GameSettingsProvider({required this.gameModel}) { + onInit(); + } + void setIsTime(int chose) { + isSettingsEdited = true; + withoutTime = chose == 0; + if (withoutTime) { + gameModel.setTimeLimit(0); + } else { + gameModel.setTimeLimit(durationOfGame); + } + notifyListeners(); + } + + void setMinutes(chose) { + if (!withoutTime) { + gameModel.setTimeLimit(chose); + } + isSettingsEdited = true; + durationOfGame = chose; + notifyListeners(); + } + + void setSeconds(chose) { + isSettingsEdited = true; + addingOfMove = chose == GameSettingConsts.longDashSymbol ? 0 : chose; + gameModel.setAddingOnMove(addingOfMove); + notifyListeners(); + } + + void setIsMoveBack(bool chose) { + isSettingsEdited = true; + isMoveBack = chose; + gameModel.setAllowUndoRedo(chose); + notifyListeners(); + } + + void setIsThreats(bool chose) { + isSettingsEdited = true; + isThreats = chose; + gameModel.setIsThreatsPicked(chose); + notifyListeners(); + } + + void setIsHints(bool chose) { + isSettingsEdited = true; + isHints = chose; + gameModel.setShowHint(chose); + notifyListeners(); + } + + Future getSettings() async { + Database database = await openDatabase(path, version: 1, + onCreate: (Database db, int version) async { + await db.execute(GameSettingConsts.dbCreateScript); + }); + List list = + await database.rawQuery(GameSettingConsts.dbGetSettingsScript); + if (list.isNotEmpty) { + Map data = list.first; + setIsTime(data["withoutTime"]); + setMinutes(data["durationGame"]); + setSeconds(data["addingOnMove"]); + setIsMoveBack(data["isMoveBack"] == 0); + setIsThreats(data["isThreats"] == 0); + setIsHints(data["isHints"] == 0); + isDBNotEmpty = true; + notifyListeners(); + } else { + gameModel.setTimeLimit(0); + gameModel.setPlayerCount(1); + gameModel.setAddingOnMove(0); + setIsMoveBack(true); + setIsThreats(false); + setIsHints(false); + } + await database.close(); + } + + Future setSettings() async { + Database database = await openDatabase(path, version: 1, + onCreate: (Database db, int version) async { + await db.execute(GameSettingConsts.dbCreateScript); + }); + List updatedSettings = [ + withoutTime ? 0 : 1, + durationOfGame, + addingOfMove, + isMoveBack ? 0 : 1, + isThreats ? 0 : 1, + isHints ? 0 : 1 + ]; + + if (isDBNotEmpty) { + await database.rawUpdate( + GameSettingConsts.dbUpdateSettingsScript, updatedSettings); + } else { + await database.rawInsert( + GameSettingConsts.dbSetSettingsScript, updatedSettings); + } + + await database.close(); + } + + Future handleStartGame(BuildContext context) async { + if (isSettingsEdited) await setSettings(); + if (!context.mounted) return; + gameModel.newGame(context, notify: false); + context.go(RouteLocations.gameScreen, extra: gameModel); + } + + void onInit() async { + var databasesPath = await getDatabasesPath(); + String p = "$databasesPath/settings.db"; + + path = p; + + await getSettings(); + + isLoading = false; + notifyListeners(); + } +} From 5e5d470930eeafe4708a3a420fd84e649dbb73af Mon Sep 17 00:00:00 2001 From: neekeetuh Date: Mon, 2 Jun 2025 22:31:34 +0600 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=D1=83=D0=BC=D0=B5=D0=BD=D1=8C?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BB=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=B2=D0=B0=20=D1=80=D0=B5=D0=B1=D0=B8=D0=BB?= =?UTF-8?q?=D0=B4=D0=BE=D0=B2=20=D0=B1=D0=BB=D0=B0=D0=B3=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=D1=80=D1=8F=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8E=20selector=20=D0=B2=D0=BC=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=20consumer=20=D0=B8=20context.watch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setting_view/game_settings_mobile.dart | 89 ++++++++++--------- .../setting_view/game_settings_tablet.dart | 45 ++++++---- .../setting_view/game_settings_view.dart | 4 +- 3 files changed, 80 insertions(+), 58 deletions(-) diff --git a/frontend/lib/views/setting_view/game_settings_mobile.dart b/frontend/lib/views/setting_view/game_settings_mobile.dart index 99c7cc4..561b632 100644 --- a/frontend/lib/views/setting_view/game_settings_mobile.dart +++ b/frontend/lib/views/setting_view/game_settings_mobile.dart @@ -8,6 +8,7 @@ class GameSettingsMobile extends StatelessWidget { @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final gameSettingsProvider = context.read(); return DefaultTabController( length: 2, child: Scaffold( @@ -25,43 +26,52 @@ class GameSettingsMobile extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(left: 24, right: 24, top: 24), - child: Consumer( - builder: (_, settingsProvider, __) => Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - AppBarSettings( - label: GameSettingConsts.appBarLabel), - CustomTabBar( - initialIndex: - settingsProvider.withoutTime ? 0 : 1, - header: GameSettingConsts.timeText, - subTitles: [ - GameSettingConsts.gameWithoutTimeText, - GameSettingConsts.gameWithTimeText, - ], - isSettingsPage: true, - onTap: (dynamic index) => settingsProvider - .setIsTime(index as int), - ), - if (!settingsProvider.withoutTime) ...[ - SetTimeSection( - minutesStartValue: - settingsProvider.durationOfGame, - minutesOnChanged: (dynamic value) => - settingsProvider - .setMinutes(value as int), - secondsStartValue: - settingsProvider.addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : settingsProvider.addingOfMove, - secondsOnChanged: (dynamic value) => - settingsProvider.setSeconds(value), - ) - ], - const SettingsRowsSection(), - const SizedBox(height: 100), - ], - )), + child: Selector< + GameSettingsProvider, + ({ + bool withoutTime, + int durationOfGame, + int addingOfMove + })>( + selector: (_, provider) => ( + withoutTime: provider.withoutTime, + durationOfGame: provider.durationOfGame, + addingOfMove: provider.addingOfMove + ), + builder: (_, values, __) => Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + AppBarSettings( + label: GameSettingConsts.appBarLabel), + CustomTabBar( + initialIndex: values.withoutTime ? 0 : 1, + header: GameSettingConsts.timeText, + subTitles: [ + GameSettingConsts.gameWithoutTimeText, + GameSettingConsts.gameWithTimeText, + ], + isSettingsPage: true, + onTap: (dynamic index) => + gameSettingsProvider.setIsTime(index as int), + ), + if (!values.withoutTime) ...[ + SetTimeSection( + minutesStartValue: values.durationOfGame, + minutesOnChanged: (dynamic value) => + gameSettingsProvider + .setMinutes(value as int), + secondsStartValue: values.addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : values.addingOfMove, + secondsOnChanged: (dynamic value) => + gameSettingsProvider.setSeconds(value), + ) + ], + const SettingsRowsSection(), + const SizedBox(height: 100), + ], + ), + ), ), ), ), @@ -82,9 +92,8 @@ class GameSettingsMobile extends StatelessWidget { textColor: ColorsConst.primaryColor0, buttonColor: scheme.secondaryContainer, isClickable: true, - onTap: () => context - .read() - .handleStartGame(context), + onTap: () => + gameSettingsProvider.handleStartGame(context), ), ), ), diff --git a/frontend/lib/views/setting_view/game_settings_tablet.dart b/frontend/lib/views/setting_view/game_settings_tablet.dart index 0cf3082..5d95758 100644 --- a/frontend/lib/views/setting_view/game_settings_tablet.dart +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -7,6 +7,8 @@ class GameSettingsTablet extends StatelessWidget { @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final gameSettingsProvider = context.read(); + return DefaultTabController( length: 2, child: Scaffold( @@ -22,16 +24,26 @@ class GameSettingsTablet extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(left: 24, right: 24, top: 24), - child: Consumer( - builder: (_, settingsProvider, __) { + child: Selector< + GameSettingsProvider, + ({ + bool withoutTime, + int durationOfGame, + int addingOfMove + })>( + selector: (_, provider) => ( + withoutTime: provider.withoutTime, + durationOfGame: provider.durationOfGame, + addingOfMove: provider.addingOfMove + ), + builder: (_, values, __) { return Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ AppBarSettings( label: GameSettingConsts.appBarLabel), CustomTabBar( - initialIndex: - settingsProvider.withoutTime ? 0 : 1, + initialIndex: values.withoutTime ? 0 : 1, header: GameSettingConsts.timeText, subTitles: [ GameSettingConsts.gameWithoutTimeText, @@ -39,21 +51,21 @@ class GameSettingsTablet extends StatelessWidget { ], isSettingsPage: true, onTap: (dynamic index) => - settingsProvider.setIsTime(index as int), + gameSettingsProvider.setIsTime(index as int), ), - if (!settingsProvider.withoutTime) ...[ + if (!values.withoutTime) ...[ const SizedBox(height: 70), SetTimeSection( - minutesStartValue: - settingsProvider.durationOfGame, + minutesStartValue: values.durationOfGame, minutesOnChanged: (dynamic value) => - settingsProvider.setMinutes(value as int), - secondsStartValue: - settingsProvider.addingOfMove == 0 - ? GameSettingConsts.longDashSymbol - : settingsProvider.addingOfMove, + gameSettingsProvider + .setMinutes(value as int), + secondsStartValue: values.addingOfMove == 0 + ? GameSettingConsts.longDashSymbol + : values.addingOfMove, secondsOnChanged: (dynamic value) => - settingsProvider.setSeconds(value as int), + gameSettingsProvider + .setSeconds(value as int), ) ], const SizedBox(height: 120), @@ -82,9 +94,8 @@ class GameSettingsTablet extends StatelessWidget { textColor: ColorsConst.primaryColor0, buttonColor: scheme.secondaryContainer, isClickable: true, - onTap: () => context - .read() - .handleStartGame(context), + onTap: () => + gameSettingsProvider.handleStartGame(context), ), ), ), diff --git a/frontend/lib/views/setting_view/game_settings_view.dart b/frontend/lib/views/setting_view/game_settings_view.dart index aa5903b..171db46 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -18,7 +18,9 @@ class GameSettingsView extends StatelessWidget { create: (context) => GameSettingsProvider(gameModel: gameModel), child: LayoutBuilder( builder: (context, constraints) { - if (context.watch().isLoading) { + final isLoading = (context + .select((GameSettingsProvider provider) => provider.isLoading)); + if (isLoading) { return const LoadingWidget(); } return SharedFunctions.isTablet(context)