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..0277b0e 100644 --- a/frontend/lib/views/setting_view/components/app_bar_settings.dart +++ b/frontend/lib/views/setting_view/components/app_bar_settings.dart @@ -7,16 +7,23 @@ class AppBarSettings extends StatelessWidget { 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 +32,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 883910c..f937f4f 100644 --- a/frontend/lib/views/setting_view/components/settings_rows_section.dart +++ b/frontend/lib/views/setting_view/components/settings_rows_section.dart @@ -18,8 +18,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); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -30,6 +36,7 @@ class SettingsRowsSection extends StatelessWidget { GameSettingConsts.gameSettingsHeader, 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, ), ), ); 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..a87849e --- /dev/null +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -0,0 +1,121 @@ +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) ...[ + 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), + ) + ], + const SizedBox(height: 120), + 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 4683a4b..1bb517a 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -3,6 +3,9 @@ import "package:go_router/go_router.dart"; import "package:sqflite/sqflite.dart"; import "../../exports.dart"; +part 'game_settings_mobile.dart'; +part 'game_settings_tablet.dart'; + class GameSettingsView extends StatefulWidget { const GameSettingsView(this.gameModel, {super.key}); final GameModel gameModel; @@ -134,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"; @@ -155,93 +165,44 @@ class _GameSettingsViewState extends State @override Widget build(BuildContext context) { - final scheme = Theme.of(context).colorScheme; - 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: GameSettingConsts.appBarLabel), - CustomTabBar( - initialIndex: withoutTime ? 0 : 1, - header: GameSettingConsts.timeText, - subTitles: [ - GameSettingConsts.gameWithoutTimeText, - GameSettingConsts.gameWithTimeText, - ], - 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: GameSettingConsts.startGameText, - 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), + ); + }, + ); } }