Files
eatvio_app/lib/core/app_router.dart

162 lines
6.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:developer' as developer;
import 'package:eatvio_app/core/routing/auth_routes.dart';
import 'package:eatvio_app/core/routing/content_routes.dart';
import 'package:eatvio_app/core/routing/main_navigation_routes.dart';
import 'package:eatvio_app/core/routing/other_routes.dart';
import 'package:eatvio_app/core/routing/route_constants.dart';
import 'package:eatvio_app/core/routing/settings_routes.dart';
import 'package:eatvio_app/features/auth/entities/auth_result_entity.dart';
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:go_router/go_router.dart';
/// Главный роутер приложения
class AppRouter {
static GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
// Домены для deep links
static const List<String> _deepLinkHosts = ['eatvio.ru', 'www.eatvio.ru'];
static GoRouter appRouter = GoRouter(
initialLocation: RouteConstants.updateScreen,
navigatorKey: navigatorKey,
redirect: _handleRedirect,
routes: [
...AuthRoutes.createRoutes(),
...MainNavigationRoutes.createRoutes(),
...ContentRoutes.createRoutes(),
...SettingsRoutes.createRoutes(),
...OtherRoutes.createRoutes(),
],
);
/// Обработка редиректов для deep links
/// Возвращает null для обычной навигации, чтобы не мешать внутренним переходам
static String? _handleRedirect(BuildContext context, GoRouterState state) {
final uri = state.uri;
final host = uri.host.toLowerCase();
final segments = uri.pathSegments;
// Проверяем, является ли это deep link по домену
final isDeepLink = _deepLinkHosts.contains(host);
// Если это не deep link, не мешаем обычной навигации
if (!isDeepLink) {
return null;
}
// Логирование для отладки
developer.log(
'Deep link detected: host=$host, path=${uri.path}, segments=$segments',
name: 'AppRouter',
);
// Проверка на пустой путь или некорректный формат
if (segments.isEmpty) {
developer.log('Empty segments in deep link, redirecting to feed', name: 'AppRouter');
FlutterNativeSplash.remove();
return RouteConstants.feedScreen;
}
// Проверка языка (первый сегмент должен быть ru или en)
if (segments[0] != 'ru' && segments[0] != 'en') {
developer.log(
'Invalid language segment: ${segments[0]}, redirecting to feed',
name: 'AppRouter',
);
FlutterNativeSplash.remove();
return RouteConstants.feedScreen;
}
// Обработка deep links с учетом языка
// Формат: /{lang}/{type}/{identifier?}
if (segments.length == 4) {
// Формат: /{lang}/diary/{...}
final type = segments[1];
if (type == 'diary') {
developer.log('Deep link: diary, redirecting to diary-screen', name: 'AppRouter');
FlutterNativeSplash.remove();
return RouteConstants.diaryScreen;
}
developer.log(
'Unknown deep link type for 4 segments: $type, redirecting to feed',
name: 'AppRouter',
);
FlutterNativeSplash.remove();
return RouteConstants.feedScreen;
} else if (segments.length == 3) {
// Формат: /{lang}/{type}/{identifier}
final type = segments[1];
final contentIdentifier = segments[2];
switch (type) {
case 'recipe':
developer.log('Deep link: recipe/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return '/about-recipes-screen?slug=$contentIdentifier';
case 'blog_post':
developer.log('Deep link: blog_post/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return '/blog-post-screen?id=$contentIdentifier';
case 'plan':
developer.log('Deep link: plan/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return '/about-plan-screen?slug=$contentIdentifier';
case 'diet':
developer.log('Deep link: diet/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return '/about-diet-screen?slug=$contentIdentifier';
case 'chat':
developer.log('Deep link: chat/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return RouteConstants.chatSelectScreen;
case 'profile':
developer.log('Deep link: profile/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return '/profile-screen?slug=$contentIdentifier';
case 'diary':
developer.log('Deep link: diary/$contentIdentifier', name: 'AppRouter');
FlutterNativeSplash.remove();
return RouteConstants.diaryScreen;
default:
developer.log(
'Unknown deep link type: $type, redirecting to feed',
name: 'AppRouter',
);
FlutterNativeSplash.remove();
return RouteConstants.feedScreen;
}
} else if (segments.length == 2) {
// Формат: /{lang}/{type} - только для chat
final type = segments[1];
if (type == 'chat') {
developer.log('Deep link: chat', name: 'AppRouter');
FlutterNativeSplash.remove();
return RouteConstants.chatSelectScreen;
} else {
developer.log(
'Unknown deep link type for 2 segments: $type, redirecting to feed',
name: 'AppRouter',
);
FlutterNativeSplash.remove();
return RouteConstants.feedScreen;
}
} else {
// Неизвестный формат deep link
developer.log(
'Unknown deep link format: ${segments.length} segments, redirecting to feed',
name: 'AppRouter',
);
FlutterNativeSplash.remove();
return RouteConstants.feedScreen;
}
}
static void navigateToRegisterViaSocial({required AuthResultEntity authResult, required String provider}) {
appRouter.pushNamed('registerViaSocialScreen', extra: {'authResult': authResult, 'provider': provider});
}
}