import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart'; import 'package:sefer_driver/views/auth/captin/login_captin.dart'; import 'package:sefer_driver/views/home/on_boarding_page.dart'; import '../../constant/box_name.dart'; import '../../main.dart'; import '../../onbording_page.dart'; import '../../print.dart'; import '../functions/encrypt_decrypt.dart'; import '../functions/secure_storage.dart'; // Assuming you have a home page to navigate to after successful login. // If not, you might need to adjust the navigation target. // import 'package:sefer_driver/views/home/home_page.dart'; class SplashScreenController extends GetxController with GetTickerProviderStateMixin { late AnimationController _animationController; late Animation animation; final progress = 0.0.obs; Timer? _progressTimer; String packageInfo = ''; @override void onInit() { super.onInit(); _setupAnimations(); _initializeAndNavigate(); } void _setupAnimations() { _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 1500), ); animation = CurvedAnimation(parent: _animationController, curve: Curves.easeInOut); _animationController.forward(); } /// This is the core function that initializes the app. /// It runs two tasks simultaneously and navigates only when necessary. Future _initializeAndNavigate() async { // Start getting package info, no need to wait for it. _getPackageInfo(); const minSplashDurationMs = 4000; _animateProgressBar(minSplashDurationMs); // Define the two concurrent tasks final minDuration = Future.delayed(const Duration(milliseconds: minSplashDurationMs)); final navigationTargetFuture = _getNavigationTarget(); // Wait for both tasks to complete await Future.wait([minDuration, navigationTargetFuture]); // The future now returns a nullable Widget (Widget?) final Widget? targetPage = await navigationTargetFuture; // *** FIX: Only navigate if the targetPage is not null. *** // This prevents navigating again if the login function already handled it. if (targetPage != null) { Get.off(() => targetPage, transition: Transition.fadeIn, duration: const Duration(milliseconds: 500)); } else { Log.print( "Navigation was handled internally by the login process. Splash screen will not navigate."); } } /// Animates the progress bar over a given duration. void _animateProgressBar(int totalMilliseconds) { const interval = 50; int elapsed = 0; _progressTimer?.cancel(); _progressTimer = Timer.periodic(const Duration(milliseconds: interval), (timer) { elapsed += interval; progress.value = (elapsed / totalMilliseconds).clamp(0.0, 1.0); if (elapsed >= totalMilliseconds) { timer.cancel(); } }); } /// Determines the correct page to navigate to, or returns null if navigation /// is expected to be handled by an internal process (like login). Future _getNavigationTarget() async { try { // 1) Onboarding final doneOnboarding = box.read(BoxName.onBoarding) == 'yes'; if (!doneOnboarding) { // الأفضل: رجّع الواجهة بدل Get.off داخل الدالة return OnBoardingPage(); } // 2) Login final isDriverDataAvailable = box.read(BoxName.phoneDriver) != null; if (!isDriverDataAvailable) { return LoginCaptin(); } final loginController = Get.put(LoginDriverController()); final AppInitializer initializer = AppInitializer(); await initializer.initializeApp(); await EncryptionHelper.initialize(); await loginController.loginWithGoogleCredential( box.read(BoxName.driverID).toString(), box.read(BoxName.emailDriver).toString(), ); return null; // لأن loginWithGoogleCredential يوجّه } catch (e) { Log.print("Error during navigation logic: $e"); return LoginCaptin(); } } Future _getPackageInfo() async { try { final info = await PackageInfo.fromPlatform(); packageInfo = info.version; await box.write(BoxName.packagInfo, packageInfo); update(); // To update any UI element that might be listening } catch (e) { Log.print("Could not get package info: $e"); packageInfo = '1.0.0'; // Default value await box.write(BoxName.packagInfo, packageInfo); } } @override void onClose() { _progressTimer?.cancel(); _animationController.dispose(); super.onClose(); } }