diff --git a/app/lib/main/app.dart b/app/lib/main/app.dart index 018ad8b..8d9e56a 100644 --- a/app/lib/main/app.dart +++ b/app/lib/main/app.dart @@ -1,16 +1,17 @@ -import 'package:flutter/material.dart'; -import 'package:domain/bloc/app/app_cubit.dart'; -import 'package:domain/bloc/app/app_state.dart'; -import 'package:domain/bloc/auth/auth_cubit.dart'; import 'package:app/presentation/navigation/routers.dart'; import 'package:app/presentation/resources/locale/generated/l10n.dart'; import 'package:app/presentation/themes/app_themes.dart'; import 'package:app/presentation/utils/lang_extensions.dart'; +import 'package:app_links/app_links.dart'; +import 'package:domain/bloc/app/app_cubit.dart'; +import 'package:domain/bloc/app/app_state.dart'; +import 'package:domain/bloc/auth/auth_cubit.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:flutter/foundation.dart' show kIsWeb; -import 'package:app_links/app_links.dart'; import 'package:go_router/go_router.dart'; + import 'init.dart'; class App extends StatefulWidget { @@ -74,6 +75,7 @@ class _AppState extends State { : BlocBuilder( builder: (context, state) { return MaterialApp.router( + debugShowCheckedModeBanner: false, theme: AppThemes.getAppTheme(state.themeType).data, locale: LangExtensions.langLocale[state.appLang], supportedLocales: LangExtensions.supportedLang, diff --git a/app/lib/presentation/navigation/routers.dart b/app/lib/presentation/navigation/routers.dart index 648fde8..cde504c 100644 --- a/app/lib/presentation/navigation/routers.dart +++ b/app/lib/presentation/navigation/routers.dart @@ -1,4 +1,5 @@ import 'package:app/main/init.dart'; +import 'package:app/presentation/ui/custom/debug_banner.dart'; import 'package:app/presentation/ui/pages/main/home/home_page.dart'; import 'package:app/presentation/ui/pages/auth/login/login_page.dart'; import 'package:app/presentation/ui/pages/auth/sign_up/sign_up_page.dart'; @@ -6,6 +7,7 @@ import 'package:app/presentation/ui/pages/splash/splash_page.dart'; import 'package:common/core/resource.dart'; import 'package:domain/bloc/auth/auth_cubit.dart'; import 'package:domain/bloc/auth/auth_state.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; @@ -36,12 +38,15 @@ extension ContextOnRouter on BuildContext { GoRouter get router => GoRouter.of(this); } +final rootNavigatorKey = GlobalKey(); + class Routers { static GoRouter appRouter( BuildContext context, { String? initialLocation, }) => GoRouter( + navigatorKey: rootNavigatorKey, initialLocation: initialLocation ?? (getIt().isLoggedIn() ? Routes.app.path @@ -85,7 +90,8 @@ class Routers { }, routes: [ ShellRoute( - builder: (context, state, child) => child, + builder: (context, state, child) => + kDebugMode ? DebugBanner(child: child) : child, routes: [ GoRoute( name: Routes.auth.name, @@ -108,7 +114,8 @@ class Routers { ], ), ShellRoute( - builder: (context, state, child) => child, + builder: (context, state, child) => + kDebugMode ? DebugBanner(child: child) : child, routes: [ GoRoute( name: Routes.app.name, diff --git a/app/lib/presentation/resources/locale/generated/intl/messages_en.dart b/app/lib/presentation/resources/locale/generated/intl/messages_en.dart index 9fe9aca..e99d512 100644 --- a/app/lib/presentation/resources/locale/generated/intl/messages_en.dart +++ b/app/lib/presentation/resources/locale/generated/intl/messages_en.dart @@ -32,6 +32,14 @@ class MessageLookup extends MessageLookupByLibrary { ), "ctaLogin": MessageLookupByLibrary.simpleMessage("Login"), "ctaSignUp": MessageLookupByLibrary.simpleMessage("Sign Up"), + "debugModeCancel": MessageLookupByLibrary.simpleMessage("Cancel"), + "debugModeConfirm": MessageLookupByLibrary.simpleMessage("Confirm"), + "debugModeLabel": MessageLookupByLibrary.simpleMessage("DEV"), + "debugModeResetApp": MessageLookupByLibrary.simpleMessage("RESET"), + "debugModeResetAppMessage": MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset the app?", + ), + "debugModeResetAppTitle": MessageLookupByLibrary.simpleMessage("Reset App"), "errorEmailInvalid": MessageLookupByLibrary.simpleMessage( "Please enter a valid email address.", ), diff --git a/app/lib/presentation/resources/locale/generated/intl/messages_es.dart b/app/lib/presentation/resources/locale/generated/intl/messages_es.dart index d295049..76be69b 100644 --- a/app/lib/presentation/resources/locale/generated/intl/messages_es.dart +++ b/app/lib/presentation/resources/locale/generated/intl/messages_es.dart @@ -25,14 +25,25 @@ class MessageLookup extends MessageLookupByLibrary { "appName": MessageLookupByLibrary.simpleMessage("Flutter Target"), "cookiesAcceptCTA": MessageLookupByLibrary.simpleMessage("Aceptar"), "cookiesBody": MessageLookupByLibrary.simpleMessage( - "Usamos cookies para personalizar el contenido y los anuncios, ofrecer funciones de redes sociales y analizar nuestro tráfico. También compartimos información sobre el uso de nuestro sitio con nuestros socios de redes sociales, publicidad y análisis, quienes pueden combinarla con otra información que les hayas proporcionado o que hayan recopilado a partir del uso de sus servicios.", + "Usamos cookies para personalizar el contenido y los anuncios, proporcionar funciones de redes sociales y analizar nuestro tráfico. También compartimos información sobre el uso que haces de nuestro sitio con nuestros socios de redes sociales, publicidad y análisis, quienes pueden combinarla con otra información que les hayas proporcionado o que hayan recopilado a partir del uso que haces de sus servicios.", ), "cookiesTitle": MessageLookupByLibrary.simpleMessage( "Este sitio web utiliza cookies", ), "ctaLogin": MessageLookupByLibrary.simpleMessage("Iniciar sesión"), + "ctaSignUp": MessageLookupByLibrary.simpleMessage("Registrarse"), + "debugModeCancel": MessageLookupByLibrary.simpleMessage("Cancelar"), + "debugModeConfirm": MessageLookupByLibrary.simpleMessage("Confirmar"), + "debugModeLabel": MessageLookupByLibrary.simpleMessage("DEV"), + "debugModeResetApp": MessageLookupByLibrary.simpleMessage("RESET"), + "debugModeResetAppMessage": MessageLookupByLibrary.simpleMessage( + "¿Estás seguro de que deseas resetear la aplicación?", + ), + "debugModeResetAppTitle": MessageLookupByLibrary.simpleMessage( + "Resetear App", + ), "errorEmailInvalid": MessageLookupByLibrary.simpleMessage( - "Por favor ingresa una dirección de correo válida.", + "Por favor ingresa un correo electrónico válido.", ), "errorEmailRequired": MessageLookupByLibrary.simpleMessage( "El correo electrónico es obligatorio.", @@ -43,13 +54,22 @@ class MessageLookup extends MessageLookupByLibrary { "errorPasswordWeak": MessageLookupByLibrary.simpleMessage( "La contraseña es demasiado débil.", ), + "errorPasswordsDoNotMatch": MessageLookupByLibrary.simpleMessage( + "Las contraseñas no coinciden.", + ), + "hintTermsAndConditions": MessageLookupByLibrary.simpleMessage( + "Esto debería abrir la URL de términos y condiciones.", + ), "labelAgreeToTerms": MessageLookupByLibrary.simpleMessage( "Acepto los Términos y Condiciones", ), + "labelConfirmPassword": MessageLookupByLibrary.simpleMessage( + "Confirmar contraseña", + ), "labelEmail": MessageLookupByLibrary.simpleMessage("Correo electrónico"), "labelPassword": MessageLookupByLibrary.simpleMessage("Contraseña"), "loginErrorInvalidCredentials": MessageLookupByLibrary.simpleMessage( - "Correo o contraseña inválidos.", + "Correo electrónico o contraseña incorrectos.", ), "noConnection": MessageLookupByLibrary.simpleMessage("Sin conexión"), "passwordInstructions": MessageLookupByLibrary.simpleMessage( @@ -57,15 +77,19 @@ class MessageLookup extends MessageLookupByLibrary { ), "pleaseTryAgainLaterWeArenworkingToFixTheIssue": MessageLookupByLibrary.simpleMessage( - "Por favor, inténtalo más tarde,\nestamos trabajando para resolver el problema.", + "Por favor intenta nuevamente más tarde,\nestamos trabajando para solucionar el problema.", ), "retry": MessageLookupByLibrary.simpleMessage("Reintentar"), "sorryWeDidntFindAnyProduct": MessageLookupByLibrary.simpleMessage( - "Lo sentimos, no hemos encontrado ningún producto", + "Lo sentimos, no encontramos ningún producto", ), "titleLogin": MessageLookupByLibrary.simpleMessage("Iniciar sesión"), "titleLoginSubtitle": MessageLookupByLibrary.simpleMessage( - "Usa tu correo y contraseña para iniciar sesión en tu cuenta.", + "Usa tu correo electrónico y contraseña para iniciar sesión en tu cuenta.", + ), + "titleSignUp": MessageLookupByLibrary.simpleMessage("Registrarse"), + "titleSignUpSubtitle": MessageLookupByLibrary.simpleMessage( + "Crea una cuenta usando tu correo electrónico y contraseña.", ), }; } diff --git a/app/lib/presentation/resources/locale/generated/l10n.dart b/app/lib/presentation/resources/locale/generated/l10n.dart index 7daf6f1..c6fbafc 100644 --- a/app/lib/presentation/resources/locale/generated/l10n.dart +++ b/app/lib/presentation/resources/locale/generated/l10n.dart @@ -269,6 +269,51 @@ class S { args: [], ); } + + /// `DEV` + String get debugModeLabel { + return Intl.message('DEV', name: 'debugModeLabel', desc: '', args: []); + } + + /// `RESET` + String get debugModeResetApp { + return Intl.message('RESET', name: 'debugModeResetApp', desc: '', args: []); + } + + /// `Reset App` + String get debugModeResetAppTitle { + return Intl.message( + 'Reset App', + name: 'debugModeResetAppTitle', + desc: '', + args: [], + ); + } + + /// `Are you sure you want to reset the app?` + String get debugModeResetAppMessage { + return Intl.message( + 'Are you sure you want to reset the app?', + name: 'debugModeResetAppMessage', + desc: '', + args: [], + ); + } + + /// `Cancel` + String get debugModeCancel { + return Intl.message('Cancel', name: 'debugModeCancel', desc: '', args: []); + } + + /// `Confirm` + String get debugModeConfirm { + return Intl.message( + 'Confirm', + name: 'debugModeConfirm', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/app/lib/presentation/resources/locale/intl_en.arb b/app/lib/presentation/resources/locale/intl_en.arb index 3ab38c5..f0b4445 100644 --- a/app/lib/presentation/resources/locale/intl_en.arb +++ b/app/lib/presentation/resources/locale/intl_en.arb @@ -24,5 +24,11 @@ "errorEmailInvalid": "Please enter a valid email address.", "errorPasswordWeak": "Password is too weak.", "loginErrorInvalidCredentials": "Invalid email or password.", - "hintTermsAndConditions": "This should open the terms and conditions URL." + "hintTermsAndConditions": "This should open the terms and conditions URL.", + "debugModeLabel": "DEV", + "debugModeResetApp": "RESET", + "debugModeResetAppTitle": "Reset App", + "debugModeResetAppMessage": "Are you sure you want to reset the app?", + "debugModeCancel": "Cancel", + "debugModeConfirm": "Confirm" } diff --git a/app/lib/presentation/resources/locale/intl_es.arb b/app/lib/presentation/resources/locale/intl_es.arb index a834509..9a95d34 100644 --- a/app/lib/presentation/resources/locale/intl_es.arb +++ b/app/lib/presentation/resources/locale/intl_es.arb @@ -2,21 +2,33 @@ "appName": "Flutter Target", "cookiesTitle": "Este sitio web utiliza cookies", "cookiesAcceptCTA": "Aceptar", - "cookiesBody": "Usamos cookies para personalizar el contenido y los anuncios, ofrecer funciones de redes sociales y analizar nuestro tráfico. También compartimos información sobre el uso de nuestro sitio con nuestros socios de redes sociales, publicidad y análisis, quienes pueden combinarla con otra información que les hayas proporcionado o que hayan recopilado a partir del uso de sus servicios.", + "cookiesBody": "Usamos cookies para personalizar el contenido y los anuncios, proporcionar funciones de redes sociales y analizar nuestro tráfico. También compartimos información sobre el uso que haces de nuestro sitio con nuestros socios de redes sociales, publicidad y análisis, quienes pueden combinarla con otra información que les hayas proporcionado o que hayan recopilado a partir del uso que haces de sus servicios.", "noConnection": "Sin conexión", "retry": "Reintentar", - "pleaseTryAgainLaterWeArenworkingToFixTheIssue": "Por favor, inténtalo más tarde,\nestamos trabajando para resolver el problema.", - "sorryWeDidntFindAnyProduct": "Lo sentimos, no hemos encontrado ningún producto", + "pleaseTryAgainLaterWeArenworkingToFixTheIssue": "Por favor intenta nuevamente más tarde,\nestamos trabajando para solucionar el problema.", + "sorryWeDidntFindAnyProduct": "Lo sentimos, no encontramos ningún producto", "ctaLogin": "Iniciar sesión", + "ctaSignUp": "Registrarse", "labelEmail": "Correo electrónico", "labelPassword": "Contraseña", + "labelConfirmPassword": "Confirmar contraseña", + "errorPasswordsDoNotMatch": "Las contraseñas no coinciden.", "passwordInstructions": "Mínimo 8 caracteres: 1 mayúscula, 1 minúscula, 1 número y 1 carácter especial.", "labelAgreeToTerms": "Acepto los Términos y Condiciones", "errorEmailRequired": "El correo electrónico es obligatorio.", "errorPasswordRequired": "La contraseña es obligatoria.", "titleLogin": "Iniciar sesión", - "titleLoginSubtitle": "Usa tu correo y contraseña para iniciar sesión en tu cuenta.", - "errorEmailInvalid": "Por favor ingresa una dirección de correo válida.", + "titleSignUp": "Registrarse", + "titleLoginSubtitle": "Usa tu correo electrónico y contraseña para iniciar sesión en tu cuenta.", + "titleSignUpSubtitle": "Crea una cuenta usando tu correo electrónico y contraseña.", + "errorEmailInvalid": "Por favor ingresa un correo electrónico válido.", "errorPasswordWeak": "La contraseña es demasiado débil.", - "loginErrorInvalidCredentials": "Correo o contraseña inválidos." -} + "loginErrorInvalidCredentials": "Correo electrónico o contraseña incorrectos.", + "hintTermsAndConditions": "Esto debería abrir la URL de términos y condiciones.", + "debugModeLabel": "DEV", + "debugModeResetApp": "RESET", + "debugModeResetAppTitle": "Resetear App", + "debugModeResetAppMessage": "¿Estás seguro de que deseas resetear la aplicación?", + "debugModeCancel": "Cancelar", + "debugModeConfirm": "Confirmar" +} \ No newline at end of file diff --git a/app/lib/presentation/themes/local_theme.dart b/app/lib/presentation/themes/local_theme.dart index f00b3b1..750b95a 100644 --- a/app/lib/presentation/themes/local_theme.dart +++ b/app/lib/presentation/themes/local_theme.dart @@ -85,6 +85,15 @@ abstract class LocalTheme { ), elevation: 10, ), + dialogTheme: DialogThemeData( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(themeData.borderRadius), + ), + ), + titleTextStyle: titleM.copyWith(color: colors.onSurface), + contentTextStyle: subtitleM.copyWith(color: colors.onSurface), + ), ); final primaryFont = 'Roboto Regular'; diff --git a/app/lib/presentation/ui/custom/app_theme_switch.dart b/app/lib/presentation/ui/custom/app_theme_switch.dart index 0cc5b3b..8aecf72 100644 --- a/app/lib/presentation/ui/custom/app_theme_switch.dart +++ b/app/lib/presentation/ui/custom/app_theme_switch.dart @@ -14,9 +14,11 @@ class AppThemeSwitch extends StatelessWidget { return Switch( value: theme == ThemeType.dark, - activeTrackColor: Colors.grey, + thumbIcon: const WidgetStatePropertyAll(Icon(Icons.brightness_6)), onChanged: (value) { - context.read().updateTheme(value ? ThemeType.dark : ThemeType.light); + context + .read() + .updateTheme(value ? ThemeType.dark : ThemeType.light); }, ); } diff --git a/app/lib/presentation/ui/custom/debug_banner.dart b/app/lib/presentation/ui/custom/debug_banner.dart new file mode 100644 index 0000000..dec65b3 --- /dev/null +++ b/app/lib/presentation/ui/custom/debug_banner.dart @@ -0,0 +1,104 @@ +import 'package:app/presentation/resources/locale/generated/l10n.dart'; +import 'package:app/presentation/resources/resources.dart'; +import 'package:app/presentation/ui/custom/app_theme_switch.dart'; +import 'package:domain/bloc/app/app_cubit.dart'; +import 'package:domain/bloc/app/app_state.dart'; +import 'package:domain/bloc/auth/auth_cubit.dart'; +import 'package:domain/models/app_lang.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:gap/gap.dart'; + +class DebugBanner extends StatelessWidget { + final Widget child; + const DebugBanner({ + super.key, + required this.child, + }); + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + + return Material( + child: Column( + children: [ + Container( + color: colorScheme.error.withAlpha(120), + child: Row( + children: [ + Icon(Icons.bug_report, color: colorScheme.onError), + const Gap(Dimen.spacingS), + Text( + S.of(context).debugModeLabel, + style: + textTheme.bodyLarge?.copyWith(color: colorScheme.onError), + ), + const Spacer(), + BlocBuilder( + builder: (context, state) { + return DropdownButton( + value: state.appLang, + padding: const EdgeInsets.symmetric( + horizontal: Dimen.spacingS, + ), + underline: Container(), + icon: Icon(Icons.language, color: colorScheme.onError), + onChanged: (AppLang? newLang) { + if (newLang != null) { + context.read().updateAppLang(newLang); + } + }, + items: AppLang.values.map((AppLang lang) { + return DropdownMenuItem( + value: lang, + child: Text(lang.name.toUpperCase()), + ); + }).toList(), + ); + }, + ), + const Gap(Dimen.spacingS), + const AppThemeSwitch(), + const Gap(Dimen.spacingS), + TextButton( + onPressed: () => resetApp(context), + child: Text(S.of(context).debugModeResetApp), + ), + ], + ), + ), + Expanded(child: child), + ], + ), + ); + } + + void resetApp(BuildContext context) async { + showDialog( + context: context, + barrierDismissible: true, + builder: (dialogContext) { + return AlertDialog( + title: Text(S.of(context).debugModeResetAppTitle), + content: Text(S.of(context).debugModeResetAppMessage), + actions: [ + TextButton( + onPressed: () => Navigator.of(dialogContext).pop(), + child: Text(S.of(context).debugModeCancel), + ), + TextButton( + onPressed: () async { + Navigator.of(dialogContext).pop(); + await context.read().resetApp(); + await context.read().logOut(); + }, + child: Text(S.of(context).debugModeConfirm), + ), + ], + ); + }, + ); + } +} diff --git a/app/lib/presentation/ui/custom/terms_services_check.dart b/app/lib/presentation/ui/custom/terms_services_check.dart new file mode 100644 index 0000000..ca75294 --- /dev/null +++ b/app/lib/presentation/ui/custom/terms_services_check.dart @@ -0,0 +1,60 @@ +import 'package:app/presentation/resources/locale/generated/l10n.dart'; +import 'package:app/presentation/resources/resources.dart'; +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; + +class TermsServicesCheck extends StatelessWidget { + final bool agreeToTerms; + final void Function(bool)? onChanged; + + const TermsServicesCheck({ + super.key, + this.agreeToTerms = false, + this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + child: TextButton( + style: Theme.of(context).textButtonTheme.style?.copyWith( + alignment: Alignment.centerLeft, // <-- important + padding: WidgetStateProperty.all( + EdgeInsets.zero, + ), // optional, but helps + ), + onPressed: () => onChanged?.call(!agreeToTerms), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Checkbox( + value: agreeToTerms, + onChanged: (value) => onChanged?.call(value ?? false), + ), + Expanded( + child: Text( + S.of(context).labelAgreeToTerms, + style: Theme.of(context).textTheme.titleSmall, + maxLines: 2, + textAlign: TextAlign.start, + ), + ), + const Gap(Dimen.spacingS), + IconButton( + onPressed: () { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(S.of(context).hintTermsAndConditions), + ), + ); + }, + icon: const Icon(Icons.info), + ), + ], + ), + ), + ); + } +} diff --git a/app/lib/presentation/ui/pages/auth/login/login_form.dart b/app/lib/presentation/ui/pages/auth/login/login_form.dart index 2aa42db..0eb85f6 100644 --- a/app/lib/presentation/ui/pages/auth/login/login_form.dart +++ b/app/lib/presentation/ui/pages/auth/login/login_form.dart @@ -2,6 +2,7 @@ import 'package:app/presentation/navigation/routers.dart'; import 'package:app/presentation/resources/locale/generated/l10n.dart'; import 'package:app/presentation/resources/resources.dart'; import 'package:app/presentation/ui/components/primary_button.dart'; +import 'package:app/presentation/ui/custom/terms_services_check.dart'; import 'package:common/core/resource.dart'; import 'package:domain/bloc/auth/auth_cubit.dart'; import 'package:flutter/material.dart'; @@ -83,35 +84,13 @@ class _LoginFormState extends State { style: Theme.of(context).textTheme.bodySmall, ), const Gap(Dimen.spacingM), - TextButton( - onPressed: () => setState(() { - agreeToTerms = !agreeToTerms; - }), - child: Row( - children: [ - Checkbox( - value: agreeToTerms, - onChanged: (value) => setState(() { - agreeToTerms = value ?? false; - }), - ), - Text( - S.of(context).labelAgreeToTerms, - style: Theme.of(context).textTheme.titleSmall, - ), - const Gap(Dimen.spacingS), - IconButton( - onPressed: () { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(S.of(context).hintTermsAndConditions), - ), - ); - }, - icon: const Icon(Icons.info), - ) - ], - ), + TermsServicesCheck( + agreeToTerms: agreeToTerms, + onChanged: (value) { + setState(() { + agreeToTerms = value; + }); + }, ), const Gap(Dimen.spacingM), BlocBuilder( diff --git a/app/lib/presentation/ui/pages/auth/sign_up/sign_up_form.dart b/app/lib/presentation/ui/pages/auth/sign_up/sign_up_form.dart index 09c1d30..162ac91 100644 --- a/app/lib/presentation/ui/pages/auth/sign_up/sign_up_form.dart +++ b/app/lib/presentation/ui/pages/auth/sign_up/sign_up_form.dart @@ -1,6 +1,7 @@ import 'package:app/presentation/resources/locale/generated/l10n.dart'; import 'package:app/presentation/resources/resources.dart'; import 'package:app/presentation/ui/components/primary_button.dart'; +import 'package:app/presentation/ui/custom/terms_services_check.dart'; import 'package:common/core/resource.dart'; import 'package:common/validators/form_validator.dart'; import 'package:domain/bloc/auth/auth_cubit.dart'; @@ -98,35 +99,13 @@ class _SignUpFormState extends State { }, ), const Gap(Dimen.spacingM), - TextButton( - onPressed: () => setState(() { - agreeToTerms = !agreeToTerms; - }), - child: Row( - children: [ - Checkbox( - value: agreeToTerms, - onChanged: (value) => setState(() { - agreeToTerms = value ?? false; - }), - ), - Text( - S.of(context).labelAgreeToTerms, - style: Theme.of(context).textTheme.titleSmall, - ), - const Gap(Dimen.spacingS), - IconButton( - onPressed: () { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(S.of(context).hintTermsAndConditions), - ), - ); - }, - icon: const Icon(Icons.info), - ) - ], - ), + TermsServicesCheck( + agreeToTerms: agreeToTerms, + onChanged: (value) { + setState(() { + agreeToTerms = value; + }); + }, ), const Gap(Dimen.spacingM), BlocBuilder( diff --git a/app/lib/presentation/ui/pages/main/home/home_view.dart b/app/lib/presentation/ui/pages/main/home/home_view.dart index f0d9eb8..74f5daf 100644 --- a/app/lib/presentation/ui/pages/main/home/home_view.dart +++ b/app/lib/presentation/ui/pages/main/home/home_view.dart @@ -1,7 +1,6 @@ import 'package:app/main/init.dart'; import 'package:domain/bloc/auth/auth_cubit.dart'; import 'package:flutter/material.dart'; -import 'package:app/presentation/ui/custom/app_theme_switch.dart'; class HomeView extends StatelessWidget { /// Given this is a global cubit, we can access it directly from getIt @@ -21,7 +20,6 @@ class HomeView extends StatelessWidget { onPressed: () => _authCubit.logOut(), icon: const Icon(Icons.logout), ), - const AppThemeSwitch(), ], ), body: const Text('Home Page'), diff --git a/modules/common/devtools_options.yaml b/modules/common/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/modules/common/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/modules/data/devtools_options.yaml b/modules/data/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/modules/data/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/modules/data/lib/repositories/common_repository_impl.dart b/modules/data/lib/repositories/common_repository_impl.dart index 17e9f73..effad64 100644 --- a/modules/data/lib/repositories/common_repository_impl.dart +++ b/modules/data/lib/repositories/common_repository_impl.dart @@ -41,4 +41,7 @@ class CommonRepositoryImpl implements CommonRepository { void setAcceptCookies(bool isAllowed) { _preferences.setCookiesAllowed(isAllowed); } + + @override + Future deepClean() => _preferences.clear(); } diff --git a/modules/domain/lib/bloc/app/app_cubit.dart b/modules/domain/lib/bloc/app/app_cubit.dart index 346d37b..0f07fcd 100644 --- a/modules/domain/lib/bloc/app/app_cubit.dart +++ b/modules/domain/lib/bloc/app/app_cubit.dart @@ -22,4 +22,12 @@ class AppCubit extends Cubit { _commonRepository.setAppLang(appLang); emit(state.copyWith(appLang: appLang)); } + + Future resetApp() async { + await _commonRepository.deepClean(); + emit(AppState( + themeType: ThemeType.light, + appLang: AppLang.en, + )); + } } diff --git a/modules/domain/lib/repositories/common_repository.dart b/modules/domain/lib/repositories/common_repository.dart index d7dcc3e..edbb520 100644 --- a/modules/domain/lib/repositories/common_repository.dart +++ b/modules/domain/lib/repositories/common_repository.dart @@ -13,4 +13,6 @@ abstract class CommonRepository { bool areCookiesAllowed(); void setAcceptCookies(bool isAllowed); + + Future deepClean(); }