2026-04-03-pre map libra

This commit is contained in:
Hamza-Ayed
2026-04-04 00:12:33 +03:00
parent 0376a835ce
commit cbb1620874
70 changed files with 933 additions and 787 deletions

View File

@@ -20,39 +20,57 @@ android {
compileSdk = 36
ndkVersion "29.0.14033849"
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
// Using a common, stable version. Your CMakeLists.txt requests 3.10.2,
// but your old gradle file had 3.22.1 and 3.31.5. Let's use a stable one.
version "3.22.1"
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
coreLibraryDesugaringEnabled true
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
jvmTarget = JavaVersion.VERSION_17
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.22.1"
}
}
// تمت الإضافة: توجيه مسار المكتبات الأصلية لمطابقة تطبيق الراكب
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
// Merged the two defaultConfig sections into one. This is the correct way.
defaultConfig {
applicationId = "com.intaleq_driver"
minSdkVersion = flutter.minSdkVersion
targetSdk = 36
versionCode = 59
versionName = '1.1.59' // I've used the higher version name
versionCode = 61
versionName = '1.1.61'
multiDexEnabled = true
ndk {
abiFilters "armeabi-v7a", "arm64-v8a" // Keep these!
abiFilters "armeabi-v7a", "arm64-v8a"
}
manifestPlaceholders += [mapsApiKey: keystoreProperties['mapsApiKey'] ?: ""]
// تمت الإضافة: تمرير تعليمات 16 KB لمترجم C++
externalNativeBuild {
cmake {
arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
}
}
}
// تمت الإضافة: منع ضغط المكتبات لتتوافق مع متطلبات نظام التشغيل
packaging {
jniLibs {
useLegacyPackaging = false
}
}
signingConfigs {
@@ -80,9 +98,17 @@ flutter {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// تمت الترقية لتطابق تطبيق الراكب
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
// تمت الترقية لتطابق تطبيق الراكب (لتجنب ملفات 4KB القديمة)
implementation "com.stripe:stripe-android:21.4.2"
implementation 'com.stripe:paymentsheet:21.4.2'
implementation 'com.scottyab:rootbeer-lib:0.1.0'
implementation 'com.stripe:paymentsheet:20.52.2'
implementation "androidx.concurrent:concurrent-futures:1.2.0" // Added this from your first file, it was missing
implementation 'com.google.android.gms:play-services-safetynet:18.0.1'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
// تمت الترقية لتطابق تطبيق الراكب
implementation 'com.google.android.gms:play-services-safetynet:18.1.0'
implementation "androidx.concurrent:concurrent-futures:1.2.0"
}

View File

@@ -1,11 +1,11 @@
buildscript {
ext.kotlin_version = '2.1.0'
ext.kotlin_version = '2.3.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.1.0'
classpath 'com.android.tools.build:gradle:8.13.2'
classpath 'com.google.gms:google-services:4.3.15'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
@@ -22,10 +22,29 @@ rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
project.evaluationDependsOn(':app')
def setupAndroid = {
if (project.plugins.hasPlugin('com.android.library') || project.plugins.hasPlugin('com.android.application')) {
project.android {
if (namespace == null || namespace == "") {
namespace = project.group
}
compileSdk 36
defaultConfig {
targetSdk 36
}
}
}
}
subprojects {
project.evaluationDependsOn(':app')
if (project.state.executed) {
setupAndroid()
} else {
project.afterEvaluate {
setupAndroid()
}
}
}
tasks.register("clean", Delete) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98713093b836ed941f0ae441b0f84ea767","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"arm64","IPHONEOS_DEPLOYMENT_TARGET":"14.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","ONLY_ACTIVE_ARCH":"NO","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2"},"guid":"bfdfe7dc352907fc980b868725387e980bc977b873df9b0e01b3c822e5c77429","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982a75f557648c19374fbba760cc62794a","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"arm64","IPHONEOS_DEPLOYMENT_TARGET":"14.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e98b75274b69084014a6a5ac37ea7a9d4bc","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982a75f557648c19374fbba760cc62794a","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"arm64","IPHONEOS_DEPLOYMENT_TARGET":"14.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e988b8e6347e534cb57e9bb1b22dc47b716","name":"Release"}],"buildPhases":[],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Release","provisioningStyle":0}],"type":"aggregate"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"guid":"dc4b70c03e8043e50e38f2068887b1d4","name":"Pods","path":"/Users/hamzaaleghwairyeen/development/App/intaleq_driver/ios/Pods/Pods.xcodeproj/project.xcworkspace","projects":["PROJECT@v11_mod=8a8e73429c1ecbff8f5eafafe69e0e09_hash=bfdfe7dc352907fc980b868725387e98plugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1"]}

File diff suppressed because one or more lines are too long

View File

@@ -16,9 +16,9 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version '8.11.0' apply false
id "com.google.gms.google-services" version "4.3.10" apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false // Updated version
id "com.android.application" version '8.13.2' apply false
id "com.google.gms.google-services" version "4.3.15" apply false
id "org.jetbrains.kotlin.android" version "2.3.10" apply false
}
include ":app"

View File

@@ -23,7 +23,7 @@ apply plugin: 'com.android.library'
android {
namespace 'com.dsaved.bubblehead.bubble'
compileSdkVersion 33
compileSdkVersion 36
defaultConfig {
minSdkVersion 16

View File

@@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_contacts/contact.dart';
@@ -124,24 +125,175 @@ Download the Intaleq app now and enjoy your ride!
/// **MODIFIED**: This function now opens the phone's native contact picker.
Future<void> pickContactFromNativeApp() async {
try {
log('=== START: FETCHING ALL CONTACTS FOR BOTTOM SHEET ===',
name: 'ContactPicker');
if (await FlutterContacts.requestPermission(readonly: true)) {
// 1. Open the native contacts app to select a single contact.
final Contact? contact = await FlutterContacts.openExternalPick();
// عرض شاشة تحميل بسيطة ريثما يتم جلب الأسماء
Get.dialog(const Center(child: CircularProgressIndicator()),
barrierDismissible: false);
// 2. If a contact is selected and has a phone number...
if (contact != null && contact.phones.isNotEmpty) {
String selectedPhone = contact.phones.first.number;
log('Permission granted. Calling FlutterContacts.getContacts()...',
name: 'ContactPicker');
// 3. Format the number and update the text field.
invitePhoneController.text = _formatSyrianPhoneNumber(selectedPhone);
update();
}
// جلب جميع جهات الاتصال إجبارياً من الصفر مع خصائصها
List<Contact> allContacts =
await FlutterContacts.getContacts(withProperties: true);
log('Total Contacts Fetched from Device: ${allContacts.length}',
name: 'ContactPicker');
// فصل الأسماء لمعرفة الخلل
List<Contact> validContacts = [];
List<Contact> invalidContacts = [];
for (var c in allContacts) {
if (c.phones.isNotEmpty) {
validContacts.add(c);
} else {
invalidContacts.add(c);
}
}
log('Contacts WITH phone numbers: ${validContacts.length}',
name: 'ContactPicker');
log('Contacts WITHOUT phone numbers: ${invalidContacts.length}',
name: 'ContactPicker');
// طباعة أول 20 اسم صالح
log('--- Sample of VALID Contacts ---', name: 'ContactPicker');
for (int i = 0; i < validContacts.length && i < 20; i++) {
log('[$i] Name: ${validContacts[i].displayName}, Phone: ${validContacts[i].phones.first.number}',
name: 'ContactPicker');
}
// طباعة أول 20 اسم غير صالح (بدون أرقام) لفحص المشكلة
log('--- Sample of INVALID Contacts (No Phone) ---',
name: 'ContactPicker');
for (int i = 0; i < invalidContacts.length && i < 20; i++) {
log('[$i] Name: ${invalidContacts[i].displayName}',
name: 'ContactPicker');
}
Get.back(); // إغلاق شاشة التحميل
if (validContacts.isEmpty) {
mySnackeBarError('No contacts with phone numbers found'.tr);
return;
}
// متغيرات للبحث داخل القائمة المنسدلة
RxList<Contact> filteredContacts = validContacts.obs;
TextEditingController searchController = TextEditingController();
// دالة لتنظيف النصوص من أي رموز معطوبة
String sanitizeText(String input) {
if (input.isEmpty) return '';
return input
.replaceAll(
RegExp(r'[^\x00-\x7F\u0600-\u06FF\u08A0-\u08FF\p{L}\p{N}\s]'),
'')
.trim();
}
// فتح دليل هاتف مخصص داخل التطبيق
Get.bottomSheet(
Container(
height: Get.height * 0.85,
decoration: BoxDecoration(
color: Theme.of(Get.context!).scaffoldBackgroundColor,
borderRadius:
const BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
children: [
Container(
margin: const EdgeInsets.only(top: 10, bottom: 10),
width: 50,
height: 5,
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(10)),
),
Text("Select a Contact".tr,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextField(
controller: searchController,
decoration: InputDecoration(
hintText: "Search name or number...".tr,
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)),
contentPadding: const EdgeInsets.symmetric(vertical: 0),
),
onChanged: (value) {
filteredContacts.value = validContacts.where((c) {
final nameMatch = c.displayName
.toLowerCase()
.contains(value.toLowerCase());
final phoneMatch =
c.phones.first.number.contains(value);
return nameMatch || phoneMatch;
}).toList();
},
),
),
Expanded(
child: Obx(() => ListView.builder(
itemCount: filteredContacts.length,
itemBuilder: (context, index) {
Contact c = filteredContacts[index];
var firstPhone = c.phones.first;
String selectedPhone =
firstPhone.normalizedNumber.isNotEmpty
? firstPhone.normalizedNumber
: firstPhone.number;
String safeName = sanitizeText(c.displayName);
if (safeName.isEmpty) safeName = 'Unknown'.tr;
String safePhone = sanitizeText(selectedPhone);
String initial = safeName.isNotEmpty
? safeName[0].toUpperCase()
: '?';
return ListTile(
leading: CircleAvatar(
backgroundColor:
Colors.blueAccent.withOpacity(0.1),
child: Text(initial,
style: const TextStyle(
color: Colors.blueAccent)),
),
title: Text(safeName),
subtitle: Text(safePhone,
textDirection: TextDirection.ltr),
onTap: () {
selectPhone(selectedPhone);
},
);
},
)),
),
],
),
),
isScrollControlled: true,
);
} else {
log('Permission DENIED', name: 'ContactPicker');
mySnackeBarError('Contact permission is required to pick contacts'.tr);
}
} catch (e) {
mySnackeBarError('An error occurred while picking contacts: $e'.tr);
if (Get.isDialogOpen ?? false) Get.back();
log('CRITICAL ERROR: $e', name: 'ContactPicker');
mySnackeBarError('An error occurred while loading contacts: $e'.tr);
}
log('=== END: FETCHING CONTACTS ===', name: 'ContactPicker');
}
/// **FIX**: Added the missing 'selectPhone' method.
@@ -197,10 +349,10 @@ Download the Intaleq app now and enjoy your ride!
} else if (isAvailable) {
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: const AuthenticationOptions(
// options: const AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
if ((driverInvitationData[index]['isGiftToken']).toString() ==
'0') {
@@ -210,23 +362,23 @@ Download the Intaleq app now and enjoy your ride!
payload: {'id': (driverInvitationData[index]['id'])});
await Get.find<CaptainWalletController>().addDriverPayment(
'paymentMethod',
('50000'),
('500'),
'',
);
await Get.find<CaptainWalletController>()
.addDriverWalletToInvitor(
'paymentMethod',
(driverInvitationData[index]['driverInviterId']),
('50000'),
('500'),
);
NotificationCaptainController().addNotificationCaptain(
driverInvitationData[index]['driverInviterId'].toString(),
"You have got a gift for invitation".tr,
'${"You have 50000".tr} ${'SYP'.tr}',
'${"You have 500".tr} ${'SYP'.tr}',
false);
NotificationController().showNotification(
"You have got a gift for invitation".tr,
'${"You have 50000".tr} ${'SYP'.tr}',
'${"You have 500".tr} ${'SYP'.tr}',
'tone1',
'');
} else {
@@ -266,20 +418,20 @@ Download the Intaleq app now and enjoy your ride!
} else if (isAvailable) {
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: const AuthenticationOptions(
// options: const AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
if (driverInvitationDataToPassengers[index]['isGiftToken']
.toString() ==
'0') {
Get.back();
await Get.find<CaptainWalletController>()
.addDriverWallet('paymentMethod', '20000', '20000');
.addDriverWallet('paymentMethod', '200', '200');
await Get.find<CaptainWalletController>()
.addDriverWalletToInvitor('paymentMethod',
driverInvitationData[index]['driverInviterId'], '20000');
driverInvitationData[index]['driverInviterId'], '200');
await CRUD().post(
link: AppLink.updatePassengerGift,
payload: {'id': driverInvitationDataToPassengers[index]['id']},
@@ -288,7 +440,7 @@ Download the Intaleq app now and enjoy your ride!
driverInvitationDataToPassengers[index]['passengerInviterId']
.toString(),
"You have got a gift for invitation".tr,
'${"You have 20000".tr} ${'SYP'.tr}',
'${"You have 200".tr} ${'SYP'.tr}',
false,
);
} else {

View File

@@ -13,19 +13,20 @@ import '../functions/add_error.dart';
import '../functions/encrypt_decrypt.dart';
class GoogleSignInHelper {
static final GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
'profile',
],
);
static final GoogleSignIn _googleSignIn = GoogleSignIn.instance;
// متغير ثابت لحفظ حالة المستخدم محلياً كبديل لخاصية currentUser المحذوفة
static GoogleSignInAccount? _cachedUser;
// Method to handle Google Sign-In
static Future<GoogleSignInAccount?> signIn() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
final GoogleSignInAccount? googleUser =
await _googleSignIn.authenticate();
if (googleUser != null) {
_cachedUser = googleUser; // حفظ الجلسة في الكاش المحلي
await _handleSignUp(googleUser);
if (box.read(BoxName.countryCode) == 'Egypt') {
Get.to(() => SmsSignupEgypt());
} else if (box.read(BoxName.countryCode) == 'Jordan') {
@@ -40,32 +41,23 @@ class GoogleSignInHelper {
Future<GoogleSignInAccount?> signInFromLogin() async {
try {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
final GoogleSignInAccount? googleUser =
await _googleSignIn.authenticate();
if (googleUser != null) {
// Handle sign-up and store user information
_cachedUser = googleUser; // حفظ الجلسة في الكاش المحلي
await _handleSignUp(googleUser);
// Retrieve driverID and emailDriver with added validation
final driverID =
(box.read(BoxName.driverID)!.toString()) ?? 'Unknown ID';
(box.read(BoxName.driverID)?.toString()) ?? 'Unknown ID';
final emailDriver =
(box.read(BoxName.emailDriver)!.toString()) ?? 'Unknown Email';
(box.read(BoxName.emailDriver)?.toString()) ?? 'Unknown Email';
// Debug print statements
print('Driver ID: $driverID');
print('Driver Email: $emailDriver');
// Check if driverID is a valid numeric string
// if (driverID != 'Unknown ID' && int.tryParse(driverID) != null) {
await Get.find<LoginDriverController>()
.loginWithGoogleCredential(driverID, emailDriver);
// }
// else {
// print('Invalid driverID format: $driverID');
// Get.snackbar('Login Error', 'Invalid driver ID format.',
// backgroundColor: AppColor.redColor);
// }
}
return googleUser;
@@ -78,204 +70,29 @@ class GoogleSignInHelper {
}
static Future<void> _handleSignUp(GoogleSignInAccount user) async {
// Store driver information
box.write(BoxName.driverID,
(user.id) ?? 'Unknown ID'); // Ensure there's a fallback value
box.write(BoxName.driverID, (user.id) ?? 'Unknown ID');
box.write(BoxName.emailDriver, (user.email) ?? 'Unknown Email');
}
// Method to handle Google Sign-Out
static Future<void> signOut() async {
try {
await _googleSignIn.signOut();
} catch (error) {
// التعامل مع الخطأ بصمت إذا كانت جلسة جوجل فارغة مسبقاً
} finally {
_cachedUser = null; // مسح الكاش المحلي بشكل إلزامي
await _handleSignOut();
} catch (error) {}
}
}
static Future<void> _handleSignOut() async {
// Clear stored driver information
box.erase();
storage.deleteAll();
Get.offAll(OnBoardingPage());
// Perform any additional sign-out tasks or API calls here
// For example, you can notify your server about the user sign-out
}
// Method to get the current signed-in user
// استخدام الكاش المحلي بدلاً من استدعاء المكتبة
static GoogleSignInAccount? getCurrentUser() {
return _googleSignIn.currentUser;
return _cachedUser;
}
}
// import 'dart:async';
// import 'dart:async';
// import 'dart:convert';
// import 'package:flutter/material.dart';
// import 'package:get/get.dart';
// import 'package:http/http.dart' as http;
// import 'package:sefer_driver/constant/box_name.dart';
// import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart';
// import 'package:sefer_driver/main.dart';
// import 'package:sefer_driver/views/auth/captin/ai_page.dart';
// import 'package:sefer_driver/views/auth/captin/cards/sms_signup.dart';
// import 'package:sefer_driver/views/home/on_boarding_page.dart';
// import 'package:sefer_driver/views/widgets/error_snakbar.dart';
// import 'package:url_launcher/url_launcher.dart';
// import '../functions/add_error.dart';
// /// Helper class to manage Google Sign-In via an external browser and polling.
// class GoogleSignInHelper {
// // URLs for your server endpoints
// static const String _startLoginUrl =
// 'https://api.tripz-egypt.com/tripz/auth/google_auth/login.php';
// static const String _checkStatusUrl =
// 'https://api.tripz-egypt.com/tripz/auth/google_auth/check_status.php';
// static Future<void> _initiateSignIn(
// Function(Map<String, dynamic> userData) onSignInSuccess) async {
// try {
// // Show a loading dialog to the user
// Get.dialog(
// const Center(
// child: Material(
// color: Colors.transparent,
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// CircularProgressIndicator(),
// SizedBox(height: 16),
// Text(
// "Waiting for browser sign-in...",
// style: TextStyle(color: Colors.white, fontSize: 16),
// ),
// ],
// ),
// ),
// ),
// barrierDismissible: false,
// );
// // 1. Get the auth URL and login token from the server
// final startResponse = await http.get(Uri.parse(_startLoginUrl));
// if (startResponse.statusCode != 200) {
// throw Exception('Failed to start login process.');
// }
// final startData = jsonDecode(startResponse.body);
// final String authUrl = startData['authUrl'];
// final String loginToken = startData['loginToken'];
// // 2. Launch the URL in an external browser
// if (!await launchUrl(Uri.parse(authUrl),
// mode: LaunchMode.externalApplication)) {
// throw Exception('Could not launch browser.');
// }
// // 3. Start polling the server for status
// await _startPolling(loginToken, onSignInSuccess);
// } catch (e) {
// addError(e.toString(), '_initiateSignIn');
// mySnackeBarError('Sign-in failed: ${e.toString()}');
// // Close the loading dialog on error
// if (Get.isDialogOpen ?? false) {
// Get.back();
// }
// }
// }
// static Future<void> _startPolling(String loginToken,
// Function(Map<String, dynamic> userData) onSignInSuccess) async {
// Timer? poller;
// const int maxAttempts = 30; // Poll for 60 seconds (30 attempts * 2s)
// int attempts = 0;
// poller = Timer.periodic(const Duration(seconds: 2), (timer) async {
// if (attempts >= maxAttempts) {
// timer.cancel();
// if (Get.isDialogOpen ?? false) Get.back();
// mySnackeBarError('Sign-in timed out. Please try again.');
// return;
// }
// attempts++;
// try {
// final statusResponse = await http.post(
// Uri.parse(_checkStatusUrl),
// headers: {'Content-Type': 'application/json'},
// body: jsonEncode({'loginToken': loginToken}),
// );
// if (statusResponse.statusCode == 200) {
// final statusData = jsonDecode(statusResponse.body);
// if (statusData['status'] == 'success') {
// timer.cancel();
// if (Get.isDialogOpen ?? false) Get.back();
// // Success!
// onSignInSuccess(statusData['userData']);
// }
// // If status is 'pending', do nothing and wait for the next poll.
// }
// } catch (e) {
// // Handle polling errors silently or log them
// debugPrint("Polling error: $e");
// }
// });
// }
// /// Triggers the sign-in process for a new user.
// static Future<void> signIn() async {
// await _initiateSignIn((userData) async {
// debugPrint('Sign-in success data: $userData');
// await _handleSignUp(userData);
// if (box.read(BoxName.countryCode) == 'Egypt') {
// Get.offAll(() => SmsSignupEgypt());
// } else if (box.read(BoxName.countryCode) == 'Jordan') {
// Get.offAll(() => AiPage());
// }
// });
// }
// /// Triggers the sign-in process for an existing user.
// static Future<void> signInFromLogin() async {
// await _initiateSignIn((userData) async {
// debugPrint('Sign-in from login success data: $userData');
// await _handleSignUp(userData);
// final driverID = userData['id']?.toString() ?? 'Unknown ID';
// final emailDriver = userData['email']?.toString() ?? 'Unknown Email';
// debugPrint('Driver ID from server: $driverID');
// debugPrint('Driver Email from server: $emailDriver');
// await Get.find<LoginDriverController>()
// .loginWithGoogleCredential(driverID, emailDriver);
// });
// }
// /// Stores user information received from the server.
// static Future<void> _handleSignUp(Map<String, dynamic> userData) async {
// box.write(BoxName.driverID, userData['id'] ?? 'Unknown ID');
// box.write(BoxName.emailDriver, userData['email'] ?? 'Unknown Email');
// }
// /// Clears local data.
// static Future<void> signOut() async {
// box.remove(BoxName.driverID);
// box.remove(BoxName.emailDriver);
// box.remove(BoxName.lang);
// box.remove(BoxName.nameDriver);
// box.remove(BoxName.passengerID);
// box.remove(BoxName.phoneDriver);
// box.remove(BoxName.tokenFCM);
// box.remove(BoxName.tokens);
// box.remove(BoxName.carPlate);
// box.remove(BoxName.lastNameDriver);
// box.remove(BoxName.agreeTerms);
// box.remove(BoxName.tokenDriver);
// box.remove(BoxName.countryCode);
// box.remove(BoxName.accountIdStripeConnect);
// box.remove(BoxName.phoneVerified);
// Get.offAll(() => OnBoardingPage());
// }
// }

View File

@@ -65,9 +65,9 @@ class NotificationController extends GetxController {
print('✅ Notifications initialized with Action Buttons Support');
await _flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: onDidReceiveNotificationResponse,
onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
settings: initializationSettings,
);
// إنشاء قناة الأندرويد ذات الأهمية القصوى
@@ -183,10 +183,10 @@ class NotificationController extends GetxController {
// عرض الإشعار
await _flutterLocalNotificationsPlugin.show(
1001, // ID ثابت لاستبدال الإشعار القديم
title,
"$price - مسافة $formattedBigText", // نص مختصر يظهر في البار العلوي
details,
id: 1001, // ID ثابت لاستبدال الإشعار القديم
title: title,
body: "$price - مسافة $formattedBigText", // نص مختصر يظهر في البار العلوي
notificationDetails: details,
payload: jsonEncode({
'type': 'Order',
'data': myListString,
@@ -215,7 +215,7 @@ class NotificationController extends GetxController {
// أ) زر القبول
if (response.actionId == 'ACCEPT_ORDER') {
await _flutterLocalNotificationsPlugin.cancel(1001); // حذف الإشعار
await _flutterLocalNotificationsPlugin.cancel(id: 1001); // حذف الإشعار
_processAcceptOrder(listData);
}
@@ -227,7 +227,7 @@ class NotificationController extends GetxController {
// ج) زر الرفض
else if (response.actionId == 'REJECT_ORDER') {
await _flutterLocalNotificationsPlugin.cancel(1001); // حذف الإشعار
await _flutterLocalNotificationsPlugin.cancel(id: 1001); // حذف الإشعار
_processRejectOrder(listData);
}
@@ -428,7 +428,11 @@ class NotificationController extends GetxController {
NotificationDetails details =
NotificationDetails(android: android, iOS: ios);
await _flutterLocalNotificationsPlugin.show(0, title, message, details,
await _flutterLocalNotificationsPlugin.show(
id: 0,
title: title,
body: message,
notificationDetails: details,
payload: jsonEncode({'title': title, 'data': payLoad}));
}
@@ -490,7 +494,7 @@ class NotificationController extends GetxController {
// ==============================================================================
Future<void> cancelOrderNotification() async {
// 1001 هو نفس الآيدي الذي استخدمناه عند عرض الإشعار
await _flutterLocalNotificationsPlugin.cancel(1001);
await _flutterLocalNotificationsPlugin.cancel(id: 1001);
print("🗑️ Order Notification Cancelled (Taken by another driver)");
}
@@ -522,14 +526,12 @@ class NotificationController extends GetxController {
}
await _flutterLocalNotificationsPlugin.zonedSchedule(
notificationId,
title,
message,
scheduledDate,
details,
androidScheduleMode: AndroidScheduleMode.exact,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
id: notificationId,
title: title,
body: message,
scheduledDate: scheduledDate,
notificationDetails: details,
androidScheduleMode: AndroidScheduleMode.exact, // أو exactAllowWhileIdle
matchDateTimeComponents: null,
);
}

View File

@@ -45,10 +45,10 @@ Future<bool> onStart(ServiceInstance service) async {
print("✅ Background Service: Socket Connected!");
if (service is AndroidServiceInstance) {
flutterLocalNotificationsPlugin.show(
notificationId,
'أنت متصل الآن',
'بانتظار الطلبات...',
const NotificationDetails(
id: notificationId,
title: 'أنت متصل الآن',
body: 'بانتظار الطلبات...',
notificationDetails: const NotificationDetails(
android: AndroidNotificationDetails(
notificationChannelId,
'خدمة السائق',
@@ -107,10 +107,10 @@ Future<bool> onStart(ServiceInstance service) async {
if (service is AndroidServiceInstance) {
if (await service.isForegroundService()) {
flutterLocalNotificationsPlugin.show(
notificationId,
'خدمة السائق نشطة',
'بانتظار الطلبات...',
const NotificationDetails(
id: notificationId,
title: 'خدمة السائق نشطة',
body: 'بانتظار الطلبات...',
notificationDetails: const NotificationDetails(
android: AndroidNotificationDetails(
notificationChannelId,
'خدمة السائق',

View File

@@ -2,10 +2,8 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:jwt_decoder/jwt_decoder.dart';
import 'package:path/path.dart';
import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart';
import 'package:sefer_driver/controller/functions/network/net_guard.dart';
import 'package:secure_string_operations/secure_string_operations.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/constant/links.dart';
import 'package:sefer_driver/controller/auth/captin/login_captin_controller.dart';
@@ -16,8 +14,6 @@ import 'package:sefer_driver/env/env.dart';
import 'package:sefer_driver/print.dart';
import '../../constant/api_key.dart';
import '../../constant/char_map.dart';
import '../../constant/info.dart';
import '../../views/widgets/error_snakbar.dart';
import 'gemeni.dart';
import 'upload_image.dart';

View File

@@ -51,7 +51,7 @@ class DeviceController {
final deviceInfo = DeviceInfo(
manufacturer: androidInfo.manufacturer,
model: androidInfo.model,
deviceId: androidInfo.serialNumber,
deviceId: androidInfo.id,
osVersion: androidInfo.version.release,
platform: 'Android',
deviceName: androidInfo.device,

View File

@@ -16,6 +16,7 @@ import 'package:trip_overlay_plugin/trip_overlay_plugin.dart';
import '../../constant/box_name.dart';
import '../../constant/links.dart';
import '../../main.dart';
import '../../print.dart';
import '../home/captin/home_captain_controller.dart';
import '../home/captin/map_driver_controller.dart';
import '../home/payment/captain_wallet_controller.dart';
@@ -74,7 +75,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
@override
Future<void> onInit() async {
super.onInit();
print('🚀 LocationController Starting...');
Log.print('🚀 LocationController Starting...');
// 1. Register Lifecycle Observer
WidgetsBinding.instance.addObserver(this);
@@ -83,7 +84,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
// مراقب الحالة (Status Watcher)
box.listenKey(BoxName.statusDriverLocation, (value) {
if (value == 'blocked') {
print("⛔ Driver is Blocked: Force Stopping Location Updates.");
Log.print("⛔ Driver is Blocked: Force Stopping Location Updates.");
stopLocationUpdates();
if (socket != null && socket!.connected) {
socket!.emit('update_location', {
@@ -113,7 +114,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
await startLocationUpdates();
}
print('✅ LocationController Initialized.');
Log.print('✅ LocationController Initialized.');
}
@override
@@ -133,7 +134,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
print("📱 Lifecycle: App is in FOREGROUND");
Log.print("📱 Lifecycle: App is in FOREGROUND");
box.write(BoxName.isAppInForeground, true);
// إيقاف خدمة الخلفية لأننا في الواجهة الآن
@@ -141,7 +142,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
// التأكد من أن السوكيت متصل، وإذا لا، نعيد الاتصال فوراً
if (socket == null || !socket!.connected) {
print("🔄 Socket disconnected in background. Reconnecting now...");
Log.print("🔄 Socket disconnected in background. Reconnecting now...");
initSocket();
} else {
// إذا كان متصلاً، ننعش المستمعين فقط للتأكد
@@ -149,7 +150,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
}
} else if (state == AppLifecycleState.paused ||
state == AppLifecycleState.detached) {
print("📱 Lifecycle: App is in BACKGROUND");
Log.print("📱 Lifecycle: App is in BACKGROUND");
box.write(BoxName.isAppInForeground, false);
// تشغيل خدمة الخلفية لضمان بقاء التطبيق حياً
@@ -186,14 +187,15 @@ class LocationController extends GetxController with WidgetsBindingObserver {
// 1. إذا كان السوكيت موجوداً، فقط تأكد من اتصاله
if (socket != null) {
if (!socket!.connected) {
print("🟡 Socket exists but disconnected. Reconnecting...");
Log.print("🟡 Socket exists but disconnected. Reconnecting...");
socket!.connect();
}
_setupSocketListeners(); // تحديث المستمعين
return;
}
print("🟡 [LocationController] Creating NEW Socket for Driver: $driverId");
Log.print(
"🟡 [LocationController] Creating NEW Socket for Driver: $driverId");
// 2. إنشاء الاتصال
socket = IO.io(
@@ -222,20 +224,27 @@ class LocationController extends GetxController with WidgetsBindingObserver {
socket!.off('ride_cancelled');
socket!.onConnect((_) {
print('✅ Socket Connected! ID: ${socket?.id}');
Log.print('✅ Socket Connected! ID: ${socket?.id}');
isSocketConnected = true;
_startHeartbeat();
});
socket!.onDisconnect((_) {
print('❌ Socket Disconnected');
Log.print('❌ Socket Disconnected');
isSocketConnected = false;
_stopHeartbeat();
});
socket!.onConnectError((err) {
Log.print('❌ Socket Connect Error: $err');
});
socket!.onError((err) {
Log.print('❌ Socket General Error: $err');
});
// 🔥 الاستماع للطلبات الجديدة
socket!.on('new_ride_request', (data) {
print("🔔 Socket: New Ride Request Arrived!");
Log.print("🔔 Socket: New Ride Request Arrived!");
// نستخدم Future.microtask لضمان عدم حظر الـ UI Thread
Future.microtask(() {
@@ -259,7 +268,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
handleIncomingOrder(convertedMap, "Socket");
}
} catch (e) {
print("❌ Error processing socket data: $e");
Log.print("❌ Error processing socket data: $e");
}
}
});
@@ -267,7 +276,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
// 🔥 الاستماع للإلغاء
socket!.on('cancel_ride', (data) {
print("🚫 Socket: Ride Cancelled Event Received");
Log.print("🚫 Socket: Ride Cancelled Event Received");
String reason = data['reason'] ?? 'No reason provided';
if (Get.isRegistered<MapDriverController>()) {
Get.find<MapDriverController>()
@@ -280,13 +289,13 @@ class LocationController extends GetxController with WidgetsBindingObserver {
Future<void> handleIncomingOrder(
Map<String, dynamic> rideData, String source) async {
print("📦 Socket Order Received from ($source)");
Log.print("📦 Socket Order Received from ($source)");
// 🔴 1. التحقق من حالة التطبيق قبل أي شيء 🔴
bool isAppInForeground = box.read(BoxName.isAppInForeground) ?? false;
if (!isAppInForeground) {
print(
Log.print(
"🛑 التطبيق في الخلفية. السوكيت سيتجاهل التوجيه ويترك المهمة للـ Overlay.");
return; // 👈 هذا السطر يمنع السوكيت من إكمال العمل وفتح الصفحة
}
@@ -294,7 +303,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
try {
// 2. التحقق من صحة البيانات
if (rideData.isEmpty || !rideData.containsKey('16')) {
print("❌ Socket Error: Invalid Ride Data.");
Log.print("❌ Socket Error: Invalid Ride Data.");
return;
}
@@ -311,25 +320,26 @@ class LocationController extends GetxController with WidgetsBindingObserver {
// 4. إغلاق النافذة (إن وجدت بالخطأ) والتنقل
try {
if (await TripOverlayPlugin.isOverlayActive()) {
print("📲 Closing Overlay because App took control via Socket");
Log.print("📲 Closing Overlay because App took control via Socket");
await TripOverlayPlugin.hideOverlay();
}
} catch (e) {
print("Overlay check error: $e");
Log.print("Overlay check error: $e");
}
if (Get.currentRoute != '/OrderRequestPage') {
print("🚀 Socket: Navigating to OrderRequestPage...");
Log.print("🚀 Socket: Navigating to OrderRequestPage...");
Get.toNamed('/OrderRequestPage', arguments: {
'myListString': jsonEncode(driverList),
'DriverList': driverList,
'body': 'New Trip Request via Socket ⚡'
});
} else {
print("⚠️ User is already on OrderRequestPage. Skipping navigation.");
Log.print(
"⚠️ User is already on OrderRequestPage. Skipping navigation.");
}
} catch (e) {
print("❌ Socket Navigation Error: $e");
Log.print("❌ Socket Navigation Error: $e");
}
}
@@ -374,8 +384,8 @@ class LocationController extends GetxController with WidgetsBindingObserver {
}
}
// Debug print to verify
// print('🚀 Emitting Location: $payload');
// DebugLog.print to verify
//Log.print('🚀 Emitting Location: $payload');
if (socket != null && socket!.connected) {
socket!.emit('update_location', payload);
@@ -437,11 +447,11 @@ class LocationController extends GetxController with WidgetsBindingObserver {
update();
emitLocationToSocket(pos, heading, speed);
await _saveBehaviorIfMoved(pos, now, currentSpeed: speed);
}, onError: (e) => print('❌ Location Stream Error: $e'));
}, onError: (e) => Log.print('❌ Location Stream Error: $e'));
}
Future<void> stopLocationUpdates() async {
print("🛑 Stopping Location Updates...");
Log.print("🛑 Stopping Location Updates...");
_locSub?.cancel();
_locSub = null;
@@ -525,7 +535,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
payload: {'driver_id': driverId, 'batch_data': jsonEncode(batch)},
);
} catch (e) {
print('❌ Failed to upload batch: $e');
Log.print('❌ Failed to upload batch: $e');
}
}
@@ -559,7 +569,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
}, TableName.behavior);
_lastSqlLoc = pos;
} catch (e) {
print('SQLite Error: $e');
Log.print('SQLite Error: $e');
}
}
@@ -594,7 +604,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
interval: 1000,
distanceFilter: 10);
} catch (e) {
print("Warning: $e");
Log.print("Warning: $e");
}
}
}
@@ -633,7 +643,7 @@ class LocationController extends GetxController with WidgetsBindingObserver {
return await location.getLocation();
}
} catch (e) {
print('❌ FAILED to get single location: $e');
Log.print('❌ FAILED to get single location: $e');
}
return null;
}

View File

@@ -28,7 +28,7 @@ class NetGuard {
// اختباري خفيف عبر TCP (80/443) — 400ms timeout
final port = mustReach.scheme == 'http' ? 80 : 443;
final socket = await Socket.connect(host, port,
timeout: const Duration(milliseconds: 400));
timeout: const Duration(seconds: 1));
socket.destroy();
} catch (_) {
return false;

View File

@@ -433,14 +433,58 @@ class HomeCaptainController extends GetxController {
return totalDuration;
}
void startPeriodicExecution() {
Timer.periodic(const Duration(seconds: 30), (timer) async {
Timer? _localDurationTimer;
RxString totalDurationDisplay = "00:00:00".obs; // لعرض الوقت في الواجهة
Duration _currentDuration = Duration.zero; // لتخزين الوقت ككائن Duration
void startPeriodicExecution() async {
await getCaptainDurationOnToday();
String? initialDurationStr = totalDurationToday;
if (initialDurationStr != null) {
// تحويل النص (01:20:30) إلى كائن Duration
List<String> parts = initialDurationStr.split(':');
_currentDuration = Duration(
hours: int.parse(parts[0]),
minutes: int.parse(parts[1]),
seconds: int.parse(parts[2]),
);
// بدء العداد المحلي
_startLocalClock();
}
// Timer.periodic(const Duration(seconds: 30), (timer) async {
// await getCaptainDurationOnToday();
// });
}
void _startLocalClock() {
_localDurationTimer?.cancel();
_localDurationTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
// زيادة ثانية واحدة محلياً
_currentDuration += const Duration(seconds: 1);
// تحديث النص المعروض في الواجهة (Formatting)
totalDurationDisplay.value = _formatDuration(_currentDuration);
// اختيارياً: كل 5 دقائق فقط، قم بتحديث القيمة من السيرفر للتأكد من المزامنة
if (timer.tick % 300 == 0) {
getCaptainDurationOnToday();
}
});
}
String _formatDuration(Duration duration) {
String twoDigits(int n) => n.toString().padLeft(2, "0");
String hours = twoDigits(duration.inHours);
String minutes = twoDigits(duration.inMinutes.remainder(60));
String seconds = twoDigits(duration.inSeconds.remainder(60));
return "$hours:$minutes:$seconds";
}
void stopTimer() {
timer?.cancel();
_localDurationTimer?.cancel();
}
getlocation() async {

View File

@@ -23,10 +23,10 @@ class PaymobPayout extends GetxController {
// Authenticate the user
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: AuthenticationOptions(
// options: AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
// var dec = await CRUD()
// .postWallet(link: AppLink.paymobPayoutDriverWallet, payload: {
@@ -117,10 +117,10 @@ class PaymobPayout extends GetxController {
// Authenticate the user
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: AuthenticationOptions(
// options: AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
var body = {
"issuer": "bank_card",
@@ -188,10 +188,10 @@ class PaymobPayout extends GetxController {
// Authenticate the user
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: AuthenticationOptions(
// options: AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
await payToDriverWallet(amount, issuer, msisdn);
} else {
@@ -214,10 +214,10 @@ class PaymobPayout extends GetxController {
// Authenticate the user
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: AuthenticationOptions(
// options: AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
await payToDriverBankAccount(amount, bankCardNumber, bankCode);
} else {

View File

@@ -439,10 +439,10 @@ class PaymentController extends GetxController {
// Authenticate the user
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: AuthenticationOptions(
// options: AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
final PaymobResponse? response = await PaymobPayment.instance.pay(
context: context,
@@ -590,10 +590,11 @@ class PaymentController extends GetxController {
// Authenticate the user
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason: 'Use Touch ID or Face ID to confirm payment',
options: AuthenticationOptions(
// options: AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
// )
);
if (didAuthenticate) {
final PaymobResponseWallet? response =
await PaymobPaymentWallet.instance.pay(

View File

@@ -32,10 +32,10 @@ class _PayoutScreenState extends State<PayoutScreen> {
// 1. طلب المصادقة البيومترية
bool didAuthenticate = await _localAuth.authenticate(
localizedReason: 'استخدم بصمة الإصبع لتأكيد عملية السحب',
options: const AuthenticationOptions(
// options: const AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
),
// ),
);
if (didAuthenticate && mounted) {

View File

@@ -312,10 +312,10 @@ class WalletCaptainRefactored extends StatelessWidget {
bool didAuthenticate = await LocalAuthentication().authenticate(
localizedReason:
'Use Touch ID or Face ID to confirm payment'.tr,
options: const AuthenticationOptions(
// options: const AuthenticationOptions(
biometricOnly: true,
sensitiveTransaction: true,
));
);
if (didAuthenticate) {
if (double.parse(controller.amountFromBudgetController.text) <
double.parse(controller.totalAmountVisa)) {

View File

@@ -17,7 +17,7 @@ import flutter_app_group_directory
import flutter_image_compress_macos
import flutter_inappwebview_macos
import flutter_local_notifications
import flutter_secure_storage_macos
import flutter_secure_storage_darwin
import flutter_tts
import geolocator_apple
import google_sign_in_ios
@@ -26,8 +26,7 @@ import local_auth_darwin
import location
import objectbox_flutter_libs
import package_info_plus
import path_provider_foundation
import record_darwin
import record_macos
import share_plus
import sign_in_with_apple
import sqflite_darwin
@@ -49,7 +48,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterImageCompressMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterImageCompressMacosPlugin"))
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin"))
FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
@@ -58,8 +57,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin"))
RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))

File diff suppressed because it is too large Load Diff

View File

@@ -20,14 +20,14 @@ dependencies:
path: ./trip_overlay_plugin
# flutter_overlay_window: ^0.4.4
cupertino_icons: ^1.0.2
firebase_messaging: ^15.0.3
firebase_core: ^3.2.0
flutter_local_notifications: ^18.0.1
firebase_messaging: ^16.1.3
firebase_core: ^4.6.0
flutter_local_notifications: ^21.0.0
google_maps_flutter: ^2.10.1
sqflite: ^2.3.0
path: ^1.8.3
# lottie: ^2.5.0
intl: ^0.19.0
intl: ^0.20.2
google_fonts: ^8.0.2
http: ^1.2.2
get: ^4.6.5
@@ -37,8 +37,8 @@ dependencies:
google_polyline_algorithm: ^3.1.0
# custom_searchable_dropdown: ^2.1.1
animated_text_kit: ^4.2.2
flutter_secure_storage: ^9.0.0
geolocator: ^13.0.2
flutter_secure_storage: ^10.0.0
geolocator: ^14.0.2
flutter_paypal: ^0.2.0
flutter_launcher_icons: ^0.14.2 #to be remove
# crypto: ^3.0.3
@@ -46,21 +46,21 @@ dependencies:
flutter_rating_bar: ^4.0.1
flutter_font_icons: ^2.2.5
image_picker: ^1.0.4
flutter_stripe: ^11.3.0
camera: ^0.11.0+1 #to be remove
flutter_widget_from_html: ^0.15.1
local_auth: ^2.1.7
flutter_stripe: ^12.4.0
camera: ^0.12.0+1 #to be remove
flutter_widget_from_html: ^0.17.1
local_auth: ^3.0.1
image: ^4.1.3 #to be remove
image_cropper: ^8.1.0
image_cropper: ^12.1.1
envied: ^1.0.0
# cached_network_image: ^3.3.0 #to be remove
calendar_builder: ^0.0.6
fl_chart: ^0.70.0
fl_chart: ^1.2.0
# agora_rtc_engine: ^6.2.6
flutter_tts: ^4.0.2
permission_handler: ^11.3.0
permission_handler: ^12.0.1
# google_generative_ai: ^0.0.1-dev
vibration: ^2.0.1
vibration: ^3.1.8
wakelock_plus:
# background_location: ^0.13.0
# background_location:
@@ -72,29 +72,29 @@ dependencies:
# git:
# url: https://github.com/Hamza-Ayed/flutter_overlay_apps.git
# ref: main
record: ^5.0.5
record: ^6.2.0
dio: ^5.4.3+1
webview_flutter: ^4.9.0
just_audio: ^0.9.37
share_plus: ^7.2.1
google_sign_in: ^6.2.1
just_audio: ^0.10.5
share_plus: ^12.0.2
google_sign_in: ^7.2.0
# google_mlkit_text_recognition: ^0.14.0
sign_in_with_apple: ^6.1.0
firebase_auth: ^5.1.2
package_info_plus: ^8.0.0
sign_in_with_apple: ^7.0.1
firebase_auth: ^6.3.0
package_info_plus: ^9.0.1
flutter_image_compress: ^2.3.0
flutter_contacts: ^1.1.8
flutter_overlay_window: ^0.4.4
googleapis_auth: ^1.6.0
flutter_overlay_window: ^0.5.0
googleapis_auth: ^2.0.0
video_player: ^2.9.2
youtube_player_flutter: ^9.0.4
flutter_confetti: ^0.3.0
flutter_confetti: ^0.5.1
slide_to_act: ^2.0.2
live_activities: ^2.3.0
quick_actions: ^1.1.0
jwt_decoder: ^2.0.1
jailbreak_root_detection: ^1.1.5
device_info_plus: ^11.3.0
device_info_plus: ^12.4.0
flutter_web_browser: ^0.17.3
# flutter_isolate: ^2.1.0
# lingo_hunter: ^1.0.3
@@ -102,14 +102,14 @@ dependencies:
flutter_svg: ^2.2.0
lottie: ^3.3.1
flutter_staggered_animations: ^1.1.1
battery_plus: ^6.2.2
battery_plus: ^7.0.0
internet_connection_checker: ^3.0.1
connectivity_plus: ^6.1.5
# pip_view: ^0.9.7
flutter_map: ^6.1.0 # (استخدم أحدث إصدار دائماً)
flutter_map: ^8.2.2 # (استخدم أحدث إصدار دائماً)
# مكتبة التخزين لتحميل الخرائط أوفلاين
flutter_map_tile_caching: ^9.0.0 # (استخدم أحدث إصدار)
flutter_map_tile_caching: ^10.1.1 # (استخدم أحدث إصدار)
latlong2: ^0.9.1
socket_io_client: ^1.0.2
flutter_background_service: ^5.1.0
@@ -120,7 +120,7 @@ dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0
flutter_lints: ^6.0.0
envied_generator: ^1.0.0
build_runner: ^2.4.6

View File

@@ -21,6 +21,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
flutter_local_notifications_windows
)
set(PLUGIN_BUNDLED_LIBRARIES)