8 Commits

Author SHA1 Message Date
Artem
6f839aea24 refactor(router): улучшить обработку ошибок при создании роутера
refactor(app): изменить AppRoot на StatefulWidget и переместить инициализацию роутера
2025-12-30 12:18:23 +07:00
Artem
617563fb6c refactor(app): перенести роутер ближе к месту инициализации в AppRoot 2025-12-30 12:13:52 +07:00
Artem
75c0ac3285 Merge branch 'main' into feat/перенести-роутер-ближе-к-месту-инициализации 2025-12-30 12:03:18 +07:00
Artem Luzin m
4260c7cc65 fix(app): remove unused parameter from _AppInternal constructor 2025-11-24 17:40:31 +07:00
Artem Luzin m
2595692107 Merge branches 'feat/перенести-роутер-ближе-к-месту-инициализации' and 'feat/перенести-роутер-ближе-к-месту-инициализации' of https://github.com/smmarty/friflex_starter into feat/перенести-роутер-ближе-к-месту-инициализации 2025-11-24 16:38:15 +07:00
Artem Luzin m
c86b4cc0bc feat(app): add mockRouter to _AppInternal for improved testing 2025-11-24 16:38:11 +07:00
Artem Luzin
d46c829959 Update lib/app/app.dart
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-24 16:23:42 +07:00
Artem Luzin m
84e5f5e869 feat/перенести роутер в место инициализации 2025-11-24 16:18:36 +07:00
8 changed files with 64 additions and 37 deletions

View File

@@ -6,6 +6,7 @@ import 'package:friflex_starter/app/theme/theme_notifier.dart';
import 'package:friflex_starter/di/di_container.dart';
import 'package:friflex_starter/l10n/gen/app_localizations.dart';
import 'package:friflex_starter/l10n/localization_notifier.dart';
import 'package:friflex_starter/router/app_router.dart';
import 'package:go_router/go_router.dart';
/// {@template app}
@@ -13,21 +14,39 @@ import 'package:go_router/go_router.dart';
///
/// Отвечает за:
/// - Настройку провайдеров для темы и локализации
/// - Инициализацию роутера приложения
/// {@endtemplate}
class AppRoot extends StatelessWidget {
class AppRoot extends StatefulWidget {
/// {@macro app_root}
const AppRoot({required this.diContainer, required this.router, super.key});
const AppRoot({required this.diContainer, super.key});
/// Контейнер зависимостей
final DiContainer diContainer;
@override
State<AppRoot> createState() => _AppRootState();
}
class _AppRootState extends State<AppRoot> {
/// Роутер приложения
final GoRouter router;
late final GoRouter router;
@override
void initState() {
super.initState();
router = AppRouter.createRouter(widget.diContainer.debugService);
}
@override
void dispose() {
router.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AppProviders(
diContainer: diContainer,
diContainer: widget.diContainer,
child: LocalizationConsumer(
builder: (localizationContext) {
return ThemeConsumer(

View File

@@ -37,7 +37,6 @@
- Статический метод `show` безопасно не откроет модалку, если `updateEntity == null`
Пример показа модального окна:
```dart
await SoftUpdateModal.show(
context,
@@ -55,9 +54,10 @@ await SoftUpdateModal.show(
- `UpdateRoutes.buildRoutes()` — регистрирует экран hard-обновления по пути `/update`
## Структура модуля
```md
```
features/update/
├── data/
│ └── repository/

View File

@@ -26,7 +26,7 @@ final class UpdateMockRepository implements IUpdateRepository {
@override
Future<UpdateEntity> checkForUpdates({
required String versionApp,
required String versionCode,
required String platform,
}) async {
// Имитация задержки для асинхронной операции

View File

@@ -14,7 +14,7 @@ final class UpdateRepository implements IUpdateRepository {
@override
Future<UpdateEntity> checkForUpdates({
required String versionApp,
required String versionCode,
required String platform,
}) {
// TODO: Реализовать реальную логику проверки обновлений

View File

@@ -6,11 +6,11 @@ import 'package:friflex_starter/features/update/domain/entity/update_entity.dart
/// {@endtemplate}
abstract interface class IUpdateRepository with DiBaseRepo {
/// Проверяет наличие обновлений
/// [versionApp] - текущий версия приложения
/// [versionCode] - текущий код версии приложения
/// [platform] - платформа (например, 'android' или 'ios')
/// Возвращает [UpdateEntity] с информацией об обновлении
Future<UpdateEntity> checkForUpdates({
required String versionApp,
required String versionCode,
required String platform,
});
}

View File

@@ -16,17 +16,17 @@ class UpdateCubit extends Cubit<UpdateState> {
final IUpdateRepository _updatesRepository;
/// Метод для проверки доступности обновлений
/// [versionApp] - текущая версия приложения
/// [versionCode] - текущий код версии приложения
/// [platform] - платформа (например, 'android' или 'ios')
Future<void> checkForUpdates({
required String versionApp,
required String versionCode,
required String platform,
}) async {
if (state is UpdateLoadingState) return;
emit(const UpdateLoadingState());
try {
final updateInfo = await _updatesRepository.checkForUpdates(
versionApp: versionApp,
versionCode: versionCode,
platform: platform,
);
emit(UpdateSuccessState(updateInfo));

View File

@@ -23,23 +23,35 @@ class AppRouter {
/// Метод для создания экземпляра GoRouter
static GoRouter createRouter(IDebugService debugService) {
return GoRouter(
navigatorKey: rootNavigatorKey,
initialLocation: initialLocation,
observers: [debugService.routeObserver],
routes: [
StatefulShellRoute.indexedStack(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state, navigationShell) =>
RootScreen(navigationShell: navigationShell),
branches: [
MainRoutes.buildShellBranch(),
ProfileRoutes.buildShellBranch(),
],
),
DebugRoutes.buildRoutes(),
UpdateRoutes.buildRoutes(),
],
);
try {
return _init(debugService);
} on Object catch (error, stackTrace) {
debugService.logError(
'Ошибка при создании роутера',
error: error,
stackTrace: stackTrace,
);
throw StateError('Не удалось создать роутер: $error');
}
}
/// Внутренний метод для инициализации роутера
static GoRouter _init(IDebugService debugService) => GoRouter(
navigatorKey: rootNavigatorKey,
initialLocation: initialLocation,
observers: [debugService.routeObserver],
routes: [
StatefulShellRoute.indexedStack(
parentNavigatorKey: rootNavigatorKey,
builder: (context, state, navigationShell) =>
RootScreen(navigationShell: navigationShell),
branches: [
MainRoutes.buildShellBranch(),
ProfileRoutes.buildShellBranch(),
],
),
DebugRoutes.buildRoutes(),
UpdateRoutes.buildRoutes(),
],
);
}

View File

@@ -10,7 +10,6 @@ import 'package:friflex_starter/di/di_container.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/error/error_screen.dart';
import 'package:friflex_starter/router/app_router.dart';
import 'package:friflex_starter/runner/timer_runner.dart';
import 'package:go_router/go_router.dart';
@@ -33,7 +32,7 @@ class AppRunner {
/// Тип окружения сборки приложения¬
final AppEnv env;
/// Сервис отладки
/// Контейнер зависимостей приложения
late IDebugService _debugService;
/// Роутер приложения
@@ -57,9 +56,6 @@ class AppRunner {
// Инициализация приложения
await _initApp();
// Инициализация роутера
router = AppRouter.createRouter(_debugService);
final diContainer = await _initDependencies(
debugService: _debugService,
env: env,
@@ -67,7 +63,7 @@ class AppRunner {
);
// Инициализация метода обработки ошибок
_initErrorHandlers(_debugService);
runApp(AppRoot(diContainer: diContainer, router: router));
runApp(AppRoot(diContainer: diContainer));
await _onAppLoaded();
} on Object catch (e, stackTrace) {
await _onAppLoaded();