25-6-23/1

This commit is contained in:
Hamza-Ayed
2025-06-23 02:24:42 +03:00
parent 5eba032887
commit 5050aab9b7
42 changed files with 2387 additions and 1783 deletions

14
.env
View File

@@ -32,18 +32,18 @@ geminiApi=QOmqZsQYm08vOqjI7klVJfvP4WBFEoemjgy396iXrXlBl
geminiApiMasa=QOmqZsQIdM4BRsKmaDJOP7dZp5-c6NWfch7PAlQXrXlBl
agoraAppId=71880f2j636509j24y5294480y30u848XrXlBl
agoraAppCertificate=j17q944u49390q758u1649448q2y6xfuXrXlBl
usernamePayMob=37319104052XrXlBl
passwordPayMob='g@nkD2#99!hD_.wXrXlBl'
integrationIdPayMob=0237730XrXlBl
payMobApikey='MDrGqKEWS1rVqHvEPDvPjJ7vZDBExrO7S3BEBgrlfUwTA3i5RnP5ZnvoL3M2S9rEBgrlNTdexH5pTPf7NJrvy1reZJv1Tn7zf7vTIDywjHg1C7Ley38HTDyNA3v7TPfdxJrax1rwPmPtMJyzqKEYZeghq3MuLUrFH3A1AgHcH15CZ9UaZTLOxnw0BTdzHHrBArisZerUMUUzZ1BnBeEijHvNjYLnS1BUICMhSmPhA15ifHyVqKEMHWyKLbyuIPvcH9UeL3vZyDf=XrXlBl'
integrationIdPayMobWallet=0237739XrXlBl
usernamePayMob=373191e04052XrXlBl
passwordPayMob='g@nkD23#99!hD_.wXrXlBl'
integrationIdPayMob=02337730XrXlBl
payMobApikey='MDrGqKEWS14rVqHvEPDvPjJ7vZDBExrO7S3BEBgrlfUwTA3i5fRnP5ZnvoL3M2S9rEBgrlNTdexH5pTPf7NJrvy1reZJv1Tn7zf7vTIDywjHg1C7Ley38HTDyNA3v7TPfdxJrax1rwPmPtMJyzqKEYZeghq3MuLUrFH3A1AgHcH15CZ9UaZTLOxnw0BTdzHHrBArisZerUMUUzZ1BnBeEijHvNjYLnS1BUICMhSmPhA15ifHyVqKEMHWyKLbyuIPvcH9UeL3vZyDf=XrXlBl'
integrationIdPayMobWallet=0237731XrXlBl
ocpApimSubscriptionKey=0f5dacccdbce4131b1a5f952996302e3
smsPasswordEgypt="J)Vh=qb/@MXrXlBl"
chatGPTkeySeferNew4=zg-vlie-2l1ZlpxiLJ6wQOvbb4TnC9XrxgUEyVQIu6TID4qP4FUUqoS5XrXlBl
anthropicAIkeySeferNew=zg-qbc-qvo39-n4VdMQ5nuJeIYhMN4PDYr7qox3-t2i1Lh7aNTDfYF-Gf8whUJZCs47EeelKn8_UcmUMmiSLaf0UJg0DvUlQrDt-76CRrkQQXrXlBl
llama3Key=kzg_uTXy3e9DBbCQ1FnMGxYwTKysx9US1burxJj4fFwOje4LZBUFKJS1XrXlBl
payMobOutPassword='D2zJFxkE#LN3vz38z2dYxpNfWXrXlBl'
payMobOutUserName='zjujl_qvo_fwjfgjlXrXlBl'
payMobOutPassword='D2zJFxkE#LN43vz328z2dYxpNfWXrXlBl'
payMobOutUserName='zjujl_qfvo_fwjf36gjlXrXlBl'
keyOfApp=nqryjjjhgjp@1bCQ1FnMGxYwsjyzjujljksvceiXrXlBl
initializationVector=ujljkdelkjlXrXlBlfghijkl
sss_pass=wqnmqqsjyvwv:nqrYJP@17378XrXlBl

View File

@@ -2,28 +2,28 @@ C/C++ Structured Log

}/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/additional_project_files.txtC
A
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  Ô¶õ§ö2  ÿÊü××2~
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ޶´Áù2  ÿÊü××2~
|
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build.json  Õ¶õ§ö2ù
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build.json  ޶´Áù2ù
˜Ëü××2„
<EFBFBD>
/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build_mini.json  Õ¶õ§ö2» êÐü××2p
/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build_mini.json  ޶´Áù2» êÐü××2p
n
l/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja  Õ¶õ§ö2⃠†Åü××2t
l/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja  ޶´Áù2⃠†Åü××2t
r
p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja.txt  Õ¶õ§ö2y
p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja.txt  ޶´Áù2y
w
u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build_file_index.txt  Õ¶õ§ö2
u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build_file_index.txt  ޶´Áù2
^ €<>àÕ×2z
x
x
v/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/compile_commands.json  ޶´Áù2« „Åü××2~
|
|
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/compile_commands.json.bin  ޶´Áù2 Æ „Åü××2†
ƒ
ƒ
/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/metadata_generation_command.txt  ޶´Áù2
Š €<>àÕ×2w
u
u
s/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/prefab_config.json  ޶´Áù2
 ( €<>àÕ×2|
 ( €<>àÕ×2|
z
x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/symbol_folder_index.txt  Õ¶õ§ö2
x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/symbol_folder_index.txt  ޶´Áù2

View File

@@ -2,27 +2,27 @@ C/C++ Structured Log
<EFBFBD>
/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/additional_project_files.txtC
A
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ®·õ§ö2  éòü××2€
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  Œ·´Áù2  éòü××2€
~
|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build.json  ®·õ§ö2<18> ïòü××2‡
|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build.json  Œ·´Áù2<18> ïòü××2‡

<EFBFBD>/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build_mini.json  ®·õ§ö2Ã ùòü××2r
<EFBFBD>/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build_mini.json  Œ·´Áù2à ùòü××2r
p
n/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja  ®·õ§ö2¨„ ¯òü××2v
n/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja  Œ·´Áù2¨„ ¯òü××2v
t
r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja.txt  ®·õ§ö2{
r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja.txt  Œ·´Áù2{
y
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build_file_index.txt  ®·õ§ö2
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build_file_index.txt  Œ·´Áù2
^ “¤àÕ×2|
z
z
x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/compile_commands.json  Œ·´Áù2Æ ®òü××2€
~
~
|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/compile_commands.json.bin  Œ·´Áù2 ï ®òü××2ˆ


/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/metadata_generation_command.txt  <08>·´Áù2
” “¤àÕ×2y
w
w
u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/prefab_config.json  <08>·´Áù2
 ( “¤àÕ×2~
 ( “¤àÕ×2~
|
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/symbol_folder_index.txt  ®·õ§ö2
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/symbol_folder_index.txt  <EFBFBD>·´Áù2

View File

@@ -2,28 +2,28 @@ C/C++ Structured Log{
y
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/additional_project_files.txtC
A
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  É·õ§ö2  þÿü××2x
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ¢·´Áù2  þÿü××2x
v
t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build.json  É·õ§ö2á
t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build.json  ¢·´Áù2á
€ý××2}
{
y/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build_mini.json  É·õ§ö2£ †€ý××2j
y/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build_mini.json  ¢·´Áù2£ †€ý××2j
h
f/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja  É·õ§ö2²ƒ Üÿü××2n
f/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja  ¢·´Áù2²ƒ Üÿü××2n
l
j/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja.txt  É·õ§ö2s
j/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja.txt  ¢·´Áù2s
q
o/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build_file_index.txt  É·õ§ö2
o/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build_file_index.txt  ¢·´Áù2
^ ªÕàÕ×2t
r
r
p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/compile_commands.json  ¢·´Áù2± Ûÿü××2x
v
v
t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/compile_commands.json.bin  ¢·´Áù2 Ó Ûÿü××2~
|
|
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/metadata_generation_command.txt  ¢·´Áù2
ì ©ÕàÕ×2q
o
o
m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/prefab_config.json  ¢·´Áù2
 ( ©ÕàÕ×2v
 ( ©ÕàÕ×2v
t
r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/symbol_folder_index.txt  É·õ§ö2
r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/symbol_folder_index.txt  ¢·´Áù2

View File

@@ -2,28 +2,28 @@ C/C++ Structured Log~
|
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/additional_project_files.txtC
A
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ß·õ§ö2  ûŠý××2{
?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ··´Áù2  ûŠý××2{
y
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build.json  ß·õ§ö2í
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build.json  ··´Áù2í
ýŠý××2€
~
|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build_mini.json  ß·õ§ö2¯ý××2m
|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build_mini.json  ··´Áù2¯ý××2m
k
i/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja  ß·õ§ö2¼ƒ çŠý××2q
i/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja  ··´Áù2¼ƒ çŠý××2q
o
m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja.txt  ß·õ§ö2v
m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja.txt  ··´Áù2v
t
r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build_file_index.txt  ß·õ§ö2
r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build_file_index.txt  ··´Áù2
^ ŒààÕ×2w
u
u
s/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/compile_commands.json  ··´Áù2§ çŠý××2{
y
y
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/compile_commands.json.bin  ··´Áù2  çŠý××2<C397>


}/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/metadata_generation_command.txt  ··´Áù2
û ŒààÕ×2t
r
r
p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/prefab_config.json  ··´Áù2
 ( ŒààÕ×2y
 ( ŒààÕ×2y
w
u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/symbol_folder_index.txt  ß·õ§ö2
u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/symbol_folder_index.txt  ··´Áù2

View File

@@ -24,34 +24,30 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.QUICKBOOT_POWERON" />
<uses-permission android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:allowBackup="true"
android:icon="@mipmap/launcher_icon"
android:label="Tripz Driver"
android:theme="@style/LaunchTheme">
<service
android:name=".MyFirebaseMessagingService"
android:exported="false"></service>
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:configChanges="orientation|keyboardHidden|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
<meta-data android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -62,85 +58,50 @@
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/api_key" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
<meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/api_key" />
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data android:name="flutterEmbedding" android:value="2" />
<service
android:name=".LocationUpdatesService"
android:exported="false"
<service android:name=".MyFirebaseMessagingService" android:exported="false" />
<service android:name=".LocationUpdatesService" android:exported="false"
android:foregroundServiceType="location" />
<!-- <service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service> -->
<service
android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false"
tools:replace="android:exported">
<service android:name="com.google.firebase.messaging.FirebaseMessagingService"
android:exported="false" tools:replace="android:exported">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name="com.phan_tech.flutter_overlay_apps.OverlayService"
<service android:name="com.phan_tech.flutter_overlay_apps.OverlayService"
android:exported="false" />
<service
android:name="flutter.overlay.window.flutter_overlay_window.OverlayService"
<service android:name="flutter.overlay.window.flutter_overlay_window.OverlayService"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="explanation_for_special_use" />
</service>
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.sefer_driver" />
</intent-filter>
</receiver>
<service
android:name="com.dsaved.bubblehead.bubble.BubbleHeadService"
android:enabled="true"
<service android:name="com.dsaved.bubblehead.bubble.BubbleHeadService" android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="intent.bring.app.to.foreground" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
<!-- <receiver
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver"
android:exported="false" />
<receiver
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver> -->
<receiver android:exported="false"
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false"
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
@@ -148,9 +109,8 @@
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver
android:name=".YourBroadcastReceiver"
android:exported="false" />
</application>
<receiver android:name=".YourBroadcastReceiver" android:exported="false" />
</application>
</manifest>

View File

@@ -1,6 +1,7 @@
package com.sefer_driver
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.LinearLayout
@@ -9,137 +10,129 @@ import android.widget.TextView
import androidx.core.view.setPadding
import com.scottyab.rootbeer.RootBeer
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.io.File
import java.util.Timer
import kotlin.concurrent.schedule
import io.flutter.embedding.engine.FlutterEngine // Import FlutterEngine
import io.flutter.plugin.common.MethodChannel // Import MethodChannel
import io.flutter.plugin.common.MethodCall // Import MethodCall
import io.flutter.plugin.common.MethodChannel.Result // Import Result
class MainActivity : FlutterFragmentActivity() {
private lateinit var channel: MethodChannel // Declare a MethodChannel variable
private val SECURITY_CHANNEL = "com.sefer_driver/security"
private val APP_CONTROL_CHANNEL = "com.sefer_driver/app_control"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// Initialize the MethodChannel
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.sefer_driver/security")
// Set a MethodCallHandler to handle method calls from Flutter
channel.setMethodCallHandler { call, result ->
// Channel for security checks (isRooted)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SECURITY_CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"isNativeRooted" -> {
val isCompromised = isDeviceCompromised()
result.success(isCompromised) // Send the result back to Flutter
}
else -> {
result.notImplemented() // Handle unknown method calls
}
}
"isNativeRooted" -> result.success(isDeviceCompromised())
else -> result.notImplemented()
}
}
// Channel for app control (bringing to foreground)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, APP_CONTROL_CHANNEL)
.setMethodCallHandler { call, result ->
when (call.method) {
"bringToForeground" -> {
Log.d("MainActivity", "Received bringToForeground request")
val intent =
Intent(this, MainActivity::class.java).apply {
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_SINGLE_TOP
)
}
try {
startActivity(intent)
Log.d(
"MainActivity",
"App brought to foreground successfully with flags: ${intent.flags}"
)
result.success(true)
} catch (e: Exception) {
Log.e(
"MainActivity",
"Error bringing app to foreground: ${e.message}",
e
)
result.error(
"ACTIVITY_START_FAILED",
e.message,
e.stackTraceToString()
)
}
}
else -> result.notImplemented()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Perform all checks. The order can matter; you might want to prioritize
// the faster checks first.
Log.d("MainActivity", "MainActivity onCreate")
if (isDeviceCompromised()) {
showSecurityWarningDialog()
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
Log.d("MainActivity", "Received new intent: ${intent.action}, flags: ${intent.flags}")
}
private fun isDeviceCompromised(): Boolean {
return try {
nativeRootCheck() || rootBeerCheck() //|| !safetyNetCheck()
val isRootedByRootBeer = RootBeer(this).isRooted
Log.d("MainActivity", "Root check result: $isRootedByRootBeer")
isRootedByRootBeer
} catch (e: Exception) {
Log.e("DEBUG", "Error during security checks: ${e.message}", e)
true // Consider the device compromised on error
Log.e("MainActivity", "Security check error: ${e.message}", e)
true // Fail-safe: assume compromised if check fails
}
}
private fun nativeRootCheck(): Boolean {
Log.d("DEBUG", "Starting native root detection...")
return try {
val isNativeRooted = RootDetection.isNativeRooted()
Log.d("DEBUG", "Native root detection result: $isNativeRooted")
isNativeRooted
} catch (e: Exception) {
Log.e("DEBUG", "Error in native root detection: ${e.message}", e)
true // Consider rooted on exception
}
}
private fun rootBeerCheck(): Boolean {
Log.d("DEBUG", "Starting RootBeer root detection...")
val rootBeer = RootBeer(this)
val isRooted = rootBeer.isRooted
Log.d("DEBUG", "RootBeer detection result: $isRooted")
return isRooted
}
private fun safetyNetCheck(): Boolean {
Log.d("DEBUG", "Starting SafetyNet check...")
var isSafe = false // Initialize a variable to store result
val semaphore = java.util.concurrent.Semaphore(0) // Create a semaphore
SafetyNetCheck.checkSafetyNet(this, getString(R.string.api_key_safety)) { result ->
isSafe = result
Log.d("DEBUG", "SafetyNet check result: $isSafe")
semaphore.release() // Release the semaphore when the callback is executed
}
try {
semaphore.acquire() // Wait for the callback to complete
} catch (e: InterruptedException) {
Log.e("DEBUG", "Interrupted while waiting for SafetyNet check", e)
return false // Or handle as appropriate for your app
}
return isSafe
}
private fun showSecurityWarningDialog() {
var secondsRemaining = 10 // Start at 10 seconds
// Create views programmatically
val progressBar = ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal)
progressBar.max = 10 // Set max to 10 for 10 seconds
progressBar.progress = 10 // Start full
val textView = TextView(this)
textView.text = getString(R.string.security_warning_message) // Your message
textView.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
val layout = LinearLayout(this)
layout.orientation = LinearLayout.VERTICAL
layout.setPadding(48)
layout.addView(textView)
layout.addView(progressBar)
var secondsRemaining = 10
val progressBar =
ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal).apply {
max = 10
progress = 10
}
val textView =
TextView(this).apply {
text = getString(R.string.security_warning_message)
textAlignment = TextView.TEXT_ALIGNMENT_CENTER
}
val layout =
LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
setPadding(48)
addView(textView)
addView(progressBar)
}
val dialog =
AlertDialog.Builder(this)
.setTitle(getString(R.string.security_warning_title)) // Your title
.setView(layout) // Set the custom layout
.setCancelable(
false
) // Prevent dismissing by tapping outside or back button
.setTitle(getString(R.string.security_warning_title))
.setView(layout)
.setCancelable(false)
.create()
dialog.show()
// Use a Timer to update the progress bar and countdown
val timer = Timer()
timer.schedule(0, 1000) { // Update every 1000ms (1 second)
timer.schedule(0, 1000) {
secondsRemaining--
runOnUiThread { // Update UI on the main thread
progressBar.progress =
secondsRemaining // Set the progress bar to show remaining seconds
runOnUiThread {
progressBar.progress = secondsRemaining
if (secondsRemaining <= 0) {
timer.cancel() // Stop the timer
dialog.dismiss() // Dismiss the dialog
clearAppDataAndExit() // Clear data and exit
timer.cancel()
dialog.dismiss()
clearAppDataAndExit()
}
}
}
@@ -147,56 +140,35 @@ class MainActivity : FlutterFragmentActivity() {
private fun clearAppDataAndExit() {
try {
val packageName = applicationContext.packageName
val runtime = Runtime.getRuntime()
runtime.exec("pm clear $packageName") // Clear app data
Runtime.getRuntime().exec("pm clear $packageName")
Log.d("MainActivity", "Cleared app data via package manager")
} catch (e: Exception) {
Log.e("MainActivity", "Error clearing app data: ${e.message}", e)
clearCache()
clearAppData()
}
finishAffinity() // Finish all activities from this app
System.exit(0) // Terminate the app's process
finishAffinity()
System.exit(0)
}
private fun clearCache() {
try {
val cacheDir = cacheDir
if (cacheDir != null && cacheDir.isDirectory) {
deleteDir(cacheDir)
}
val externalCacheDir = externalCacheDir
if (externalCacheDir != null && externalCacheDir.isDirectory) {
deleteDir(externalCacheDir)
}
} catch (e: Exception) {
Log.e("DEBUG", "Error clearing cache: ${e.message}", e)
}
Log.d("MainActivity", "Cleared cache directories")
}
private fun clearAppData() {
try {
val dataDir = applicationContext.dataDir
if (dataDir != null && dataDir.isDirectory) {
deleteDir(dataDir)
}
} catch (e: Exception) {
Log.e("DEBUG", "Error clearing app data: ${e.message}", e)
}
// Be careful with this, it deletes all app data.
// deleteDir(applicationContext.dataDir)
Log.d("MainActivity", "App data clearing skipped (commented out)")
}
private fun deleteDir(dir: File?): Boolean {
if (dir != null && dir.isDirectory) {
val children = dir.list()
if (children != null) {
for (child in children) {
val success = deleteDir(File(dir, child))
if (!success) {
return false
}
}
}
}
return dir?.delete() ?: false
dir.list()?.forEach { deleteDir(File(dir, it)) }
}
val deleted = dir?.delete() ?: false
Log.d("MainActivity", "Deleted directory ${dir?.path}: $deleted")
return deleted
}
}

View File

@@ -6,6 +6,10 @@ class BoxName {
static const String initializationVector = 'initializationVector';
static const String firstTimeLoadKey = 'firstTimeLoadKey';
static const String jwt = "jwt";
static const String rideId = "rideId";
static const String rideArgumentsFromBackground =
"rideArgumentsFromBackground";
static const String FCM_PRIVATE_KEY = "FCM_PRIVATE_KEY";
static const String hmac = "hmac";
static const String fingerPrint = "fingerPrint";
static const String payMobApikey = "payMobApikey";

View File

@@ -101,6 +101,10 @@ class AppLink {
static String getTripCountByCaptain = "$ride/rides/getTripCountByCaptain.php";
static String getRideOrderID = "$ride/rides/getRideOrderID.php";
static String getRideStatus = "$ride/rides/getRideStatus.php";
static String getOverLayStatus = "$ride/overLay/get.php";
static String getArgumentAfterAppliedFromBackground =
"$ride/overLay/getArgumentAfterAppliedFromBackground.php";
static String addOverLayStatus = "$ride/overLay/add.php";
static String getapiKey = "$ride/apiKey/get.php";
static String getapiKeySefer = "$ride/apiKey/get.php";
@@ -123,6 +127,12 @@ class AppLink {
////-----------------DriverPayment------------------
static String addDrivePayment = "$seferPaymentServer/ride/payment/add.php";
static String payWithPayMobCardDriver =
"$seferPaymentServer/ride/payMob/paymob_driver/payWithCard.php";
static String payWithWallet =
"$seferPaymentServer/ride/payMob/paymob_driver/payWithWallet.php";
static String paymetVerifyDriver =
"$seferPaymentServer/ride/payMob/paymob_driver/paymet_verfy.php";
static String updatePaymetToPaid =
"$seferPaymentServer/ride/payment/updatePaymetToPaid.php";

View File

@@ -188,16 +188,16 @@ Download the Tripz app now and enjoy your ride!
(driverInvitationData[index]['driverInviterId']),
('500'),
);
await Get.find<CaptainWalletController>()
.addSeferWallet('giftInvitation', ('-1000'));
// await Get.find<CaptainWalletController>()
// .addSeferWallet('giftInvitation', ('-1000'));
NotificationCaptainController().addNotificationCaptain(
driverInvitationData[index]['driverInviterId'].toString(),
"You have got a gift for invitation".tr,
'${"You have 500".tr} ${'LE'}',
'${"You have 500".tr} ${'LE'.tr}',
false);
NotificationController().showNotification(
"You have got a gift for invitation".tr,
'${"You have 500".tr} ${'LE'}',
'${"You have 500".tr} ${'LE'.tr}',
'tone1',
'');
} else {
@@ -264,6 +264,7 @@ Download the Tripz app now and enjoy your ride!
link: AppLink.updatePassengerGift,
payload: {'id': driverInvitationDataToPassengers[index]['id']},
);
// Notify the inviter
NotificationCaptainController().addNotificationCaptain(
driverInvitationDataToPassengers[index]['passengerInviterId']

View File

@@ -98,7 +98,7 @@ class LoginDriverController extends GetxController {
final random = Random();
if (random.nextBool()) {
// await SecurityHelper.performSecurityChecks();
await SecurityHelper.performSecurityChecks();
} else {
await SecurityChecks.isDeviceRootedFromNative(Get.context!);
}
@@ -145,20 +145,21 @@ class LoginDriverController extends GetxController {
);
if (response0.statusCode == 200) {
final decodedResponse1 = jsonDecode(response0.body);
// Log.print('decodedResponse1: ${decodedResponse1}');
Log.print('decodedResponse1: ${decodedResponse1}');
final jwt = decodedResponse1['jwt'];
box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs));
// await box.write(BoxName.hmac, decodedResponse1['hmac']);
await AppInitializer().getAIKey(Driver.keyOfApp);
await AppInitializer().getAIKey(Driver.initializationVector);
await Future.delayed(Duration.zero);
await EncryptionHelper.initialize();
await AppInitializer().getAIKey(Driver.payMobApikey);
await AppInitializer().getAIKey(Driver.FCM_PRIVATE_KEY);
await AppInitializer().getAIKey(Driver.initializationVector);
await AppInitializer().getAIKey(Driver.keyOfApp);
// ✅ بعد التأكد أن كل المفاتيح موجودة
await EncryptionHelper.initialize();
await AppInitializer().getKey();
} else {}
} else {

View File

@@ -44,7 +44,7 @@ class AccessTokenManager {
_accessToken = client.credentials.accessToken;
_expiryDate = client.credentials.accessToken.expiry;
client.close();
Log.print('_accessToken!.data: ${_accessToken!.data}');
// Log.print('_accessToken!.data: ${_accessToken!.data}');
return _accessToken!.data;
} catch (e) {
throw Exception('Failed to obtain access token');

View File

@@ -14,6 +14,7 @@ import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../main.dart';
import '../../print.dart';
import '../../views/auth/captin/criminal_documents_page.dart';
import '../../views/home/Captin/home_captain/home_captin.dart';
import '../../views/home/Captin/orderCaptin/order_speed_request.dart';
@@ -180,6 +181,7 @@ class FirebaseMessagesController extends GetxController {
'Trip Cancelled. The cost of the trip will be added to your wallet.'
.tr, () {
box.write(BoxName.rideStatus, 'Cancel');
Log.print('rideStatus from 184 : ${box.read(BoxName.rideStatus)}');
Get.offAll(HomeCaptain());
});
// cancelTripDialog1();
@@ -341,6 +343,8 @@ class FirebaseMessagesController extends GetxController {
title: 'Ok'.tr,
onPressed: () {
box.write(BoxName.rideStatus, 'Cancel');
Log.print(
'rideStatus from 347 : ${box.read(BoxName.rideStatus)}');
Get.offAll(HomeCaptain());
}));
}
@@ -356,6 +360,8 @@ class FirebaseMessagesController extends GetxController {
title: 'Ok'.tr,
onPressed: () {
box.write(BoxName.rideStatus, 'Cancel');
Log.print(
'rideStatus from 364 : ${box.read(BoxName.rideStatus)}');
Get.offAll(HomeCaptain());
}));
}
@@ -405,7 +411,7 @@ class FirebaseMessagesController extends GetxController {
Future<void> onInit() async {
super.onInit();
try {
var encryptedKey = await storage.read(key: 'FCM_PRIVATE_KEY');
var encryptedKey = await storage.read(key: BoxName.FCM_PRIVATE_KEY);
// Log.print('encryptedKey: ${encryptedKey}');
if (encryptedKey != null) {
serviceAccountKeyJson =
@@ -707,32 +713,39 @@ class FirebaseMessagesController extends GetxController {
if (response.statusCode == 200) {
print(
'Notification sent successfully. Status code: ${response.statusCode}');
print('Response body: ${response.body}');
} else if (response.statusCode == 404) {
// Handle UNREGISTERED token
final responseBody = jsonDecode(response.body);
final errorCode = responseBody['error']['details']?[0]?['errorCode'];
if (errorCode == 'UNREGISTERED') {
print('Token is unregistered/invalid: $token');
// Remove token from your database
await removeInvalidToken(token);
return; // Don't retry for invalid tokens
}
} else {
print(
'Failed to send notification. Status code: ${response.statusCode}');
print('Response body: ${response.body}');
if (retryCount > 0) {
print('Retrying... Attempts remaining: $retryCount');
await Future.delayed(
const Duration(seconds: 2)); // Optional delay before retrying
return sendNotificationToPassengerTokenCALL(
title, body, token, data, tone,
await Future.delayed(const Duration(seconds: 2));
return sendNotificationToDriverMAP(title, body, token, data, tone,
retryCount: retryCount - 1);
}
}
} catch (e) {
print('Error sending notification: $e');
if (retryCount > 0) {
print('Retrying... Attempts remaining: $retryCount');
await Future.delayed(
const Duration(seconds: 2)); // Optional delay before retrying
return sendNotificationToPassengerTokenCALL(
title, body, token, data, tone,
retryCount: retryCount - 1);
// ... existing error handling ...
}
}
Future<void> removeInvalidToken(String token) async {
// Remove token from your database/storage
// This prevents future attempts to send to invalid tokens
print('Removing invalid token from database: $token');
// Your database cleanup logic here
}
}

View File

@@ -522,7 +522,7 @@ class NotificationController extends GetxController {
if (data is String) {
var orderData = jsonDecode(data);
if (orderData is List && orderData.length == 34) {
closeOverLay();
//closeOverLay();
Get.put(HomeCaptainController()).changeRideId();
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
} else {
@@ -537,7 +537,7 @@ class NotificationController extends GetxController {
if (data is String) {
var orderData = jsonDecode(data);
if (orderData is List && orderData.length == 34) {
closeOverLay();
//closeOverLay();
Get.put(HomeCaptainController()).changeRideId();
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
} else {
@@ -550,7 +550,7 @@ class NotificationController extends GetxController {
void _handleADSNotification() {
// var orderData = jsonDecode(data);
closeOverLay();
//closeOverLay();
Get.to(
() => const NotificationCaptain(),
);

View File

@@ -94,9 +94,9 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
},
);
Log.print('response.request: ${response.request}');
Log.print('response.body: ${response.body}');
print(payload);
// Log.print('response.request: ${response.request}');
// Log.print('response.body: ${response.body}');
// print(payload);
if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
if (jsonData['status'] == 'success') {
@@ -128,11 +128,13 @@ class CRUD {
Future<dynamic> postWallet(
{required String link, Map<String, dynamic>? payload}) async {
var s = await LoginDriverController().getJwtWallet();
// Log.print('jwt: ${s}');
final hmac = box.read(BoxName.hmac);
Log.print('hmac: ${hmac}');
// Log.print('hmac: ${hmac}');
var url = Uri.parse(link);
// Log.print('url: ${url}');
try {
await LoginDriverController().getJWT();
// await LoginDriverController().getJWT();
var response = await http.post(
url,
@@ -143,9 +145,9 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
},
);
print(response.request);
Log.print('response.body: ${response.body}');
print(payload);
// Log.print('response.request:${response.request}');
// Log.print('response.body: ${response.body}');
// Log.print('payload:$payload');
if (response.statusCode == 200) {
try {
var jsonData = jsonDecode(response.body);
@@ -201,9 +203,9 @@ class CRUD {
// 'Authorization': 'Bearer ${box.read(BoxName.jwt)}'
},
);
print(response.request);
Log.print('response.body: ${response.body}');
print(payload);
// print(response.request);
// Log.print('response.body: ${response.body}');
// print(payload);
if (response.statusCode == 200) {
try {
var jsonData = jsonDecode(response.body);
@@ -439,22 +441,46 @@ class CRUD {
}
}
sendEmail(
String link,
Map<String, String>? payload,
) async {
var headers = {
Future<void> sendEmail(String link, Map<String, String>? payload) async {
// التحقق من صلاحية التوكن
String rawJwt = box.read(BoxName.jwt);
String token = X
.r(X.r(X.r(rawJwt, cn), cC), cs)
.toString()
.split(AppInformation.addd)[0];
bool isTokenExpired = JwtDecoder.isExpired(token);
if (isTokenExpired) {
await LoginDriverController().getJWT();
rawJwt = box.read(BoxName.jwt); // تحديث التوكن بعد التجديد
token = X
.r(X.r(X.r(rawJwt, cn), cC), cs)
.toString()
.split(AppInformation.addd)[0];
}
// إعداد الهيدر
final headers = {
"Content-Type": "application/x-www-form-urlencoded",
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
"Authorization": "Bearer $token",
};
var request = http.Request('POST', Uri.parse(link));
request.bodyFields = payload!;
// إعداد الطلب
final request = http.Request('POST', Uri.parse(link));
request.bodyFields = payload ?? {};
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
// إرسال الطلب
final response = await request.send();
// التحقق من النتيجة
if (response.statusCode == 200) {
} else {}
print("✅ Email sent successfully.");
} else {
print("❌ Failed to send email. Status: ${response.statusCode}");
final responseBody = await response.stream.bytesToString();
print("Response body: $responseBody");
}
}
Future<dynamic> postFromDialogue({

View File

@@ -105,7 +105,7 @@ class AI extends GetxController {
NotificationController().showNotification(
"Code approved".tr, "Code approved".tr, 'tone2', '');
// Notification text with dynamic token
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
'You have received a gift token!'.tr,
'for '.tr + box.read(BoxName.phoneDriver).toString(),
jsonDecode(res)['message'][0]['token'].toString(),

View File

@@ -133,8 +133,8 @@ class LocationController extends GetxController {
// ✅ إدخال للسيرفر كل دقيقة
_insertCounter++;
Log.print('_insertCounter: ${_insertCounter}');
if (_insertCounter >= 12) {
// Log.print('_insertCounter: ${_insertCounter}');
if (_insertCounter == 12) {
_insertCounter = 0;
await CRUD().post(
link: box.read(BoxName.serverChosen) + '/ride/location/add.php',

View File

@@ -247,15 +247,15 @@ class SecurityHelper {
await box.write('isTampered', isTampered); // Use await
await box.write('isJailBroken', isJailBroken); // Use await
debugPrint("Security Check Results:");
debugPrint("isNotTrust: $isNotTrust");
debugPrint("isJailBroken: $isJailBroken");
debugPrint("isRealDevice: $isRealDevice");
debugPrint("isOnExternalStorage: $isOnExternalStorage");
debugPrint("checkForIssues: $checkForIssues");
debugPrint("isDevMode: $isDevMode");
debugPrint("isTampered: $isTampered");
debugPrint("Bundle ID: $bundleId"); // Print the bundle ID
// debugPrint("Security Check Results:");
// debugPrint("isNotTrust: $isNotTrust");
// debugPrint("isJailBroken: $isJailBroken");
// debugPrint("isRealDevice: $isRealDevice");
// debugPrint("isOnExternalStorage: $isOnExternalStorage");
// debugPrint("checkForIssues: $checkForIssues");
// debugPrint("isDevMode: $isDevMode");
// debugPrint("isTampered: $isTampered");
// debugPrint("Bundle ID: $bundleId"); // Print the bundle ID
// Check for security risks and potentially show a warning
if (isJailBroken || isRealDevice == false || isTampered) {

View File

@@ -40,7 +40,6 @@ class AppInitializer {
Future<void> initializeApp() async {
if (box.read(BoxName.jwt) == null) {
Log.print('box.read(BoxName.jwt): ${box.read(BoxName.jwt)}');
await LoginDriverController().getJWT();
} else {
bool isTokenExpired = JwtDecoder.isExpired(X
@@ -55,15 +54,18 @@ class AppInitializer {
// await getKey();
}
getAIKey(String key1) async {
if (box.read(BoxName.firstTimeLoadKey) == null) {
Future<void> getAIKey(String key1) async {
var res =
await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key1});
if (res != 'failure') {
var d = jsonDecode(res)['message'];
await storage.write(key: key1, value: d[key1].toString());
final rawValue = d[key1].toString();
// ✅ اكتبها في storage
await storage.write(key: key1, value: rawValue);
await Future.delayed(Duration.zero);
} else {}
}
}

View File

@@ -12,8 +12,10 @@ import '../../../constant/links.dart';
import '../../../constant/style.dart';
import '../../../constant/table_names.dart';
import '../../../main.dart';
import '../../../print.dart';
import '../../../views/home/my_wallet/walet_captain.dart';
import '../../../views/widgets/elevated_btn.dart';
import '../../firebase/firbase_messge.dart';
import '../../functions/crud.dart';
import '../../functions/location_background_controller.dart';
import '../../functions/location_controller.dart';
@@ -264,7 +266,7 @@ class HomeCaptainController extends GetxController {
@override
void onInit() async {
// await locationBackController.requestLocationPermission();
Get.put(FirebaseMessagesController());
addToken();
await getlocation();
onButtonSelected();
@@ -429,6 +431,7 @@ class HomeCaptainController extends GetxController {
void changeToAppliedRide(String status) {
box.write(BoxName.rideStatus, status);
Log.print('rideStatus from homcaptain : ${box.read(BoxName.rideStatus)}');
update();
}

View File

@@ -25,6 +25,7 @@ import '../../firebase/firbase_messge.dart';
import '../../functions/crud.dart';
import '../../functions/encrypt_decrypt.dart';
import '../../functions/location_controller.dart';
import '../../functions/tts.dart';
class MapDriverController extends GetxController {
bool isLoading = true;
@@ -174,7 +175,7 @@ class MapDriverController extends GetxController {
cancelTripFromDriverAfterApplied() async {
if (formKeyCancel.currentState!.validate()) {
box.write(BoxName.statusDriverLocation, 'off');
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
"Cancel Trip from driver",
"Trip Cancelled from driver. We are looking for a new driver. Please wait."
.tr,
@@ -235,6 +236,8 @@ class MapDriverController extends GetxController {
'created_at': DateTime.now().toString(),
'driver_id': box.read(BoxName.driverID).toString(),
}, TableName.driverOrdersRefuse);
box.write(BoxName.rideStatus, 'Cancel');
Log.print('rideStatus from map 240 : ${box.read(BoxName.rideStatus)}');
Get.find<HomeCaptainController>().getRefusedOrderByCaptain();
Get.offAll(() => HomeCaptain());
}
@@ -242,6 +245,7 @@ class MapDriverController extends GetxController {
void startTimerToShowPassengerInfoWindowFromDriver() async {
if (box.read(BoxName.rideStatus) == 'Begin') {
Log.print('rideStatus from map 248 : ${box.read(BoxName.rideStatus)}');
isPassengerInfoWindow = false;
} else {
isPassengerInfoWindow = true;
@@ -298,6 +302,7 @@ class MapDriverController extends GetxController {
void driverGoToPassenger() async {
changeRideToBeginToPassenger();
box.write(BoxName.rideStatus, 'Applied');
Log.print('rideStatus from map 304 : ${box.read(BoxName.rideStatus)}');
update();
await CRUD().post(
link: "${AppLink.seferCairoServer}/ride/rides/update.php",
@@ -315,7 +320,7 @@ class MapDriverController extends GetxController {
}
// Get.find<HomeCaptainController>().changeToAppliedRide('Applied');
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'Driver Is Going To Passenger'.tr,
box.read(BoxName.nameDriver).toString(), //todo name driver
tokenPassenger,
@@ -392,6 +397,7 @@ class MapDriverController extends GetxController {
// todo ride details
// Get.find<HomeCaptainController>().changeToAppliedRide('Begin');
box.write(BoxName.rideStatus, 'Begin');
Log.print('rideStatus from map 399 : ${box.read(BoxName.rideStatus)}');
// Get.find<HomeCaptainController>().update();
update();
await CRUD().post(link: AppLink.updateRides, payload: {
@@ -418,7 +424,7 @@ class MapDriverController extends GetxController {
'status': 'Begin'
});
}
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'Trip is Begin'.tr,
box.read(BoxName.nameDriver).toString(),
tokenPassenger,
@@ -584,17 +590,29 @@ class MapDriverController extends GetxController {
}
}
void finishRideFromDriver() {
Future<void> finishRideFromDriver() async {
double distanceToDestination = Geolocator.distanceBetween(
latLngPassengerLocation.latitude,
latLngPassengerLocation.longitude,
latLngPassengerDestination.latitude,
latLngPassengerDestination.longitude,
Get.find<LocationController>().myLocation.latitude,
Get.find<LocationController>().myLocation.longitude,
);
final originalDistanceM = double.parse(distance.toString()) * 1000;
if (distanceToDestination > (double.parse(distance.toString()) / 3)) {
Log.print('distanceToDestination: ${distanceToDestination}');
// 2. احسب المسافة التي قطعها السائق حتى الآن
final movedDistanceM = originalDistanceM - distanceToDestination;
// 3. عتبة ثلث المسافة
final oneThirdDistanceM = originalDistanceM / 3;
// Logging للتتبع
Log.print('originalDistanceM: $originalDistanceM');
Log.print('distanceToDestinationM: $distanceToDestination');
Log.print('movedDistanceM: $movedDistanceM');
Log.print('oneThirdDistanceM: $oneThirdDistanceM');
// 4. إذا لم يقطع السائق ثلث المسافة، نعرض التأكيد
if (movedDistanceM < oneThirdDistanceM) {
MyDialog().getDialog(
'Are you sure to exit ride?'.tr,
'',
@@ -603,33 +621,39 @@ class MapDriverController extends GetxController {
finishRideFromDriver1();
},
);
} else {
} /////
else {
final textToSpeechController = Get.put(TextToSpeechController());
MyDialog().getDialog(
"You haven't moved sufficiently!".tr,
'',
() => Get.back(),
);
await textToSpeechController
.speakText("You haven't moved sufficiently!".tr);
}
}
String paymentToken = '';
Future<String> generateTokenDriver(String amount) async {
var res = await CRUD().post(link: AppLink.addPaymentTokenDriver, payload: {
var res =
await CRUD().postWallet(link: AppLink.addPaymentTokenDriver, payload: {
'driverID': box.read(BoxName.driverID).toString(),
'amount': amount.toString(),
});
var d = jsonDecode(res);
var d = (res);
return d['message'];
}
String paymentTokenPassenger = '';
Future<String> generateTokenPassenger(String amount) async {
var res =
await CRUD().post(link: AppLink.addPaymentTokenPassenger, payload: {
var res = await CRUD()
.postWallet(link: AppLink.addPaymentTokenPassenger, payload: {
'passengerId': passengerId,
'amount': amount.toString(),
});
var d = jsonDecode(res);
var d = (res);
return d['message'];
}
@@ -638,6 +662,7 @@ class MapDriverController extends GetxController {
isRideStarted = false;
isPriceWindow = false;
box.write(BoxName.rideStatus, 'Finished');
Log.print('rideStatus from map 664 : ${box.read(BoxName.rideStatus)}');
// Calculate totalCost more concisely
if (price < 20) {
@@ -699,7 +724,8 @@ class MapDriverController extends GetxController {
if (walletChecked == 'true') {
paymentToken = await generateTokenPassenger(
((-1) * double.parse(paymentAmount)).toString());
futures.add(CRUD().post(link: AppLink.addPassengersWallet, payload: {
futures
.add(CRUD().postWallet(link: AppLink.addPassengersWallet, payload: {
'passenger_id': (passengerId),
'balance': ((-1) * double.parse(paymentAmount)).toString(),
'token': paymentToken,
@@ -707,7 +733,7 @@ class MapDriverController extends GetxController {
}
paymentToken = await generateTokenDriver(paymentAmount.toString());
futures.add(CRUD().post(link: AppLink.addDrivePayment, payload: {
futures.add(CRUD().postWallet(link: AppLink.addDrivePayment, payload: {
'rideId': (rideId),
'amount': paymentAmount,
'payment_method':
@@ -720,7 +746,8 @@ class MapDriverController extends GetxController {
if (double.parse(passengerWalletBurc) < 0) {
final paymentToken1 = await generateTokenPassenger(
((-1) * double.parse(passengerWalletBurc)).toString());
futures.add(CRUD().post(link: AppLink.addPassengersWallet, payload: {
futures
.add(CRUD().postWallet(link: AppLink.addPassengersWallet, payload: {
'passenger_id': (passengerId),
'token': paymentToken1,
'balance': ((-1) * double.parse(passengerWalletBurc)).toString()
@@ -730,7 +757,8 @@ class MapDriverController extends GetxController {
double pointsSubtraction = double.parse(paymentAmount) * (-1) * 0.08;
final paymentToken2 =
await generateTokenDriver((pointsSubtraction).toStringAsFixed(0));
futures.add(CRUD().post(link: AppLink.addDriversWalletPoints, payload: {
futures
.add(CRUD().postWallet(link: AppLink.addDriversWalletPoints, payload: {
'paymentID': 'rideId${(rideId)}',
'amount': (pointsSubtraction).toStringAsFixed(0),
'paymentMethod': paymentMethod,
@@ -743,7 +771,7 @@ class MapDriverController extends GetxController {
Get.put(DriverBehaviorController()).sendSummaryToServer(driverId, rideId);
// Send notification (this likely depends on previous steps)
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
"Driver Finish Trip".tr,
'${'you will pay to Driver'.tr} $paymentAmount \$',
tokenPassenger,
@@ -862,7 +890,7 @@ class MapDriverController extends GetxController {
// 'driverID': box.read(BoxName.driverID).toString(),
// });
// Future.delayed(const Duration(milliseconds: 300));
// FirebaseMessagesController().sendNotificationToDriverMAP(
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
// "Driver Finish Trip".tr,
// '${'you will pay to Driver'.tr} $paymentAmount \$',
// tokenPassenger,
@@ -1362,7 +1390,8 @@ class MapDriverController extends GetxController {
void onInit() async {
mapAPIKEY = await storage.read(key: BoxName.mapAPIKEY);
// Get the passenger location from the arguments.
// await argumentLoading();
await argumentLoading();
Get.put(FirebaseMessagesController());
runGoogleMapDirectly();
addCustomCarIcon();
addCustomPassengerIcon();

View File

@@ -82,7 +82,7 @@ class CaptainWalletController extends GetxController {
//get new driver details
isNewTransfer = true;
update();
var res = await CRUD().getWallet(
var res = await CRUD().get(
link: AppLink.getDriverDetails,
payload: {'driver_phone': '+2${newDriverPhoneController.text}'});
isNewTransfer = false;
@@ -155,7 +155,7 @@ class CaptainWalletController extends GetxController {
'driverID': box.read(BoxName.driverID).toString(),
'amount': amount.toString(),
});
var d = jsonDecode(res);
var d = (res);
return d['message'];
}
@@ -168,14 +168,14 @@ class CaptainWalletController extends GetxController {
'amount': amount.toString(),
'payment_method': paymentMethod.toString(),
});
var d = jsonDecode(res);
var d = (res);
// paymentID = d['message'].toString();
return d['message'];
}
Future addDriverWallet(String paymentMethod, point, count) async {
paymentToken = await generateToken(count);
var paymentID = await getPaymentId(paymentMethod, point);
var paymentID = await getPaymentId(paymentMethod, point.toString());
await CRUD().postWallet(link: AppLink.addDriversWalletPoints, payload: {
'driverID': box.read(BoxName.driverID).toString(),
'paymentID': paymentID.toString(),
@@ -245,7 +245,8 @@ class CaptainWalletController extends GetxController {
'payment_method': paymentMethod.toString(),
'passengerID': paymentMethod,
});
await addSeferWallet(paymentMethod, (double.parse(point) * -1).toString());
await addSeferWallet(paymentMethod,
(double.parse(point) * -2).toString()); // deduct 2 from sefer wallet
}
Future addSeferWallet(String paymentMethod, String point) async {
@@ -290,7 +291,7 @@ class CaptainWalletController extends GetxController {
'paymentMethod': paymentMethod2.toString(),
});
if (res1 != 'failure') {
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'Transfer',
'${'You have transfer to your wallet from'.tr}'
'${box.read(BoxName.nameDriver)}',

View File

@@ -1,15 +1,12 @@
import 'dart:convert';
import 'package:local_auth/local_auth.dart';
import 'package:sefer_driver/constant/api_key.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/main.dart';
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:secure_string_operations/secure_string_operations.dart';
import '../../../constant/char_map.dart';
import '../../../constant/links.dart';
import '../../../views/widgets/mydialoug.dart';
import '../../functions/crud.dart';
@@ -19,39 +16,8 @@ class PaymobPayout extends GetxController {
bool isLoading = false;
String dropdownValue = 'etisalat';
Future<String> getToken() async {
var headers = {
'Content-Type': 'application/x-www-form-urlencoded',
// 'Cookie':
// 'csrftoken=74iZJ8XYyuTm5WRq2W4tpWX5eqoJLZVK5QhuDrChWpDtzpgGA269bbCWuEcW85t4'
};
var payMobOutClientSecrret =
X.r(X.r(X.r(await getAIKey(KN.pmobsec), cn), cC), cs);
var payMobOutClientId =
X.r(X.r(X.r(await getAIKey(KN.pmobid), cn), cC), cs);
var body = {
'grant_type': 'password',
'username': AK.payMobOutUserName,
'password': AK.payMobOutPassword,
'client_id': payMobOutClientId,
'client_secret': payMobOutClientSecrret
};
var res = await http.post(
Uri.parse('https://payouts.paymobsolutions.com/api/secure/o/token/'),
headers: headers,
body: body,
);
String token = '';
if (res.statusCode == 200) {
var decode = jsonDecode(res.body);
token = decode['access_token'];
}
return token;
}
int payOutFee = 5;
payToDriverWallet(
String token, String amount, String issuer, String msisdn) async {
payToDriverWallet(String amount, String issuer, String msisdn) async {
bool isAvailable = await LocalAuthentication().isDeviceSupported();
if (isAvailable) {
// Authenticate the user
@@ -62,21 +28,18 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
var headers = {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
};
var body = json.encode({
"amount": amount, //"10.00",
"issuer": issuer, //"vodafone",
"msisdn": msisdn, // "01023456789"
var dec = await CRUD().postWallet(
link:
'wl.tripz-egypt.com/v1/main/ride/payMob/paymob_driver/paymob_payout.php',
payload: {
"issuer": issuer,
"method": "wallet",
"amount": amount, //9.0,
"full_name":
'${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}',
"msisdn": msisdn, //"01010101010",
"bank_transaction_type": "cash_transfer"
});
var res = await http.post(
Uri.parse('https://payouts.paymobsolutions.com/api/secure/disburse/'),
headers: headers,
body: body,
);
var dec = jsonDecode(res.body);
if (dec['disbursement_status'] == 'successful') {
var paymentToken = await Get.find<CaptainWalletController>()
.generateToken(
@@ -149,8 +112,8 @@ class PaymobPayout extends GetxController {
} else {}
}
payToDriverBankAccount(String token, String amount, String bankCardNumber,
String bankCode) async {
payToDriverBankAccount(
String amount, String bankCardNumber, String bankCode) async {
bool isAvailable = await LocalAuthentication().isDeviceSupported();
if (isAvailable) {
// Authenticate the user
@@ -161,12 +124,9 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
var headers = {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json',
};
var body = {
"issuer": "bank_card",
"method": "bank_card",
"amount": amount, //9.0,
"full_name":
'${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}',
@@ -174,12 +134,11 @@ class PaymobPayout extends GetxController {
"bank_code": bankCode, //"CIB",
"bank_transaction_type": "cash_transfer"
};
var res = await http.post(
Uri.parse('https://payouts.paymobsolutions.com/api/secure/disburse/'),
headers: headers,
body: body,
var dec = await CRUD().postWallet(
link:
'wl.tripz-egypt.com/v1/main/ride/payMob/paymob_driver/paymob_payout.php',
payload: body,
);
var dec = jsonDecode(res.body);
if (dec['disbursement_status'] == 'successful') {
var paymentToken = await Get.find<CaptainWalletController>()
.generateToken(
@@ -236,8 +195,7 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
String token = await getToken();
await payToDriverWallet(token, amount, issuer, msisdn);
await payToDriverWallet(amount, issuer, msisdn);
} else {
MyDialog().getDialog('Authentication failed'.tr, ''.tr, () {
Get.back();
@@ -263,8 +221,7 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
String token = await getToken();
await payToDriverBankAccount(token, amount, bankCardNumber, bankCode);
await payToDriverBankAccount(amount, bankCardNumber, bankCode);
} else {
MyDialog().getDialog('Authentication failed'.tr, ''.tr, () {
Get.back();

View File

@@ -65,6 +65,17 @@ class MyTranslation extends Translations {
"Order Applied": "تم تطبيق الطلب",
//firebase above
"payment_success": "تمت العملية بنجاح",
"transaction_id": "رقم العملية",
"amount_paid": "المبلغ المدفوع",
"bonus_added": "البونص المضاف",
"points": "نقطة",
"transaction_failed": "فشل العملية",
"connection_failed": "فشل الاتصال",
"server_error": "خطأ في الخادم",
"server_error_message": "حدث خطأ أثناء الاتصال بالخادم",
"cancel": "إلغاء", "Syria": "‏سوريا",
"Security Warning": "تحذير أمني",
"Potential security risks detected. The application will close in @seconds seconds.":
@@ -75,7 +86,28 @@ class MyTranslation extends Translations {
"Security Warning": "⚠️ تحذير أمني",
"Potential security risks detected. The application may not function correctly.":
"تم اكتشاف ثغرات أمنية على هذا الجهاز. للحفاظ على أمان بياناتك، سيتم حذف جميع البيانات وإغلاق التطبيق.",
"How to use Tripz": "كيفية استخدام Tripz",
"What are the order details we provide to you?":
"ما هي تفاصيل الطلب التي نوفرها لك؟",
"Tripz Wallet Features:\n\nTransfer money multiple times.\nTransfer to anyone.\nMake purchases.\nCharge your account.\nCharge a friend's Tripz account.\nStore your money with us and receive it in your bank as a monthly salary.":
"ميزات محفظة Tripz:\n\nتحويل الأموال عدة مرات.\nالتحويل إلى أي شخص.\nإجراء عمليات شراء.\nشحن حسابك.\nشحن حساب Tripz لصديق.\nقم بتخزين أموالك معنا واستلامها في بنكك كراتب شهري.",
"What is the feature of our wallet?": "ما هي مميزات محفظتنا؟",
"What is Types of Trips in Tripz?": "ما هي أنواع الرحلات في Tripz؟",
'''Types of Trips in Tripz:
Comfort: For cars newer than 2017 with air conditioning.
Lady: For girl drivers.
Speed: For fixed salary and endpoints.
Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.
Raih Gai: For same-day return trips longer than 50km.
''': """أنواع الرحلات في Tripz:
راحة: للسيارات الأحدث من 2017 مع تكييف الهواء.
للسائقات الإناث.
سبيد: براتب ثابت ونقاط نهاية محددة.
مشاوير: للرحلات المرنة حيث يختار الركاب السيارة والسائق باتفاق مسبق.
رحّي غاي: للرحلات ذات العودة في نفس اليوم التي تزيد عن 50 كم.
""",
"I will go now": "هروح دلوقتي",
"Yes": "أيوة",
"No,I want": "لا، أنا عاوز",

View File

@@ -67,7 +67,7 @@ class RateController extends GetxController {
'driverID': box.read(BoxName.driverID).toString(),
});
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'Wallet Added'.tr,
'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr,
Get.find<MapDriverController>().tokenPassenger,

View File

@@ -1,9 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/payment/paymob/paymob_response.dart';
import 'package:sefer_driver/views/home/Captin/orderCaptin/order_request_page.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -15,103 +12,102 @@ import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'constant/api_key.dart';
import 'constant/info.dart';
import 'constant/notification.dart';
import 'controller/firebase/firbase_messge.dart';
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/local/local_controller.dart';
import 'controller/local/translations.dart';
import 'controller/payment/paymob/paymob_wallet.dart';
import 'firebase_options.dart';
import 'models/db_sql.dart';
import 'print.dart';
import 'splash_screen_page.dart';
import 'views/home/Captin/driver_map_page.dart';
import 'views/home/Captin/orderCaptin/order_over_lay.dart';
//--- Global Variables ---
final box = GetStorage();
const storage = FlutterSecureStorage();
final PaymobPayment paymobPayment = PaymobPayment();
final PaymobPaymentWallet paymobPaymentWallet = PaymobPaymentWallet();
DbSql sql = DbSql.instance;
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
const platform = MethodChannel('com.sefer_driver/app_control');
//--- Entry Points for Background/Terminated States ---
@pragma('vm:entry-point')
Future<void> backgroundMessageHandler(RemoteMessage message) async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await GetStorage.init();
if (!await FlutterOverlayWindow.isPermissionGranted()) {
// بإمكانك تجاهل الطلب في الخلفية والاكتفاء بالتنبيه
Log.print("Overlay permission not granted; showing only notification.");
}
if (Platform.isAndroid) {
if (message.notification != null && message.notification!.title != null) {
Log.print('message.notification!.title: ${message.notification!.title}');
if (message.notification?.title == 'طلب' ||
if (message.notification?.title == 'Order' ||
message.notification?.title == 'OrderSpeed') {
var myListString = message.data['DriverList'] ?? '[]';
Log.print('myListString: $myListString');
// Decode the JSON string to a list
List<dynamic> myList;
try {
myList = jsonDecode(myListString) as List<dynamic>;
Log.print('myList: ${myList}');
} catch (e) {
Log.print('Error decoding JSON: $e');
myList = [];
}
await Future.delayed(const Duration(seconds: 1));
bool isOverlayActive = await FlutterOverlayWindow.isActive();
if (isOverlayActive) {
await FlutterOverlayWindow.closeOverlay();
}
await FlutterOverlayWindow.shareData(myList);
} else {
await FlutterOverlayWindow.showOverlay(
enableDrag: true,
flag: OverlayFlag.focusPointer,
// visibility: NotificationVisibility.visibilityPublic,
positionGravity: PositionGravity.auto,
height: 1300,
height: 1400,
width: WindowSize.matchParent,
startPosition: const OverlayPosition(0, -40),
startPosition: const OverlayPosition(0, -30),
);
await FlutterOverlayWindow.shareData(myList);
}
// It's better to manage notifications in one place if possible
// but this is fine if it works for you.
NotificationController().showNotification(
message.notification!.title.toString(),
message.notification!.body.toString(),
'order',
myListString,
);
await FlutterOverlayWindow.shareData(myList);
}
} else {
// Handle other types of notifications
FirebaseMessagesController().fireBaseTitles(message);
}
}
}
}
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
// handle background notification taps here
print('Notification tapped in background!');
Log.print('Notification tapped in background!');
NotificationController().handleNotificationResponse(notificationResponse);
// You can add your logic here to handle the notification tap
}
@pragma('vm:entry-point')
void overlayMain() async {
WidgetsFlutterBinding.ensureInitialized();
await GetStorage.init();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: OrderOverlay(),
@@ -119,12 +115,12 @@ void overlayMain() async {
}
Future<void> closeOverLay() async {
// FlutterOverlayWindow.closeOverlay();
bool isOverlayActive = await FlutterOverlayWindow.isActive();
if (isOverlayActive) {
await FlutterOverlayWindow.closeOverlay();
}
}
//--- Main Application ---
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -136,21 +132,29 @@ void main() async {
DeviceOrientation.portraitDown,
]);
runApp(MyApp());
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_initApp();
}
@override
void dispose() {
super.dispose();
}
Future<void> _initApp() async {
try {
await Firebase.initializeApp(
@@ -159,62 +163,23 @@ class _MyAppState extends State<MyApp> {
await initializer.initializeApp();
await EncryptionHelper.initialize();
if (Platform.isAndroid || Platform.isIOS) {
Get.put(
NotificationController()); // Initialize NotificationController here
Get.put(NotificationController());
Get.put(FirebaseMessagesController());
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",
);
// You can add your other initializations here
// For example:
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 = (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,
);
}
}
// Your other startup logic...
} catch (e) {
print("Error initializing app: $e");
// Handle initialization errors appropriately. Maybe show an error message to the user.
Log.print("Error during _initApp: $e");
}
}
//--- Build Method ---
@override
Widget build(BuildContext context) {
LocaleController localController = Get.put(LocaleController());
@@ -231,105 +196,11 @@ class _MyAppState extends State<MyApp> {
GetPage(
name: '/order-page',
page: () => OrderRequestPage(),
arguments: box.read(BoxName.rideArguments),
),
GetPage(
name: '/passenger-location-map',
page: () => PassengerLocationMapPage()),
],
);
}
}
// 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

@@ -1,16 +1,18 @@
// lib/models/order_data.dart
// lib/models/model/order_data.dart
class OrderData {
final String customerName;
final double tripDistanceKm; // المسافة الكلية للرحلة بالكيلومتر
final String customerToken;
final double tripDistanceKm; // The total trip distance in kilometers
final String price;
final String startLocationAddress;
final String endLocationAddress;
final double distanceToPassengerKm; // المسافة إلى الراكب بالكيلومتر
final int tripDurationMinutes; // مدة الرحلة الكلية بالدقائق (مقربة لأعلى)
final double
distanceToPassengerKm; // The distance to the passenger in kilometers
final int tripDurationMinutes; // Total trip duration in minutes (rounded up)
final int
durationToPassengerMinutes; // المدة إلى الراكب بالدقائق (مقربة لأعلى)
durationToPassengerMinutes; // Duration to reach the passenger in minutes (rounded up)
final String rideType;
final String orderId;
@@ -22,6 +24,7 @@ class OrderData {
OrderData({
required this.customerName,
required this.customerToken,
required this.tripDistanceKm,
required this.price,
required this.startLocationAddress,
@@ -37,26 +40,57 @@ class OrderData {
this.rawEndCoordinates,
});
// دالة مساعدة لتحويل الثواني إلى دقائق وتقريبها لأعلى
// --- NEW: Factory constructor to create an instance from a Map ---
// This is the missing method that was causing the error.
factory OrderData.fromMap(Map<String, dynamic> map) {
return OrderData(
// For strings, provide a default value in case the map key is null
customerName: map['customerName']?.toString() ?? 'Unknown Customer',
customerToken: map['customerToken']?.toString() ?? 'Unknown token',
// For numbers, cast from 'num' to handle both int and double, with a default value
tripDistanceKm: (map['tripDistanceKm'] as num?)?.toDouble() ?? 0.0,
price: map['price']?.toString() ?? '0',
startLocationAddress:
map['startLocationAddress']?.toString() ?? 'Unknown Address',
endLocationAddress:
map['endLocationAddress']?.toString() ?? 'Unknown Address',
distanceToPassengerKm:
(map['distanceToPassengerKm'] as num?)?.toDouble() ?? 0.0,
tripDurationMinutes: (map['tripDurationMinutes'] as num?)?.toInt() ?? 0,
durationToPassengerMinutes:
(map['durationToPassengerMinutes'] as num?)?.toInt() ?? 0,
rideType: map['rideType']?.toString() ?? 'Unknown',
orderId: map['orderId']?.toString() ?? 'N/A',
passengerId: map['passengerId']?.toString() ?? 'N/A',
passengerRate: map['passengerRate']?.toString() ?? 'N/A',
// For nullable strings, direct access is fine as it returns null if the key doesn't exist
rawStartCoordinates: map['rawStartCoordinates'],
rawEndCoordinates: map['rawEndCoordinates'],
);
}
// A helper function to convert seconds to rounded-up minutes
static int _secondsToRoundedUpMinutes(String secondsString) {
final seconds = double.tryParse(secondsString) ?? 0.0;
if (seconds <= 0) return 0;
return (seconds / 60)
.ceil(); // .ceil() لتقريب الكسر لأعلى (مثلاً 0.1 دقيقة تصبح 1 دقيقة)
.ceil(); // .ceil() rounds up (e.g., 0.1 minutes becomes 1 minute)
}
// Your existing factory for creating an instance from a List
factory OrderData.fromList(List<dynamic> list) {
// بناءً على testList والافتراضات الجديدة:
// list[4]: durationToRide (مدة الرحلة الكلية بالثواني)
// list[5]: distance (المسافة الكلية للرحلة بالكيلومتر)
// list[12]: distanceByPassenger (المسافة إلى الراكب بالمتر)
// list[15]: durationToPassenger (المدة إلى الراكب بالثواني)
double distanceToPassengerMeters =
list.length > 12 ? (double.tryParse(list[12].toString()) ?? 0.0) : 0.0;
return OrderData(
customerName: list.length > 8 ? list[8].toString() : 'Unknown Customer',
customerToken: list.length > 9 ? list[9].toString() : 'Unknown token',
tripDistanceKm:
list.length > 5 ? (double.tryParse(list[5].toString()) ?? 0.0) : 0.0,
price: list.length > 2 ? list[2].toString().split('.')[0] : '0',
@@ -66,7 +100,7 @@ class OrderData {
list.length > 30 ? list[30].toString() : 'Unknown Address',
distanceToPassengerKm:
distanceToPassengerMeters / 1000.0, // تحويل من متر إلى كيلومتر
distanceToPassengerMeters / 1000.0, // Convert meters to kilometers
tripDurationMinutes:
list.length > 4 ? _secondsToRoundedUpMinutes(list[4].toString()) : 0,
@@ -102,6 +136,7 @@ class OrderData {
}
}
// Getter to parse start coordinates
Map<String, double?>? get startCoordinates {
if (rawStartCoordinates == null) return null;
final parts = rawStartCoordinates!.split(',');
@@ -114,6 +149,7 @@ class OrderData {
return null;
}
// Getter to parse end coordinates
Map<String, double?>? get endCoordinates {
if (rawEndCoordinates == null) return null;
final parts = rawEndCoordinates!.split(',');
@@ -126,6 +162,8 @@ class OrderData {
return null;
}
// Your existing method to convert the object TO a Map.
// This is used to pass the data from the overlay to the main app.
Map<String, dynamic> toMap() {
return {
'customerName': customerName,

View File

@@ -0,0 +1,13 @@
import 'package:flutter/services.dart';
class OverlayMethodChannel {
static const _channel = MethodChannel('com.sefer_driver/app_control');
static Future<void> bringToForeground() async {
try {
await _channel.invokeMethod('bringToForeground');
} on PlatformException catch (e) {
print('Error bringing app to foreground: $e');
}
}
}

View File

@@ -104,13 +104,14 @@ class CountryPickerFromSetting extends StatelessWidget {
final List<String> countryOptions = [
'Jordan',
'USA',
"Syria",
'Egypt',
'Turkey',
'Saudi Arabia',
'Qatar',
'Bahrain',
'Kuwait',
'USA',
];
CountryPickerFromSetting({Key? key}) : super(key: key);

View File

@@ -28,7 +28,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
'Step-by-step instructions on how to request a ride through the Sefer app.'
'Step-by-step instructions on how to request a ride through the Tripz app.'
.tr,
style: AppStyle.title,
),
@@ -43,7 +43,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
'Sefer offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.'
'Tripz offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.'
.tr,
style: AppStyle.title,
),
@@ -58,7 +58,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
'Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
'Tripz offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
.tr,
style: AppStyle.title,
),
@@ -73,7 +73,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.'
'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Tripz cancellation policy for details.'
.tr,
style: AppStyle.title,
),
@@ -98,7 +98,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
});
},
child: Text(
'Visit our website or contact Sefer support for information on driver registration and requirements.'
'Visit our website or contact Tripz support for information on driver registration and requirements.'
.tr,
style: AppStyle.title,
),
@@ -115,22 +115,22 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
'Sefer provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.'
'Tripz provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.'
.tr,
style: AppStyle.title,
),
],
),
// Question 8: What safety measures does Sefer offer?
// Question 8: What safety measures does Tripz offer?
ExpansionTile(
title: Text(
'What safety measures does Sefer offer?'.tr,
'What safety measures does Tripz offer?'.tr,
style: AppStyle.title,
),
children: [
Text(
'Sefer prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
'Tripz prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
.tr,
style: AppStyle.title,
),

View File

@@ -120,7 +120,7 @@ class SettingsCaptain extends StatelessWidget {
CupertinoListTile(
leading: const Icon(CupertinoIcons.hand_raised_fill),
title:
Text("How to use SEFER".tr, style: AppStyle.headTitle2),
Text("How to use Tripz".tr, style: AppStyle.headTitle2),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(() => const UsingAppPage()),
),

View File

@@ -10,7 +10,7 @@ class UsingAppPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MyScafolld(
title: "How to use SEFER".tr,
title: "How to use Tripz".tr,
body: [
SizedBox(
child: Padding(
@@ -22,12 +22,13 @@ class UsingAppPage extends StatelessWidget {
MyDialogContent().getDialog(
"What are the order details we provide to you?".tr,
Image.network(
'https://api.sefer.live/sefer/imageForUsingApp/order_page.jpg',
'https://api.tripz-egypt.com/tripz/imageForUsingApp/order_page.jpg',
height: 300,
width: 300,
fit: BoxFit.cover,
),
() {});
), () {
Get.back();
});
},
child: Container(
decoration: AppStyle.boxDecoration1,
@@ -47,16 +48,17 @@ class UsingAppPage extends StatelessWidget {
onTap: () {
MyDialog().getDialog(
"What are the order details we provide to you?".tr,
'''Sefer Wallet Features:
'''Tripz Wallet Features:
Transfer money multiple times.
Transfer to anyone.
Make purchases.
Charge your account.
Charge a friend's Sefer account.
Charge a friend's Tripz account.
Store your money with us and receive it in your bank as a monthly salary.'''
.tr,
() {});
.tr, () {
Get.back();
});
},
child: Container(
decoration: AppStyle.boxDecoration1,
@@ -75,8 +77,8 @@ Store your money with us and receive it in your bank as a monthly salary.'''
InkWell(
onTap: () {
MyDialog().getDialog(
"What are the order details we provide to you?".tr,
'''Types of Trips in Sefer:
"What is Types of Trips in Tripz?".tr,
'''Types of Trips in Tripz:
Comfort: For cars newer than 2017 with air conditioning.
Lady: For girl drivers.
@@ -84,15 +86,16 @@ Speed: For fixed salary and endpoints.
Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.
Raih Gai: For same-day return trips longer than 50km.
'''
.tr,
() {});
.tr, () {
Get.back();
});
},
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"What is Types of Trips in Sefer?".tr,
"What is Types of Trips in Tripz?".tr,
style: AppStyle.title,
),
),

View File

@@ -21,16 +21,20 @@ class PassengerLocationMapPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// if (!mapDriverController.initialized) {
// // Call a method to initialize the controller
// mapDriverController.initialized;
// } else {
// Get.put(MapDriverController()).argumentLoading();
// Get.put(MapDriverController())
// .startTimerToShowPassengerInfoWindowFromDriver();
// }
if (Get.arguments != null && Get.arguments is Map<String, dynamic>) {
// نستخدم addPostFrameCallback لضمان أن هذا الكود يعمل بعد اكتمال بناء الإطار الأول
// هذا يعطي GetX وقته لتجهيز كل شيء
WidgetsBinding.instance.addPostFrameCallback((_) {
// نستدعي دالة التهيئة الجديدة ونمرر لها البيانات
mapDriverController.argumentLoading();
});
} else {
// في حال عدم وجود arguments، يجب التعامل مع هذا الخطأ
WidgetsBinding.instance.addPostFrameCallback((_) {
Get.snackbar("Error", "No order data found.");
Get.back();
});
}
mapDriverController.argumentLoading();
mapDriverController.startTimerToShowPassengerInfoWindowFromDriver();

View File

@@ -19,6 +19,7 @@ import '../../../../controller/functions/location_controller.dart';
import '../../../../controller/functions/overlay_permisssion.dart';
import '../../../../controller/functions/package_info.dart';
import '../../../../controller/home/captin/home_captain_controller.dart';
import '../../../../print.dart';
import '../../../widgets/circle_container.dart';
import '../driver_map_page.dart';
import 'widget/connect.dart';
@@ -482,6 +483,8 @@ class HomeCaptain extends StatelessWidget {
),
GetBuilder<HomeCaptainController>(
builder: (homeCaptainController) {
Log.print(
'rideStatus from home 486 : ${box.read(BoxName.rideStatus)}');
return box.read(BoxName.rideStatus) == 'Applied' ||
box.read(BoxName.rideStatus) == 'Begin'
? Positioned(
@@ -520,7 +523,7 @@ class HomeCaptain extends StatelessWidget {
};
},
icon: const Icon(
Icons.rice_bowl,
Icons.directions_rounded,
size: 29,
color: AppColor.blueColor,
),

View File

@@ -1,13 +1,21 @@
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/firebase/local_notification.dart';
import 'package:sefer_driver/main.dart';
import 'package:sefer_driver/print.dart';
import 'package:sefer_driver/views/home/Captin/driver_map_page.dart';
import 'package:sefer_driver/views/home/Captin/orderCaptin/vip_order_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
import 'package:sefer_driver/views/widgets/mydialoug.dart';
import '../../../../../constant/colors.dart';
import '../../../../../constant/links.dart';
import '../../../../../controller/firebase/firbase_messge.dart';
import '../../../../../controller/functions/crud.dart';
import '../../../../../controller/home/captin/order_request_controller.dart';
import '../../../../Rate/ride_calculate_driver.dart';
GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
@@ -17,6 +25,46 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
left: 6,
child: Column(
children: [
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
decoration: BoxDecoration(
color: AppColor.secondaryColor,
border: Border.all(color: AppColor.blueColor),
borderRadius: BorderRadius.circular(15)),
child: Builder(builder: (context) {
return IconButton(
onPressed: () async {
await checkForPendingOrderFromServer();
box.read(BoxName.rideArgumentsFromBackground) != 'failure'
? Get.to(() => PassengerLocationMapPage(),
arguments:
box.read(BoxName.rideArgumentsFromBackground))
: MyDialog().getDialog(
'Ride info'.tr,
'you dont have accepted ride'.tr,
() {
Get.back();
},
);
// Log.print(
// 'box.read(BoxName.rideArgumentsFromBackground): ${box.read(BoxName.rideArgumentsFromBackground)}');
},
icon: Icon(
Icons.directions_car_rounded,
size: 29,
color:
box.read(BoxName.rideArgumentsFromBackground) == 'failure'
? AppColor.redColor
: AppColor.greenColor,
),
);
}),
),
const SizedBox(
height: 5,
),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
@@ -89,7 +137,10 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
}),
)
: const SizedBox(),
// : const SizedBox(),
// const SizedBox(
// height: 5,
// ),
// AnimatedContainer(
// duration: const Duration(microseconds: 200),
// width: controller.widthMapTypeAndTraffic,
@@ -100,53 +151,7 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
// child: Builder(builder: (context) {
// return IconButton(
// onPressed: () async {
// final List<dynamic> testList = const [
// "32.1117875,36.0669891",
// "32.1364001,36.0707479",
// "24.84",
// "7.56",
// "436",
// "4.38",
// "109270481246447459618",
// "113172279072358305645",
// "hamza",
// "e4QWqe7K607luM7qUMOPCL:APA91bFjX4XBM4I5COJl9fyxCTKJ1ZQpT3vzY7iEbOTuT4uo0-OSCAt5zgVhlhw4aC33s-VhyucDnP1tQGFd9svaazQ8A_SKgolPk3owzug8dCsiXoPeJ0k",
// "+201010101010",
// "6",
// "43",
// "true",
// "c2tXiuBJQCSg4CU4IfqYOL:APA91bFA0f8R3QMnPQnPEEdNyjY-jcoKt4nLBHxcLLsmDSuJn5yd4jSvwq7qDIZpkkPkjfjdwdKsGL0-G0aHpPyjfiBvbCwFmlRMCUKftNMNT7MJx2Bp16Y",
// "6",
// "1188",
// "false",
// "109270481246447459618",
// "436",
// "startEnd",
// "32.12404505187645,36.06566168367863",
// "",
// "",
// "",
// "",
// "5.42",
// "0",
// "hamzaayedflutter@gmail.com",
// "4368+PPP، السخنة، الأردن",
// "43PC+C4G، السخنة، الأردن",
// "Speed",
// "8",
// "5.00"
// ];
// await FlutterOverlayWindow.shareData(testList);
// await FlutterOverlayWindow.showOverlay(
// enableDrag: true,
// flag: OverlayFlag.focusPointer,
// // visibility: NotificationVisibility.visibilityPublic,
// positionGravity: PositionGravity.auto,
// height: 1300,
// width: WindowSize.matchParent,
// startPosition: const OverlayPosition(0, -90),
// );
// debugPrint('Overlay opened: ');
// Log.print('phoneDriver: ${box.read(BoxName.phoneDriver)}');
// },
// icon: const Icon(
// FontAwesome5.grin_tears,
@@ -165,3 +170,142 @@ GetBuilder<HomeCaptainController> leftMainMenuCaptainIcons() {
),
);
}
void _log(String message) => print(message);
Future<void> checkForPendingOrderFromServer() async {
bool _isProcessingOrder = false;
if (_isProcessingOrder) return;
final driverId = box.read(BoxName.driverID)?.toString();
if (driverId == null) return; // Can't check without a driver ID
_isProcessingOrder = true; // Lock
try {
// You need to create this CRUD method
var response = await CRUD().post(
link: AppLink.getArgumentAfterAppliedFromBackground,
payload: {'driver_id': driverId},
);
// Assuming the server returns order data if found, or 'failure'/'none' if not
if (response != 'failure') {
Log.print('response: ${response}');
_log("MAIN_APP_LOG: Pending order DETECTED from server!");
final Map<String, dynamic> orderInfoFromServer = response['message'];
final Map<String, dynamic> rideArguments =
_transformServerDataToAppArguments(orderInfoFromServer);
// 2. Build the new arguments map, matching your Flutter structure
_log("MAIN_APP_LOG: Constructed rideArguments map successfully.");
/////////////
final customerToken = (response)['message']['token_passenger'];
final orderId = (response)['message']['ride_id'].toString();
Log.print('orderId: ${orderId}');
box.write(BoxName.rideArgumentsFromBackground, rideArguments);
box.write(BoxName.statusDriverLocation, 'on');
box.write(BoxName.rideStatus, 'Apply');
Get.put(OrderRequestController()).changeApplied();
// MyDialog().getDialog(orderId.toString(), customerToken, () {});
// Now proceed with the UI flow
_sendAcceptanceNotification(customerToken, orderId.toString());
// await _bringAppToForegroundAndNavigate(orderId);
} else {
_log("MAIN_APP_LOG: No pending orders found on server.");
box.write(BoxName.rideArgumentsFromBackground, 'failure');
}
} catch (e) {
_log("Error while polling server: $e");
} finally {
_isProcessingOrder = false; // Release lock
}
}
Map<String, dynamic> _transformServerDataToAppArguments(
Map<String, dynamic> serverData) {
_log("Transforming server data to match app's argument structure.");
// Helper function to safely get and convert values to String
String _getString(String key, [String defaultValue = 'unknown']) {
// serverData[key] might be an int, double, or string. .toString() handles all.
// If it's null, use the default value.
return serverData[key]?.toString() ?? defaultValue;
}
return {
'passengerLocation': _getString('passenger_location'),
'passengerDestination': _getString('passenger_destination'),
'Duration': _getString('duration'),
'totalCost': _getString('total_cost'),
'Distance': _getString('distance'),
'name': _getString('name'),
'phone': _getString('phone'),
'email': _getString('email'),
'tokenPassenger': _getString('token_passenger'),
'direction': _getString('direction_url'),
'DurationToPassenger': _getString('duration_to_passenger'),
'rideId': _getString('ride_id'),
'passengerId': _getString('passenger_id'),
'driverId': _getString('driver_id'),
'durationOfRideValue': _getString('duration_of_ride'),
'paymentAmount': _getString('payment_amount'),
'paymentMethod': _getString('payment_method'),
'passengerWalletBurc': _getString('passenger_wallet_burc'),
'timeOfOrder': _getString('time_of_order'),
'totalPassenger': _getString('total_passenger'),
'carType': _getString('car_type'),
'kazan': _getString('kazan'),
'startNameLocation': _getString('start_name_location'),
'endNameLocation': _getString('end_name_location'),
// --- Special Handling ---
// Steps (handle null values by providing an empty string)
'step0': _getString('step0'),
'step1': _getString('step1'),
'step2': _getString('step2'),
'step3': _getString('step3'),
'step4': _getString('step4'),
// Boolean conversion (1/0 from server to 'true'/'false' string for the app)
'WalletChecked': (serverData['wallet_checked'] == 1).toString(),
// Logic-based conversion for isHaveSteps
// Your app's `rideArguments` expects 'startEnd', so we provide that if has_steps is 1.
// You might need to adjust this logic if 'haveSteps' is also a possibility.
'isHaveSteps': (serverData['has_steps'] == 1)
? 'startEnd'
: 'noSteps', // Providing a default
};
}
void _sendAcceptanceNotification(String? customerToken, rideId) {
try {
if (customerToken == null) return;
final FirebaseMessagesController _firebaseMessagesController =
Get.put(FirebaseMessagesController());
_log("Attempting to send acceptance notification to passenger...");
List<String> bodyToPassenger = [
box.read(BoxName.driverID).toString(),
box.read(BoxName.nameDriver).toString(),
box.read(BoxName.tokenDriver).toString(),
rideId.toString()
];
// Safely check for customer token
final String? token = customerToken;
if (token != null && token.isNotEmpty) {
_firebaseMessagesController.sendNotificationToDriverMAP('Accepted Ride',
'your ride is applied'.tr, token, bodyToPassenger, 'start.wav');
_log("Acceptance notification task was fired.");
} else {
_log("Could not send notification: Customer token is missing or empty.");
}
} catch (e) {
_log("Error while firing notification task: $e");
}
}

View File

@@ -51,7 +51,7 @@ import 'package:get/get.dart';
// child: Padding(
// padding: const EdgeInsets.all(14),
// child: Text(
// "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
// "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Tripz app and be part of our Tripz family."
// .tr,
// style: AppStyle.title,
// ),
@@ -186,7 +186,7 @@ class MaintainCenterPage extends StatelessWidget {
),
const SizedBox(height: 8),
Text(
"We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
"We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Tripz app and be part of our Tripz family."
.tr,
style: Theme.of(context)
.textTheme

View File

@@ -13,8 +13,11 @@ import 'package:sefer_driver/controller/firebase/firbase_messge.dart';
import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart';
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
import '../../../../constant/box_name.dart';
import '../../../../constant/style.dart';
import '../../../../controller/functions/launch.dart';
import '../../../../main.dart';
import '../../../../print.dart';
class PassengerInfoWindow extends StatelessWidget {
const PassengerInfoWindow({super.key});
@@ -179,7 +182,7 @@ class PassengerInfoWindow extends StatelessWidget {
if (await controller
.calculateDistanceBetweenDriverAndPassengerLocation() <
140) {
FirebaseMessagesController()
Get.find<FirebaseMessagesController>()
.sendNotificationToDriverMAP(
'Hi ,I Arrive your site',
'I Arrive at your site'.tr,
@@ -245,7 +248,7 @@ class PassengerInfoWindow extends StatelessWidget {
MyDialog().getDialog(
'Are you sure to cancel?'.tr, '',
() async {
FirebaseMessagesController()
Get.find<FirebaseMessagesController>()
.sendNotificationToDriverMAP(
'Driver Cancelled Your Trip',
'You will need to pay the cost to the driver, or it will be deducted from your next trip'
@@ -254,6 +257,9 @@ class PassengerInfoWindow extends StatelessWidget {
[],
'cancel.wav',
);
Log.print(
'rideStatus from passenge info 261 : ${box.read(BoxName.rideStatus)}');
box.write(BoxName.rideStatus, 'Cancel');
await controller
.addWaitingTimeCostFromPassengerToDriverWallet();
controller.isdriverWaitTimeEnd = false;
@@ -296,7 +302,7 @@ class PassengerInfoWindow extends StatelessWidget {
_buildMessageTile(
text: "Where are you, sir?".tr,
onTap: () {
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'message From Driver',
"Where are you, sir?".tr,
controller.tokenPassenger,
@@ -309,7 +315,7 @@ class PassengerInfoWindow extends StatelessWidget {
_buildMessageTile(
text: "I've been trying to reach you but your phone is off.".tr,
onTap: () {
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'message From Driver',
"I've been trying to reach you but your phone is off.".tr,
controller.tokenPassenger,
@@ -324,7 +330,7 @@ class PassengerInfoWindow extends StatelessWidget {
"Please don't be late, I'm waiting for you at the specified location."
.tr,
onTap: () {
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'message From Driver',
"Please don't be late, I'm waiting for you at the specified location."
.tr,
@@ -338,7 +344,7 @@ class PassengerInfoWindow extends StatelessWidget {
_buildMessageTile(
text: "Please don't be late".tr,
onTap: () {
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
'message From Driver',
"Please don't be late".tr,
controller.tokenPassenger,
@@ -364,7 +370,8 @@ class PassengerInfoWindow extends StatelessWidget {
),
IconButton(
onPressed: () {
FirebaseMessagesController().sendNotificationToDriverMAP(
Get.find<FirebaseMessagesController>()
.sendNotificationToDriverMAP(
'message From Driver',
controller.messageToPassenger.text,
controller.tokenPassenger,

View File

@@ -171,7 +171,7 @@ class SosConnect extends StatelessWidget {
} else {
throw 'Could not launch google maps';
}
};
}();
}
void _sendWhatsAppMessage(MapDriverController mapDriverController) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,5 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/colors.dart';
@@ -5,9 +7,13 @@ import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart';
import 'package:sefer_driver/controller/payment/payment_controller.dart';
import 'package:sefer_driver/views/widgets/mydialoug.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../../constant/box_name.dart';
import '../../../constant/links.dart';
import '../../../controller/functions/crud.dart';
import '../../../main.dart';
import '../../../print.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_textField.dart';
@@ -44,21 +50,34 @@ class PointsCaptain extends StatelessWidget {
title: 'Pay with Credit Card'.tr,
onPressed: () async {
Get.back();
await paymentController.payWithPayMob(
context,
pricePoint.toStringAsFixed(2),
box.read(BoxName.countryCode) == 'Egypt'
? 'EGP'
: 'JOD', () async {
// await captainWalletController.getPaymentId(
// 'visa-in', pricePoint);
await captainWalletController.addDriverWallet(
'visa-in', countPoint, pricePoint);
await captainWalletController.addSeferWallet(
'visa-in', pricePoint.toString());
await captainWalletController
.getCaptainWalletFromBuyPoints();
var res = await CRUD().postWallet(
// link: AppLink.payWithPayMobWalletPasenger,
link: AppLink.payWithPayMobCardDriver,
payload: {
"amount": pricePoint.toStringAsFixed(2),
"email": box.read(BoxName.emailDriver),
"first_name": (box
.read(BoxName.nameDriver)
.toString()
.split(' ')[0])
.toString(),
"last_name": (box
.read(BoxName.nameDriver)
.toString()
.split(' ')[1])
.toString(),
"phone_number": (box.read(BoxName.phoneDriver)),
});
// var d = jsonDecode(res);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PaymentScreen(
iframeUrl: res['message'],
countPrice: countPoint.toString()),
),
);
}, //51524
),
// Add some spacing between buttons
@@ -88,31 +107,45 @@ class PointsCaptain extends StatelessWidget {
BoxName.phoneWallet,
paymentController
.walletphoneController.text);
await paymentController.payWithPayMobWallet(
context,
var res = await CRUD().postWallet(
// link: AppLink.payWithPayMobWalletPasenger,
link: AppLink.payWithWallet,
payload: {
"amount":
pricePoint.toStringAsFixed(2),
box.read(BoxName.countryCode) == 'Egypt'
? 'EGP'
: 'JOD', () async {
// await captainWalletController
// .getPaymentId('visa-in', pricePoint);
await captainWalletController
.addDriverWallet('visa-in',
countPoint, pricePoint);
await captainWalletController
.addSeferWallet(
'visa-in', pricePoint.toString());
await captainWalletController
.getCaptainWalletFromBuyPoints();
"email":
box.read(BoxName.emailDriver),
"first_name": (box
.read(BoxName.nameDriver)
.toString()
.split(' ')[0])
.toString(),
"last_name": (box
.read(BoxName.nameDriver)
.toString()
.split(' ')[1])
.toString(),
"phone_number":
(box.read(BoxName.phoneWallet)),
});
}
MyDialog().getDialog(
'phone number is wrong'.tr,
'',
() {
Get.back();
},
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PaymentScreenWallet(
iframeUrl: res['message'],
countPrice:
countPoint.toString()),
),
);
}
// MyDialog().getDialog(
// 'phone number is wrong'.tr,
// '',
// () {
// Get.back();
// },
// );
// Get.back();
}));
},
@@ -173,3 +206,311 @@ class PointsCaptain extends StatelessWidget {
);
}
}
class PaymentScreen extends StatefulWidget {
final String iframeUrl;
final String countPrice;
const PaymentScreen(
{required this.iframeUrl, Key? key, required this.countPrice})
: super(key: key);
@override
State<PaymentScreen> createState() => _PaymentScreenState();
}
class _PaymentScreenState extends State<PaymentScreen> {
late final WebViewController _controller;
final controller = Get.find<CaptainWalletController>();
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(NavigationDelegate(
onPageFinished: (url) {
if (url.contains("success")) {
_fetchPaymentStatus(); // ✅ استدعاء الويب هوك بعد نجاح الدفع
} else if (url.contains("failed")) {
showCustomDialog(
title: "Error".tr,
message: 'Payment Failed'.tr, // يتم جلب رسالة الخطأ من الخادم
isSuccess: false,
);
}
},
))
..loadRequest(Uri.parse(widget.iframeUrl));
}
Future<void> _fetchPaymentStatus() async {
final String userId = box.read(BoxName.phoneDriver);
await Future.delayed(const Duration(seconds: 2));
try {
final response = await CRUD().postWallet(
link: AppLink.paymetVerifyDriver,
payload: {
'user_id': userId,
'driverID': box.read(BoxName.driverID),
'paymentMethod': 'visa-in',
},
);
if (response != 'failure' && response != 'token_expired') {
if (response['status'] == 'success') {
final payment = response['message'];
final amount = payment['amount'].toString();
final bonus = payment['bonus'].toString();
final paymentID = payment['paymentID'].toString();
await controller.getCaptainWalletFromBuyPoints();
showCustomDialog(
title: "payment_success".tr,
message:
"${"transaction_id".tr}: $paymentID\n${"amount_paid".tr}: $amount EGP\n${"bonus_added".tr}: $bonus ${"points".tr}",
isSuccess: true,
);
} else {
showCustomDialog(
title: "transaction_failed".tr,
message: response['message'].toString(),
isSuccess: false,
);
}
} else {
showCustomDialog(
title: "connection_failed".tr,
message: response.toString(),
isSuccess: false,
);
}
} catch (e) {
showCustomDialog(
title: "server_error".tr,
message: "server_error_message".tr,
isSuccess: false,
);
}
}
void showCustomDialog({
required String title,
required String message,
required bool isSuccess,
}) {
showDialog(
barrierDismissible: false,
context: Get.context!,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
title: Row(
children: [
Icon(
isSuccess ? Icons.check_circle : Icons.error,
color: isSuccess ? Colors.green : Colors.red,
),
const SizedBox(width: 8),
Text(
title,
style: TextStyle(
color: isSuccess ? Colors.green : Colors.red,
fontWeight: FontWeight.bold,
),
),
],
),
content: Text(
message,
style: const TextStyle(fontSize: 16),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
Navigator.pop(context);
},
style: TextButton.styleFrom(
backgroundColor: isSuccess ? Colors.green : Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
child: Text(
"OK",
style: const TextStyle(color: Colors.white),
),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('إتمام الدفع')),
body: WebViewWidget(controller: _controller),
);
}
}
class PaymentScreenWallet extends StatefulWidget {
final String iframeUrl;
final String countPrice;
const PaymentScreenWallet(
{required this.iframeUrl, Key? key, required this.countPrice})
: super(key: key);
@override
State<PaymentScreenWallet> createState() => _PaymentScreenWalletState();
}
class _PaymentScreenWalletState extends State<PaymentScreenWallet> {
late final WebViewController _controller;
final controller = Get.find<CaptainWalletController>();
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(NavigationDelegate(
onPageFinished: (url) {
if (url.contains("success")) {
_fetchPaymentStatus(); // ✅ استدعاء الويب هوك بعد نجاح الدفع
} else if (url.contains("failed")) {
showCustomDialog(
title: "Error".tr,
message: 'Payment Failed'.tr, // يتم جلب رسالة الخطأ من الخادم
isSuccess: false,
);
}
},
))
..loadRequest(Uri.parse(widget.iframeUrl));
}
Future<void> _fetchPaymentStatus() async {
final String userId = '+2' + box.read(BoxName.phoneWallet);
await Future.delayed(const Duration(seconds: 2));
try {
final response = await CRUD().postWallet(
link: AppLink.paymetVerifyDriver,
payload: {
'user_id': userId,
'driverID': box.read(BoxName.driverID),
'paymentMethod': 'visa-in',
},
);
if (response != 'failure' && response != 'token_expired') {
if (response['status'] == 'success') {
final payment = response['message'];
final amount = payment['amount'].toString();
final bonus = payment['bonus'].toString();
final paymentID = payment['paymentID'].toString();
await controller.getCaptainWalletFromBuyPoints();
showCustomDialog(
title: "payment_success".tr,
message:
"${"transaction_id".tr}: $paymentID\n${"amount_paid".tr}: $amount EGP\n${"bonus_added".tr}: $bonus ${"points".tr}",
isSuccess: true,
);
} else {
showCustomDialog(
title: "transaction_failed".tr,
message: response['message'].toString(),
isSuccess: false,
);
}
} else {
showCustomDialog(
title: "connection_failed".tr,
message: response.toString(),
isSuccess: false,
);
}
} catch (e) {
showCustomDialog(
title: "server_error".tr,
message: "server_error_message".tr,
isSuccess: false,
);
}
}
void showCustomDialog({
required String title,
required String message,
required bool isSuccess,
}) {
showDialog(
barrierDismissible: false,
context: Get.context!,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
title: Row(
children: [
Icon(
isSuccess ? Icons.check_circle : Icons.error,
color: isSuccess ? Colors.green : Colors.red,
),
const SizedBox(width: 8),
Text(
title,
style: TextStyle(
color: isSuccess ? Colors.green : Colors.red,
fontWeight: FontWeight.bold,
),
),
],
),
content: Text(
message,
style: const TextStyle(fontSize: 16),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
Navigator.pop(context);
},
style: TextButton.styleFrom(
backgroundColor: isSuccess ? Colors.green : Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
child: Text(
"OK",
style: const TextStyle(color: Colors.white),
),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('إتمام الدفع')),
body: WebViewWidget(controller: _controller),
);
}
}

View File

@@ -93,6 +93,7 @@ dependencies:
jwt_decoder: ^2.0.1
jailbreak_root_detection: ^1.1.5
device_info_plus: ^11.3.0
# flutter_isolate: ^2.1.0
# lingo_hunter: ^1.0.3
dev_dependencies: