feat(debug): Удалить Talker (#2)

Co-authored-by: petrovyuri <y.petrov@friflex.com>
This commit is contained in:
Yuri Petrov
2025-02-04 10:18:41 +03:00
committed by GitHub
parent 40fc2209a4
commit 933c1a0f0f
17 changed files with 165 additions and 378 deletions

76
.vscode/launch.json vendored
View File

@@ -2,47 +2,45 @@
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "GMS_dev", "name": "dev",
"type": "dart", "type": "dart",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/lib/targets/dev.dart", "program": "${workspaceFolder}/lib/targets/dev.dart"
"preLaunchTask": "switch_to_gms"
}, },
{ // {
"name": "GMS_stage", // "name": "GMS_stage",
"type": "dart", // "type": "dart",
"request": "launch", // "request": "launch",
"program": "${workspaceFolder}/lib/targets/stage.dart", // "program": "${workspaceFolder}/lib/targets/stage.dart",
"preLaunchTask": "switch_to_gms" // "preLaunchTask": "switch_to_gms"
}, // },
{ // {
"name": "GMS_prod", // "name": "GMS_prod",
"type": "dart", // "type": "dart",
"request": "launch", // "request": "launch",
"program": "${workspaceFolder}/lib/targets/prod.dart", // "program": "${workspaceFolder}/lib/targets/prod.dart",
"preLaunchTask": "switch_to_gms" // "preLaunchTask": "switch_to_gms"
}, // },
{ // {
"name": "Aurora_dev", // "name": "Aurora_dev",
"type": "dart", // "type": "dart",
"request": "launch", // "request": "launch",
"program": "${workspaceFolder}/lib/targets/dev.dart", // "program": "${workspaceFolder}/lib/targets/dev.dart",
"preLaunchTask": "switch_to_aurora" // "preLaunchTask": "switch_to_aurora"
}, // },
{ // {
"name": "Aurora_stage", // "name": "Aurora_stage",
"type": "dart", // "type": "dart",
"request": "launch", // "request": "launch",
"program": "${workspaceFolder}/lib/targets/stage.dart", // "program": "${workspaceFolder}/lib/targets/stage.dart",
"preLaunchTask": "switch_to_aurora" // "preLaunchTask": "switch_to_aurora"
}, // },
{ // {
"name": "Aurora_prod", // "name": "Aurora_prod",
"type": "dart", // "type": "dart",
"request": "launch", // "request": "launch",
"program": "${workspaceFolder}/lib/targets/prod.dart", // "program": "${workspaceFolder}/lib/targets/prod.dart",
"preLaunchTask": "switch_to_aurora" // "preLaunchTask": "switch_to_aurora"
}, // },
] ]
} }

View File

@@ -11,11 +11,6 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
# Зависимости для сервиса логирования
talker_flutter: 4.6.4
talker_dio_logger: 4.6.4
talker_bloc_logger: 4.6.4
# Зависимости для сервиса защищенного хранилища # Зависимости для сервиса защищенного хранилища
flutter_secure_storage: 9.2.4 flutter_secure_storage: 9.2.4

View File

@@ -1,60 +0,0 @@
import 'package:flutter/material.dart';
/// Интерфейс для сервиса отладки
abstract interface class IDebugService {
/// Наименование сервиса
static const name = 'IDebugService';
/// Метод для создания обработчика для BLoC
Object createBlocObserver();
/// Метод для создания обработчика для роутера
NavigatorObserver createRouterObserver();
/// Метод для создания обработчика для http-клиентов
Object createHttpInterceptor();
/// Метод для логгирования предупреждений
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
void warning(String message);
/// Метод для логгирования ошибок
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
/// - [exception] - исключение
/// - [stackTrace] - стек вызова
void error(String message, [Object? exception, StackTrace? stackTrace]);
/// Метод для обработки ошибок
///
/// Принимает:
/// - [error] - исключение
/// - [stackTrace] - стек вызова
/// - [message] - сообщение для логгирования в формате [String]
void handleError(Object error, [StackTrace? stackTrace, String? message]);
/// Метод для логгирования информативных сообщений
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
void info(String message);
/// Метод для логгирования сообщений
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
void log(String message);
/// Метод для открытия окна отладки
///
/// Принимает:
/// - [context] - для определения навигатора по нему
/// - [useRootNavigator] - при true, открывает окно в корневом навигаторе
Future<T?> openDebugScreen<T>(
BuildContext context, {
bool useRootNavigator = false,
});
}

View File

@@ -1,6 +1,5 @@
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:friflex_starter/app/app_config/i_app_config.dart'; import 'package:friflex_starter/app/app_config/i_app_config.dart';
import 'package:friflex_starter/app/app_env.dart';
import 'package:friflex_starter/app/http/i_http_client.dart'; import 'package:friflex_starter/app/http/i_http_client.dart';
import 'package:friflex_starter/features/debug/i_debug_service.dart'; import 'package:friflex_starter/features/debug/i_debug_service.dart';
@@ -26,14 +25,7 @@ final class AppHttpClient implements IHttpClient {
..headers = { ..headers = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}; };
debugService.log('HTTP client created');
// Добавление интерцептора для логирования запросов
if (appConfig.env != AppEnv.prod) {
final interceptor = debugService.createHttpInterceptor();
if (interceptor is Interceptor) {
_httpClient.interceptors.add(interceptor);
}
}
} }
/// Конфигурация приложения /// Конфигурация приложения

View File

@@ -15,8 +15,7 @@ import 'package:i_app_services/i_app_services.dart';
/// {@endtemplate} /// {@endtemplate}
final class DiContainer { final class DiContainer {
/// {@macro dependencies_container} /// {@macro dependencies_container}
DiContainer({required this.env, required IDebugService dService}) DiContainer({required this.env, required IDebugService dService}) : debugService = dService;
: debugService = dService;
final AppEnv env; final AppEnv env;
/// Сервис для отладки, получаем из конструктора /// Сервис для отладки, получаем из конструктора
@@ -84,8 +83,8 @@ final class DiContainer {
} on Object catch (error, stackTrace) { } on Object catch (error, stackTrace) {
onError( onError(
'Ошибка инициализации ${IPathProvider.name}', 'Ошибка инициализации ${IPathProvider.name}',
error: error, error,
stackTrace: stackTrace, stackTrace,
); );
} }
@@ -95,8 +94,8 @@ final class DiContainer {
} on Object catch (error, stackTrace) { } on Object catch (error, stackTrace) {
onError( onError(
'Ошибка инициализации ${ISecureStorage.name}', 'Ошибка инициализации ${ISecureStorage.name}',
error: error, error,
stackTrace: stackTrace, stackTrace,
); );
} }
} }

View File

@@ -60,8 +60,8 @@ final class DiRepositories {
} on Object catch (error, stackTrace) { } on Object catch (error, stackTrace) {
onError( onError(
'Ошибка инициализации репозитория $IAuthRepository', 'Ошибка инициализации репозитория $IAuthRepository',
error: error, error,
stackTrace: stackTrace, stackTrace,
); );
} }
@@ -79,8 +79,8 @@ final class DiRepositories {
} on Object catch (error, stackTrace) { } on Object catch (error, stackTrace) {
onError( onError(
'Ошибка инициализации репозитория $IMainRepository', 'Ошибка инициализации репозитория $IMainRepository',
error: error, error,
stackTrace: stackTrace, stackTrace,
); );
} }
@@ -105,9 +105,8 @@ final class DiRepositories {
final repo = switch (environment) { final repo = switch (environment) {
AppEnv.dev => mockFactory(), AppEnv.dev => mockFactory(),
AppEnv.prod => mainFactory(), AppEnv.prod => mainFactory(),
AppEnv.stage => _mockReposToSwitch.contains(mockFactory().name) AppEnv.stage =>
? mockFactory() _mockReposToSwitch.contains(mockFactory().name) ? mockFactory() : mainFactory(),
: mainFactory(),
}; };
onProgress(repo.name); onProgress(repo.name);
return repo; return repo;

View File

@@ -1,9 +1,9 @@
/// Обратный вызов при ошибки инициализации /// Обратный вызов при ошибки инициализации
typedef OnError = void Function( typedef OnError = void Function(
String message, { String message,
Object? error, Object error, [
StackTrace? stackTrace, StackTrace? stackTrace,
}); ]);
/// Обратный вызов при прогрессе /// Обратный вызов при прогрессе
typedef OnProgress = void Function(String name); typedef OnProgress = void Function(String name);

View File

@@ -1,60 +0,0 @@
import 'package:flutter/material.dart';
import 'package:friflex_starter/features/debug/i_debug_service.dart';
import 'package:talker_bloc_logger/talker_bloc_logger.dart';
import 'package:talker_dio_logger/talker_dio_logger_interceptor.dart';
import 'package:talker_flutter/talker_flutter.dart';
/// Класс реализации интерфейса дебаг сервиса
class AppDebugService implements IDebugService {
/// Наименование сервиса
static const name = 'GmsDebugService';
final Talker _talker = TalkerFlutter.init();
@override
TalkerBlocObserver createBlocObserver() =>
TalkerBlocObserver(talker: _talker);
@override
TalkerDioLogger createHttpInterceptor() => TalkerDioLogger(talker: _talker);
@override
TalkerRouteObserver createRouterObserver() => TalkerRouteObserver(_talker);
@override
void error(String msg, [Object? exception, StackTrace? stackTrace]) {
_talker.error(msg, exception, stackTrace);
}
@override
void handleError(Object error, [StackTrace? stackTrace, String? message]) {
_talker.handle(error, stackTrace, message);
}
@override
void info(String message) {
_talker.info(message);
}
@override
void log(String message) {
_talker.log(message);
}
@override
void warning(String message) {
_talker.warning(message);
}
@override
Future<T?> openDebugScreen<T>(
BuildContext context, {
bool useRootNavigator = false,
}) {
return Navigator.of(context).push<T>(
MaterialPageRoute(
builder: (context) => TalkerScreen(talker: _talker),
),
);
}
}

View File

@@ -31,7 +31,7 @@ class DebugScreen extends StatelessWidget {
onPressed: () async { onPressed: () async {
await context.di.debugService.openDebugScreen(context); await context.di.debugService.openDebugScreen(context);
}, },
child: const Text('Вызывать Talker'), child: const Text('Вызывать Экран отладки'),
), ),
], ],
), ),

View File

@@ -0,0 +1,66 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:friflex_starter/features/debug/i_debug_service.dart';
/// Класс реализации интерфейса Debug сервиса
class DebugService implements IDebugService {
/// Наименование сервиса
static const name = 'DebugService';
@override
void logDebug(Object message, {Object? logLevel, Map<String, dynamic>? args}) {
if (kDebugMode) {
print('Message: $message');
}
/// Реализация логики
}
@override
void logError(
Object message, {
Object? error,
Object? logLevel,
Map<String, dynamic>? args,
StackTrace? stackTrace,
}) {
final logMessage = message is Function ? Function.apply(message, []) as Object : message;
if (kDebugMode) {
print('Message: $logMessage');
print('Error: $error');
print('StackTrace: $stackTrace');
}
/// Реализация логики
}
@override
void log(Object message, {Object? logLevel, Map<String, dynamic>? args}) {
final logMessage = message is Function ? Function.apply(message, []) as Object : message;
if (kDebugMode) {
print('Message: $logMessage');
}
/// Реализация логики
}
@override
void logWarning(Object message, {Object? logLevel, Map<String, dynamic>? args}) {
final logMessage = message is Function ? Function.apply(message, []) as Object : message;
if (kDebugMode) {
print('Message: $logMessage');
}
/// Реализация логики
}
@override
Future<T?> openDebugScreen<T>(BuildContext context, {bool useRootNavigator = false}) {
if (kDebugMode) {
print('Переход на страницу отладки');
}
/// Реализация логики
return Future.value();
}
}

View File

@@ -2,51 +2,37 @@ import 'package:flutter/material.dart';
/// Интерфейс для сервиса отладки /// Интерфейс для сервиса отладки
abstract interface class IDebugService { abstract interface class IDebugService {
/// Наименование сервиса
static const name = 'IDebugService'; static const name = 'IDebugService';
/// Метод для создания обработчика для BLoC /// Метод для логирования сообщений
Object createBlocObserver(); void log(
Object message, {
Object logLevel,
Map<String, dynamic>? args,
});
/// Метод для создания обработчика для роутера /// Метод для логирования предупреждений
NavigatorObserver createRouterObserver(); void logWarning(
Object message, {
Object logLevel,
Map<String, dynamic>? args,
});
/// Метод для создания обработчика для http-клиентов /// Метод для логирования ошибок
Object createHttpInterceptor(); void logError(
Object message, {
/// Метод для логгирования предупреждений Object error,
/// StackTrace? stackTrace,
/// Принимает: Object logLevel,
/// - [message] - сообщение для логгирования в формате [String] Map<String, dynamic>? args,
void warning(String message); });
/// Метод для логгирования ошибок
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
/// - [exception] - исключение
/// - [stackTrace] - стек вызова
void error(String message, [Object? exception, StackTrace? stackTrace]);
/// Метод для обработки ошибок /// Метод для обработки ошибок
/// void logDebug(
/// Принимает: Object message, {
/// - [error] - исключение Object logLevel,
/// - [stackTrace] - стек вызова Map<String, dynamic>? args,
/// - [message] - сообщение для логгирования в формате [String] });
void handleError(Object error, [StackTrace? stackTrace, String? message]);
/// Метод для логгирования информативных сообщений
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
void info(String message);
/// Метод для логгирования сообщений
///
/// Принимает:
/// - [message] - сообщение для логгирования в формате [String]
void log(String message);
/// Метод для открытия окна отладки /// Метод для открытия окна отладки
/// ///

View File

@@ -22,9 +22,6 @@ class AppRouter {
navigatorKey: rootNavigatorKey, navigatorKey: rootNavigatorKey,
debugLogDiagnostics: true, debugLogDiagnostics: true,
initialLocation: initialLocation, initialLocation: initialLocation,
observers: [
debugService.createRouterObserver(),
],
routes: [ routes: [
StatefulShellRoute.indexedStack( StatefulShellRoute.indexedStack(
parentNavigatorKey: rootNavigatorKey, parentNavigatorKey: rootNavigatorKey,

View File

@@ -6,7 +6,7 @@ import 'package:flutter/services.dart';
import 'package:friflex_starter/app/app.dart'; import 'package:friflex_starter/app/app.dart';
import 'package:friflex_starter/app/app_env.dart'; import 'package:friflex_starter/app/app_env.dart';
import 'package:friflex_starter/di/di_container.dart'; import 'package:friflex_starter/di/di_container.dart';
import 'package:friflex_starter/features/debug/app_debug_service.dart'; import 'package:friflex_starter/features/debug/debug_service.dart';
import 'package:friflex_starter/features/debug/i_debug_service.dart'; import 'package:friflex_starter/features/debug/i_debug_service.dart';
import 'package:friflex_starter/features/error/error_screen.dart'; import 'package:friflex_starter/features/error/error_screen.dart';
import 'package:friflex_starter/router/app_router.dart'; import 'package:friflex_starter/router/app_router.dart';
@@ -45,7 +45,7 @@ class AppRunner {
Future<void> run() async { Future<void> run() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
// Инициализация сервиса отладки // Инициализация сервиса отладки
_debugService = AppDebugService(); _debugService = DebugService();
_timerRunner = TimerRunner(_debugService); _timerRunner = TimerRunner(_debugService);
@@ -91,7 +91,7 @@ class AppRunner {
/// Метод для инициализации зависимостей приложения /// Метод для инициализации зависимостей приложения
Future<DiContainer> _initDependencies(IDebugService debugService) async { Future<DiContainer> _initDependencies(IDebugService debugService) async {
debugService.log('Тип сборки: ${env.name}'); debugService.log(() => 'Тип сборки: ${env.name}');
final diContainer = DiContainer( final diContainer = DiContainer(
env: env, env: env,
dService: debugService, dService: debugService,

View File

@@ -5,16 +5,24 @@ void _initErrorHandlers(IDebugService debugService) {
// Обработка ошибок в приложении // Обработка ошибок в приложении
FlutterError.onError = (details) { FlutterError.onError = (details) {
_showErrorScreen(); _showErrorScreen();
debugService.handleError(details.exception, details.stack, debugService.logError(
'FlutterError.onError: ${details.exceptionAsString()}',); () => 'FlutterError.onError: ${details.exceptionAsString()}',
error: details.exception,
stackTrace: details.stack,
);
}; };
// Обработка асинхронных ошибок в приложении // Обработка асинхронных ошибок в приложении
PlatformDispatcher.instance.onError = (error, stack) { PlatformDispatcher.instance.onError = (error, stack) {
_showErrorScreen(); _showErrorScreen();
debugService.handleError(error, stack, 'PlatformDispatcher: $error'); debugService.logError(
() => 'PlatformDispatcher.instance.onError',
error: error,
stackTrace: stack,
);
return true; return true;
}; };
} }
/// Метод для показа экрана ошибки /// Метод для показа экрана ошибки
void _showErrorScreen() { void _showErrorScreen() {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {

View File

@@ -40,10 +40,10 @@ class TimerRunner {
/// Метод для обработки прогресса инициализации зависимостей /// Метод для обработки прогресса инициализации зависимостей
void logOnError( void logOnError(
String message, { String message,
Object? error, Object error, [
StackTrace? stackTrace, StackTrace? stackTrace,
}) { ]) {
_debugService.error(message, error, stackTrace); _debugService.logError(() => message, error: error, stackTrace: stackTrace);
} }
} }

View File

@@ -22,14 +22,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.11.0" version: "6.11.0"
ansicolor:
dependency: transitive
description:
name: ansicolor
sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
app_services: app_services:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -181,14 +173,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
url: "https://pub.dev"
source: hosted
version: "0.3.4+2"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -409,14 +393,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.3.2"
group_button:
dependency: transitive
description:
name: group_button
sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940"
url: "https://pub.dev"
source: hosted
version: "5.3.4"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
@@ -680,22 +656,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.1.0"
share_plus:
dependency: transitive
description:
name: share_plus
sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da
url: "https://pub.dev"
source: hosted
version: "10.1.4"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b
url: "https://pub.dev"
source: hosted
version: "5.0.2"
shared_preferences: shared_preferences:
dependency: transitive dependency: transitive
description: description:
@@ -789,14 +749,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.0" version: "1.10.0"
sprintf:
dependency: transitive
description:
name: sprintf
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@@ -829,46 +781,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
talker:
dependency: transitive
description:
name: talker
sha256: "4c3b9b7b8c8882fc30253bbbe7c75d2f68d63ea35b7c1b6be2debe4a323c2ec9"
url: "https://pub.dev"
source: hosted
version: "4.6.4"
talker_bloc_logger:
dependency: "direct main"
description:
name: talker_bloc_logger
sha256: c14510bfb36af5d1648683a2707bb5bbb2858e3cabd549e363262db100bae374
url: "https://pub.dev"
source: hosted
version: "4.6.4"
talker_dio_logger:
dependency: "direct main"
description:
name: talker_dio_logger
sha256: b0d2c3486d1f17cb9eb187ee91bc23e5d7c438b80464432c3deb809d29228f8d
url: "https://pub.dev"
source: hosted
version: "4.6.4"
talker_flutter:
dependency: "direct main"
description:
name: talker_flutter
sha256: f23d184bc1ea675ed0fe1bfda636707f155f0596e898a7709bc488ead2c546b3
url: "https://pub.dev"
source: hosted
version: "4.6.4"
talker_logger:
dependency: transitive
description:
name: talker_logger
sha256: "27e4d0ba5c6950643a2500ad6c2e189099d0b9912f67389a49155e48fc2d9a55"
url: "https://pub.dev"
source: hosted
version: "4.6.4"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@@ -901,46 +813,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.0"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
uuid:
dependency: transitive
description:
name: uuid
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
url: "https://pub.dev"
source: hosted
version: "4.5.1"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@@ -1015,4 +887,4 @@ packages:
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.6.0 <4.0.0" dart: ">=3.6.0 <4.0.0"
flutter: ">=3.27.0" flutter: ">=3.24.0"

View File

@@ -21,11 +21,6 @@ dependencies:
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
# Зависимости для сервиса логирования
talker_flutter: 4.6.4
talker_dio_logger: 4.6.4
talker_bloc_logger: 4.6.4
### основной сервис с интерфейсами ### основной сервис с интерфейсами
i_app_services: i_app_services:
path: ./app_services/i_app_services path: ./app_services/i_app_services