From a1304e4612006011d49d3e240c4ee73bb8331d61 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Fri, 19 Dec 2025 15:15:54 +0300 Subject: [PATCH] feat(router): enhance deep link handling with logging and support for various content types --- lib/core/app_router.dart | 119 ++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 19 deletions(-) diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index 47f25430..776aea35 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -1,3 +1,4 @@ +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'; @@ -13,6 +14,9 @@ import 'package:go_router/go_router.dart'; class AppRouter { static GlobalKey navigatorKey = GlobalKey(); + // Домены для deep links + static const List _deepLinkHosts = ['eatvio.ru', 'www.eatvio.ru']; + static GoRouter appRouter = GoRouter( initialLocation: RouteConstants.updateScreen, navigatorKey: navigatorKey, @@ -27,51 +31,128 @@ class AppRouter { ); /// Обработка редиректов для deep links + /// Возвращает null для обычной навигации, чтобы не мешать внутренним переходам static String? _handleRedirect(BuildContext context, GoRouterState state) { - final segments = state.uri.pathSegments; - if (segments.length == 4) { - final type = segments[1]; - switch (type) { - case 'diary': - FlutterNativeSplash.remove(); - return '/diary-screen'; - } + 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; } - if (segments.length == 3) { + + // Логирование для отладки + 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 '/chat-select-screen'; + return RouteConstants.chatSelectScreen; case 'profile': + developer.log('Deep link: profile/$contentIdentifier', name: 'AppRouter'); FlutterNativeSplash.remove(); return '/profile-screen?slug=$contentIdentifier'; - } - } - if (segments.length == 2) { - final type = segments[1]; - switch (type) { - case 'chat': + case 'diary': + developer.log('Deep link: diary/$contentIdentifier', name: 'AppRouter'); FlutterNativeSplash.remove(); - return '/chat-select-screen'; + 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; } - - return null; } static void navigateToRegisterViaSocial({required AuthResultEntity authResult, required String provider}) {