import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '../screens/category_management_screen.dart'; import '../screens/app_lock_screen.dart'; import '../models/subscription_model.dart'; import '../providers/navigation_provider.dart'; import '../routes/app_routes.dart'; import 'animated_page_transitions.dart'; /// 앱 전체의 네비게이션을 관리하는 클래스 class AppNavigator { // NavigationProvider를 사용하여 상태를 관리하므로 더 이상 싱글톤 패턴이 필요하지 않음 /// 홈으로 네비게이션 static Future toHome(BuildContext context) async { HapticFeedback.lightImpact(); final navigationProvider = context.read(); navigationProvider.clearHistoryAndGoHome(); await Navigator.of(context).pushNamedAndRemoveUntil( AppRoutes.main, (route) => false, ); } /// 분석 화면으로 네비게이션 static Future toAnalysis(BuildContext context) async { HapticFeedback.lightImpact(); final navigationProvider = context.read(); navigationProvider.updateCurrentIndex(1); await Navigator.of(context).pushNamed(AppRoutes.analysis); } /// 구독 추가 화면으로 네비게이션 static Future toAddSubscription(BuildContext context) async { HapticFeedback.mediumImpact(); await Navigator.of(context).pushNamed(AppRoutes.addSubscription); } /// 구독 상세 화면으로 네비게이션 static Future toDetail(BuildContext context, SubscriptionModel subscription) async { print('AppNavigator.toDetail 호출됨: ${subscription.serviceName}'); HapticFeedback.lightImpact(); try { await Navigator.of(context).pushNamed( AppRoutes.subscriptionDetail, arguments: subscription, ); print('DetailScreen 네비게이션 성공'); } catch (e) { print('DetailScreen 네비게이션 오류: $e'); } } /// SMS 스캔 화면으로 네비게이션 static Future toSmsScan(BuildContext context) async { HapticFeedback.lightImpact(); final navigationProvider = context.read(); navigationProvider.updateCurrentIndex(3); await Navigator.of(context).pushNamed(AppRoutes.smsScanner); } /// 설정 화면으로 네비게이션 static Future toSettings(BuildContext context) async { HapticFeedback.lightImpact(); final navigationProvider = context.read(); navigationProvider.updateCurrentIndex(4); await Navigator.of(context).pushNamed(AppRoutes.settings); } /// 카테고리 관리 화면으로 네비게이션 static Future toCategoryManagement(BuildContext context) async { HapticFeedback.lightImpact(); await Navigator.of(context).push( SlidePageRoute( page: const CategoryManagementScreen(), direction: AxisDirection.up, ), ); } /// 앱 잠금 화면으로 네비게이션 static Future toAppLock(BuildContext context) async { await Navigator.of(context).push( MaterialPageRoute( builder: (context) => const AppLockScreen(), fullscreenDialog: true, ), ); } /// 뒤로가기 처리 static Future handleBackButton(BuildContext context) async { final navigator = Navigator.of(context); final navigationProvider = context.read(); // 네비게이션 스택이 있으면 팝 if (navigator.canPop()) { HapticFeedback.lightImpact(); // NavigationProvider의 히스토리를 사용하여 이전 인덱스로 복원 if (navigationProvider.canPop()) { navigationProvider.pop(); } navigator.pop(); return false; } // 앱 종료 확인 final shouldExit = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('앱 종료'), content: const Text('SubManager를 종료하시겠습니까?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('취소'), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('종료'), ), ], ), ); return shouldExit ?? false; } /// 플로팅 네비게이션 바 탭 처리 static void handleFloatingNavTap(BuildContext context, int index) { final navigationProvider = context.read(); final currentIndex = navigationProvider.currentIndex; // 같은 탭을 다시 탭하면 아무 동작 안 함 if (currentIndex == index) { return; } // 현재 화면이 메인이 아니면 먼저 메인으로 돌아가기 if (Navigator.of(context).canPop()) { Navigator.of(context).popUntil((route) => route.isFirst); } // 선택된 인덱스에 따라 네비게이션 switch (index) { case 0: // 홈 navigationProvider.updateCurrentIndex(0); break; case 1: // 분석 toAnalysis(context); break; case 2: // 추가 toAddSubscription(context); break; case 3: // SMS toSmsScan(context); break; case 4: // 설정 toSettings(context); break; } } } /// 네비게이션 관찰자 (디버깅용) class AppNavigationObserver extends NavigatorObserver { @override void didPush(Route route, Route? previousRoute) { super.didPush(route, previousRoute); debugPrint('Navigation: Push ${route.settings.name}'); } @override void didPop(Route route, Route? previousRoute) { super.didPop(route, previousRoute); debugPrint('Navigation: Pop ${route.settings.name}'); } @override void didRemove(Route route, Route? previousRoute) { super.didRemove(route, previousRoute); debugPrint('Navigation: Remove ${route.settings.name}'); } @override void didReplace({Route? newRoute, Route? oldRoute}) { super.didReplace(newRoute: newRoute, oldRoute: oldRoute); debugPrint('Navigation: Replace ${oldRoute?.settings.name} with ${newRoute?.settings.name}'); } }