import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:onufitness/constants/asset_constants.dart'; import 'package:onufitness/services/logger_service/logger_service.dart'; import 'package:onufitness/routes/route_constant.dart'; import 'package:onufitness/screens/chat/views/call_ui.dart'; import 'package:onufitness/services/deep_link_services/deep_link_service.dart'; import 'package:onufitness/services/local_storage_services/shared_services.dart'; import 'package:onufitness/services/notification_services/navigation_controller.dart'; import 'package:onufitness/widgets/others/mvp_stage_popup.dart'; class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override SplashScreenState createState() => SplashScreenState(); } class SplashScreenState extends State { final logger = LoggerService(); NotificationNavigationController? notifController; DeepLinkService? deepLinkService; @override void initState() { super.initState(); notifController = Get.find(); deepLinkService = Get.find(); WidgetsBinding.instance.addPostFrameCallback((_) async { deepLinkService!.initDeepLinks(); await handleNavigation(); }); } Future handleNavigation() async { // Give post-frame startup handlers a short window to set navigation flags. await Future.delayed( Platform.isIOS ? const Duration(milliseconds: 500) : const Duration(milliseconds: 500), ); // CRITICAL FIX: Poll for flag changes with timeout int retries = 0; const maxRetries = 10; // 10 * 100ms = 1 second max wait while (retries < maxRetries) { final calling = notifController?.isCallingNotificationNavigation.value ?? false; final notification = notifController?.isNotificationNavigation.value ?? false; final deepLink = deepLinkService?.isDeepLinkNavigating.value ?? false; // If any flag is set, stop polling if (calling || notification || deepLink) { return; // Exit early - navigation will be handled } // Wait before next check await Future.delayed(const Duration(milliseconds: 100)); retries++; } // After polling, do final check final calling = notifController?.isCallingNotificationNavigation.value ?? false; final notification = notifController?.isNotificationNavigation.value ?? false; final deepLink = deepLinkService?.isDeepLinkNavigating.value ?? false; if (calling || notification || deepLink) { return; } // Only proceed with normal navigation if NO flags are set final route = SharedServices.isUserDataExist() ? RouteConstant.dashboardScreen : RouteConstant.getStartedScreen; Get.offNamed(route); // Add this for MVP popup logic after navigation if (route == RouteConstant.getStartedScreen) { if (SharedServices.shouldShowMvpPopup()) { await SharedServices.markMvpPopupShownToday(); await Future.delayed(const Duration(milliseconds: 300)); MvpStagePopup.show(); } } } @override Widget build(BuildContext context) { if (notifController == null) { return const Scaffold( body: Center(child: CircularProgressIndicator(color: Colors.black)), ); } return Obx(() { if (notifController!.isCallingNotificationNavigation.value) { return IncomingCallScreen(); } return AnnotatedRegion( value: const SystemUiOverlayStyle( systemNavigationBarColor: Colors.white, statusBarColor: Colors.white, systemNavigationBarIconBrightness: Brightness.dark, statusBarIconBrightness: Brightness.dark, ), child: Scaffold( body: LayoutBuilder( builder: (context, constraints) { bool isTablet = constraints.maxWidth >= 600; return Stack( children: [ Center( child: Image.asset( AssetConstants.appLogo, width: isTablet ? 200.w : 150.w, height: isTablet ? 200.h : 150.h, fit: BoxFit.contain, ), ), Positioned( bottom: isTablet ? 60.h : 60.h, left: 0, right: 0, child: Text( "© 2025 OnUFitness", textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, ), ), ), ], ); }, ), ), ); }); } }