diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml
index b4071fe3..4ad594f6 100644
--- a/.gitea/workflows/build.yml
+++ b/.gitea/workflows/build.yml
@@ -3,7 +3,7 @@ name: Eatvio App Android Test
on: [ pull_request ]
env:
- flutter_version: "3.38.6"
+ flutter_version: "3.38.9"
java_version: "21.x"
flutter_channel: "stable"
diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml
index a26ff075..f07c8dd3 100644
--- a/.gitea/workflows/test.yml
+++ b/.gitea/workflows/test.yml
@@ -3,7 +3,7 @@ name: Eatvio App Android Test
on: [ pull_request ]
env:
- flutter_version: "3.38.6"
+ flutter_version: "3.38.9"
java_version: "21.x"
flutter_channel: "stable"
my_local_cache_dir: "/opt/hostedtoolcache/"
diff --git a/android/app/agconnect-services.json b/android/app/agconnect-services.json
index 8ca899db..e2f8dec1 100644
--- a/android/app/agconnect-services.json
+++ b/android/app/agconnect-services.json
@@ -1 +1,94 @@
-{"agcgw":{"url":"connect-drru.hispace.dbankcloud.ru","backurl":"connect-drru.hispace.dbankcloud.cn","websocketurl":"connect-ws-drru.hispace.dbankcloud.ru","websocketbackurl":"connect-ws-drru.hispace.dbankcloud.cn"},"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"20007000036693451","product_id":"461323198429446894","client_id":"1595824543740483264","client_secret":"2A1727B0D31AA9BE1F5D9E8A5CDA1A67B9EF084AC9FB68D6C633A3CCB08ECDEE","project_id":"461323198429446894","app_id":"113238569","api_key":"DQEDAJNRITp9M3uc1rPHyT8PzLc7bnVcKJAeavZZk0TQNMx9ifvBebr+JOmZe9tEvjnLwv7c1hAHXmPGR/gWG86iABDrCVotq+NGnw==","package_name":"com.eatvioapp.app"},"oauth_client":{"client_id":"113238569","client_type":1},"app_info":{"app_id":"113238569","package_name":"com.eatvioapp.app"},"service":{"analytics":{"collector_url":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn","collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn","resource_id":"p1","channel_id":""},"ml":{"mlservice_url":"ml-api-drru.ai.dbankcloud.ru,ml-api-drru.ai.dbankcloud.cn"},"cloudstorage":{"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg":"https://ops-dra.agcstorage.link","storage_url_de":"https://ops-dre.agcstorage.link","storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia","storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu","storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn"},"search":{"url":"https://search-drru.cloud.huawei.ru"},"edukit":{"edu_url":"edukit.cloud.huawei.com.cn","dh_url":"edukit.cloud.huawei.com.cn"}},"region":"RU","configuration_version":"3.0","appInfos":[{"package_name":"com.eatvioapp.app","client":{"app_id":"113238569"},"app_info":{"package_name":"com.eatvioapp.app","app_id":"113238569"},"oauth_client":{"client_type":1,"client_id":"113238569"}}]}
\ No newline at end of file
+{
+ "agcgw" : {
+ "url" : "connect-drru.hispace.dbankcloud.ru",
+ "backurl" : "connect-drru.hispace.dbankcloud.cn",
+ "websocketurl" : "connect-ws-drru.hispace.dbankcloud.ru",
+ "websocketbackurl" : "connect-ws-drru.hispace.dbankcloud.cn"
+ },
+ "agcgw_all" : {
+ "SG" : "connect-dra.dbankcloud.cn",
+ "SG_back" : "connect-dra.hispace.hicloud.com",
+ "CN" : "connect-drcn.dbankcloud.cn",
+ "CN_back" : "connect-drcn.hispace.hicloud.com",
+ "RU" : "connect-drru.hispace.dbankcloud.ru",
+ "RU_back" : "connect-drru.hispace.dbankcloud.cn",
+ "DE" : "connect-dre.dbankcloud.cn",
+ "DE_back" : "connect-dre.hispace.hicloud.com"
+ },
+ "websocketgw_all" : {
+ "SG" : "connect-ws-dra.hispace.dbankcloud.cn",
+ "SG_back" : "connect-ws-dra.hispace.dbankcloud.com",
+ "CN" : "connect-ws-drcn.hispace.dbankcloud.cn",
+ "CN_back" : "connect-ws-drcn.hispace.dbankcloud.com",
+ "RU" : "connect-ws-drru.hispace.dbankcloud.ru",
+ "RU_back" : "connect-ws-drru.hispace.dbankcloud.cn",
+ "DE" : "connect-ws-dre.hispace.dbankcloud.cn",
+ "DE_back" : "connect-ws-dre.hispace.dbankcloud.com"
+ },
+ "client" : {
+ "cp_id" : "20007000036693451",
+ "product_id" : "461323198429446894",
+ "client_id" : "1595824543740483264",
+ "client_secret" : "2A1727B0D31AA9BE1F5D9E8A5CDA1A67B9EF084AC9FB68D6C633A3CCB08ECDEE",
+ "project_id" : "461323198429446894",
+ "app_id" : "113238569",
+ "api_key" : "DQEDAJNRITp9M3uc1rPHyT8PzLc7bnVcKJAeavZZk0TQNMx9ifvBebr+JOmZe9tEvjnLwv7c1hAHXmPGR/gWG86iABDrCVotq+NGnw==",
+ "package_name" : "com.eatvioapp.app"
+ },
+ "oauth_client" : {
+ "client_id" : "113238569",
+ "client_type" : 1
+ },
+ "app_info" : {
+ "app_id" : "113238569",
+ "package_name" : "com.eatvioapp.app"
+ },
+ "service" : {
+ "analytics" : {
+ "collector_url" : "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
+ "collector_url_cn" : "datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn",
+ "collector_url_de" : "datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn",
+ "collector_url_ru" : "datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com",
+ "collector_url_sg" : "datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn",
+ "resource_id" : "p1",
+ "channel_id" : ""
+ },
+ "ml" : {
+ "mlservice_url" : "ml-api-drru.ai.dbankcloud.ru,ml-api-drru.ai.dbankcloud.cn"
+ },
+ "cloudstorage" : {
+ "storage_url" : "https://agc-storage-drcn.platform.dbankcloud.cn",
+ "storage_url_ru" : "https://agc-storage-drru.cloud.huawei.ru",
+ "storage_url_sg" : "https://ops-dra.agcstorage.link",
+ "storage_url_de" : "https://ops-dre.agcstorage.link",
+ "storage_url_cn" : "https://agc-storage-drcn.platform.dbankcloud.cn",
+ "storage_url_ru_back" : "https://agc-storage-drru.cloud.huawei.ru",
+ "storage_url_sg_back" : "https://agc-storage-dra.cloud.huawei.asia",
+ "storage_url_de_back" : "https://agc-storage-dre.cloud.huawei.eu",
+ "storage_url_cn_back" : "https://agc-storage-drcn.cloud.huawei.com.cn"
+ },
+ "search" : {
+ "url" : "https://search-drru.cloud.huawei.ru"
+ },
+ "edukit" : {
+ "edu_url" : "edukit.cloud.huawei.com.cn",
+ "dh_url" : "edukit.cloud.huawei.com.cn"
+ }
+ },
+ "region" : "RU",
+ "configuration_version" : "3.0",
+ "appInfos" : [ {
+ "package_name" : "com.eatvioapp.app",
+ "client" : {
+ "app_id" : "113238569"
+ },
+ "app_info" : {
+ "package_name" : "com.eatvioapp.app",
+ "app_id" : "113238569"
+ },
+ "oauth_client" : {
+ "client_type" : 1,
+ "client_id" : "113238569"
+ }
+ } ]
+}
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 864f1a2c..e7a94938 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -21,6 +21,12 @@
+
+
deleteComment({required int id}) async {
try {
return service.deleteComment(id);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -17,7 +19,8 @@ class CommentsRepository {
Future updateComment({required int id, required String body}) async {
try {
return service.updateComment(id, CommentUpdateModel(body: body));
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/core/constants/app_constants.dart b/lib/core/constants/app_constants.dart
index f9c945c9..317ddb94 100644
--- a/lib/core/constants/app_constants.dart
+++ b/lib/core/constants/app_constants.dart
@@ -69,4 +69,9 @@ class AppConstants {
static const String usersEndpoint = '/users';
static const String postsEndpoint = '/posts';
static const String commentsEndpoint = '/comments';
+
+ // Delay of pending requests
+ /// 30 секунд стоит потому что запрос может идти 12-15 секунд
+ /// Особенно если производится отладка на сервере разработчика
+ static const Duration pendingDelay = Duration(seconds: 30);
}
diff --git a/lib/core/di/external_registrations.dart b/lib/core/di/external_registrations.dart
index aecd2707..34f93aa6 100644
--- a/lib/core/di/external_registrations.dart
+++ b/lib/core/di/external_registrations.dart
@@ -1,10 +1,12 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/app_config.dart';
+import 'package:eatvio_app/core/constants/app_constants.dart';
import 'package:eatvio_app/core/interceptors/phone_verify_error_interceptor.dart';
import 'package:eatvio_app/core/interceptors/token_interceptor.dart';
import 'package:eatvio_app/core/prefs.dart';
import 'package:get_it/get_it.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:sentry_dio/sentry_dio.dart';
/// Регистрация внешних зависимостей в системе внедрения зависимостей
class ExternalRegistrations {
@@ -19,15 +21,16 @@ class ExternalRegistrations {
/// Регистрация Dio HTTP клиента
static void _registerDio() {
sl.registerLazySingleton(
- () =>
- Dio(BaseOptions(
- baseUrl: sl().baseUrl,
- headers: {'accept': 'application/json', 'content-type': 'application/json'},
- connectTimeout: const Duration(seconds: 10),
- receiveTimeout: const Duration(seconds: 10),
- sendTimeout: const Duration(seconds: 10),
- ))
- ..interceptors.addAll([TokenInterceptor(), PhoneVerifyErrorInterceptor()]),
+ () => Dio(
+ BaseOptions(
+ baseUrl: sl().baseUrl,
+ headers: {'accept': 'application/json', 'content-type': 'application/json'},
+ connectTimeout: AppConstants.pendingDelay,
+ receiveTimeout: AppConstants.pendingDelay,
+ sendTimeout: AppConstants.pendingDelay,
+ ),
+ )..interceptors.addAll([TokenInterceptor(), PhoneVerifyErrorInterceptor()])
+ ..addSentry(),
);
}
diff --git a/lib/core/firebase_api.dart b/lib/core/firebase_api.dart
index a96aa9d5..e85807ee 100644
--- a/lib/core/firebase_api.dart
+++ b/lib/core/firebase_api.dart
@@ -12,6 +12,7 @@ import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/token_storage.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/services.dart' show MethodChannel, PlatformException;
+import 'package:sentry_flutter/sentry_flutter.dart';
class FirebaseApi {
final _firebaseMessaging = FirebaseMessaging.instance;
@@ -49,7 +50,7 @@ class FirebaseApi {
await sl().post(
'/api/anonymous_token',
data: {
- 'platform': Platform.isIOS ? 'ios' : 'android',
+ 'platform': Platform.isIOS ? 'ios' : (await _isHuaweiDevice()) ? 'huawei' : 'android',
'hw_id': Platform.isIOS ? (await deviceInfo.iosInfo).identifierForVendor : (await deviceInfo.androidInfo).id,
'token': await getToken(),
},
@@ -61,6 +62,7 @@ class FirebaseApi {
);
} catch (e, st) {
log(e.toString(), stackTrace: st);
+ await Sentry.captureException(e, stackTrace: st);
// Не пробрасываем ошибку дальше, так как это не критичная операция
}
}
@@ -85,6 +87,7 @@ class FirebaseApi {
);
} catch (e, st) {
log(e.toString(), stackTrace: st);
+ await Sentry.captureException(e, stackTrace: st);
// Не пробрасываем ошибку дальше, так как это не критичная операция
}
}
@@ -110,10 +113,12 @@ class FirebaseApi {
} on PlatformException catch (e, st) {
showErrorToast('$e $st');
log(e.toString(), stackTrace: st);
+ await Sentry.captureException(e, stackTrace: st);
return null;
} catch (e, st) {
showErrorToast('$e $st');
log(e.toString(), stackTrace: st);
+ await Sentry.captureException(e, stackTrace: st);
return null;
}
}
diff --git a/lib/core/interceptors/token_interceptor.dart b/lib/core/interceptors/token_interceptor.dart
index b2cd9207..05f6be0c 100644
--- a/lib/core/interceptors/token_interceptor.dart
+++ b/lib/core/interceptors/token_interceptor.dart
@@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/core/app_router.dart';
import 'package:eatvio_app/core/token_storage.dart';
+import 'package:eatvio_app/core/websockets/ws_manager.dart';
+import 'package:eatvio_app/core/locator_service.dart';
import 'package:go_router/go_router.dart';
class TokenInterceptor extends Interceptor {
@@ -23,6 +25,7 @@ class TokenInterceptor extends Interceptor {
ErrorInterceptorHandler handler,
) async {
if (err.response?.statusCode == 401) {
+ await sl().clear();
await TokenStorage.removeTokenInStorage();
AppRouter.navigatorKey.currentContext?.go('/auth-screen');
}
diff --git a/lib/core/theme/theme_helper.dart b/lib/core/theme/theme_helper.dart
index 01f9a96b..d1344e62 100644
--- a/lib/core/theme/theme_helper.dart
+++ b/lib/core/theme/theme_helper.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
-import 'package:google_fonts/google_fonts.dart';
+
/// Helper class for managing themes and colors.
class ThemeHelper {
@@ -34,7 +34,8 @@ class ThemeHelper {
var colorScheme = _supportedColorScheme[_appTheme] ?? ColorSchemes.primaryColorScheme;
return ThemeData(
- textTheme: GoogleFonts.mulishTextTheme(),
+ fontFamily: 'Mulish-Local',
+ textTheme: ThemeData.light().textTheme.apply(fontFamily: 'Mulish-Local'),
visualDensity: VisualDensity.standard,
colorScheme: colorScheme,
scaffoldBackgroundColor: colorScheme.onPrimary,
diff --git a/lib/core/utils/validation_utils.dart b/lib/core/utils/validation_utils.dart
index 1add6cda..0e9bbccd 100644
--- a/lib/core/utils/validation_utils.dart
+++ b/lib/core/utils/validation_utils.dart
@@ -16,6 +16,21 @@ class ValidationUtils {
return regex.hasMatch(phone);
}
+ /// Нормализация номера телефона (+79991234455)
+ static String normalizePhone(String phone) {
+ if (phone.isEmpty) return '';
+ final digits = phone.replaceAll(RegExp(r'[^\d]'), '');
+ if (digits.isEmpty) return '';
+
+ String normalized = digits;
+ if (digits.startsWith('8')) {
+ normalized = '7${digits.substring(1)}';
+ } else if (digits.length == 10) {
+ normalized = '7$digits';
+ }
+ return '+$normalized';
+ }
+
/// Валидация URL
static bool isValidUrl(String url) {
if (url.isEmpty) return false;
diff --git a/lib/core/views/repository/views_repository.dart b/lib/core/views/repository/views_repository.dart
index 165a4956..869819ca 100644
--- a/lib/core/views/repository/views_repository.dart
+++ b/lib/core/views/repository/views_repository.dart
@@ -1,5 +1,6 @@
import 'package:eatvio_app/core/views/service/views_service.dart';
import 'package:eatvio_app/features/feed/models/view_model.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class ViewsRepository {
final ViewsService viewsService;
@@ -9,7 +10,8 @@ class ViewsRepository {
Future viewContent({required ViewModel viewModel}) async {
try {
await viewsService.viewContent(viewModel: viewModel);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/core/websockets/ws_manager.dart b/lib/core/websockets/ws_manager.dart
index 24430f6c..3a711177 100644
--- a/lib/core/websockets/ws_manager.dart
+++ b/lib/core/websockets/ws_manager.dart
@@ -1,3 +1,4 @@
+import 'dart:async';
import 'dart:convert';
import 'dart:developer';
@@ -8,6 +9,7 @@ import 'package:eatvio_app/core/const.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/websockets/ws_service.dart';
import 'package:eatvio_app/core/token_storage.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
class WsManager {
@@ -22,6 +24,10 @@ class WsManager {
PrivateChannel? _privateMessagesChannel;
PrivateChannel? _privateDirectChatChannel;
+ StreamSubscription? _lifecycleSubscription;
+ StreamSubscription? _eventSubscription;
+ StreamSubscription? _connectionEstablishedSubscription;
+
Stream? get newMessagesStream => _privateMessagesChannel?.bind('App\\Events\\ChatMessageUpdated');
Stream? get newNotificationsStream => _privateNotificationChannel?.bind('Illuminate\\Notifications\\Events\\BroadcastNotificationCreated');
@@ -33,7 +39,7 @@ class WsManager {
Future initialize() async {
if (client == null) {
try {
- await TokenStorage.haveTokenInStorage();
+ if (!await TokenStorage.haveTokenInStorage()) return;
final wsUrl = await wsService.getWebsocket();
final options = PusherChannelsOptions.fromHost(
@@ -71,7 +77,7 @@ class WsManager {
}
}
- client?.eventStream.listen((event) async {
+ _connectionEstablishedSubscription = client?.eventStream.listen((event) async {
if (event.name == 'pusher:connection_established') {
final data = event.data;
final socketId = extractSocketId(data);
@@ -87,21 +93,26 @@ class WsManager {
await _initPrivateNotificationsChannel();
await _initPrivateMessagesChannel();
- client?.lifecycleStream.listen((data) {
+ _lifecycleSubscription = client?.lifecycleStream.listen((data) {
if (data == PusherChannelsClientLifeCycleState.establishedConnection) {
_unsubscribe();
_subscribe();
}
});
- client?.eventStream.listen((event) {
- EasyDebounce.debounce(
- 'searchChatRoom',
- const Duration(milliseconds: 300),
- () => sl().getChatRooms(),
- );
+ _eventSubscription = client?.eventStream.listen((event) {
+ log('WsManager received event: ${event.name}');
+ // Только если это не системные сообщения Pusher, обновляем список чатов
+ if (!event.name.startsWith('pusher:')) {
+ EasyDebounce.debounce(
+ 'searchChatRoom',
+ const Duration(milliseconds: 300),
+ () => sl().getChatRooms(),
+ );
+ }
});
_subscribe();
} catch (e, st) {
+ await Sentry.captureException(e, stackTrace: st);
log(e.toString(), stackTrace: st);
}
}
@@ -166,6 +177,12 @@ class WsManager {
Future clear() async {
await client?.disconnect();
+ await _lifecycleSubscription?.cancel();
+ await _eventSubscription?.cancel();
+ await _connectionEstablishedSubscription?.cancel();
+ _lifecycleSubscription = null;
+ _eventSubscription = null;
+ _connectionEstablishedSubscription = null;
client = null;
userId = null;
_privateDirectChatChannel?.unsubscribe();
diff --git a/lib/core/widgets/feed_icon_button.dart b/lib/core/widgets/feed_icon_button.dart
index bd5748f1..ee96cd0b 100644
--- a/lib/core/widgets/feed_icon_button.dart
+++ b/lib/core/widgets/feed_icon_button.dart
@@ -27,7 +27,7 @@ class FeedIconButton extends StatelessWidget {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
- svgIcon ?? const SizedBox.shrink(),
+ ?svgIcon,
if (icon != null)
Icon(
icon,
diff --git a/lib/features/auth/presentation/pages/register_via_social_screen.dart b/lib/features/auth/presentation/pages/register_via_social_screen.dart
index 4967930e..1b27237f 100644
--- a/lib/features/auth/presentation/pages/register_via_social_screen.dart
+++ b/lib/features/auth/presentation/pages/register_via_social_screen.dart
@@ -16,6 +16,7 @@ import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widge
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
import 'package:eatvio_app/core/firebase_api.dart';
import 'package:eatvio_app/core/utils/toasts.dart';
+import 'package:eatvio_app/core/utils/validation_utils.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@@ -330,6 +331,25 @@ class _RegisterViaSocialScreenState extends State {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
+ SizedBox(
+ width: MediaQuery.of(context).size.width / 2 - 22,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ const Text('Рост'),
+ const SizedBox(height: 4),
+ CustomTextFormField(
+ controller: heightController,
+ hintText: 'Введите рост',
+ keyboardType: TextInputType.number,
+ onChanged: (newValue) {},
+ hasError: heightError,
+ ),
+ if (heightError) ...[const SizedBox(height: 4), const ValidationErrorWidget(error: 'Рост должен быть от 100 до 250 см')],
+ ],
+ ),
+ ),
+ const SizedBox(width: 12),
SizedBox(
width: MediaQuery.of(context).size.width / 2 - 22,
child: Column(
@@ -349,25 +369,6 @@ class _RegisterViaSocialScreenState extends State {
],
),
),
- const SizedBox(width: 12),
- SizedBox(
- width: MediaQuery.of(context).size.width / 2 - 22,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- const Text('Рост'),
- const SizedBox(height: 4),
- CustomTextFormField(
- controller: heightController,
- hintText: 'Введите рост',
- keyboardType: TextInputType.number,
- onChanged: (newValue) {},
- hasError: heightError,
- ),
- if (heightError) ...[const SizedBox(height: 4), const ValidationErrorWidget(error: 'Рост должен быть от 100 до 250 см')],
- ],
- ),
- ),
],
),
const SizedBox(height: 28),
@@ -538,7 +539,7 @@ class _RegisterViaSocialScreenState extends State {
if (hasErrorWeightOrHeightError) return;
// Очищаем номер телефона от маски для отправки
- final cleanPhone = phoneController.text.replaceAll(RegExp(r'[^\d+]'), '');
+ final cleanPhone = ValidationUtils.normalizePhone(phoneController.text);
if (clientID == null) return;
// Вызываем OAuth регистрацию
@@ -615,7 +616,7 @@ class _RegisterViaSocialScreenState extends State {
final oauthCubit = CubitRegistrations.sl();
// Всегда передаем и email и phone
final String email = emailController.text;
- final String phone = phoneController.text.replaceAll(RegExp(r'[^\d+]'), '');
+ final String phone = ValidationUtils.normalizePhone(phoneController.text);
final response = await oauthCubit.requestOAuthVerification(email: email, phone: phone);
@@ -726,7 +727,7 @@ class _RegisterViaSocialScreenState extends State {
// Всегда передаем и email и phone (полный набор данных от провайдера)
// Используем данные из формы, если они есть, иначе из authResult
final String email = emailController.text.isNotEmpty ? emailController.text : (authResult.email ?? '');
- final String phone = phoneController.text.isNotEmpty ? phoneController.text.replaceAll(RegExp(r'[^\d+]'), '') : (authResult.phone ?? '');
+ final String phone = phoneController.text.isNotEmpty ? ValidationUtils.normalizePhone(phoneController.text) : ValidationUtils.normalizePhone(authResult.phone ?? '');
// Проверяем, что данные есть
if (email.isEmpty && phone.isEmpty) {
diff --git a/lib/features/auth/repositories/auth_repository.dart b/lib/features/auth/repositories/auth_repository.dart
index eedd295a..6c2b4c15 100644
--- a/lib/features/auth/repositories/auth_repository.dart
+++ b/lib/features/auth/repositories/auth_repository.dart
@@ -7,6 +7,7 @@ import 'package:eatvio_app/features/auth/models/oauth_verification_confirm_respo
import 'package:eatvio_app/features/auth/models/oauth_verification_request_response.dart';
import 'package:eatvio_app/features/auth/models/token_model.dart';
import 'package:eatvio_app/features/auth/services/auth_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class AuthRepository {
final AuthService authService;
@@ -18,7 +19,8 @@ class AuthRepository {
return await authService.getTokenByCredentials(
credentials: CredentialsModel(email: email, password: password),
);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -33,7 +35,8 @@ class AuthRepository {
return await authService.signInViaSocialMedia(
body: OAuthLoginRequest(provider: provider, accessToken: accessToken, refreshToken: refreshToken, clientId: clientId),
);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -72,7 +75,8 @@ class AuthRepository {
),
))['token']!
as String;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -89,7 +93,8 @@ class AuthRepository {
return await authService.requestOAuthVerification(body: body);
}
return null;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -134,8 +139,9 @@ class AuthRepository {
'AuthRepository: Sending OAuth verification confirm request: provider=$provider, verificationType=$verificationType, code=$code, email=$email, phone=$phone',
);
return await authService.confirmOAuthVerification(body: request);
- } catch (e) {
+ } catch (e, s) {
log('AuthRepository: Error in confirmOAuthVerification: $e');
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/auth/repositories/reset_password_repository.dart b/lib/features/auth/repositories/reset_password_repository.dart
index e0b1d69f..d04270cb 100644
--- a/lib/features/auth/repositories/reset_password_repository.dart
+++ b/lib/features/auth/repositories/reset_password_repository.dart
@@ -1,4 +1,5 @@
import 'package:eatvio_app/features/auth/services/reset_password_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class ResetPasswordRepository {
final ResetPasswordService resetPasswordService;
@@ -20,7 +21,8 @@ class ResetPasswordRepository {
} else {
return false;
}
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -46,7 +48,8 @@ class ResetPasswordRepository {
} else {
return false;
}
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/auth/sdk/social_auth_facade.dart b/lib/features/auth/sdk/social_auth_facade.dart
index de6e14e7..af787e61 100644
--- a/lib/features/auth/sdk/social_auth_facade.dart
+++ b/lib/features/auth/sdk/social_auth_facade.dart
@@ -11,6 +11,7 @@ import 'package:eatvio_app/core/env_config.dart';
import 'package:eatvio_app/generated/l10n.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
+import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:vk_id/vk_id.dart';
import 'package:webview_flutter/webview_flutter.dart';
@@ -41,7 +42,8 @@ class SocialAuthFacade {
return null;
}
return await _parseVKAuthResult(redirectParams: redirectParams, controller: controller, codeVerifier: codeVerifier, clientId: clientIdStr);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
return null;
}
}
@@ -157,8 +159,9 @@ class SocialAuthFacade {
birthDate: yandexProfileData.birthday,
clientId: clientId,
);
- } catch (e) {
+ } catch (e, s) {
log(e.toString());
+ await Sentry.captureException(e, stackTrace: s);
}
return null;
}
@@ -205,7 +208,8 @@ class SocialAuthFacade {
if (code == null || deviceId == null) return null;
return await _parseVKAuthResult(redirectParams: redirectParams, controller: controller, codeVerifier: codeVerifier, clientId: clientIdStr);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
return null;
}
}
diff --git a/lib/features/barcode/repositories/barcode_repository.dart b/lib/features/barcode/repositories/barcode_repository.dart
index b83ace5c..030eca7e 100644
--- a/lib/features/barcode/repositories/barcode_repository.dart
+++ b/lib/features/barcode/repositories/barcode_repository.dart
@@ -1,6 +1,7 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/barcode/models/barcode_product_model.dart';
import 'package:eatvio_app/features/barcode/services/barcode_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class BarcodeRepository {
final BarcodeService barcodeService;
@@ -28,14 +29,16 @@ class BarcodeRepository {
}
throw Exception('Unexpected status code: ${response.statusCode}');
- } on DioException catch (e) {
+ } on DioException catch (e, s) {
if (e.response?.statusCode == 202) {
// Если получен статус 202, значит запущена задача обработки
final taskStatus = BarcodeTaskStatusModel.fromJson(e.response!.data as Map);
return BarcodeResult.processing(taskStatus.taskId ?? '');
}
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -52,7 +55,8 @@ class BarcodeRepository {
} else {
return BarcodeTaskStatus.processing();
}
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/blog_post_create/repositories/blog_post_repository.dart b/lib/features/blog_post_create/repositories/blog_post_repository.dart
index 48f4f0c1..7f1fc49b 100644
--- a/lib/features/blog_post_create/repositories/blog_post_repository.dart
+++ b/lib/features/blog_post_create/repositories/blog_post_repository.dart
@@ -8,6 +8,7 @@ import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class BlogPostRepository {
final BlogPostService blogPostService;
@@ -29,9 +30,14 @@ class BlogPostRepository {
if (image != null) 'image': await MultipartFile.fromFile((await ImageCompressUtility.compressFile(File(image.path))).path, filename: image.name),
});
- return await blogPostService.createBlogPost(
- formData: formData,
- );
+ try {
+ return await blogPostService.createBlogPost(
+ formData: formData,
+ );
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
+ rethrow;
+ }
}
Future downloadImage(String imageUrl) async {
@@ -54,8 +60,9 @@ class BlogPostRepository {
log('Ошибка загрузки изображения: ${response.statusCode}');
return null;
}
- } catch (e) {
+ } catch (e, s) {
log('Произошла ошибка: $e');
+ await Sentry.captureException(e, stackTrace: s);
return null;
}
}
@@ -79,11 +86,23 @@ class BlogPostRepository {
: null,
});
- return await blogPostService.updateBlogPost(
- id: id,
- formData: formData,
- );
+ try {
+ return await blogPostService.updateBlogPost(
+ id: id,
+ formData: formData,
+ );
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
+ rethrow;
+ }
}
- Future deleteBlogPost(int id) async => await blogPostService.deleteBlogPost(id: id);
+ Future deleteBlogPost(int id) async {
+ try {
+ await blogPostService.deleteBlogPost(id: id);
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
+ rethrow;
+ }
+ }
}
diff --git a/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart b/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart
index f177d57a..efac96bf 100644
--- a/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart
+++ b/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart
@@ -1,5 +1,6 @@
import 'package:badges/badges.dart' as badges;
import 'package:eatvio_app/core/app_config.dart';
+import 'package:eatvio_app/core/env_config.dart';
import 'package:eatvio_app/core/locator_service.dart';
import 'package:eatvio_app/core/utils/image_constant.dart';
import 'package:eatvio_app/features/dev_tools/presentation/dev_tools_screen.dart';
@@ -19,10 +20,7 @@ import 'package:go_router/go_router.dart';
class BottomNavigationBarWidget extends StatefulWidget {
final Widget child;
- const BottomNavigationBarWidget({
- super.key,
- required this.child,
- });
+ const BottomNavigationBarWidget({super.key, required this.child});
@override
State createState() => _BottomNavigationBarWidgetState();
@@ -35,24 +33,9 @@ class _BottomNavigationBarWidgetState extends State {
List _getPages(bool isConsultant) {
if (isConsultant) {
- return [
- '/my-profile-screen',
- '/feed-screen',
- '/diary-screen',
- '/consultations-screen',
- '/chat-select-screen',
- '/notifications-screen',
- '/menu-screen',
- ];
+ return ['/my-profile-screen', '/feed-screen', '/diary-screen', '/consultations-screen', '/chat-select-screen', '/notifications-screen', '/menu-screen'];
} else {
- return [
- '/my-profile-screen',
- '/feed-screen',
- '/diary-screen',
- '/chat-select-screen',
- '/notifications-screen',
- '/menu-screen',
- ];
+ return ['/my-profile-screen', '/feed-screen', '/diary-screen', '/chat-select-screen', '/notifications-screen', '/menu-screen'];
}
}
@@ -83,6 +66,49 @@ class _BottomNavigationBarWidgetState extends State {
}
}
+ static const Color _devAccentColor = Color(0xFFF59E0B); // amber-500
+
+ Widget _buildLogoIcon() {
+ final isProduction = sl().baseUrl == EnvConfig.baseUrl;
+ final logo = SvgPicture.asset(
+ ImageConstant.imgLogo,
+ height: 32,
+ colorFilter: isProduction ? null : const ColorFilter.mode(_devAccentColor, BlendMode.srcIn),
+ );
+ if (isProduction) return logo;
+ return Stack(
+ clipBehavior: Clip.none,
+ alignment: Alignment.center,
+ children: [
+ Container(
+ padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(color: _devAccentColor.withValues(alpha: 0.6), width: 1.5),
+ color: _devAccentColor.withValues(alpha: 0.08),
+ ),
+ child: logo,
+ ),
+ Positioned(
+ top: -6,
+ right: -4,
+ child: Container(
+ padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
+ decoration: BoxDecoration(
+ color: _devAccentColor,
+ borderRadius: BorderRadius.circular(4),
+ boxShadow: [BoxShadow(color: _devAccentColor.withValues(alpha: 0.4), blurRadius: 4, offset: const Offset(0, 1))],
+ ),
+ child: const Text(
+ 'DEV',
+ style: TextStyle(fontSize: 8, fontWeight: FontWeight.w700, color: Colors.white, letterSpacing: 0.3, height: 1.0),
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+
@override
Widget build(BuildContext context) {
final s = S.of(context);
@@ -91,10 +117,10 @@ class _BottomNavigationBarWidgetState extends State {
if (state is ProfileAvatarStateLoaded) {
final profileModel = state.profile;
final isConsultant = profileModel.roles.contains('consultant');
-
+
// Инициализируем pages на основе profileModel
pages ??= _getPages(isConsultant);
-
+
return Scaffold(
body: widget.child,
bottomNavigationBar: BottomNavigationBar(
@@ -117,52 +143,26 @@ class _BottomNavigationBarWidgetState extends State {
),
BottomNavigationBarItem(
label: 'Лента',
- icon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- width: 20,
- height: 20,
- ImageConstant.icnFeed,
- ),
- ),
- activeIcon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnFeed,
- width: 20,
- height: 20,
- colorFilter: ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- ),
- ),
- ),
+ icon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn), width: 20, height: 20, ImageConstant.icnFeed),
+ ),
+ activeIcon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(ImageConstant.icnFeed, width: 20, height: 20, colorFilter: ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn)),
+ ),
),
BottomNavigationBarItem(
label: s.diary,
- icon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- ImageConstant.icnDiary,
- width: 20,
- height: 20,
- ),
- ),
- activeIcon: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnDiary,
- width: 20,
- height: 20,
- colorFilter: ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
+ icon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn), ImageConstant.icnDiary, width: 20, height: 20),
+ ),
+ activeIcon: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(ImageConstant.icnDiary, width: 20, height: 20, colorFilter: ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn)),
+ ),
),
- ),
- ),
- ),
if (profileModel.roles.contains('consultant'))
BottomNavigationBarItem(
label: 'Консультации',
@@ -181,97 +181,69 @@ class _BottomNavigationBarWidgetState extends State {
'assets/icons/consultations.svg',
width: 20,
height: 20,
- colorFilter: ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- ),
- ),
- ),
- ),
+ colorFilter: ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn),
+ ),
+ ),
+ ),
BottomNavigationBarItem(
label: s.chat,
- icon: BlocBuilder(
- builder: (BuildContext context, ChatsState state) {
- final hasUnreadMessages = state.chatsWithUnreadMessagesCount > 0;
- return badges.Badge(
- position: badges.BadgePosition.topEnd(),
- badgeAnimation: const badges.BadgeAnimation.fade(),
- badgeStyle: badges.BadgeStyle(
- badgeColor: hasUnreadMessages ? Colors.red : Colors.transparent,
+ icon: BlocBuilder(
+ builder: (BuildContext context, ChatsState state) {
+ final hasUnreadMessages = state.chatsWithUnreadMessagesCount > 0;
+ return badges.Badge(
+ position: badges.BadgePosition.topEnd(),
+ badgeAnimation: const badges.BadgeAnimation.fade(),
+ badgeStyle: badges.BadgeStyle(badgeColor: hasUnreadMessages ? Colors.red : Colors.transparent),
+ badgeContent: Text(
+ hasUnreadMessages ? state.chatsWithUnreadMessagesCount.toString() : '',
+ style: TextStyle(color: hasUnreadMessages ? Colors.white : Colors.transparent, fontSize: 8),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ ImageConstant.icnChat,
+ width: 20,
+ height: 20,
+ colorFilter: pages![currentBottomNavBarIndex] == '/chat-select-screen'
+ ? ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn)
+ : const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
+ ),
+ ),
+ );
+ },
),
- badgeContent: Text(
- hasUnreadMessages ? state.chatsWithUnreadMessagesCount.toString() : '',
- style: TextStyle(
- color: hasUnreadMessages ? Colors.white : Colors.transparent,
- fontSize: 8,
- ),
- ),
- child: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnChat,
- width: 20,
- height: 20,
- colorFilter: pages![currentBottomNavBarIndex] == '/chat-select-screen'
- ? ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- )
- : const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- ),
- ),
- );
- },
- ),
),
BottomNavigationBarItem(
label: 'Уведомления',
- icon: BlocBuilder(
- builder: (BuildContext context, NotificationsState state) {
- return badges.Badge(
- position: badges.BadgePosition.topEnd(),
- badgeAnimation: const badges.BadgeAnimation.fade(),
- showBadge: state is NotificationsStateLoaded && state.hasUnreadNotifications,
- badgeContent: const Text(
- '',
- style: TextStyle(
- color: Colors.white,
- fontSize: 8,
- ),
- ),
- child: Padding(
- padding: const EdgeInsets.only(bottom: 2),
- child: SvgPicture.asset(
- ImageConstant.icnBell,
- colorFilter: pages![currentBottomNavBarIndex] == '/notifications-screen'
- ? ColorFilter.mode(
- appTheme.blueA400,
- BlendMode.srcIn,
- )
- : const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
- width: 20,
- height: 20,
- ),
- ),
- );
- },
- ),
- ),
- BottomNavigationBarItem(
- label: '',
- icon: SvgPicture.asset(
- ImageConstant.imgLogo,
- height: 32,
+ icon: BlocBuilder(
+ builder: (BuildContext context, NotificationsState state) {
+ return badges.Badge(
+ position: badges.BadgePosition.topEnd(),
+ badgeAnimation: const badges.BadgeAnimation.fade(),
+ showBadge: state is NotificationsStateLoaded && state.hasUnreadNotifications,
+ badgeContent: const Text('', style: TextStyle(color: Colors.white, fontSize: 8)),
+ child: Padding(
+ padding: const EdgeInsets.only(bottom: 2),
+ child: SvgPicture.asset(
+ ImageConstant.icnBell,
+ colorFilter: pages![currentBottomNavBarIndex] == '/notifications-screen'
+ ? ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn)
+ : const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
+ width: 20,
+ height: 20,
+ ),
+ ),
+ );
+ },
),
),
+ BottomNavigationBarItem(label: '', icon: _buildLogoIcon()),
],
),
);
}
// Показываем child даже когда профиль еще загружается, чтобы экраны могли инициализироваться
- return Scaffold(
- body: widget.child,
- );
+ return Scaffold(body: widget.child);
},
);
}
diff --git a/lib/features/calendar/repositories/calendar_repository.dart b/lib/features/calendar/repositories/calendar_repository.dart
index fd9f734c..87af6b20 100644
--- a/lib/features/calendar/repositories/calendar_repository.dart
+++ b/lib/features/calendar/repositories/calendar_repository.dart
@@ -1,5 +1,6 @@
import 'package:eatvio_app/features/calendar/models/calendar_model.dart';
import 'package:eatvio_app/features/calendar/services/calendar_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class CalendarRepository {
final CalendarService calendarService;
@@ -9,7 +10,8 @@ class CalendarRepository {
Future> getCalendar() async {
try {
return await calendarService.getCalendar();
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/cancel_plan_bottom_sheet/repository/cancel_plan_repository.dart b/lib/features/cancel_plan_bottom_sheet/repository/cancel_plan_repository.dart
index 2e55549a..2a7ccc66 100644
--- a/lib/features/cancel_plan_bottom_sheet/repository/cancel_plan_repository.dart
+++ b/lib/features/cancel_plan_bottom_sheet/repository/cancel_plan_repository.dart
@@ -1,5 +1,6 @@
import 'package:eatvio_app/features/cancel_plan_bottom_sheet/models/cancelation_model.dart';
import 'package:eatvio_app/features/cancel_plan_bottom_sheet/service/cancel_plan_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class CancelPlanRepository {
final CancelPlanService cancelService;
@@ -10,7 +11,8 @@ class CancelPlanRepository {
}) async {
try {
await cancelService.cancelChosenPlan(id: id, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/chat/repositories/chat_repository.dart b/lib/features/chat/repositories/chat_repository.dart
index 0a3e2960..36682421 100644
--- a/lib/features/chat/repositories/chat_repository.dart
+++ b/lib/features/chat/repositories/chat_repository.dart
@@ -12,6 +12,7 @@ import 'package:eatvio_app/features/chat/models/plan_complain_model.dart';
import 'package:eatvio_app/features/chat/services/chat_service.dart';
import 'package:eatvio_app/features/plans/models/chosen_plan_model.dart';
import 'package:http_parser/http_parser.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class ChatRepository {
final ChatService chatService;
@@ -60,6 +61,7 @@ class ChatRepository {
);
} catch (e, st) {
log(e.toString(), stackTrace: st);
+ await Sentry.captureException(e, stackTrace: st);
rethrow;
}
}
@@ -69,6 +71,7 @@ class ChatRepository {
return (await chatService.getChatRoom(uuid: uuid));
} catch (e, st) {
log(e.toString(), stackTrace: st);
+ await Sentry.captureException(e, stackTrace: st);
rethrow;
}
}
@@ -76,7 +79,8 @@ class ChatRepository {
Future getChatRooms({String? query, int page = 1}) async {
try {
return (await chatService.getChatRooms(query: query, page: page));
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -84,7 +88,8 @@ class ChatRepository {
Future getChatMessages(String id, int page) async {
try {
return (await chatService.getChatMessages(id: id, page: page));
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -92,7 +97,8 @@ class ChatRepository {
Future getChatRoomIdByUserSlug({required String slug}) async {
try {
return (await chatService.getChatRoomIdByUserSlug(user: slug));
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -100,7 +106,8 @@ class ChatRepository {
Future markMessagesAsRead(String id, List messageIds) async {
try {
await chatService.markMessagesAsRead(id: id, body: {'messages_ids': messageIds});
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -110,7 +117,8 @@ class ChatRepository {
}) async {
try {
await chatService.cancelChosenPlan(id: id);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -118,7 +126,8 @@ class ChatRepository {
Future choseStartPlanDate({required int id, required Map date}) async {
try {
await chatService.choseStartPlanDate(id: id, date: date);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -128,7 +137,8 @@ class ChatRepository {
}) async {
try {
return await chatService.getPaymentLink(id: id);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -138,7 +148,8 @@ class ChatRepository {
}) async {
try {
return await chatService.getChosenPlan(id: id);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -148,7 +159,8 @@ class ChatRepository {
}) async {
try {
await chatService.finishChosenPlan(id: id);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -159,7 +171,8 @@ class ChatRepository {
}) async {
try {
await chatService.complainAboutConsultation(id: id, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -172,7 +185,8 @@ class ChatRepository {
} else {
return response.data['id'];
}
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
return 'error';
}
}
diff --git a/lib/features/complaining/repositories/complaining_repository.dart b/lib/features/complaining/repositories/complaining_repository.dart
index 32aab577..10a1cce3 100644
--- a/lib/features/complaining/repositories/complaining_repository.dart
+++ b/lib/features/complaining/repositories/complaining_repository.dart
@@ -1,5 +1,6 @@
import 'package:eatvio_app/features/complaining/models/complain_model.dart';
import 'package:eatvio_app/features/complaining/services/complaining_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class ComplainingRepository {
final ComplainingService service;
@@ -12,7 +13,8 @@ class ComplainingRepository {
}) async {
try {
await service.sendPlanComplain(slug: slug, category: category, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -24,7 +26,8 @@ class ComplainingRepository {
}) async {
try {
await service.sendRecipeComplain(slug: slug, category: category, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -36,7 +39,8 @@ class ComplainingRepository {
}) async {
try {
await service.sendBlogPostsComplain(id: id, category: category, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -48,7 +52,8 @@ class ComplainingRepository {
}) async {
try {
await service.sendProfileComplain(slug: slug, category: category, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -60,7 +65,8 @@ class ComplainingRepository {
}) async {
try {
await service.sendDietComplain(id: id, category: category, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -72,7 +78,8 @@ class ComplainingRepository {
}) async {
try {
await service.sendCommentComplain(id: id, category: category, body: body);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/consultant/become_consultant/repositories/consultant_repository.dart b/lib/features/consultant/become_consultant/repositories/consultant_repository.dart
index 05f357c3..b3a95e7f 100644
--- a/lib/features/consultant/become_consultant/repositories/consultant_repository.dart
+++ b/lib/features/consultant/become_consultant/repositories/consultant_repository.dart
@@ -5,6 +5,7 @@ import 'package:eatvio_app/features/consultant/become_consultant/models/consulta
import 'package:eatvio_app/features/consultant/become_consultant/models/consultation_request_model.dart';
import 'package:eatvio_app/features/consultant/become_consultant/services/consultant_service.dart';
import 'package:http_parser/http_parser.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class ConsultantRepository {
final ConsultantService consultantService;
@@ -18,7 +19,8 @@ class ConsultantRepository {
} else {
return await consultantService.consultantRegistration(consultantModel: consultant);
}
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -26,7 +28,8 @@ class ConsultantRepository {
Future getConsultantRequestStatus(String slug) async {
try {
return await consultantService.getConsultantRequestStatus(slug: slug);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -34,7 +37,8 @@ class ConsultantRepository {
Future getMyRequestStatus(String slug) async {
try {
return await consultantService.getMyRequestStatus(slug: slug);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -42,7 +46,8 @@ class ConsultantRepository {
Future> getConsultantCertPhotos() async {
try {
return await consultantService.getConsultantCertPhotos();
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -62,7 +67,8 @@ class ConsultantRepository {
}
return await consultantService.storeConsultantCertPhotos(photos: multipartFiles);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -70,7 +76,8 @@ class ConsultantRepository {
Future hideConsultantCertPhoto(int id) async {
try {
await consultantService.hideConsultantCertPhoto(payload: {'cert_photo_id': id});
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -78,7 +85,8 @@ class ConsultantRepository {
Future unHideConsultantCertPhoto(int id) async {
try {
await consultantService.unHideConsultantCertPhoto(payload: {'cert_photo_id': id});
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/consultant_rating/repositories/consultant_rating_repository.dart b/lib/features/consultant_rating/repositories/consultant_rating_repository.dart
index b4ac3770..3d66e879 100644
--- a/lib/features/consultant_rating/repositories/consultant_rating_repository.dart
+++ b/lib/features/consultant_rating/repositories/consultant_rating_repository.dart
@@ -1,6 +1,7 @@
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
import 'package:eatvio_app/features/consultant_rating/models/statistics_model.dart';
import 'package:eatvio_app/features/consultant_rating/services/consultant_rating_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class ConsultantRatingRepository {
final ConsultantRatingService service;
@@ -10,7 +11,8 @@ class ConsultantRatingRepository {
Future getConsultantStatistics({String? date}) async {
try {
return await service.getConsultantStatistics(date: date);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -19,7 +21,8 @@ class ConsultantRatingRepository {
try {
final data = (await service.getScoreLogs(date: date)).data;
return data;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/consultations/repositories/consultations_repository.dart b/lib/features/consultations/repositories/consultations_repository.dart
index 15490dc9..06c2ee39 100644
--- a/lib/features/consultations/repositories/consultations_repository.dart
+++ b/lib/features/consultations/repositories/consultations_repository.dart
@@ -1,6 +1,7 @@
import 'package:eatvio_app/core/enums/filters_comparison_enum.dart';
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
import 'package:eatvio_app/features/consultations/services/consultation_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:eatvio_app/features/finances_and_consultations_archive/models/consultant_finance_model.dart';
import 'package:eatvio_app/features/finances_and_consultations_archive/models/statistic_model.dart';
import 'package:eatvio_app/features/finances_and_consultations_archive/models/user_purchases_model.dart';
@@ -13,7 +14,8 @@ class ConsultationsRepository {
try {
final consultations = await consultationService.getConsultations();
return consultations.data;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -32,7 +34,8 @@ class ConsultationsRepository {
dateComparison: dateComparison,
);
return model.data;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -40,7 +43,8 @@ class ConsultationsRepository {
Future getStatistic() async {
try {
return await consultationService.getStatistics();
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -48,7 +52,8 @@ class ConsultationsRepository {
Future> getConsultantFinances(String? date, FiltersComparisonEnum? dateComparison) async {
try {
return await consultationService.getConsultantFinances(date, dateComparison);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -56,7 +61,8 @@ class ConsultationsRepository {
Future> getUserPurchases(String? date, FiltersComparisonEnum? dateComparison) async {
try {
return await consultationService.getUserPurchases(date, dateComparison);
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
diff --git a/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart b/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart
index 59be7492..989ea170 100644
--- a/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart
+++ b/lib/features/create_diet/presentation/cubit/create_diet_cubit.dart
@@ -1,7 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'dart:developer';
-import 'package:dio/dio.dart';
import 'package:eatvio_app/core/app_config.dart';
import 'package:eatvio_app/core/app_initializer.dart';
import 'package:eatvio_app/core/const.dart';
@@ -16,6 +15,7 @@ import 'package:eatvio_app/features/profile/repositories/profile_repository.dart
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:http/http.dart' as http;
+import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:path_provider/path_provider.dart';
class CreateDietCubit extends Cubit {
@@ -347,10 +347,11 @@ class CreateDietCubit extends Cubit {
emit(state.copyWith(published: dietState != DietState.draft, drafted: dietState == DietState.draft));
return null;
- } on DioException catch (e, stackTrace) {
- log(e.toString(), stackTrace: stackTrace);
+ } catch (e, st) {
+ await Sentry.captureException(e, stackTrace: st);
+ log(e.toString(), stackTrace: st);
+ emit(state.copyWith(isDietPublishing: false));
}
- emit(state.copyWith(isDietPublishing: false));
return 'error';
}
@@ -381,6 +382,7 @@ class CreateDietCubit extends Cubit {
);
return null;
} catch (e, st) {
+ await Sentry.captureException(e, stackTrace: st);
log(e.toString(), stackTrace: st);
return 'error';
}
diff --git a/lib/features/create_diet/repositories/create_diet_repository.dart b/lib/features/create_diet/repositories/create_diet_repository.dart
index 825e9424..d63be30f 100644
--- a/lib/features/create_diet/repositories/create_diet_repository.dart
+++ b/lib/features/create_diet/repositories/create_diet_repository.dart
@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class CreateDietRepository {
final CreateDietService createDietService;
@@ -18,7 +19,7 @@ class CreateDietRepository {
required String? details,
required File? image,
required List>>? dailySchedule,
- }) {
+ }) async {
final dietMap = {};
if (dailySchedule != null) {
for (final (dayIndex, day) in dailySchedule.indexed) {
@@ -61,13 +62,18 @@ class CreateDietRepository {
dietMap.addAll({'name': name, 'duration': duration});
final formData = FormData.fromMap(dietMap);
- switch (state) {
- case DietState.active:
- return createDietService.createPublishedDiet(formData: formData);
- case DietState.draft:
- return createDietService.createDraftedDiet(formData: formData);
- case DietState.personal:
- return createDietService.createPersonalDiet(formData: formData);
+ try {
+ switch (state) {
+ case DietState.active:
+ return await createDietService.createPublishedDiet(formData: formData);
+ case DietState.draft:
+ return await createDietService.createDraftedDiet(formData: formData);
+ case DietState.personal:
+ return await createDietService.createPersonalDiet(formData: formData);
+ }
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
+ rethrow;
}
}
@@ -94,7 +100,8 @@ class CreateDietRepository {
);
});
return dailySchedule;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
rethrow;
}
}
@@ -111,7 +118,7 @@ class CreateDietRepository {
String? details,
File? image,
List>>? dailySchedule,
- }) {
+ }) async {
final dietMap = {};
if (dailySchedule != null) {
for (final (dayIndex, day) in dailySchedule.indexed) {
@@ -154,13 +161,18 @@ class CreateDietRepository {
}
final formData = FormData.fromMap(dietMap);
- switch (state) {
- case DietState.active:
- return createDietService.updatePublished(diet: dietId, formData: formData);
- case DietState.draft:
- return createDietService.updateDrafted(diet: dietId, formData: formData);
- case DietState.personal:
- return createDietService.updatePersonal(diet: dietId, formData: formData);
+ try {
+ switch (state) {
+ case DietState.active:
+ return await createDietService.updatePublished(diet: dietId, formData: formData);
+ case DietState.draft:
+ return await createDietService.updateDrafted(diet: dietId, formData: formData);
+ case DietState.personal:
+ return await createDietService.updatePersonal(diet: dietId, formData: formData);
+ }
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
+ rethrow;
}
}
}
diff --git a/lib/features/create_plan/presentation/cubit/create_plan_cubit.dart b/lib/features/create_plan/presentation/cubit/create_plan_cubit.dart
index 2289b31f..21b07b68 100644
--- a/lib/features/create_plan/presentation/cubit/create_plan_cubit.dart
+++ b/lib/features/create_plan/presentation/cubit/create_plan_cubit.dart
@@ -341,7 +341,7 @@ class CreatePlanCubit extends Cubit {
bool validateSelectedOptionDescription() {
final option = state.planData.options[state.selectedOptionIndex ?? 0];
final optionsValidationsStates = [...state.validationState.optionsValidationState];
- if (option.description.length < 3) {
+ if (option.description == null || option.description!.length < 3) {
optionsValidationsStates[state.selectedOptionIndex ?? 0] = optionsValidationsStates[state.selectedOptionIndex ?? 0].copyWith(descriptionHasError: true);
emit(state.copyWith.validationState(optionsValidationState: optionsValidationsStates));
return false;
@@ -356,7 +356,7 @@ class CreatePlanCubit extends Cubit {
final optionsValidationsStates = [...state.validationState.optionsValidationState];
bool result = true;
- if (options[0].description.length < 3) {
+ if (options[0].description == null || options[0].description!.length < 3) {
optionsValidationsStates[0] = optionsValidationsStates[0].copyWith(descriptionHasError: true);
emit(state.copyWith.validationState(optionsValidationState: optionsValidationsStates));
result = false;
@@ -365,7 +365,7 @@ class CreatePlanCubit extends Cubit {
emit(state.copyWith.validationState(optionsValidationState: optionsValidationsStates));
}
if (state.selectedOptionIndex == null) return result;
- if (options[1].description.length < 3) {
+ if (options[1].description == null || options[1].description!.length < 3) {
optionsValidationsStates[1] = optionsValidationsStates[1].copyWith(descriptionHasError: true);
emit(state.copyWith.validationState(optionsValidationState: optionsValidationsStates));
result = false;
@@ -374,7 +374,7 @@ class CreatePlanCubit extends Cubit {
emit(state.copyWith.validationState(optionsValidationState: optionsValidationsStates));
}
- if (options[2].description.length < 3) {
+ if (options[2].description == null || options[2].description!.length < 3) {
optionsValidationsStates[2] = optionsValidationsStates[2].copyWith(descriptionHasError: true);
emit(state.copyWith.validationState(optionsValidationState: optionsValidationsStates));
result = false;
diff --git a/lib/features/create_plan/presentation/widgets/option_widget.dart b/lib/features/create_plan/presentation/widgets/option_widget.dart
index 24cde52b..cc4eb816 100644
--- a/lib/features/create_plan/presentation/widgets/option_widget.dart
+++ b/lib/features/create_plan/presentation/widgets/option_widget.dart
@@ -94,7 +94,7 @@ class _OptionWidgetState extends State {
final price = double.tryParse(customerPriceController.text.replaceAll('₽', ''));
creatorPriceController.text = '${((price ?? 0) * 0.8).toStringAsFixed(2)}₽';
firstOptionTitleController.text = state.planData.options[selectedOptionIndex].short;
- firstOptionDescriptionController.text = state.planData.options[selectedOptionIndex].description;
+ firstOptionDescriptionController.text = state.planData.options[selectedOptionIndex].description ?? '';
return MainBackgroundBouble(
padding: const EdgeInsets.all(16),
child: Column(
diff --git a/lib/features/create_plan/repositories/create_plan_repository.dart b/lib/features/create_plan/repositories/create_plan_repository.dart
index 96e961d7..1011005e 100644
--- a/lib/features/create_plan/repositories/create_plan_repository.dart
+++ b/lib/features/create_plan/repositories/create_plan_repository.dart
@@ -1,5 +1,6 @@
import 'package:dio/dio.dart';
import 'package:eatvio_app/features/create_plan/services/create_plan_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
class CreatePlanRepository {
final CreatePlanService createPlanService;
@@ -9,7 +10,13 @@ class CreatePlanRepository {
Future createPlan({
required Map model,
}) async {
- final formData = FormData.fromMap(model);
- return await createPlanService.createPlan(formData: formData);
- }
+ try {
+ final formData = FormData.fromMap(model);
+ return await createPlanService.createPlan(formData: formData);
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
+ rethrow;
+ }
+ }
+
}
diff --git a/lib/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart b/lib/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart
index ded7cb1f..8f7bca23 100644
--- a/lib/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart
+++ b/lib/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart
@@ -11,6 +11,7 @@ import 'package:eatvio_app/features/feed/models/recipes_model.dart';
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
import 'package:eatvio_app/features/glossary/repositories/glossary_repository.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
@@ -165,6 +166,7 @@ class CreateRecipeCubit extends Cubit {
await recipeRepository.publishRecipe(model, update, slug);
return true;
} catch (e, st) {
+ await Sentry.captureException(e, stackTrace: st);
log(e.toString(), stackTrace: st);
return false;
}
@@ -329,7 +331,8 @@ class CreateRecipeCubit extends Cubit {
try {
await recipeRepository.deleteRecipe(slug);
return true;
- } catch (e) {
+ } catch (e, s) {
+ await Sentry.captureException(e, stackTrace: s);
return false;
}
}
diff --git a/lib/features/create_recipe/reporitories/recipe_repository.dart b/lib/features/create_recipe/reporitories/recipe_repository.dart
index 289233a2..b1b5fce9 100644
--- a/lib/features/create_recipe/reporitories/recipe_repository.dart
+++ b/lib/features/create_recipe/reporitories/recipe_repository.dart
@@ -6,6 +6,7 @@ import 'package:eatvio_app/features/create_recipe/models/recipe_model.dart';
import 'package:eatvio_app/features/create_recipe/models/recipe_tag_model.dart';
import 'package:eatvio_app/features/create_recipe/models/step.dart';
import 'package:eatvio_app/features/create_recipe/services/recipe_service.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:eatvio_app/features/create_recipe/models/product.dart';
class RecipeRepository {
@@ -16,7 +17,8 @@ class RecipeRepository {
Future