Files
tripz-llc/apps/driver/lib/controller/home/splash_screen_controlle.dart
T
Hamza-AyedandClaude Opus 5 4d8414c96b feat: استيراد كود سيرو إلى تريبز (سيرو @ecfe7568) — بلا تعديل
قرار المالك 2026-07-27: باك إند سيرو PHP هو المعتمد، وتطبيقاته المجرّبة
ميدانياً تحل محل إعادة البناء المؤرشفة. سيرو نفسه لم يُمسّ.

الخريطة:
  backend · payment_server · loction_server · ride_server ·
  passenger_server · docker · dashboard · stress_test  → الجذر
  siro_rider  → apps/rider          siro_driver  → apps/driver
  siro_admin  → dashboards/admin    siro_service → dashboards/service
  android_bot → apps/android_bot    socialBot    → apps/socialBot

نُسخ المتعقَّب في git سيرو فقط عبر `git archive` (3,198 ملفاً / ~169 م.ب)
لا `cp -r` — فاستُثنيت مخلفات البناء تلقائياً. بلا أي تعديل محتوى عمداً:
كل ما يلي يصير فرقاً مقروءاً مقابل المصدر.

لم يُستورد وسببه: siromove.com (الموقع التسويقي يبقى marketing/ في تريبز،
سيرو فيه 8 ملفات) · docs و planning (تريبز له docs/ الخاص) · deploy.sh
(ليس نشراً على سيرفر بل `git add . && git push origin --all` — فخّ في
مستودع آخر) · transit_dashboard (بانتظار قرار مصير backend-transit و
dashboards/transit-web).

⚠️ لا يبني بعد — ثلاثة نواقص متوقعة ومقصودة:
1. `.env` و `lib/env/env.g.dart` غير متعقَّبين في سيرو (أسرار لكل مستأجر):
   كل تطبيق فلاتر يحتاج .env خاصاً ثم توليد env.g.dart بـ build_runner.
2. إعدادات Firebase (9 ملفات google-services.json و GoogleService-Info.plist)
   يستبعدها .gitignore تريبز — ولكل مستأجر مشروع Firebase خاص أصلاً.
3. apps/driver في سيرو يشير إلى `../../Intaleq/packages/get` خارج المستودع →
   يجب ضمّ الحزم داخله أسوة بـ apps/rider.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 05:14:13 +03:00

168 lines
5.3 KiB
Dart
Executable File

import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:siro_driver/controller/auth/captin/login_captin_controller.dart';
import 'package:siro_driver/views/auth/captin/login_captin.dart';
import 'package:siro_driver/views/home/on_boarding_page.dart';
import '../functions/app_update_controller.dart';
import '../../constant/box_name.dart';
import '../../main.dart';
import '../../onbording_page.dart';
import '../../print.dart';
import '../functions/encrypt_decrypt.dart';
import '../functions/package_info.dart';
import '../functions/secure_storage.dart';
import '../functions/security_checks.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:siro_driver/views/home/home_page.dart';
class SplashScreenController extends GetxController
with GetTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> animation;
final progress = 0.0.obs;
Timer? _progressTimer;
String packageInfo = '';
@override
void onInit() {
super.onInit();
Get.put(AppUpdateController()); // تهيئة متحكم التحديثات الذكي
_setupAnimations();
_initializeAndNavigate();
checkSecurity();
}
checkSecurity() async {
final random = Random();
if (random.nextBool()) {
await SecurityHelper.performSecurityChecks();
} else {
await SecurityChecks.isDeviceRootedFromNative(Get.context!);
}
}
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<void> _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<Widget?> _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 DeviceHelper.getDeviceFingerprint();
await loginController.getJWT();
await loginController.loginDriver(
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<void> _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();
}
}