25-3/12/1

This commit is contained in:
Hamza-Ayed
2025-03-12 15:18:21 +03:00
parent 5a4664ed67
commit a07a1b10ea
603 changed files with 66922 additions and 328 deletions

View File

@@ -29,6 +29,7 @@ import '../../firebase/firbase_messge.dart';
import '../../functions/encrypt_decrypt.dart';
import '../../functions/package_info.dart';
import '../../functions/secure_storage.dart';
import '../../functions/security_checks.dart';
class LoginDriverController extends GetxController {
final formKey = GlobalKey<FormState>();
@@ -94,7 +95,13 @@ class LoginDriverController extends GetxController {
var dev = '';
getJwtWallet() async {
await SecurityHelper.performSecurityChecks();
final random = Random();
if (random.nextBool()) {
await SecurityHelper.performSecurityChecks();
} else {
await SecurityChecks.isDeviceRootedFromNative(Get.context!);
}
String fingerPrint = await getDeviceFingerprint();
dev = Platform.isAndroid ? 'android' : 'ios';
var payload = {
@@ -365,7 +372,8 @@ class LoginDriverController extends GetxController {
'email': EncryptionHelper.instance.encryptData(email),
'password': password,
});
box.write(BoxName.emailDriver, (email).toString());
box.write(BoxName.emailDriver,
EncryptionHelper.instance.decryptData(email).toString());
print(res);
if (res == 'failure') {
//Failure

View File

@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
@@ -235,7 +236,7 @@ class SecurityHelper {
// debugPrint("Bundle ID: $bundleId"); // Print the bundle ID
// Check for security risks and potentially show a warning
if (isJailBroken || isNotTrust || !isRealDevice || isTampered) {
if (isJailBroken || isRealDevice == false || isTampered) {
// print("security_warning".tr); //using easy_localization
// Use a more robust approach to show a warning, like a dialog:
_showSecurityWarning();
@@ -249,30 +250,89 @@ class SecurityHelper {
exit(0); // This will terminate the app. Be VERY careful with this.
}
// static void _showSecurityWarning() {
// // Show a dialog, navigate to an error screen, etc.
// // Example using Get.dialog (if you use GetX):
//
// Get.dialog(
// AlertDialog(
// title: Text("Security Warning".tr), // Or use localized string
// content: Text(
// "Potential security risks detected. The application may not function correctly."
// .tr), //Or use localized string
// actions: [
// TextButton(
// onPressed: () async {
// await storage.deleteAll();
// await box.erase();
// Get.back(); // Close the dialog
// // Or, if you really must, exit the app (but give the user a chance!)
// exit(0);
// },
// child: Text("OK"), // Or use a localized string
// ),
// ],
// ),
// barrierDismissible: false, // Prevent closing by tapping outside
// );
// }
static void _showSecurityWarning() {
// Show a dialog, navigate to an error screen, etc.
// Example using Get.dialog (if you use GetX):
// Use an RxInt to track the remaining seconds. This is the KEY!
RxInt secondsRemaining = 10.obs;
Get.dialog(
AlertDialog(
title: Text("Security Warning".tr), // Or use localized string
content: Text(
"Potential security risks detected. The application may not function correctly."
.tr), //Or use localized string
actions: [
TextButton(
onPressed: () async {
await storage.deleteAll();
await box.erase();
Get.back(); // Close the dialog
// Or, if you really must, exit the app (but give the user a chance!)
exit(0);
},
child: Text("OK"), // Or use a localized string
),
],
CupertinoAlertDialog(
title: Text("Security Warning".tr),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Obx(() => Text(
"Potential security risks detected. The application will close in @seconds seconds."
.trParams({
// Use trParams for placeholders
'seconds': secondsRemaining.value.toString(),
}),
// Wrap the Text widget in Obx
)),
SizedBox(height: 24), // More spacing before the progress bar
Obx(() => SizedBox(
width: double.infinity, // Make progress bar full width
child: CupertinoActivityIndicator(
// in case of loading
radius: 15,
animating: true,
))),
SizedBox(height: 8),
Obx(() => ClipRRect(
borderRadius: BorderRadius.circular(8), // Rounded corners
child: LinearProgressIndicator(
value: secondsRemaining.value / 10,
backgroundColor: Colors.grey.shade300, // Lighter background
valueColor: AlwaysStoppedAnimation<Color>(
CupertinoColors.systemRed), // iOS-style red
minHeight: 8, // Slightly thicker progress bar
),
)),
],
),
),
barrierDismissible: false, // Prevent closing by tapping outside
barrierDismissible: false,
);
Timer.periodic(Duration(seconds: 1), (timer) {
secondsRemaining.value--;
if (secondsRemaining.value <= 0) {
timer.cancel();
// Get.back();
_clearDataAndExit();
}
});
}
static Future<void> _clearDataAndExit() async {
await storage.deleteAll();
await box.erase();
exit(0); // Exit the app
print('exit');
}
}

View File

@@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
class SecurityChecks {
static const platform = MethodChannel(
'com.sefer_driver/security'); // Choose a unique channel name
static Future<bool> isDeviceCompromised() async {
try {
final bool result = await platform
.invokeMethod('isNativeRooted'); // Invoke the native method
return result;
} on PlatformException catch (e) {
print("Failed to check security status: ${e.message}");
return true; // Treat platform errors as a compromised device (for safety)
}
}
static isDeviceRootedFromNative(BuildContext context) async {
bool compromised = await isDeviceCompromised();
if (compromised) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => AlertDialog(
title: Text("Security Warning".tr),
content: Text(
"Your device appears to be compromised. The app will now close."
.tr),
actions: [
TextButton(
onPressed: () {
SystemNavigator.pop(); // Close the app
},
child: Text("OK"),
),
],
),
);
} else {
// Continue with normal app flow
print("Device is secure.");
}
}
}

View File

@@ -66,6 +66,9 @@ class MyTranslation extends Translations {
//firebase above
"cancel": "إلغاء",
"Security Warning": "تحذير أمني",
"Potential security risks detected. The application will close in @seconds seconds.":
"تم اكتشاف مخاطر أمنية محتملة. سيتم إغلاق التطبيق خلال @seconds ثانية.",
'please order now': " ‏الرجاء الطلب مرة أخرى",
'Session expired. Please log in again.':
'انتهت الجلسة. يرجى تسجيل الدخول مرة أخرى.',

View File

@@ -25,7 +25,6 @@ import 'controller/firebase/local_notification.dart';
import 'controller/functions/encrypt_decrypt.dart';
import 'controller/functions/location_controller.dart';
import 'controller/functions/secure_storage.dart';
import 'controller/home/payment/captain_wallet_controller.dart';
import 'controller/local/local_controller.dart';
import 'controller/local/translations.dart';
import 'controller/payment/paymob/paymob_wallet.dart';
@@ -123,76 +122,92 @@ Future<void> closeOverLay() async {
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await WakelockPlus.enable();
await GetStorage.init();
final AppInitializer initializer = AppInitializer();
await initializer.initializeApp();
await Future.delayed(Duration.zero);
await EncryptionHelper.initialize();
Stripe.publishableKey = AK.publishableKeyStripe;
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
PermissionStatus status1 = await Permission.location.status;
// if (status1.isGranted) {
await LocationController().startLocationUpdates();
// }
if (Platform.isAndroid || Platform.isIOS) {
NotificationController notificationController =
Get.put(NotificationController());
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await FirebaseMessagesController().requestFirebaseMessagingPermission();
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
await notificationController.initNotifications();
// Generate a random index to pick a message
final random = Random();
final randomMessage = driverMessages[random.nextInt(driverMessages.length)];
// Schedule the notification with the random message
notificationController.scheduleNotificationsForSevenDays(
randomMessage.split(':')[0],
randomMessage.split(':')[1],
"ding",
);
await Future.wait([
FirebaseMessagesController().getNotificationSettings(),
FirebaseMessagesController().getToken(),
]);
// await FacebookAuth.instance.init();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
String? key = (await storage.read(key: BoxName.payMobApikey));
String? apiKey = EncryptionHelper.instance.decryptData(key!);
PaymobPayment.instance.initialize(
apiKey: apiKey,
integrationID: int.parse(AK.integrationIdPayMob),
userTokenExpiration: 200,
iFrameID: 837992,
);
PaymobPaymentWallet.instance.initialize(
apiKey: apiKey,
integrationID: int.parse(AK.integrationIdPayMobWallet),
userTokenExpiration: 200,
iFrameID: 837992,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
_initApp();
}
Future<void> _initApp() async {
try {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform);
final AppInitializer initializer = AppInitializer();
await initializer.initializeApp();
await EncryptionHelper.initialize();
if (Platform.isAndroid || Platform.isIOS) {
Get.put(
NotificationController()); // Initialize NotificationController here
await FirebaseMessaging.instance.requestPermission();
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
await NotificationController().initNotifications();
// Generate a random index to pick a message
final random = Random();
final randomMessage =
driverMessages[random.nextInt(driverMessages.length)];
// Schedule the notification with the random message
NotificationController().scheduleNotificationsForSevenDays(
randomMessage.split(':')[0],
randomMessage.split(':')[1],
"ding",
);
await Future.wait([
FirebaseMessagesController().getNotificationSettings(),
FirebaseMessagesController().getToken(),
]);
PermissionStatus status1 = await Permission.location.status;
if (status1.isGranted) {
await LocationController().startLocationUpdates();
}
}
String? key = (await storage.read(key: BoxName.payMobApikey));
if (key != null) {
String? apiKey = EncryptionHelper.instance.decryptData(key);
if (apiKey != null) {
PaymobPayment.instance.initialize(
// Use .instance
apiKey: apiKey,
integrationID: int.parse(AK.integrationIdPayMob),
userTokenExpiration: 200,
iFrameID: 837992,
);
PaymobPaymentWallet.instance.initialize(
// Use .instance
apiKey: apiKey,
integrationID: int.parse(AK.integrationIdPayMobWallet),
userTokenExpiration: 200,
iFrameID: 837992,
);
}
}
} catch (e) {
print("Error initializing app: $e");
// Handle initialization errors appropriately. Maybe show an error message to the user.
}
}
@override
Widget build(BuildContext context) {
LocaleController localController = Get.put(LocaleController());
@@ -215,3 +230,99 @@ class MyApp extends StatelessWidget {
);
}
}
// void main() async {
// WidgetsFlutterBinding.ensureInitialized();
// await WakelockPlus.enable();
//
// await GetStorage.init();
//
// final AppInitializer initializer = AppInitializer();
//
// await initializer.initializeApp();
// await Future.delayed(Duration.zero);
// await EncryptionHelper.initialize();
//
// Stripe.publishableKey = AK.publishableKeyStripe;
//
// PermissionStatus status1 = await Permission.location.status;
// // if (status1.isGranted) {
// await LocationController().startLocationUpdates();
// // }
//
// if (Platform.isAndroid || Platform.isIOS) {
// NotificationController notificationController =
// Get.put(NotificationController());
// await Firebase.initializeApp(
// options: DefaultFirebaseOptions.currentPlatform,
// );
// await FirebaseMessagesController().requestFirebaseMessagingPermission();
//
// FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
//
// await notificationController.initNotifications();
//
// // Generate a random index to pick a message
// final random = Random();
// final randomMessage = driverMessages[random.nextInt(driverMessages.length)];
//
// // Schedule the notification with the random message
// notificationController.scheduleNotificationsForSevenDays(
// randomMessage.split(':')[0],
// randomMessage.split(':')[1],
// "ding",
// );
//
// await Future.wait([
// FirebaseMessagesController().getNotificationSettings(),
// FirebaseMessagesController().getToken(),
// ]);
// // await FacebookAuth.instance.init();
// SystemChrome.setPreferredOrientations([
// DeviceOrientation.portraitUp,
// DeviceOrientation.portraitDown,
// ]);
// }
//
// String? key = (await storage.read(key: BoxName.payMobApikey));
//
// String? apiKey = EncryptionHelper.instance.decryptData(key!);
// PaymobPayment.instance.initialize(
// apiKey: apiKey,
// integrationID: int.parse(AK.integrationIdPayMob),
// userTokenExpiration: 200,
// iFrameID: 837992,
// );
//
// PaymobPaymentWallet.instance.initialize(
// apiKey: apiKey,
// integrationID: int.parse(AK.integrationIdPayMobWallet),
// userTokenExpiration: 200,
// iFrameID: 837992,
// );
// runApp(MyApp());
// }
//
// class MyApp extends StatelessWidget {
// @override
// Widget build(BuildContext context) {
// LocaleController localController = Get.put(LocaleController());
// return GetMaterialApp(
// navigatorKey: navigatorKey,
// title: AppInformation.appName,
// translations: MyTranslation(),
// debugShowCheckedModeBanner: false,
// locale: localController.language,
// theme: localController.appTheme,
// initialRoute: '/',
// getPages: [
// GetPage(name: '/', page: () => SplashScreen()),
// GetPage(
// name: '/order-page',
// page: () => OrderRequestPage(),
// arguments: box.read(BoxName.rideArguments),
// ),
// ],
// );
// }
// }

View File

@@ -0,0 +1,66 @@
// lib/models/order_data.dart
class OrderData {
final String customerName;
final double distance;
final String price;
final String startLocation;
final String endLocation;
final String passengerDistance;
final String duration;
final String rideType;
final String orderId;
final String passengerId;
final String passengerRate;
OrderData({
required this.customerName,
required this.distance,
required this.price,
required this.startLocation,
required this.endLocation,
required this.passengerDistance,
required this.duration,
required this.rideType,
required this.orderId,
required this.passengerId,
required this.passengerRate,
});
// Factory constructor to create an OrderData instance from a List<dynamic>.
// This handles parsing and provides default values for safety.
factory OrderData.fromList(List<dynamic> list) {
return OrderData(
customerName: list.length > 8 ? list[8].toString() : 'Unknown Customer',
distance:
list.length > 5 ? (double.tryParse(list[5].toString()) ?? 0.0) : 0.0,
price: list.length > 2 ? list[2].toString().split('.')[0] : '0',
startLocation: list.length > 29 ? list[29].toString() : 'Unknown',
endLocation: list.length > 30 ? list[30].toString() : 'Unknown',
passengerDistance: list.length > 12 ? list[12].toString() : 'Unknown',
duration: list.length > 4
? (double.parse(list[4].toString()) / 60).toStringAsFixed(0)
: 'Unknown',
rideType:
list.length > 31 ? _getRideType(list[31].toString()) : 'Unknown',
orderId: list.length > 16 ? list[16].toString() : 'Unknown',
passengerId: list.length > 7 ? list[7].toString() : 'Unknown',
passengerRate: list.length > 33 ? list[33].toString() : 'Unknown',
);
}
static String _getRideType(String type) {
switch (type) {
case 'Comfort':
return '‏كمفورت ❄️';
case 'Lady':
return '‏ليدي 👩';
case 'Speed':
return '‏‏‏سبيد 🔻';
case 'Mashwari':
return '‏مشواري';
case 'Rayeh Gai':
return 'رايح جاي';
default:
return '';
}
}
}

View File

@@ -17,6 +17,8 @@ import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart
import '../../../../../constant/colors.dart';
import '../../../../../controller/functions/face_detect.dart';
import '../../../../../controller/functions/location_controller.dart';
import '../../../../../controller/functions/package_info.dart';
import '../../../../../controller/functions/security_checks.dart';
import '../../../../../print.dart';
import '../../../../Rate/ride_calculate_driver.dart';
@@ -110,30 +112,13 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
child: Builder(builder: (context) {
return IconButton(
onPressed: () async {
// String shortHash(String password) {
// var bytes = utf8.encode(password);
// var digest = sha256.convert(bytes);
// return base64UrlEncode(digest.bytes);
// }
final random = Random();
// String password =
// '${EncryptionHelper.instance.decryptData(box.read(BoxName.emailDriver))}${box.read(BoxName.driverID)}';
// String hashedPassword = shortHash(password);
// Log.print('password: ${password}');
// print("Hashed Password: $hashedPassword");
Location location = Location();
LocationData _locationData = await location.getLocation();
Log.print('location: ${_locationData}');
print(
'Location: ${controller.myLocation.latitude}, ${controller.myLocation.longitude}');
var status1 = await Permission.location.status;
Log.print('status1: ${status1}');
// if (status1.isGranted) {
await LocationController().startLocationUpdates();
// } else {
// // openAppSettings();
// await Permission.locationAlways.request();
// }
if (random.nextBool()) {
await SecurityHelper.performSecurityChecks();
} else {
await SecurityChecks.isDeviceRootedFromNative(Get.context!);
}
},
icon: const Icon(
FontAwesome5.grin_tears,

View File

@@ -1,14 +1,400 @@
// import 'dart:async';
// import 'package:sefer_driver/constant/colors.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter_overlay_window/flutter_overlay_window.dart';
// import 'package:get/get.dart';
// import 'package:just_audio/just_audio.dart';
// import '../../../../constant/box_name.dart';
// import '../../../../constant/links.dart';
// import '../../../../constant/style.dart';
// import '../../../../controller/functions/crud.dart';
// import '../../../../main.dart';
// import '../../../../print.dart';
//
// class OrderOverlay extends StatefulWidget {
// const OrderOverlay({Key? key}) : super(key: key);
//
// @override
// State<OrderOverlay> createState() => _OrderOverlayState();
// }
//
// class _OrderOverlayState extends State<OrderOverlay>
// with WidgetsBindingObserver {
// List d = [];
// Timer? _timer;
// double _progress = 1.0;
// bool _isOverlayActive = false;
// final AudioPlayer _audioPlayer = AudioPlayer();
//
// @override
// void initState() {
// super.initState();
// WidgetsBinding.instance.addObserver(this);
// _setupOverlayListener();
// }
//
// void _setupOverlayListener() {
// FlutterOverlayWindow.overlayListener.listen((event) {
// if (mounted) {
// setState(() {
// d = event;
// _resetAndStartTimer();
// });
// }
// });
// }
//
// @override
// void didChangeAppLifecycleState(AppLifecycleState state) {
// if (state == AppLifecycleState.resumed) {
// _checkOverlayStatus();
// }
// }
//
// void _checkOverlayStatus() async {
// bool isActive = await FlutterOverlayWindow.isActive();
// if (isActive && mounted) {
// _resetAndStartTimer();
// }
// }
//
// void _resetAndStartTimer() {
// _timer?.cancel();
// setState(() {
// _progress = 1.0;
// _isOverlayActive = true;
// });
// _playAudio();
// _startTimer();
// }
//
// void _startTimer() {
// _timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
// if (!_isOverlayActive) {
// timer.cancel();
// _stopAudio();
// return;
// }
// if (mounted) {
// setState(() {
// _progress -=
// 1 / 100; // Decrease progress over 15 seconds (150 * 100ms)
// if (_progress <= 0) {
// timer.cancel();
// _rejectOrder();
// _stopAudio();
// }
// });
// }
// });
// }
//
// void _playAudio() async {
// try {
// await _audioPlayer.setAsset(
// 'assets/order.mp3',
// preload: true,
// initialPosition: Duration.zero,
// );
// await _audioPlayer.play();
// } catch (e) {
// print('An error occurred while playing the audio: $e');
// }
// }
//
// void _stopAudio() {
// _audioPlayer.stop();
// }
//
// @override
// void dispose() {
// _timer?.cancel();
// _stopAudio();
// WidgetsBinding.instance.removeObserver(this);
// super.dispose();
// }
//
// void refuseOrder(
// orderID,
// ) async {
// await CRUD().postFromDialogue(link: AppLink.addDriverOrder, payload: {
// //TODO need review
// 'driver_id': box.read(BoxName.driverID),
// // box.read(BoxName.driverID).toString(),
// 'order_id': orderID,
// 'status': 'Refused'
// });
// await CRUD().post(link: AppLink.updateRides, payload: {
// 'id': orderID,
// // 'rideTimeStart': DateTime.now().toString(),
// 'status': 'Refused',
// 'driver_id': box.read(BoxName.driverID),
// });
// }
//
// addRideToNotificationDriverString(
// orderID,
// String startLocation,
// String endLocation,
// String date,
// String time,
// String price,
// String passengerId,
// String status,
// String carType,
// String passengerRate,
// String priceForPassenger,
// String distance,
// String duration,
// ) async {
// await CRUD().post(link: AppLink.addWaitingRide, payload: {
// 'id': orderID,
// 'start_location': startLocation,
// 'end_location': endLocation,
// 'date': date,
// 'time': time,
// 'price': price,
// 'passenger_id': passengerId,
// 'status': status,
// 'carType': carType,
// 'passengerRate': passengerRate,
// 'price_for_passenger': priceForPassenger,
// 'distance': distance,
// 'duration': duration,
// });
// }
//
// @override
// Widget build(BuildContext context) {
// String duration = (double.parse(d[4].toString()) / 60).toStringAsFixed(0);
// Log.print('duration: ${duration}');
// String price = d[2].toString().split('.')[0];
// return Material(
// color: Colors.transparent,
// child: Center(
// child: Container(
// padding: const EdgeInsets.all(12.0),
// width: double.infinity,
// height: 450, // Adjust height as needed
// decoration: BoxDecoration(
// gradient: const LinearGradient(colors: [
// AppColor.blueColor,
// AppColor.blueColor,
// ]),
// borderRadius: BorderRadius.circular(12.0),
// ),
// child: GestureDetector(
// onTap: () async {
// bool isOverlayActive = await FlutterOverlayWindow.isActive();
// if (isOverlayActive) {
// await FlutterOverlayWindow.closeOverlay();
// }
// },
// child: ListView(
// // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// children: [
// ListTile(
// leading: _buildPriceAvatar(price),
// title: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Text(
// d.isNotEmpty ? d[8] : '', // Customer name
// style: const TextStyle(
// fontSize: 16,
// fontWeight: FontWeight.bold,
// color: AppColor.secondaryColor,
// ),
// ),
// Container(
// decoration: BoxDecoration(
// border: Border.all(
// color: AppColor.redColor, width: 2)),
// child: Padding(
// padding: const EdgeInsets.all(3),
// child: Text(
// "${d[5]} KM",
// style: AppStyle.number.copyWith(
// color: AppColor.secondaryColor, fontSize: 18),
// ),
// )),
// const Text('🛣️')
// ],
// ),
// // subtitle: Text(d.isNotEmpty ? d[10] : ''), // Phone number
// ),
// Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// _buildDetailRow("🟢", d.isNotEmpty ? d[29] : ''),
// _buildDetailRow("🔴".tr, d.isNotEmpty ? d[30] : ''),
// _buildDetailRow(
// "‏المسافة للراكب", d.isNotEmpty ? d[12] : ''),
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// _buildDetailRow("‏مدة الرحلة".tr, '$duration '),
// _buildDetailRow("‏نوع الطلب".tr, _getRideType(d[31]))
// ],
// ),
// const SizedBox(
// height: 30,
// ),
// const SizedBox(height: 8),
// LinearProgressIndicator(
// value: _progress,
// minHeight: 15,
// backgroundColor: Colors.white.withOpacity(0.3),
// valueColor:
// const AlwaysStoppedAnimation<Color>(Colors.white),
// ),
// ],
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
//
// Widget _buildDetailRow(String label, String value) {
// return Padding(
// padding: const EdgeInsets.symmetric(vertical: 2.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: [
// Text(
// value,
// style: AppStyle.title.copyWith(color: AppColor.secondaryColor),
// ),
// Text(
// label,
// style: const TextStyle(
// fontWeight: FontWeight.bold, color: AppColor.secondaryColor),
// ),
// ],
// ),
// );
// }
//
// Widget _buildPriceAvatar(String price) {
// return Container(
// width: 80,
// height: 80,
// decoration: BoxDecoration(
// shape: BoxShape.circle,
// gradient: const RadialGradient(
// colors: [Color(0xFF4CAF50), Color(0xFF2E7D32)],
// center: Alignment.center,
// radius: 0.8,
// ),
// boxShadow: [
// BoxShadow(
// color: Colors.black.withOpacity(0.2),
// blurRadius: 8,
// offset: const Offset(0, 4),
// ),
// ],
// ),
// child: Center(
// child: Text(
// '\$$price',
// style: const TextStyle(
// fontSize: 22,
// fontWeight: FontWeight.bold,
// color: Colors.white,
// ),
// ),
// ),
// );
// }
//
// Widget _buildInfoRow(IconData icon, String label, String value) {
// return Padding(
// padding: const EdgeInsets.symmetric(vertical: 8.0),
// child: Row(
// children: [
// Icon(icon, color: Colors.white.withOpacity(0.8), size: 24),
// const SizedBox(width: 12),
// Expanded(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// label,
// style: TextStyle(
// color: Colors.white.withOpacity(0.8), fontSize: 14),
// ),
// Text(
// value,
// style: const TextStyle(
// color: Colors.white,
// fontSize: 16,
// fontWeight: FontWeight.bold),
// ),
// ],
// ),
// ),
// ],
// ),
// );
// }
//
// String _getRideType(String type) {
// switch (type) {
// case 'Comfort':
// return '‏كمفورت ❄️';
// case 'Lady':
// return '‏ليدي 👩';
// case 'Speed':
// return '‏‏‏سبيد 🔻';
// case 'Mashwari':
// return '‏مشواري';
// case 'Rayeh Gai':
// return 'رايح جاي';
// default:
// return '';
// }
// }
//
// void _rejectOrder() async {
// box.write(BoxName.rideStatus, 'reject');
// refuseOrder(
// d[16].toString(),
// );
// addRideToNotificationDriverString(
// d[16].toString(),
// d[29].toString(),
// d[30].toString(),
// '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}',
// '${DateTime.now().hour}:${DateTime.now().minute}',
// d[2].toString(),
// d[7].toString(),
// 'wait',
// d[31].toString(),
// d[33].toString(),
// d[2].toString(),
// d[5].toString(),
// d[4].toString()); //
// bool isOverlayActive = await FlutterOverlayWindow.isActive();
// if (isOverlayActive) {
// await FlutterOverlayWindow.closeOverlay();
// }
// }
// }
import 'dart:async';
import 'package:sefer_driver/constant/colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import 'package:get/get.dart';
import 'package:get/get.dart'; // If you're using GetX for translations
import 'package:just_audio/just_audio.dart';
import '../../../../constant/box_name.dart';
import '../../../../constant/box_name.dart'; //
import '../../../../constant/links.dart';
import '../../../../constant/style.dart';
import '../../../../controller/functions/crud.dart';
import '../../../../main.dart';
import '../../../../models/model/order_data.dart';
import '../../../../print.dart';
class OrderOverlay extends StatefulWidget {
@@ -20,7 +406,7 @@ class OrderOverlay extends StatefulWidget {
class _OrderOverlayState extends State<OrderOverlay>
with WidgetsBindingObserver {
List d = [];
OrderData? _orderData; // Use the OrderData model
Timer? _timer;
double _progress = 1.0;
bool _isOverlayActive = false;
@@ -36,13 +422,22 @@ class _OrderOverlayState extends State<OrderOverlay>
void _setupOverlayListener() {
FlutterOverlayWindow.overlayListener.listen((event) {
if (mounted) {
setState(() {
d = event;
_resetAndStartTimer();
});
// Check if the event is a List<dynamic>
if (event is List<dynamic>) {
setState(() {
_orderData = OrderData.fromList(event); // Parse the list
_resetAndStartTimer();
});
} else {
// Handle unexpected data format. Maybe log an error.
print("Error: Received unexpected data format in overlay: $event");
}
}
});
}
// ... (rest of your methods: didChangeAppLifecycleState, _checkOverlayStatus,
// _resetAndStartTimer, _startTimer remain mostly the same. Just make sure
// to use _orderData?.property where appropriate) ...
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
@@ -110,43 +505,40 @@ class _OrderOverlayState extends State<OrderOverlay>
void dispose() {
_timer?.cancel();
_stopAudio();
_audioPlayer.dispose(); // Dispose the player
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
void refuseOrder(
orderID,
) async {
void refuseOrder(String orderID) async {
await CRUD().postFromDialogue(link: AppLink.addDriverOrder, payload: {
//TODO need review
'driver_id': box.read(BoxName.driverID),
// box.read(BoxName.driverID).toString(),
'order_id': orderID,
'status': 'Refused'
});
await CRUD().post(link: AppLink.updateRides, payload: {
'id': orderID,
// 'rideTimeStart': DateTime.now().toString(),
'status': 'Refused',
'driver_id': box.read(BoxName.driverID),
});
}
addRideToNotificationDriverString(
orderID,
String startLocation,
String endLocation,
String date,
String time,
String price,
String passengerId,
String status,
String carType,
String passengerRate,
String priceForPassenger,
String distance,
String duration,
) async {
addRideToNotificationDriverString({
required String orderID,
required String startLocation,
required String endLocation,
required String date,
required String time,
required String price,
required String passengerId,
required String status,
required String carType,
required String passengerRate,
required String priceForPassenger,
required String distance,
required String duration,
}) async {
await CRUD().post(link: AppLink.addWaitingRide, payload: {
'id': orderID,
'start_location': startLocation,
@@ -166,16 +558,28 @@ class _OrderOverlayState extends State<OrderOverlay>
@override
Widget build(BuildContext context) {
String duration = (double.parse(d[4].toString()) / 60).toStringAsFixed(0);
Log.print('duration: ${duration}');
String price = d[2].toString().split('.')[0];
if (_orderData == null) {
// Show a loading indicator or an empty state while waiting for data.
return Material(
color: Colors.transparent,
child: Container(
color: Colors.black.withOpacity(0.5),
child: Center(child: CircularProgressIndicator()),
),
);
}
// Access data using the model's properties:
final orderData =
_orderData!; // Safe to use ! because of the null check above
return Material(
color: Colors.transparent,
child: Center(
child: Container(
padding: const EdgeInsets.all(12.0),
width: double.infinity,
height: 450, // Adjust height as needed
height: 450,
decoration: BoxDecoration(
gradient: const LinearGradient(colors: [
AppColor.blueColor,
@@ -191,15 +595,14 @@ class _OrderOverlayState extends State<OrderOverlay>
}
},
child: ListView(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ListTile(
leading: _buildPriceAvatar(price),
leading: _buildPriceAvatar(orderData.price),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
d.isNotEmpty ? d[8] : '', // Customer name
orderData.customerName,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
@@ -207,39 +610,37 @@ class _OrderOverlayState extends State<OrderOverlay>
),
),
Container(
decoration: BoxDecoration(
border: Border.all(
color: AppColor.redColor, width: 2)),
child: Padding(
padding: const EdgeInsets.all(3),
child: Text(
"${d[5]} KM",
style: AppStyle.number.copyWith(
color: AppColor.secondaryColor, fontSize: 18),
),
)),
decoration: BoxDecoration(
border:
Border.all(color: AppColor.redColor, width: 2)),
child: Padding(
padding: const EdgeInsets.all(3),
child: Text(
"${orderData.distance} KM",
style: AppStyle.number.copyWith(
color: AppColor.secondaryColor, fontSize: 18),
),
),
),
const Text('🛣️')
],
),
// subtitle: Text(d.isNotEmpty ? d[10] : ''), // Phone number
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildDetailRow("🟢", d.isNotEmpty ? d[29] : ''),
_buildDetailRow("🔴".tr, d.isNotEmpty ? d[30] : ''),
_buildDetailRow("🟢", orderData.startLocation),
_buildDetailRow("🔴".tr, orderData.endLocation),
_buildDetailRow(
"‏المسافة للراكب", d.isNotEmpty ? d[12] : ''),
"‏المسافة للراكب", orderData.passengerDistance),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildDetailRow("‏مدة الرحلة".tr, '$duration '),
_buildDetailRow("‏نوع الطلب".tr, _getRideType(d[31]))
_buildDetailRow("‏مدة الرحلة".tr, orderData.duration),
_buildDetailRow("‏نوع الطلب".tr, orderData.rideType)
],
),
const SizedBox(
height: 30,
),
const SizedBox(height: 30),
const SizedBox(height: 8),
LinearProgressIndicator(
value: _progress,
@@ -257,6 +658,8 @@ class _OrderOverlayState extends State<OrderOverlay>
),
);
}
// ... (rest of your helper methods: _buildDetailRow, _buildPriceAvatar,
// _buildInfoRow. Update them to use orderData.property) ...
Widget _buildDetailRow(String label, String value) {
return Padding(
@@ -341,42 +744,29 @@ class _OrderOverlayState extends State<OrderOverlay>
);
}
String _getRideType(String type) {
switch (type) {
case 'Comfort':
return '‏كمفورت ❄️';
case 'Lady':
return '‏ليدي 👩';
case 'Speed':
return '‏‏‏سبيد 🔻';
case 'Mashwari':
return '‏مشواري';
case 'Rayeh Gai':
return 'رايح جاي';
default:
return '';
}
}
void _rejectOrder() async {
box.write(BoxName.rideStatus, 'reject');
refuseOrder(
d[16].toString(),
);
addRideToNotificationDriverString(
d[16].toString(),
d[29].toString(),
d[30].toString(),
'${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}',
'${DateTime.now().hour}:${DateTime.now().minute}',
d[2].toString(),
d[7].toString(),
'wait',
d[31].toString(),
d[33].toString(),
d[2].toString(),
d[5].toString(),
d[4].toString()); //
if (_orderData != null) {
// Check for null
refuseOrder(_orderData!.orderId);
addRideToNotificationDriverString(
orderID: _orderData!.orderId,
startLocation: _orderData!.startLocation,
endLocation: _orderData!.endLocation,
date:
'${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}',
time: '${DateTime.now().hour}:${DateTime.now().minute}',
price: _orderData!.price,
passengerId: _orderData!.passengerId,
status: 'wait',
carType: _orderData!.rideType,
passengerRate: _orderData!.passengerRate,
priceForPassenger: _orderData!.price,
distance: _orderData!.distance.toString(),
duration: _orderData!.duration,
);
}
bool isOverlayActive = await FlutterOverlayWindow.isActive();
if (isOverlayActive) {
await FlutterOverlayWindow.closeOverlay();