Files
intaleq/lib/controller/home/splash_screen_controlle.dart
Hamza-Ayed f5dfe2c0fe 25-10-5/1
2025-10-05 14:12:23 +03:00

197 lines
7.1 KiB
Dart

import 'dart:async';
import 'dart:math';
import 'package:Intaleq/controller/functions/crud.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:Intaleq/constant/box_name.dart';
import 'package:Intaleq/onbording_page.dart';
import 'package:Intaleq/views/auth/login_page.dart';
import 'package:Intaleq/controller/auth/login_controller.dart';
import 'package:Intaleq/controller/functions/secure_storage.dart';
import 'package:quick_actions/quick_actions.dart';
import '../../../constant/notification.dart';
import '../../../main.dart';
import '../firebase/firbase_messge.dart';
import '../firebase/local_notification.dart';
import '../functions/encrypt_decrypt.dart';
class SplashScreenController extends GetxController
with GetTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> titleFadeAnimation,
titleScaleAnimation,
taglineFadeAnimation,
footerFadeAnimation;
late Animation<Offset> taglineSlideAnimation;
final progress = 0.0.obs;
Timer? _progressTimer;
@override
void onInit() {
super.onInit();
_animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 2000));
// Animation definitions
titleFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.5, curve: Curves.easeOut)));
titleScaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.0, 0.5, curve: Curves.easeOut)));
taglineFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.3, 0.8, curve: Curves.easeOut)));
taglineSlideAnimation =
Tween<Offset>(begin: const Offset(0, 0.5), end: Offset.zero).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.3, 0.8, curve: Curves.easeOut)));
footerFadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _animationController,
curve: const Interval(0.5, 1.0, curve: Curves.easeOut)));
_animationController.forward();
_initializeApp();
}
Future<void> _initializeApp() async {
_startProgressAnimation();
// Run navigation logic and background services in parallel.
final logicFuture = _performNavigationLogic();
final backgroundServicesFuture = _initializeBackgroundServices();
// Ensure the splash screen is visible for a minimum duration.
final minTimeFuture = Future.delayed(const Duration(seconds: 3));
// Wait for all tasks to complete.
await Future.wait([logicFuture, backgroundServicesFuture, minTimeFuture]);
}
void _startProgressAnimation() {
// Visual timer for the progress bar.
const totalTime = 2800; // ms
const interval = 50; // ms
int elapsed = 0;
_progressTimer =
Timer.periodic(const Duration(milliseconds: interval), (timer) {
elapsed += interval;
progress.value = (elapsed / totalTime).clamp(0.0, 1.0);
if (elapsed >= totalTime) timer.cancel();
});
}
/// Initializes all heavy background services while the splash animation is running.
Future<void> _initializeBackgroundServices() async {
try {
await EncryptionHelper.initialize();
// --- [LAZY LOADING IN ACTION] ---
// This `Get.find()` call will create the NotificationController instance
// for the first time because it was defined with `lazyPut`.
final notificationController = Get.find<NotificationController>();
await notificationController.initNotifications();
// The same happens for FirebaseMessagesController.
final fcm = Get.find<FirebaseMessagesController>();
await fcm.requestFirebaseMessagingPermission();
_scheduleDailyNotifications(notificationController);
_initializeQuickActions();
} catch (e, st) {
CRUD.addError('background_init_error: $e', st.toString(), 'SplashScreen');
}
}
/// Determines the next screen based on user's login state.
Future<void> _performNavigationLogic() async {
await _getPackageInfo();
SecureStorage().saveData('iss', 'mobile-app:');
if (box.read(BoxName.onBoarding) == null) {
Get.off(() => OnBoardingPage());
} else if (box.read(BoxName.email) != null &&
box.read(BoxName.phone) != null &&
box.read(BoxName.isVerified) == '1') {
// `Get.find()` creates the LoginController instance here.
final loginController = Get.find<LoginController>();
// The loginController itself will handle navigation via Get.offAll() upon success.
await loginController.loginUsingCredentials(
box.read(BoxName.passengerID).toString(),
box.read(BoxName.email).toString(),
);
} else {
Get.off(() => LoginPage());
}
}
Future<void> _getPackageInfo() async {
try {
final info = await PackageInfo.fromPlatform();
box.write(BoxName.packagInfo, info.version);
update();
} catch (e) {
print("Could not get package info: $e");
}
}
void _scheduleDailyNotifications(NotificationController controller) {
try {
final List<String> msgs = passengerMessages ?? const [];
if (msgs.isEmpty) {
controller.scheduleNotificationsForSevenDays(
'Intaleq', 'مرحباً بك! تابع رحلاتك بأمان مع انطلق.', "tone1");
} else {
final rnd = Random();
final raw = msgs[rnd.nextInt(msgs.length)];
final parts = raw.split(':');
final title = parts.isNotEmpty ? parts.first.trim() : 'Intaleq';
final body = parts.length > 1
? parts.sublist(1).join(':').trim()
: 'مرحباً بك! تابع رحلاتك بأمان مع انطلق.';
controller.scheduleNotificationsForSevenDays(
title.isEmpty ? 'Intaleq' : title,
body.isEmpty ? 'مرحباً بك! تابع رحلاتك بأمان مع انطلق.' : body,
"tone1");
}
} catch (e, st) {
CRUD.addError('notif_init: $e', st.toString(), 'SplashScreen');
}
}
void _initializeQuickActions() {
final QuickActions quickActions = QuickActions();
quickActions.initialize((String shortcutType) {
Get.toNamed('/$shortcutType');
});
quickActions.setShortcutItems(<ShortcutItem>[
ShortcutItem(
type: 'shareApp', localizedTitle: 'Share App'.tr, icon: 'icon_share'),
ShortcutItem(
type: 'wallet', localizedTitle: 'Wallet'.tr, icon: 'icon_wallet'),
ShortcutItem(
type: 'profile', localizedTitle: 'Profile'.tr, icon: 'icon_user'),
ShortcutItem(
type: 'contactSupport',
localizedTitle: 'Contact Support'.tr,
icon: 'icon_support'),
]);
}
@override
void onClose() {
_progressTimer?.cancel();
_animationController.dispose();
super.onClose();
}
}