diff --git a/frontend/lib/common/shared_functions.dart b/frontend/lib/common/shared_functions.dart new file mode 100644 index 00000000..e5169940 --- /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 49715cf4..c1abb7aa 100644 --- a/frontend/lib/router/router.dart +++ b/frontend/lib/router/router.dart @@ -69,7 +69,9 @@ final shellRoutes = [ path: RouteLocations.settingsScreen, parentNavigatorKey: shellNavigatorKey, builder: (BuildContext context, GoRouterState state) { - return GameSettingsView(state.extra as GameModel); + return GameSettingsView( + gameModel: state.extra as GameModel, + ); }, ), GoRoute( diff --git a/frontend/lib/views/components/pro_functions_tooltip.dart b/frontend/lib/views/components/pro_functions_tooltip.dart index fef1d507..64fa7d95 100644 --- a/frontend/lib/views/components/pro_functions_tooltip.dart +++ b/frontend/lib/views/components/pro_functions_tooltip.dart @@ -21,7 +21,19 @@ class ProFunctionsTooltip extends StatefulWidget { } class _ProFunctionsTooltipState extends State { - final _controller = SuperTooltipController(); + late final SuperTooltipController _controller; + + @override + void initState() { + super.initState(); + _controller = SuperTooltipController(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { @@ -62,14 +74,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/app_bar_settings.dart b/frontend/lib/views/setting_view/components/app_bar_settings.dart index bed9a942..6ed2754a 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"; @@ -10,13 +11,14 @@ class AppBarSettings extends StatelessWidget { @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; + final isTablet = SharedFunctions.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 +27,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 b65b5f35..31d28fbd 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 4ecdaaf0..dc7ec97a 100644 --- a/frontend/lib/views/setting_view/components/settings_row.dart +++ b/frontend/lib/views/setting_view/components/settings_row.dart @@ -1,9 +1,10 @@ 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"; -class SettingsRow extends StatelessWidget { +class SettingsRow extends StatefulWidget { const SettingsRow({ super.key, this.chose, @@ -19,10 +20,16 @@ class SettingsRow extends StatelessWidget { final Widget? choseDiffWidget; final void Function(bool)? onChanged; + @override + State createState() => _SettingsRowState(); +} + +class _SettingsRowState extends State { @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; final isPro = context.watch().isPro; + final isTablet = SharedFunctions.isTablet(context); return Padding( padding: const EdgeInsets.only(bottom: 8), child: SizedBox( @@ -33,17 +40,16 @@ class SettingsRow extends StatelessWidget { Row( children: [ Text( - text, + widget.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, - modalHeader: modalHeader, + modalHeader: widget.modalHeader, child: SvgPicture.asset( "assets/images/icons/question_icon.svg", colorFilter: ColorFilter.mode( @@ -57,17 +63,22 @@ class SettingsRow extends StatelessWidget { ), Theme( data: ThemeData(useMaterial3: false), - child: Switch( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - value: isPro ? chose! : false, - inactiveThumbColor: - isPro ? scheme.surfaceTint : ColorsConst.disabledColor, - inactiveTrackColor: scheme.outline, - activeColor: scheme.inversePrimary, - activeTrackColor: ColorsConst.primaryColor100, - onChanged: onChanged, + 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 1e757147..5a9d4f75 100644 --- a/frontend/lib/views/setting_view/components/settings_rows_section.dart +++ b/frontend/lib/views/setting_view/components/settings_rows_section.dart @@ -1,23 +1,14 @@ 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( - {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; + const SettingsRowsSection({ + super.key, + }); @override Widget build(BuildContext context) { @@ -32,32 +23,34 @@ class SettingsRowsSection extends StatelessWidget { l10n.gameSettings, style: TextStyles.title3.copyWith( color: Theme.of(context).colorScheme.primary, + fontSize: SharedFunctions.isTablet(context) ? 45 : null, ), ), ), ), - Column( - children: [ - SettingsRow( - chose: choseMoveBack, - text: l10n.undoMoves, - modalHeader: l10n.undoMovesDescription, - onChanged: moveBackOnChanged, - ), - SettingsRow( - chose: choseThreats, - text: l10n.threats, - modalHeader: l10n.threatsDescription, - onChanged: threatsOnChanged, - ), - SettingsRow( - chose: choseHints, - text: l10n.hints, - modalHeader: l10n.hintsDescription, - onChanged: hintsOnChanged, - ) - ], - ), + 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/components/text_heading.dart b/frontend/lib/views/setting_view/components/text_heading.dart index 724474d1..4dfa6566 100644 --- a/frontend/lib/views/setting_view/components/text_heading.dart +++ b/frontend/lib/views/setting_view/components/text_heading.dart @@ -1,26 +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}); + 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; @override Widget build(BuildContext context) { - final scheme = Theme.of(context).colorScheme; return Container( margin: EdgeInsets.only(top: topMargin, bottom: bottomMargin), child: Text( text, style: TextStyles.title3.copyWith( - color: scheme.primary, + 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 new file mode 100644 index 00000000..561b6329 --- /dev/null +++ b/frontend/lib/views/setting_view/game_settings_mobile.dart @@ -0,0 +1,107 @@ +part of 'game_settings_view.dart'; + +class GameSettingsMobile extends StatelessWidget { + const GameSettingsMobile({ + super.key, + }); + + @override + Widget build(BuildContext context) { + final scheme = Theme.of(context).colorScheme; + final gameSettingsProvider = context.read(); + 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: 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), + ], + ), + ), + ), + ), + ), + ), + 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: () => + 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 new file mode 100644 index 00000000..5d95758d --- /dev/null +++ b/frontend/lib/views/setting_view/game_settings_tablet.dart @@ -0,0 +1,109 @@ +part of 'game_settings_view.dart'; + +class GameSettingsTablet extends StatelessWidget { + const GameSettingsTablet({ + super.key, + }); + @override + Widget build(BuildContext context) { + final scheme = Theme.of(context).colorScheme; + final gameSettingsProvider = context.read(); + + 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: 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: 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) ...[ + const SizedBox(height: 70), + 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 as int), + ) + ], + const SizedBox(height: 120), + const SettingsRowsSection(), + 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: () => + 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 4ec8b3f3..171db46c 100644 --- a/frontend/lib/views/setting_view/game_settings_view.dart +++ b/frontend/lib/views/setting_view/game_settings_view.dart @@ -1,248 +1,33 @@ 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"; - -class GameSettingsView extends StatefulWidget { - const GameSettingsView(this.gameModel, {super.key}); - final GameModel gameModel; - - @override - State createState() => _GameSettingsViewState(); -} - -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); - }); - } +import "package:frontend/common/shared_functions.dart"; +import "package:frontend/views/setting_view/providers/game_settings_provider.dart"; - void setIsThreats(bool chose) { - setState(() { - isSettingsEdited = true; - isThreats = chose; - widget.gameModel.setIsThreatsPicked(chose); - }); - } +import "package:provider/provider.dart"; - 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(); - } - - void onInit() async { - var databasesPath = await getDatabasesPath(); - String p = "$databasesPath/settings.db"; - setState(() { - path = p; - }); - await getSettings(); - - setState(() { - isLoading = false; - }); - } +import "../../exports.dart"; +part 'game_settings_mobile.dart'; +part 'game_settings_tablet.dart'; - @override - void initState() { - onInit(); - super.initState(); - } +class GameSettingsView extends StatelessWidget { + final GameModel gameModel; + const GameSettingsView({super.key, required this.gameModel}); @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); - }, - ), - ), - ), - ), - ], - ), - ), - ), - ); + return ChangeNotifierProvider( + create: (context) => GameSettingsProvider(gameModel: gameModel), + child: LayoutBuilder( + builder: (context, constraints) { + final isLoading = (context + .select((GameSettingsProvider provider) => provider.isLoading)); + if (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 00000000..0fc967ee --- /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(); + } +}