diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index 3c5c98f3..4226b718 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -22,6 +22,7 @@ import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart'; import 'package:eatvio_app/features/feed/models/recipes_model.dart'; import 'package:eatvio_app/features/feed/presentation/pages/feed_screen.dart'; +import 'package:eatvio_app/features/glossary/presentation/pages/glossary_screen.dart'; import 'package:eatvio_app/features/menu/presentation/pages/menu_screen.dart'; import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart'; import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart'; @@ -65,7 +66,17 @@ class AppRouter { } return null; }, - builder: (context, state) => AuthScreen.builder(context), + builder: (context, state) { + final bool needLogout; + if (state.extra == null) { + needLogout = false; + } else { + needLogout = true; + } + return AuthScreen( + needLogout: needLogout, + ); + }, routes: [ GoRoute( path: 'registration-screen', @@ -127,6 +138,11 @@ class AppRouter { ); }, ), + GoRoute( + path: '/glossary-screen', + name: '/glossaryScreen', + builder: (context, state) => GlossaryScreen(), + ), GoRoute( path: '/about-recipes-screen', name: 'aboutRecipesScreen', diff --git a/lib/core/const.dart b/lib/core/const.dart index 4e8b3650..dfeae1fc 100644 --- a/lib/core/const.dart +++ b/lib/core/const.dart @@ -1,5 +1,5 @@ -// String baseUrl = 'https://eatvio.ru'; -String baseUrl = 'https://dev2.eatvio.com'; +String baseUrl = 'https://eatvio.ru'; +// String baseUrl = 'https://dev2.eatvio.com'; const List durationValues = [7, 14, 21]; diff --git a/lib/core/credentials_storage.dart b/lib/core/credentials_storage.dart new file mode 100644 index 00000000..6cf97c90 --- /dev/null +++ b/lib/core/credentials_storage.dart @@ -0,0 +1,32 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +abstract class CredentialsStorage { + static Future haveCredentialsInStorage() async { + try { + if (await FlutterSecureStorage().read(key: 'email') == null || await FlutterSecureStorage().read(key: 'password') == null) { + return false; + } else { + return true; + } + } catch (e) { + return false; + } + } + + static Future> getCredentialsFromStorage() async { + return { + 'email': (await FlutterSecureStorage().read(key: 'email'))!, + 'password': (await FlutterSecureStorage().read(key: 'password'))!, + }; + } + + static saveCredentials(String email, String password) async { + await FlutterSecureStorage().write(key: 'email', value: email); + await FlutterSecureStorage().write(key: 'password', value: password); + } + + static removeCredentials() async { + await FlutterSecureStorage().delete(key: 'email'); + await FlutterSecureStorage().delete(key: 'password'); + } +} diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart index 39f86908..cf873dd2 100644 --- a/lib/core/locator_service.dart +++ b/lib/core/locator_service.dart @@ -67,6 +67,7 @@ import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/se import 'package:eatvio_app/features/settings/repositories/service_repository.dart'; import 'package:eatvio_app/features/settings/services/settings_service.dart'; import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get_it/get_it.dart'; import 'package:eatvio_app/features/profile/presentation/bloc/plans_cubit/plans_cubit.dart' as profilePlans; @@ -161,4 +162,5 @@ Future init() async { ), ), ); + sl.registerLazySingleton(() async => await FlutterSecureStorage()); } diff --git a/lib/core/token_storage.dart b/lib/core/token_storage.dart index 4a8bb21d..9332ceb5 100644 --- a/lib/core/token_storage.dart +++ b/lib/core/token_storage.dart @@ -7,7 +7,7 @@ abstract class TokenStorage { sl().options.headers['Authorization'] = 'Bearer $token'; } - static haveTokenInStorage() async { + static Future haveTokenInStorage() async { try { if (await FlutterSecureStorage().read(key: 'token') == null) { return false; diff --git a/lib/features/auth/auth_screen/auth_screen.dart b/lib/features/auth/auth_screen/auth_screen.dart index 914398f1..9d1a45ab 100644 --- a/lib/features/auth/auth_screen/auth_screen.dart +++ b/lib/features/auth/auth_screen/auth_screen.dart @@ -1,41 +1,22 @@ import 'dart:convert'; - -import 'package:dio/dio.dart'; import 'package:eatvio_app/core/const.dart'; +import 'package:eatvio_app/core/credentials_storage.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/token_storage.dart'; -import 'package:eatvio_app/core/utils/image_constant.dart'; -import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; +import 'package:eatvio_app/features/auth/const/strings.dart'; import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart'; -import 'package:eatvio_app/generated/l10n.dart'; -import 'package:eatvio_app/core/theme/theme_helper.dart'; -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; -import 'package:url_launcher/url_launcher.dart'; -import 'package:validators/validators.dart'; import 'package:webview_flutter/webview_flutter.dart'; -import 'bloc/auth_bloc.dart'; -import 'models/auth_model.dart'; - class AuthScreen extends StatefulWidget { - static Widget builder(BuildContext context) { - return BlocProvider( - create: (context) => AuthBloc( - AuthState( - authModelObj: AuthModel(), - ), - )..add( - AuthInitialEvent(), - ), - child: AuthScreen(), - ); - } + final bool needLogout; + + const AuthScreen({ + this.needLogout = false, + }); @override State createState() => _AuthScreenState(); @@ -47,51 +28,80 @@ class _AuthScreenState extends State { final baseUrlController = TextEditingController(); late final WebViewController _controller; + String email = ''; + String password = ''; + bool needLogout = false; + + Future logoutFromWeb() async { + await CredentialsStorage.removeCredentials(); + await _controller.runJavaScript(''' + document.querySelector('.header-list__link button[type="submit"]').click(); + '''); + } + + Future loginInApplication() async { + final credentialsFromStorage = await CredentialsStorage.getCredentialsFromStorage(); + final Map credentials = { + 'email': credentialsFromStorage['email']!, + 'password': credentialsFromStorage['password']!, + }; + final response = await http.post( + Uri.parse(baseUrl + '/api/login'), + headers: {'Content-Type': 'application/json'}, + body: json.encode(credentials), + encoding: utf8, + ); + var res = await jsonDecode(response.body); + final token = res['token']; + await TokenStorage.saveTokenInStorage(token); + await Future.delayed(Duration.zero, () => GoRouter.of(context).go('/my-profile-screen')); + await sl().getMyProfile(); + } + @override void initState() { super.initState(); + needLogout = widget.needLogout; _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..addJavaScriptChannel( 'FlutterChannel', onMessageReceived: (JavaScriptMessage message) { - // Handle messages from JavaScript final data = jsonDecode(message.message); - final email = data['email']; - final password = data['password']; - print('Email: $email, Password: $password'); + email = data['email']; + password = data['password']; }, ) ..setNavigationDelegate( NavigationDelegate( onPageFinished: (String url) async { - await _controller.runJavaScript(''' - function initializeListeners() { - const emailInput = document.getElementById("inputEmail_main"); - const passwordInput = document.getElementById("inputPassword_main"); + final bool tokenInStorage = await TokenStorage.haveTokenInStorage(); + final bool credentialsInStorage = await CredentialsStorage.haveCredentialsInStorage(); - if (emailInput && passwordInput) { - function sendToFlutter() { - const email = emailInput.value; - const password = passwordInput.value; - const data = JSON.stringify({ email: email, password: password }); - if (window.FlutterChannel) { - window.FlutterChannel.postMessage(data); - } - } - - emailInput.addEventListener("input", sendToFlutter); - passwordInput.addEventListener("input", sendToFlutter); + if (needLogout) { + await logoutFromWeb(); + needLogout = false; + } else if (!url.contains('profile') && !url.contains('registration')) { + await _controller.runJavaScript(jsChannelAuthScript); + } else if (url.contains('profile')) { + if (credentialsInStorage) { + await loginInApplication(); + } else { + if (email.isNotEmpty && password.isNotEmpty) { + await CredentialsStorage.saveCredentials(email, password); + await loginInApplication(); } else { - console.error("Email or Password input not found."); + await logoutFromWeb(); } } - - // Ensure DOM is loaded before attaching listeners - document.addEventListener("DOMContentLoaded", initializeListeners); - initializeListeners(); - '''); + } else { + if (tokenInStorage && credentialsInStorage) { + GoRouter.of(context).go('/my-profile-screen'); + } else if (!tokenInStorage && credentialsInStorage) { + await loginInApplication(); + } + } }, ), ) @@ -101,269 +111,13 @@ class _AuthScreenState extends State { @override Widget build(BuildContext context) { FlutterNativeSplash.remove(); - final s = S.of(context); - - // return Scaffold( - // appBar: AppBar( - // toolbarHeight: 0, - // ), - // body: WebViewWidget(controller: _controller), - // ); - return Scaffold( appBar: AppBar( - centerTitle: true, - title: GestureDetector( - onLongPress: () { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Base url без https:// и /api'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CustomTextFormField( - controller: baseUrlController, - hintText: 'dev2.eatvio.com', - ), - const SizedBox(height: 12), - InkWell( - onTap: () async { - baseUrl = 'https://${baseUrlController.text}'; - sl().options.baseUrl = baseUrl; - }, - borderRadius: BorderRadius.circular(20), - child: Ink( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: appTheme.blueA400, - ), - child: Container( - padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), - alignment: Alignment.center, - child: Text( - 'Сохранить', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ), - ], - ), - ), - ); - }, - child: SvgPicture.asset( - ImageConstant.imgLogoEatvio, - height: 70, - fit: BoxFit.contain, - ), - ), + toolbarHeight: 0, ), body: SafeArea( - child: Padding( - padding: EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.email), - const SizedBox(height: 4), - BlocSelector( - selector: (state) => state.emailController, - builder: (context, emailController) { - return CustomTextFormField( - controller: emailController, - textInputAction: TextInputAction.next, - keyboardType: TextInputType.emailAddress, - textInputType: TextInputType.emailAddress, - hintText: 'Введите email', - ); - }, - ), - const SizedBox(height: 16), - Text(s.password), - const SizedBox(height: 4), - BlocSelector( - selector: (state) => state.passwordController, - builder: (context, passwordController) { - return CustomTextFormField( - obscureText: hidePassword, - controller: passwordController, - hintText: 'Введите пароль', - suffix: IconButton( - onPressed: () { - setState(() { - hidePassword = !hidePassword; - }); - }, - icon: Icon( - hidePassword ? Icons.visibility_outlined : Icons.visibility_off_outlined, - color: Colors.grey, - ), - ), - ); - }, - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Нет аккаунта? '), - GestureDetector( - onTap: () => GoRouter.of(context).goNamed('registrationScreen'), - child: Text( - 'Зарегистрироваться', - style: TextStyle( - color: appTheme.blueA400, - decorationColor: appTheme.blueA400, - decoration: TextDecoration.underline, - ), - ), - ), - ], - ), - Spacer(), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - text: 'Нажимая "Войти", Вы соглашаетесь \n', - style: TextStyle( - fontSize: 12, - color: Colors.black, - ), - children: [ - TextSpan(text: 'c '), - TextSpan( - text: ' Публичной офертой', - style: TextStyle( - fontSize: 12, - color: appTheme.blueA400, - decorationColor: appTheme.blueA400, - decoration: TextDecoration.underline, - ), - recognizer: TapGestureRecognizer()..onTap = () async => await launchUrl(Uri.parse(baseUrl + '/oferta_bs.pdf')), - ), - ], - ), - ), - ), - const SizedBox(height: 16), - BlocBuilder( - builder: (context, state) { - return Container( - height: 48, - width: MediaQuery.of(context).size.width - 32, - child: FloatingActionButton.extended( - heroTag: 'authButton', - highlightElevation: 0, - elevation: 0, - focusElevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - backgroundColor: appTheme.blueA400, - onPressed: onTapAuth(state, context), - label: Text( - 'Войти', - style: theme.textTheme.titleSmall!.copyWith(color: Colors.white), - ), - ), - ); - }, - ), - ], - ), - ), + child: WebViewWidget(controller: _controller), ), ); } - - onTapAuth(AuthState state, BuildContext context) { - final s = S.of(context); - return () async { - List errors = validateFields(state.emailController!.text, state.passwordController!.text); - if (errors.isEmpty) { - final Map credentials = { - 'email': state.emailController!.text, - 'password': state.passwordController!.text, - }; - final response = await http.post( - Uri.parse(baseUrl + '/api/login'), - headers: {'Content-Type': 'application/json'}, - body: json.encode(credentials), - encoding: utf8, - ); - - if (response.statusCode == 200) { - var res = await jsonDecode(response.body); - final token = res['token']; - await TokenStorage.saveTokenInStorage(token); - GoRouter.of(context).go('/my-profile-screen'); - sl().getMyProfile(); - } else { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(s.wrong_credentials), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text('OK'), - ), - ], - ), - ); - } - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text('OK'), - ), - ], - ), - ); - } - }; - } - - List validateFields(String email, String password) { - final s = S.of(context); - - List errors = []; - - if (!isEmail(email)) { - errors.add(s.email_invalid); - } - - if (email.isEmpty) { - errors.add(s.email_empty); - } - - if (password.isEmpty) { - errors.add(s.password_empty); - } - - if (password.length < 6) { - errors.add(s.password_short); - } - - return errors; - } } diff --git a/lib/features/auth/auth_screen/bloc/auth_bloc.dart b/lib/features/auth/auth_screen/bloc/auth_bloc.dart deleted file mode 100644 index f2df813c..00000000 --- a/lib/features/auth/auth_screen/bloc/auth_bloc.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:eatvio_app/features/auth/auth_screen/models/auth_model.dart'; -import 'package:equatable/equatable.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'auth_event.dart'; -part 'auth_state.dart'; - -/// A bloc that manages the state of a Auth according to the event that is dispatched to it. -class AuthBloc extends Bloc { - AuthBloc(AuthState initialState) : super(initialState) { - on(_onInitialize); - } - - _onInitialize( - AuthInitialEvent event, - Emitter emit, - ) async { - emit( - state.copyWith( - emailController: TextEditingController(), - passwordController: TextEditingController(), - ), - ); - } -} diff --git a/lib/features/auth/auth_screen/bloc/auth_event.dart b/lib/features/auth/auth_screen/bloc/auth_event.dart deleted file mode 100644 index a395a45b..00000000 --- a/lib/features/auth/auth_screen/bloc/auth_event.dart +++ /dev/null @@ -1,16 +0,0 @@ -// ignore_for_file: must_be_immutable - -part of 'auth_bloc.dart'; - -/// Abstract class for all events that can be dispatched from the -///Credentials widget. -/// -/// Events must be immutable and implement the [Equatable] interface. -@immutable -abstract class AuthEvent extends Equatable {} - -/// Event that is dispatched when the Credentials widget is first created. -class AuthInitialEvent extends AuthEvent { - @override - List get props => []; -} diff --git a/lib/features/auth/auth_screen/bloc/auth_state.dart b/lib/features/auth/auth_screen/bloc/auth_state.dart deleted file mode 100644 index 86e8e3b0..00000000 --- a/lib/features/auth/auth_screen/bloc/auth_state.dart +++ /dev/null @@ -1,37 +0,0 @@ -// ignore_for_file: must_be_immutable - -part of 'auth_bloc.dart'; - -/// Represents the state of Auth in the application. -class AuthState extends Equatable { - AuthState({ - this.emailController, - this.passwordController, - this.authModelObj, - }); - - TextEditingController? emailController; - - TextEditingController? passwordController; - - AuthModel? authModelObj; - - @override - List get props => [ - emailController, - passwordController, - authModelObj, - ]; - - AuthState copyWith({ - TextEditingController? emailController, - TextEditingController? passwordController, - AuthModel? authModelObj, - }) { - return AuthState( - emailController: emailController ?? this.emailController, - passwordController: passwordController ?? this.passwordController, - authModelObj: authModelObj ?? this.authModelObj, - ); - } -} diff --git a/lib/features/auth/auth_screen/models/auth_model.dart b/lib/features/auth/auth_screen/models/auth_model.dart deleted file mode 100644 index 829b38c8..00000000 --- a/lib/features/auth/auth_screen/models/auth_model.dart +++ /dev/null @@ -1,16 +0,0 @@ -// ignore_for_file: must_be_immutable - -import 'package:equatable/equatable.dart'; - -/// This class defines the variables used in the [auth_screen], -/// and is typically used to hold data that is passed between different parts of the application. -class AuthModel extends Equatable { - AuthModel(); - - AuthModel copyWith() { - return AuthModel(); - } - - @override - List get props => []; -} diff --git a/lib/features/auth/const/strings.dart b/lib/features/auth/const/strings.dart new file mode 100644 index 00000000..66d05c4d --- /dev/null +++ b/lib/features/auth/const/strings.dart @@ -0,0 +1,22 @@ +const String jsChannelAuthScript = ''' + function initializeListeners() { + const emailInput = document.getElementById("inputEmail_main"); + const passwordInput = document.getElementById("inputPassword_main"); + if (emailInput && passwordInput) { + function sendToFlutter() { + const email = emailInput.value; + const password = passwordInput.value; + const data = JSON.stringify({ email: email, password: password }); + if (window.FlutterChannel) { + window.FlutterChannel.postMessage(data); + } + } + emailInput.addEventListener("input", sendToFlutter); + passwordInput.addEventListener("input", sendToFlutter); + } else { + console.error("Email or Password input not found."); + } + } + document.addEventListener("DOMContentLoaded", initializeListeners); + initializeListeners(); + '''; diff --git a/lib/features/glossary/presentation/pages/glossary_screen.dart b/lib/features/glossary/presentation/pages/glossary_screen.dart new file mode 100644 index 00000000..97d59810 --- /dev/null +++ b/lib/features/glossary/presentation/pages/glossary_screen.dart @@ -0,0 +1,33 @@ +import 'package:eatvio_app/core/const.dart'; +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class GlossaryScreen extends StatefulWidget { + const GlossaryScreen({super.key}); + + @override + State createState() => _GlossaryScreenState(); +} + +class _GlossaryScreenState extends State { + late final WebViewController _controller; + + @override + void initState() { + super.initState(); + + _controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..loadRequest(Uri.parse(baseUrl + '/product_nutritional_value')); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Глоссарий'), + ), + body: WebViewWidget(controller: _controller), + ); + } +} diff --git a/lib/features/menu/presentation/pages/menu_screen.dart b/lib/features/menu/presentation/pages/menu_screen.dart index a1102186..cfc2e8a1 100644 --- a/lib/features/menu/presentation/pages/menu_screen.dart +++ b/lib/features/menu/presentation/pages/menu_screen.dart @@ -127,7 +127,7 @@ class MenuScreen extends StatelessWidget { } catch (e) { } finally { await TokenStorage.removeTokenInStorage(); - GoRouter.of(context).go('/auth-screen'); + GoRouter.of(context).go('/auth-screen', extra: true); } }; } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 0d06adf7..2bcea0e1 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -22,350 +22,381 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "Moscow": MessageLookupByLibrary.simpleMessage("Москва"), - "Russia": MessageLookupByLibrary.simpleMessage("Россия"), - "about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"), - "about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"), - "about_recipe": MessageLookupByLibrary.simpleMessage("Об этом рецепте"), - "active": MessageLookupByLibrary.simpleMessage("Активен"), - "active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"), - "add": MessageLookupByLibrary.simpleMessage("Добавить"), - "add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"), - "add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"), - "adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"), - "additional_information": - MessageLookupByLibrary.simpleMessage("Дополнительная информация"), - "admin": MessageLookupByLibrary.simpleMessage("Админ"), - "all": MessageLookupByLibrary.simpleMessage("Все"), - "allergies_presence": - MessageLookupByLibrary.simpleMessage("Наличие аллергии"), - "another_form_of_comment": - MessageLookupByLibrary.simpleMessage("комментария"), - "another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"), - "another_form_of_hour": MessageLookupByLibrary.simpleMessage("часа"), - "another_form_of_minute": MessageLookupByLibrary.simpleMessage("минут"), - "another_form_of_stage": MessageLookupByLibrary.simpleMessage("этапа"), - "answer": MessageLookupByLibrary.simpleMessage("Ответить"), - "archived": MessageLookupByLibrary.simpleMessage("В архиве"), - "authentificate": MessageLookupByLibrary.simpleMessage("Войти"), - "average_pressure": MessageLookupByLibrary.simpleMessage( - "Средние показатели давления:"), - "bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"), - "by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"), - "calories": MessageLookupByLibrary.simpleMessage("Калории"), - "cancel_diet": MessageLookupByLibrary.simpleMessage("Отменить диету?"), - "carb_type": MessageLookupByLibrary.simpleMessage("Мучное"), - "carb_type_desc": MessageLookupByLibrary.simpleMessage( - "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."), - "carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"), - "chat": MessageLookupByLibrary.simpleMessage("Чат"), - "check_out_video_recipe": - MessageLookupByLibrary.simpleMessage("Посмотреть видео рецепт"), - "chest": MessageLookupByLibrary.simpleMessage("Грудь"), - "chest_circumference": - MessageLookupByLibrary.simpleMessage("Обхват груди"), - "choose_diet_duration": - MessageLookupByLibrary.simpleMessage("Выберите срок диеты"), - "choose_plan_duration": - MessageLookupByLibrary.simpleMessage("Выберите срок плана"), - "choose_start_diet_date": MessageLookupByLibrary.simpleMessage( - "Выберите дату старты диеты. Она отобразиться у Вас в дневнике"), - "circumference_empty": MessageLookupByLibrary.simpleMessage( - "Все замеры обязательны к заполнению"), - "circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage( - "Все замеры должны быть числами"), - "circumferences_chart": - MessageLookupByLibrary.simpleMessage("График обхватов"), - "city": MessageLookupByLibrary.simpleMessage("Город"), - "city_of_living": - MessageLookupByLibrary.simpleMessage("Город проживания"), - "comfort": MessageLookupByLibrary.simpleMessage("Комфорт"), - "comment": MessageLookupByLibrary.simpleMessage("комментарий"), - "comments": MessageLookupByLibrary.simpleMessage("Комментарии"), - "comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"), - "complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"), - "confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"), - "continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"), - "continue_": MessageLookupByLibrary.simpleMessage("Продолжить"), - "copied": MessageLookupByLibrary.simpleMessage("cкопирован"), - "copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"), - "could_not_cancel_diet": - MessageLookupByLibrary.simpleMessage("Не удалось отменить диету"), - "could_not_launch_video": - MessageLookupByLibrary.simpleMessage("Не удалось запустить видео"), - "country": MessageLookupByLibrary.simpleMessage("Страна"), - "create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"), - "customer_price": - MessageLookupByLibrary.simpleMessage("Цена для покупателя"), - "date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"), - "day": MessageLookupByLibrary.simpleMessage("День"), - "days": MessageLookupByLibrary.simpleMessage("дней"), - "deleted": MessageLookupByLibrary.simpleMessage("Удалена"), - "diary": MessageLookupByLibrary.simpleMessage("Дневник"), - "diet": MessageLookupByLibrary.simpleMessage("Диета"), - "diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"), - "diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"), - "diet_started": - MessageLookupByLibrary.simpleMessage("Диета уже начата"), - "diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"), - "diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"), - "do_you_have_hypertension_tendency": - MessageLookupByLibrary.simpleMessage("Есть ли у вас гипертония?"), - "do_you_have_hypotension_tendency": - MessageLookupByLibrary.simpleMessage("Есть ли у вас гипотония?"), - "do_you_take_pills": MessageLookupByLibrary.simpleMessage( - "Принимаете ли вы лекарства или бады?"), - "down_pressure": - MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"), - "draft": MessageLookupByLibrary.simpleMessage("Черновик"), - "drafted": MessageLookupByLibrary.simpleMessage("Черновики"), - "eating_behavior": - MessageLookupByLibrary.simpleMessage("Пищевое поведение"), - "eating_behavior_type": MessageLookupByLibrary.simpleMessage( - "Формирование пищевого поведения"), - "eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage( - "Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;"), - "economy": MessageLookupByLibrary.simpleMessage("Эконом"), - "edit": MessageLookupByLibrary.simpleMessage("Редактировать"), - "email": MessageLookupByLibrary.simpleMessage("Электронная почта"), - "email_empty": MessageLookupByLibrary.simpleMessage( - "Необходимо ввести адрес электронной почты"), - "email_invalid": MessageLookupByLibrary.simpleMessage( - "Некорректный адрес электронной почты"), - "enter_additional_information": MessageLookupByLibrary.simpleMessage( - "Введите любую дополнительную информацию на своё усмотрение:"), - "enter_diet_description": - MessageLookupByLibrary.simpleMessage("Введите описание диеты"), - "enter_diet_name": - MessageLookupByLibrary.simpleMessage("Выведите название диеты"), - "enter_information": - MessageLookupByLibrary.simpleMessage("Введите информацию..."), - "exit": MessageLookupByLibrary.simpleMessage("Выйти"), - "expand": MessageLookupByLibrary.simpleMessage("Показать полностью"), - "fats": MessageLookupByLibrary.simpleMessage("Жиры"), - "favorite_foods": - MessageLookupByLibrary.simpleMessage("Любимые продукты"), - "favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage( - "Ваши любимые/нелюбимые продукты питания?"), - "female": MessageLookupByLibrary.simpleMessage("Женский"), - "fill_in_information": - MessageLookupByLibrary.simpleMessage("Заполните информацию:"), - "finish": MessageLookupByLibrary.simpleMessage("Завершить"), - "first_name": MessageLookupByLibrary.simpleMessage("Имя"), - "first_name_empty": MessageLookupByLibrary.simpleMessage( - "Имя обязательно для заполнения"), - "first_name_short": MessageLookupByLibrary.simpleMessage( - "В имени должен быть минимум 1 символ"), - "fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"), - "fit_type_desc": MessageLookupByLibrary.simpleMessage( - "План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;"), - "fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"), - "from": MessageLookupByLibrary.simpleMessage("от"), - "from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"), - "from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"), - "gallery": MessageLookupByLibrary.simpleMessage("Галерея"), - "general_info": - MessageLookupByLibrary.simpleMessage("Общая информация"), - "gr": MessageLookupByLibrary.simpleMessage("гр"), - "grams": MessageLookupByLibrary.simpleMessage("гр"), - "has_alergy": MessageLookupByLibrary.simpleMessage("Наличие аллергии"), - "has_hyper": - MessageLookupByLibrary.simpleMessage("Склонность к гипертонии"), - "has_hypo": - MessageLookupByLibrary.simpleMessage("Склонность к гипотонии"), - "height": MessageLookupByLibrary.simpleMessage("Рост"), - "height_measurements": - MessageLookupByLibrary.simpleMessage("Замер роста"), - "hide": MessageLookupByLibrary.simpleMessage("Свернуть"), - "hip_circumference": - MessageLookupByLibrary.simpleMessage("Обхват бедер"), - "hips": MessageLookupByLibrary.simpleMessage("Бедра"), - "hour": MessageLookupByLibrary.simpleMessage("час"), - "hours": MessageLookupByLibrary.simpleMessage("часов"), - "in_progress": MessageLookupByLibrary.simpleMessage("В процессе"), - "inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"), - "ingredients": MessageLookupByLibrary.simpleMessage("Ингредиенты"), - "initial_measurements": - MessageLookupByLibrary.simpleMessage("Первичные замеры"), - "label": MessageLookupByLibrary.simpleMessage("Название"), - "language": MessageLookupByLibrary.simpleMessage("Язык"), - "last_name": MessageLookupByLibrary.simpleMessage("Фамилия"), - "last_name_empty": MessageLookupByLibrary.simpleMessage( - "Фамилия обязательна для заполнения"), - "last_name_short": MessageLookupByLibrary.simpleMessage( - "В фамилии должен быть минимум 6 символов"), - "lbl_english": MessageLookupByLibrary.simpleMessage("English"), - "light_type": MessageLookupByLibrary.simpleMessage("Легкая"), - "light_type_desc": MessageLookupByLibrary.simpleMessage( - "С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."), - "liked_groceries": - MessageLookupByLibrary.simpleMessage("Любимые продукты"), - "link_was_copied": - MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"), - "loading": MessageLookupByLibrary.simpleMessage("Загрузка..."), - "lower": MessageLookupByLibrary.simpleMessage("Нижнее"), - "male": MessageLookupByLibrary.simpleMessage("Мужской"), - "meal": MessageLookupByLibrary.simpleMessage("Приём пищи"), - "meat": MessageLookupByLibrary.simpleMessage("Мясо"), - "meat_type": MessageLookupByLibrary.simpleMessage("С мясом"), - "meat_type_desc": MessageLookupByLibrary.simpleMessage( - "Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."), - "milliliter": MessageLookupByLibrary.simpleMessage("мл"), - "minimal_customer_price": MessageLookupByLibrary.simpleMessage( - "Минимальная цена для покупателя: 1200₽"), - "minute": MessageLookupByLibrary.simpleMessage("минута"), - "minutes": MessageLookupByLibrary.simpleMessage("минуты"), - "most_new": MessageLookupByLibrary.simpleMessage("Самые новые"), - "most_old": MessageLookupByLibrary.simpleMessage("Самые старые"), - "msg_network_err": - MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"), - "msg_something_went_wrong": - MessageLookupByLibrary.simpleMessage("Что то пошло не так!"), - "my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"), - "my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"), - "my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"), - "my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"), - "name_empty": MessageLookupByLibrary.simpleMessage( - "Имя пользователя обязательно для заполнения"), - "name_short": MessageLookupByLibrary.simpleMessage( - "В имени пользователя должно быть минимум 6 символов"), - "no": MessageLookupByLibrary.simpleMessage("Нет"), - "no_account": - MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"), - "not_liked_groceries": - MessageLookupByLibrary.simpleMessage("Не любимые продукты"), - "one_option": MessageLookupByLibrary.simpleMessage("1 опция"), - "option": MessageLookupByLibrary.simpleMessage("Опция"), - "option_content": - MessageLookupByLibrary.simpleMessage("Содержание опции"), - "option_content_hint_text": - MessageLookupByLibrary.simpleMessage("На связи 7 дней в неделю"), - "option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"), - "option_desc_hint_text": MessageLookupByLibrary.simpleMessage( - "Этот план питания для похудения на 7 дней сбалансированный и разнообразный"), - "option_duration": - MessageLookupByLibrary.simpleMessage("Продолжительность опции"), - "option_personal_diet_desc": MessageLookupByLibrary.simpleMessage( - "Опция подразумевает создание индивидуальной диеты"), - "option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"), - "order": MessageLookupByLibrary.simpleMessage("Порядок"), - "other_info": MessageLookupByLibrary.simpleMessage("Прочая информация"), - "password": MessageLookupByLibrary.simpleMessage("Пароль"), - "password_confirmation": - MessageLookupByLibrary.simpleMessage("Подтвердите пароль"), - "password_confirmation_mismatch": - MessageLookupByLibrary.simpleMessage("Пароли не совпадают"), - "password_empty": MessageLookupByLibrary.simpleMessage( - "Пароль обязателен для заполнения"), - "password_short": MessageLookupByLibrary.simpleMessage( - "В пароле должно быть минимум 6 символов"), - "pcs": MessageLookupByLibrary.simpleMessage("шт"), - "personal": MessageLookupByLibrary.simpleMessage("Персональные"), - "personal_diet_state": - MessageLookupByLibrary.simpleMessage("Персональная"), - "photo": MessageLookupByLibrary.simpleMessage("Фото"), - "physical_fitness": - MessageLookupByLibrary.simpleMessage("Физическая форма"), - "place_of_living": - MessageLookupByLibrary.simpleMessage("Место проживания"), - "plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"), - "plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"), - "plan_desc_example": MessageLookupByLibrary.simpleMessage( - "Большое подробное, привлекательное описание плана"), - "plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"), - "plan_label_desc": - MessageLookupByLibrary.simpleMessage("План для поддержания формы"), - "plan_type": MessageLookupByLibrary.simpleMessage("Тип плана"), - "plans_complete": - MessageLookupByLibrary.simpleMessage("Пройденные планы"), - "popular": MessageLookupByLibrary.simpleMessage("Популярные"), - "preferred_language": - MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"), - "pressure": MessageLookupByLibrary.simpleMessage("Давление"), - "pressure_empty": MessageLookupByLibrary.simpleMessage( - "Все показатели давления обязательны к заполнению"), - "pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage( - "Все показатели давления должны быть числами"), - "preview": MessageLookupByLibrary.simpleMessage("Превью"), - "price": MessageLookupByLibrary.simpleMessage("Цена"), - "price_explanation": MessageLookupByLibrary.simpleMessage( - "Разница в ценах, это комиссия Итвио"), - "profile": MessageLookupByLibrary.simpleMessage("Профиль"), - "proteins": MessageLookupByLibrary.simpleMessage("Белки"), - "publish": MessageLookupByLibrary.simpleMessage("Опубликовать"), - "published": MessageLookupByLibrary.simpleMessage("Опубликованные"), - "recipe_author": MessageLookupByLibrary.simpleMessage("Автор рецепта"), - "removeFromActive": - MessageLookupByLibrary.simpleMessage("Снять с публикации"), - "save": MessageLookupByLibrary.simpleMessage("Сохранить"), - "services": MessageLookupByLibrary.simpleMessage("Оказание услуг"), - "settings": MessageLookupByLibrary.simpleMessage("Настройки"), - "sex": MessageLookupByLibrary.simpleMessage("Пол"), - "share": MessageLookupByLibrary.simpleMessage("Поделиться"), - "skip": MessageLookupByLibrary.simpleMessage("Пропустить"), - "slim": MessageLookupByLibrary.simpleMessage("Похудение"), - "slim_type": MessageLookupByLibrary.simpleMessage("Похудение"), - "slim_type_desc": MessageLookupByLibrary.simpleMessage( - "План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;"), - "sport_hobbies": - MessageLookupByLibrary.simpleMessage("Спортивные увлечения"), - "stage": MessageLookupByLibrary.simpleMessage("этап"), - "stages": MessageLookupByLibrary.simpleMessage("этапов"), - "standard": MessageLookupByLibrary.simpleMessage("Стандарт"), - "startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"), - "step": MessageLookupByLibrary.simpleMessage("Шаг"), - "step_by_step_photo_recipe": - MessageLookupByLibrary.simpleMessage("Пошаговый фоторецепт"), - "takes_pills": - MessageLookupByLibrary.simpleMessage("Принимает лекарства"), - "tell_your_schedule": MessageLookupByLibrary.simpleMessage( - "Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"), - "there_is_a_video": MessageLookupByLibrary.simpleMessage("Есть видео"), - "three_options": MessageLookupByLibrary.simpleMessage("3 опции"), - "time": MessageLookupByLibrary.simpleMessage("Время прохождения"), - "toOffer": MessageLookupByLibrary.simpleMessage("Предложить"), - "to_draft": MessageLookupByLibrary.simpleMessage("В черновик"), - "unfavorite_foods": - MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"), - "up_pressure": MessageLookupByLibrary.simpleMessage( - "Верхние показатели давления:"), - "upper": MessageLookupByLibrary.simpleMessage("Верхнее"), - "user_authorization": - MessageLookupByLibrary.simpleMessage("Аутентификация"), - "user_data": - MessageLookupByLibrary.simpleMessage("Данные пользователя"), - "user_registration": - MessageLookupByLibrary.simpleMessage("Регистрация пользователя"), - "username": MessageLookupByLibrary.simpleMessage("Имя пользователя"), - "vegan": MessageLookupByLibrary.simpleMessage("Веган."), - "vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"), - "vegan_type_desc": MessageLookupByLibrary.simpleMessage( - "Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."), - "waist": MessageLookupByLibrary.simpleMessage("Талия"), - "waist_circumference": - MessageLookupByLibrary.simpleMessage("Обхват талии"), - "weight": MessageLookupByLibrary.simpleMessage("Вес"), - "weight_chart": MessageLookupByLibrary.simpleMessage("График веса"), - "weight_measurements": - MessageLookupByLibrary.simpleMessage("Замер веса"), - "wellness": - MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"), - "wellness_type": - MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"), - "wellness_type_desc": MessageLookupByLibrary.simpleMessage( - "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."), - "what_is_your_name": - MessageLookupByLibrary.simpleMessage("Как вас зовут?"), - "wrong_credentials": MessageLookupByLibrary.simpleMessage( - "Неверные данные пользователя"), - "you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"), - "your_blood_pressure": - MessageLookupByLibrary.simpleMessage("Ваше артериальное давление?"), - "your_favorite_sports": - MessageLookupByLibrary.simpleMessage("Ваши спортивные увлечения?"), - "your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"), - "your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"), - "your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"), - "your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:") - }; + "Moscow": MessageLookupByLibrary.simpleMessage("Москва"), + "Russia": MessageLookupByLibrary.simpleMessage("Россия"), + "about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"), + "about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"), + "active": MessageLookupByLibrary.simpleMessage("Активен"), + "active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"), + "add": MessageLookupByLibrary.simpleMessage("Добавить"), + "add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"), + "add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"), + "adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"), + "additional_information": MessageLookupByLibrary.simpleMessage( + "Дополнительная информация", + ), + "admin": MessageLookupByLibrary.simpleMessage("Админ"), + "all": MessageLookupByLibrary.simpleMessage("Все"), + "allergies_presence": MessageLookupByLibrary.simpleMessage( + "Наличие аллергии", + ), + "another_form_of_comment": MessageLookupByLibrary.simpleMessage( + "комментария", + ), + "another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"), + "answer": MessageLookupByLibrary.simpleMessage("Ответить"), + "archived": MessageLookupByLibrary.simpleMessage("В архиве"), + "authentificate": MessageLookupByLibrary.simpleMessage("Войти"), + "average_pressure": MessageLookupByLibrary.simpleMessage( + "Средние показатели давления:", + ), + "bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"), + "by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"), + "calories": MessageLookupByLibrary.simpleMessage("Калории"), + "cancel_diet": MessageLookupByLibrary.simpleMessage("Отменить диету?"), + "carb_type": MessageLookupByLibrary.simpleMessage("Мучное"), + "carb_type_desc": MessageLookupByLibrary.simpleMessage( + "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.", + ), + "carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"), + "chat": MessageLookupByLibrary.simpleMessage("Чат"), + "chest": MessageLookupByLibrary.simpleMessage("Грудь"), + "chest_circumference": MessageLookupByLibrary.simpleMessage("Обхват груди"), + "choose_diet_duration": MessageLookupByLibrary.simpleMessage( + "Выберите срок диеты", + ), + "choose_plan_duration": MessageLookupByLibrary.simpleMessage( + "Выберите срок плана", + ), + "choose_start_diet_date": MessageLookupByLibrary.simpleMessage( + "Выберите дату старты диеты. Она отобразиться у Вас в дневнике", + ), + "circumference_empty": MessageLookupByLibrary.simpleMessage( + "Все замеры обязательны к заполнению", + ), + "circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage( + "Все замеры должны быть числами", + ), + "circumferences_chart": MessageLookupByLibrary.simpleMessage( + "График обхватов", + ), + "city": MessageLookupByLibrary.simpleMessage("Город"), + "city_of_living": MessageLookupByLibrary.simpleMessage("Город проживания"), + "comfort": MessageLookupByLibrary.simpleMessage("Комфорт"), + "comment": MessageLookupByLibrary.simpleMessage("комментарий"), + "comments": MessageLookupByLibrary.simpleMessage("Комментарии"), + "comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"), + "complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"), + "confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"), + "continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"), + "continue_": MessageLookupByLibrary.simpleMessage("Продолжить"), + "copied": MessageLookupByLibrary.simpleMessage("cкопирован"), + "copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"), + "could_not_cancel_diet": MessageLookupByLibrary.simpleMessage( + "Не удалось отменить диету", + ), + "country": MessageLookupByLibrary.simpleMessage("Страна"), + "create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"), + "customer_price": MessageLookupByLibrary.simpleMessage( + "Цена для покупателя", + ), + "date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"), + "day": MessageLookupByLibrary.simpleMessage("День"), + "days": MessageLookupByLibrary.simpleMessage("дней"), + "deleted": MessageLookupByLibrary.simpleMessage("Удалена"), + "diary": MessageLookupByLibrary.simpleMessage("Дневник"), + "diet": MessageLookupByLibrary.simpleMessage("Диета"), + "diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"), + "diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"), + "diet_started": MessageLookupByLibrary.simpleMessage("Диета уже начата"), + "diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"), + "diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"), + "do_you_have_hypertension_tendency": MessageLookupByLibrary.simpleMessage( + "Есть ли у вас гипертония?", + ), + "do_you_have_hypotension_tendency": MessageLookupByLibrary.simpleMessage( + "Есть ли у вас гипотония?", + ), + "do_you_take_pills": MessageLookupByLibrary.simpleMessage( + "Принимаете ли вы лекарства или бады?", + ), + "down_pressure": MessageLookupByLibrary.simpleMessage( + "Нижние показатели давления:", + ), + "draft": MessageLookupByLibrary.simpleMessage("Черновик"), + "drafted": MessageLookupByLibrary.simpleMessage("Черновики"), + "eating_behavior": MessageLookupByLibrary.simpleMessage( + "Пищевое поведение", + ), + "eating_behavior_type": MessageLookupByLibrary.simpleMessage( + "Формирование пищевого поведения", + ), + "eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage( + "Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;", + ), + "economy": MessageLookupByLibrary.simpleMessage("Эконом"), + "edit": MessageLookupByLibrary.simpleMessage("Редактировать"), + "email": MessageLookupByLibrary.simpleMessage("Электронная почта"), + "email_empty": MessageLookupByLibrary.simpleMessage( + "Необходимо ввести адрес электронной почты", + ), + "email_invalid": MessageLookupByLibrary.simpleMessage( + "Некорректный адрес электронной почты", + ), + "enter_additional_information": MessageLookupByLibrary.simpleMessage( + "Введите любую дополнительную информацию на своё усмотрение:", + ), + "enter_diet_description": MessageLookupByLibrary.simpleMessage( + "Введите описание диеты", + ), + "enter_diet_name": MessageLookupByLibrary.simpleMessage( + "Выведите название диеты", + ), + "enter_information": MessageLookupByLibrary.simpleMessage( + "Введите информацию...", + ), + "exit": MessageLookupByLibrary.simpleMessage("Выйти"), + "expand": MessageLookupByLibrary.simpleMessage("Показать полностью"), + "fats": MessageLookupByLibrary.simpleMessage("Жиры"), + "favorite_foods": MessageLookupByLibrary.simpleMessage("Любимые продукты"), + "favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage( + "Ваши любимые/нелюбимые продукты питания?", + ), + "female": MessageLookupByLibrary.simpleMessage("Женский"), + "fill_in_information": MessageLookupByLibrary.simpleMessage( + "Заполните информацию:", + ), + "finish": MessageLookupByLibrary.simpleMessage("Завершить"), + "first_name": MessageLookupByLibrary.simpleMessage("Имя"), + "first_name_empty": MessageLookupByLibrary.simpleMessage( + "Имя обязательно для заполнения", + ), + "first_name_short": MessageLookupByLibrary.simpleMessage( + "В имени должен быть минимум 1 символ", + ), + "fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"), + "fit_type_desc": MessageLookupByLibrary.simpleMessage( + "План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;", + ), + "fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"), + "from": MessageLookupByLibrary.simpleMessage("от"), + "from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"), + "from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"), + "gallery": MessageLookupByLibrary.simpleMessage("Галерея"), + "general_info": MessageLookupByLibrary.simpleMessage("Общая информация"), + "gr": MessageLookupByLibrary.simpleMessage("гр"), + "grams": MessageLookupByLibrary.simpleMessage("гр"), + "has_alergy": MessageLookupByLibrary.simpleMessage("Наличие аллергии"), + "has_hyper": MessageLookupByLibrary.simpleMessage( + "Склонность к гипертонии", + ), + "has_hypo": MessageLookupByLibrary.simpleMessage("Склонность к гипотонии"), + "height": MessageLookupByLibrary.simpleMessage("Рост"), + "height_measurements": MessageLookupByLibrary.simpleMessage("Замер роста"), + "hide": MessageLookupByLibrary.simpleMessage("Свернуть"), + "hip_circumference": MessageLookupByLibrary.simpleMessage("Обхват бедер"), + "hips": MessageLookupByLibrary.simpleMessage("Бедра"), + "in_progress": MessageLookupByLibrary.simpleMessage("В процессе"), + "inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"), + "initial_measurements": MessageLookupByLibrary.simpleMessage( + "Первичные замеры", + ), + "label": MessageLookupByLibrary.simpleMessage("Название"), + "language": MessageLookupByLibrary.simpleMessage("Язык"), + "last_name": MessageLookupByLibrary.simpleMessage("Фамилия"), + "last_name_empty": MessageLookupByLibrary.simpleMessage( + "Фамилия обязательна для заполнения", + ), + "last_name_short": MessageLookupByLibrary.simpleMessage( + "В фамилии должен быть минимум 6 символов", + ), + "lbl_english": MessageLookupByLibrary.simpleMessage("English"), + "light_type": MessageLookupByLibrary.simpleMessage("Легкая"), + "light_type_desc": MessageLookupByLibrary.simpleMessage( + "С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.", + ), + "liked_groceries": MessageLookupByLibrary.simpleMessage("Любимые продукты"), + "link_was_copied": MessageLookupByLibrary.simpleMessage( + "Ссылка успешно скопирована", + ), + "loading": MessageLookupByLibrary.simpleMessage("Загрузка..."), + "lower": MessageLookupByLibrary.simpleMessage("Нижнее"), + "male": MessageLookupByLibrary.simpleMessage("Мужской"), + "meal": MessageLookupByLibrary.simpleMessage("Приём пищи"), + "meat": MessageLookupByLibrary.simpleMessage("Мясо"), + "meat_type": MessageLookupByLibrary.simpleMessage("С мясом"), + "meat_type_desc": MessageLookupByLibrary.simpleMessage( + "Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму.", + ), + "milliliter": MessageLookupByLibrary.simpleMessage("мл"), + "minimal_customer_price": MessageLookupByLibrary.simpleMessage( + "Минимальная цена для покупателя: 1200₽", + ), + "most_new": MessageLookupByLibrary.simpleMessage("Самые новые"), + "most_old": MessageLookupByLibrary.simpleMessage("Самые старые"), + "msg_network_err": MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"), + "msg_something_went_wrong": MessageLookupByLibrary.simpleMessage( + "Что то пошло не так!", + ), + "my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"), + "my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"), + "my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"), + "my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"), + "name_empty": MessageLookupByLibrary.simpleMessage( + "Имя пользователя обязательно для заполнения", + ), + "name_short": MessageLookupByLibrary.simpleMessage( + "В имени пользователя должно быть минимум 6 символов", + ), + "no": MessageLookupByLibrary.simpleMessage("Нет"), + "no_account": MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"), + "not_liked_groceries": MessageLookupByLibrary.simpleMessage( + "Не любимые продукты", + ), + "one_option": MessageLookupByLibrary.simpleMessage("1 опция"), + "option": MessageLookupByLibrary.simpleMessage("Опция"), + "option_content": MessageLookupByLibrary.simpleMessage("Содержание опции"), + "option_content_hint_text": MessageLookupByLibrary.simpleMessage( + "На связи 7 дней в неделю", + ), + "option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"), + "option_desc_hint_text": MessageLookupByLibrary.simpleMessage( + "Этот план питания для похудения на 7 дней сбалансированный и разнообразный", + ), + "option_duration": MessageLookupByLibrary.simpleMessage( + "Продолжительность опции", + ), + "option_personal_diet_desc": MessageLookupByLibrary.simpleMessage( + "Опция подразумевает создание индивидуальной диеты", + ), + "option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"), + "order": MessageLookupByLibrary.simpleMessage("Порядок"), + "other_info": MessageLookupByLibrary.simpleMessage("Прочая информация"), + "password": MessageLookupByLibrary.simpleMessage("Пароль"), + "password_confirmation": MessageLookupByLibrary.simpleMessage( + "Подтвердите пароль", + ), + "password_confirmation_mismatch": MessageLookupByLibrary.simpleMessage( + "Пароли не совпадают", + ), + "password_empty": MessageLookupByLibrary.simpleMessage( + "Пароль обязателен для заполнения", + ), + "password_short": MessageLookupByLibrary.simpleMessage( + "В пароле должно быть минимум 6 символов", + ), + "pcs": MessageLookupByLibrary.simpleMessage("шт"), + "personal": MessageLookupByLibrary.simpleMessage("Персональные"), + "personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"), + "photo": MessageLookupByLibrary.simpleMessage("Фото"), + "physical_fitness": MessageLookupByLibrary.simpleMessage( + "Физическая форма", + ), + "place_of_living": MessageLookupByLibrary.simpleMessage("Место проживания"), + "plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"), + "plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"), + "plan_desc_example": MessageLookupByLibrary.simpleMessage( + "Большое подробное, привлекательное описание плана", + ), + "plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"), + "plan_label_desc": MessageLookupByLibrary.simpleMessage( + "План для поддержания формы", + ), + "plan_type": MessageLookupByLibrary.simpleMessage("Тип плана"), + "plans_complete": MessageLookupByLibrary.simpleMessage("Пройденные планы"), + "popular": MessageLookupByLibrary.simpleMessage("Популярные"), + "preferred_language": MessageLookupByLibrary.simpleMessage( + "Предпочитаемый язык общения", + ), + "pressure": MessageLookupByLibrary.simpleMessage("Давление"), + "pressure_empty": MessageLookupByLibrary.simpleMessage( + "Все показатели давления обязательны к заполнению", + ), + "pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage( + "Все показатели давления должны быть числами", + ), + "preview": MessageLookupByLibrary.simpleMessage("Превью"), + "price": MessageLookupByLibrary.simpleMessage("Цена"), + "price_explanation": MessageLookupByLibrary.simpleMessage( + "Разница в ценах, это комиссия Итвио", + ), + "profile": MessageLookupByLibrary.simpleMessage("Профиль"), + "proteins": MessageLookupByLibrary.simpleMessage("Белки"), + "publish": MessageLookupByLibrary.simpleMessage("Опубликовать"), + "published": MessageLookupByLibrary.simpleMessage("Опубликованные"), + "removeFromActive": MessageLookupByLibrary.simpleMessage( + "Снять с публикации", + ), + "save": MessageLookupByLibrary.simpleMessage("Сохранить"), + "services": MessageLookupByLibrary.simpleMessage("Оказание услуг"), + "settings": MessageLookupByLibrary.simpleMessage("Настройки"), + "sex": MessageLookupByLibrary.simpleMessage("Пол"), + "share": MessageLookupByLibrary.simpleMessage("Поделиться"), + "skip": MessageLookupByLibrary.simpleMessage("Пропустить"), + "slim": MessageLookupByLibrary.simpleMessage("Похудение"), + "slim_type": MessageLookupByLibrary.simpleMessage("Похудение"), + "slim_type_desc": MessageLookupByLibrary.simpleMessage( + "План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;", + ), + "sport_hobbies": MessageLookupByLibrary.simpleMessage( + "Спортивные увлечения", + ), + "standard": MessageLookupByLibrary.simpleMessage("Стандарт"), + "startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"), + "takes_pills": MessageLookupByLibrary.simpleMessage("Принимает лекарства"), + "tell_your_schedule": MessageLookupByLibrary.simpleMessage( + "Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:", + ), + "three_options": MessageLookupByLibrary.simpleMessage("3 опции"), + "time": MessageLookupByLibrary.simpleMessage("Время прохождения"), + "toOffer": MessageLookupByLibrary.simpleMessage("Предложить"), + "to_draft": MessageLookupByLibrary.simpleMessage("В черновик"), + "unfavorite_foods": MessageLookupByLibrary.simpleMessage( + "Нелюбимые продукты", + ), + "up_pressure": MessageLookupByLibrary.simpleMessage( + "Верхние показатели давления:", + ), + "upper": MessageLookupByLibrary.simpleMessage("Верхнее"), + "user_authorization": MessageLookupByLibrary.simpleMessage( + "Аутентификация", + ), + "user_data": MessageLookupByLibrary.simpleMessage("Данные пользователя"), + "user_registration": MessageLookupByLibrary.simpleMessage( + "Регистрация пользователя", + ), + "username": MessageLookupByLibrary.simpleMessage("Имя пользователя"), + "vegan": MessageLookupByLibrary.simpleMessage("Веган."), + "vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"), + "vegan_type_desc": MessageLookupByLibrary.simpleMessage( + "Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья.", + ), + "waist": MessageLookupByLibrary.simpleMessage("Талия"), + "waist_circumference": MessageLookupByLibrary.simpleMessage("Обхват талии"), + "weight": MessageLookupByLibrary.simpleMessage("Вес"), + "weight_chart": MessageLookupByLibrary.simpleMessage("График веса"), + "weight_measurements": MessageLookupByLibrary.simpleMessage("Замер веса"), + "wellness": MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"), + "wellness_type": MessageLookupByLibrary.simpleMessage( + "Улучшение самочувствия", + ), + "wellness_type_desc": MessageLookupByLibrary.simpleMessage( + "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.", + ), + "what_is_your_name": MessageLookupByLibrary.simpleMessage("Как вас зовут?"), + "wrong_credentials": MessageLookupByLibrary.simpleMessage( + "Неверные данные пользователя", + ), + "you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"), + "your_blood_pressure": MessageLookupByLibrary.simpleMessage( + "Ваше артериальное давление?", + ), + "your_favorite_sports": MessageLookupByLibrary.simpleMessage( + "Ваши спортивные увлечения?", + ), + "your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"), + "your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"), + "your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"), + "your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:"), + }; } diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 22e67fef..79e15f7f 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -2352,12 +2352,7 @@ class S { /// `Подтвердить` String get confirm { - return Intl.message( - 'Подтвердить', - name: 'confirm', - desc: '', - args: [], - ); + return Intl.message('Подтвердить', name: 'confirm', desc: '', args: []); } /// `Не удалось отменить диету` @@ -2369,176 +2364,6 @@ class S { args: [], ); } - - /// `часов` - String get hours { - return Intl.message( - 'часов', - name: 'hours', - desc: '', - args: [], - ); - } - - /// `час` - String get hour { - return Intl.message( - 'час', - name: 'hour', - desc: '', - args: [], - ); - } - - /// `часа` - String get another_form_of_hour { - return Intl.message( - 'часа', - name: 'another_form_of_hour', - desc: '', - args: [], - ); - } - - /// `минуты` - String get minutes { - return Intl.message( - 'минуты', - name: 'minutes', - desc: '', - args: [], - ); - } - - /// `минута` - String get minute { - return Intl.message( - 'минута', - name: 'minute', - desc: '', - args: [], - ); - } - - /// `минут` - String get another_form_of_minute { - return Intl.message( - 'минут', - name: 'another_form_of_minute', - desc: '', - args: [], - ); - } - - /// `Есть видео` - String get there_is_a_video { - return Intl.message( - 'Есть видео', - name: 'there_is_a_video', - desc: '', - args: [], - ); - } - - /// `Автор рецепта` - String get recipe_author { - return Intl.message( - 'Автор рецепта', - name: 'recipe_author', - desc: '', - args: [], - ); - } - - /// `Об этом рецепте` - String get about_recipe { - return Intl.message( - 'Об этом рецепте', - name: 'about_recipe', - desc: '', - args: [], - ); - } - - /// `этапов` - String get stages { - return Intl.message( - 'этапов', - name: 'stages', - desc: '', - args: [], - ); - } - - /// `этап` - String get stage { - return Intl.message( - 'этап', - name: 'stage', - desc: '', - args: [], - ); - } - - /// `этапа` - String get another_form_of_stage { - return Intl.message( - 'этапа', - name: 'another_form_of_stage', - desc: '', - args: [], - ); - } - - /// `Посмотреть видео рецепт` - String get check_out_video_recipe { - return Intl.message( - 'Посмотреть видео рецепт', - name: 'check_out_video_recipe', - desc: '', - args: [], - ); - } - - /// `Не удалось запустить видео` - String get could_not_launch_video { - return Intl.message( - 'Не удалось запустить видео', - name: 'could_not_launch_video', - desc: '', - args: [], - ); - } - - /// `Ингредиенты` - String get ingredients { - return Intl.message( - 'Ингредиенты', - name: 'ingredients', - desc: '', - args: [], - ); - } - - /// `Шаг` - String get step { - return Intl.message( - 'Шаг', - name: 'step', - desc: '', - args: [], - ); - } - - /// `Пошаговый фоторецепт` - String get step_by_step_photo_recipe { - return Intl.message( - 'Пошаговый фоторецепт', - name: 'step_by_step_photo_recipe', - desc: '', - args: [], - ); - } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/main.dart b/lib/main.dart index ea6fb543..5b223f8a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,12 +14,19 @@ import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:keyboard_dismisser/keyboard_dismisser.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; Future main() async { WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); await di.init(); - runApp(MyApp()); + await SentryFlutter.init( + (options) { + options.dsn = 'http://ba7f2653067776f3034e6e89850e85a1@sentry.md-desk.ru:9000/2'; + options.tracesSampleRate = 1.0; + }, + appRunner: () => runApp(MyApp()), + ); FlutterNativeSplash.remove(); } diff --git a/pubspec.yaml b/pubspec.yaml index 9ff64948..dbff2756 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,14 +23,14 @@ dependencies: validators: ^3.0.0 path_provider: ^2.1.5 carousel_slider_plus: ^7.1.0 - flutter_form_builder: ^7.0.0-alpha.3 + flutter_form_builder: ^9.7.0 image_picker: ^1.1.2 flutter_typeahead: ^5.2.0 - go_router: ^14.7.1 + go_router: ^14.7.2 keyboard_dismisser: ^3.0.0 retrofit: ^4.4.2 get_it: ^8.0.3 - dio: ^5.7.0 + dio: ^5.8.0+1 dart_pusher_channels: ^1.2.3 photo_view: ^0.15.0 dismissible_page: ^1.0.2 @@ -38,14 +38,14 @@ dependencies: easy_debounce: ^2.0.3 badges: ^3.1.2 google_fonts: ^6.2.1 - syncfusion_flutter_charts: ^28.1.38 - syncfusion_flutter_gauges: ^28.1.38 + syncfusion_flutter_charts: ^28.2.3 + syncfusion_flutter_gauges: ^28.2.3 table_calendar: ^3.2.0 flutter_keyboard_visibility: ^6.0.0 share_plus: ^10.1.4 flutter_html: ^3.0.0-beta.2 - file_picker: ^8.1.7 - audioplayers: ^6.1.0 + file_picker: ^8.3.1 + audioplayers: ^6.1.1 intl: ^0.20.2 rive: ^0.13.20 mask_text_input_formatter: ^2.9.0 @@ -59,6 +59,7 @@ dependencies: http: ^1.3.0 flutter_native_splash: ^2.4.4 webview_flutter: ^4.10.0 + sentry_flutter: ^8.13.0 connectivity_plus: ^6.1.2 dev_dependencies: