Update: 2026-05-15 03:27:21

This commit is contained in:
Hamza-Ayed
2026-05-15 03:27:21 +03:00
parent dd4fcb9bee
commit 8916b4648d
9 changed files with 361 additions and 17 deletions

View File

@@ -44,6 +44,7 @@
</activity> </activity>
<activity android:name=".SubscriptionActivity" android:exported="false" /> <activity android:name=".SubscriptionActivity" android:exported="false" />
<activity android:name=".SettingsActivity" android:exported="false" />
<service <service
android:name=".service.RideNotificationListener" android:name=".service.RideNotificationListener"

View File

@@ -25,6 +25,9 @@ import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import com.jordanbot.autoride.subscription.SubscriptionManager import com.jordanbot.autoride.subscription.SubscriptionManager
import androidx.appcompat.app.AppCompatDelegate
import com.jordanbot.autoride.filter.FilterEngine
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var tvStatus: TextView private lateinit var tvStatus: TextView
@@ -33,8 +36,21 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Apply Theme
val prefs = getSharedPreferences("ThemePrefs", MODE_PRIVATE)
val isDark = prefs.getBoolean("dark_mode", true)
if (isDark) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
// Load Settings
FilterEngine.init(this)
// Load cached subscription data // Load cached subscription data
SubscriptionManager.loadLocalCache(this) SubscriptionManager.loadLocalCache(this)
@@ -51,6 +67,10 @@ class MainActivity : AppCompatActivity() {
startActivity(Intent(this, SubscriptionActivity::class.java)) startActivity(Intent(this, SubscriptionActivity::class.java))
} }
findViewById<Button>(R.id.btn_settings).setOnClickListener {
startActivity(Intent(this, SettingsActivity::class.java))
}
findViewById<Button>(R.id.btn_notification).setOnClickListener { findViewById<Button>(R.id.btn_notification).setOnClickListener {
startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS)) startActivity(Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS))
} }

View File

@@ -0,0 +1,81 @@
package com.jordanbot.autoride
import android.os.Bundle
import android.widget.Button
import android.widget.CheckBox
import android.widget.EditText
import android.widget.Switch
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.jordanbot.autoride.filter.FilterEngine
class SettingsActivity : AppCompatActivity() {
private lateinit var etMinPrice: EditText
private lateinit var etMaxMinutes: EditText
private lateinit var switchAutoAccept: Switch
private lateinit var cbUber: CheckBox
private lateinit var cbCareem: CheckBox
private lateinit var cbJeeny: CheckBox
private lateinit var switchDarkMode: Switch
private lateinit var btnSave: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
etMinPrice = findViewById(R.id.et_min_price)
etMaxMinutes = findViewById(R.id.et_max_minutes)
switchAutoAccept = findViewById(R.id.switch_auto_accept)
cbUber = findViewById(R.id.cb_uber)
cbCareem = findViewById(R.id.cb_careem)
cbJeeny = findViewById(R.id.cb_jeeny)
switchDarkMode = findViewById(R.id.switch_dark_mode)
btnSave = findViewById(R.id.btn_save_settings)
loadCurrentSettings()
btnSave.setOnClickListener {
saveSettings()
}
}
private fun loadCurrentSettings() {
FilterEngine.init(this)
etMinPrice.setText(FilterEngine.minPriceJod.toString())
etMaxMinutes.setText(FilterEngine.maxMinutesAway.toString())
switchAutoAccept.isChecked = FilterEngine.isEnabled
cbUber.isChecked = FilterEngine.enableUber
cbCareem.isChecked = FilterEngine.enableCareem
cbJeeny.isChecked = FilterEngine.enableJeeny
val prefs = getSharedPreferences("ThemePrefs", MODE_PRIVATE)
switchDarkMode.isChecked = prefs.getBoolean("dark_mode", true)
}
private fun saveSettings() {
val price = etMinPrice.text.toString().toDoubleOrNull() ?: 1.0
val minutes = etMaxMinutes.text.toString().toIntOrNull() ?: 10
val autoAccept = switchAutoAccept.isChecked
val uber = cbUber.isChecked
val careem = cbCareem.isChecked
val jeeny = cbJeeny.isChecked
FilterEngine.save(price, minutes, autoAccept, uber, careem, jeeny)
val prefs = getSharedPreferences("ThemePrefs", MODE_PRIVATE)
val currentDark = prefs.getBoolean("dark_mode", true)
val newDark = switchDarkMode.isChecked
prefs.edit().putBoolean("dark_mode", newDark).apply()
Toast.makeText(this, "تم حفظ الإعدادات بنجاح", Toast.LENGTH_SHORT).show()
if (currentDark != newDark) {
// Theme changed, restart app or recreate
Toast.makeText(this, "يرجى إعادة تشغيل التطبيق لتطبيق المظهر الجديد", Toast.LENGTH_LONG).show()
}
finish()
}
}

View File

@@ -1,17 +1,58 @@
package com.jordanbot.autoride.filter package com.jordanbot.autoride.filter
import android.content.Context
import android.content.SharedPreferences
import com.jordanbot.autoride.model.RideRequest import com.jordanbot.autoride.model.RideRequest
class FilterEngine { object FilterEngine {
private const val PREFS_NAME = "BotSettings"
private lateinit var prefs: SharedPreferences
// These will eventually come from SharedPreferences / UI
var minPriceJod: Double = 1.0 var minPriceJod: Double = 1.0
var maxMinutesAway: Int = 10 var maxMinutesAway: Int = 10
var isEnabled: Boolean = true var isEnabled: Boolean = true
var enableUber: Boolean = true
var enableCareem: Boolean = true
var enableJeeny: Boolean = true
fun init(context: Context) {
prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
load()
}
fun load() {
minPriceJod = prefs.getFloat("min_price", 1.0f).toDouble()
maxMinutesAway = prefs.getInt("max_minutes", 10)
isEnabled = prefs.getBoolean("auto_accept", true)
enableUber = prefs.getBoolean("enable_uber", true)
enableCareem = prefs.getBoolean("enable_careem", true)
enableJeeny = prefs.getBoolean("enable_jeeny", true)
}
fun save(price: Double, minutes: Int, autoAccept: Boolean, uber: Boolean, careem: Boolean, jeeny: Boolean) {
prefs.edit().apply {
putFloat("min_price", price.toFloat())
putInt("max_minutes", minutes)
putBoolean("auto_accept", autoAccept)
putBoolean("enable_uber", uber)
putBoolean("enable_careem", careem)
putBoolean("enable_jeeny", jeeny)
apply()
}
load()
}
fun evaluate(request: RideRequest): Boolean { fun evaluate(request: RideRequest): Boolean {
if (!isEnabled) return false if (!isEnabled) return false
// Check app package
val pkg = request.appPackage
if (pkg.contains("uber") && !enableUber) return false
if (pkg.contains("careem") && !enableCareem) return false
if (pkg.contains("jeeny") && !enableJeeny) return false
// Check Price // Check Price
if (request.priceJod != null && request.priceJod < minPriceJod) { if (request.priceJod != null && request.priceJod < minPriceJod) {
return false return false

View File

@@ -16,7 +16,6 @@ import com.jordanbot.autoride.model.RideRequest
class RideAccessibilityService : AccessibilityService() { class RideAccessibilityService : AccessibilityService() {
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
private val filterEngine = FilterEngine()
override fun onAccessibilityEvent(event: AccessibilityEvent) { override fun onAccessibilityEvent(event: AccessibilityEvent) {
val rootNode = rootInActiveWindow ?: return val rootNode = rootInActiveWindow ?: return
@@ -114,8 +113,10 @@ class RideAccessibilityService : AccessibilityService() {
override fun onServiceConnected() { override fun onServiceConnected() {
super.onServiceConnected() super.onServiceConnected()
FilterEngine.init(this)
RideDataMerger.onRideReady = { mergedRide -> RideDataMerger.onRideReady = { mergedRide ->
val passesFilters = filterEngine.evaluate(mergedRide) val passesFilters = FilterEngine.evaluate(mergedRide)
val canAccept = SubscriptionManager.canAcceptRides val canAccept = SubscriptionManager.canAcceptRides
Log.d("JordanBot", "🏁 Merger callback: PassesFilters=$passesFilters, CanAcceptQuota=$canAccept for ${mergedRide.appPackage}") Log.d("JordanBot", "🏁 Merger callback: PassesFilters=$passesFilters, CanAcceptQuota=$canAccept for ${mergedRide.appPackage}")

View File

@@ -15,6 +15,7 @@ import android.util.Log
import com.jordanbot.autoride.api.ApiClient import com.jordanbot.autoride.api.ApiClient
import com.jordanbot.autoride.api.RideLogRequest import com.jordanbot.autoride.api.RideLogRequest
import com.jordanbot.autoride.filter.FilterEngine import com.jordanbot.autoride.filter.FilterEngine
import com.jordanbot.autoride.engine.RideDataMerger
import com.jordanbot.autoride.parser.* import com.jordanbot.autoride.parser.*
import com.jordanbot.autoride.utils.DeviceUtils import com.jordanbot.autoride.utils.DeviceUtils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@@ -25,7 +26,6 @@ import kotlinx.coroutines.launch
class RideNotificationListener : NotificationListenerService() { class RideNotificationListener : NotificationListenerService() {
private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
private val filterEngine = FilterEngine()
private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var fusedLocationClient: FusedLocationProviderClient
override fun onCreate() { override fun onCreate() {

View File

@@ -211,6 +211,15 @@
android:backgroundTint="#2A2A4A" android:backgroundTint="#2A2A4A"
android:text="💳 إدارة الاشتراكات" android:text="💳 إدارة الاشتراكات"
android:textColor="#FFFFFF" android:textColor="#FFFFFF"
android:layout_marginBottom="8dp" />
<Button
android:id="@+id/btn_settings"
android:layout_width="match_parent"
android:layout_height="48dp"
android:backgroundTint="#2A2A4A"
android:text="⚙️ الإعدادات والفلاتر"
android:textColor="#FFFFFF"
android:layout_marginBottom="24dp" /> android:layout_marginBottom="24dp" />
<!-- Launch Button --> <!-- Launch Button -->

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="⚙️ الإعدادات"
android:textColor="?attr/colorPrimary"
android:textSize="32sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="32dp"
android:text="تخصيص فلاتر البوت والمظهر"
android:textColor="?attr/colorOnSurface"
android:textSize="16sp" />
<!-- Filters Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="فلاتر الطلبات"
android:textColor="?attr/colorOnSurface"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="16dp"
android:layout_marginBottom="24dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="الحد الأدنى للسعر (JOD)"
android:textColor="?attr/colorOnSurface" />
<EditText
android:id="@+id/et_min_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:text="1.0"
android:textColor="?attr/colorOnSurface"
android:layout_marginBottom="16dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="أقصى وقت لوصول السائق (بالدقائق)"
android:textColor="?attr/colorOnSurface" />
<EditText
android:id="@+id/et_max_minutes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="10"
android:textColor="?attr/colorOnSurface"
android:layout_marginBottom="16dp" />
<Switch
android:id="@+id/switch_auto_accept"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="تفعيل القبول التلقائي"
android:textColor="?attr/colorOnSurface"
android:checked="true" />
</LinearLayout>
<!-- Supported Apps Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="التطبيقات المفعلة"
android:textColor="?attr/colorOnSurface"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="16dp"
android:layout_marginBottom="24dp">
<CheckBox
android:id="@+id/cb_uber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Uber (أوبر)"
android:textColor="?attr/colorOnSurface"
android:checked="true" />
<CheckBox
android:id="@+id/cb_careem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Careem (كريم)"
android:textColor="?attr/colorOnSurface"
android:checked="true" />
<CheckBox
android:id="@+id/cb_jeeny"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Jeeny (جيني)"
android:textColor="?attr/colorOnSurface"
android:checked="true" />
</LinearLayout>
<!-- Appearance Section -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="المظهر"
android:textColor="?attr/colorOnSurface"
android:textSize="18sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_card"
android:orientation="vertical"
android:padding="16dp"
android:layout_marginBottom="24dp">
<Switch
android:id="@+id/switch_dark_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="الوضع الليلي (Dark Mode)"
android:textColor="?attr/colorOnSurface"
android:checked="true" />
</LinearLayout>
<Button
android:id="@+id/btn_save_settings"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@drawable/bg_button_primary"
android:text="💾 حفظ الإعدادات"
android:textColor="#FFFFFF"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="24dp" />
</LinearLayout>
</ScrollView>

View File

@@ -1,14 +1,35 @@
<resources xmlns:tools="http://schemas.android.com/tools"> <?xml version="1.0" encoding="utf-8"?>
<style name="Theme.JordanBot" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <resources>
<!-- Primary brand color. -->
<item name="colorPrimary">#6200EE</item> <style name="Theme.JordanBot" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="colorPrimaryVariant">#3700B3</item> <!-- Default mapping to Dark since we rely on system DayNight or override it -->
<item name="colorOnPrimary">#FFFFFF</item> <item name="colorPrimary">#00D4AA</item>
<!-- Secondary brand color. --> <item name="colorPrimaryDark">#00B894</item>
<item name="colorSecondary">#03DAC5</item> <item name="colorAccent">#00D4AA</item>
<item name="colorSecondaryVariant">#018786</item> <item name="colorSurface">#1A1A2E</item>
<item name="colorOnSecondary">#000000</item> <item name="colorOnSurface">#FFFFFF</item>
<!-- Status bar color. --> <item name="android:windowBackground">#0F0F1A</item>
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <item name="android:textColor">#FFFFFF</item>
</style> </style>
<style name="Theme.JordanBot.Light" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#00B894</item>
<item name="colorPrimaryDark">#009688</item>
<item name="colorAccent">#00B894</item>
<item name="colorSurface">#FFFFFF</item>
<item name="colorOnSurface">#1A1A2E</item>
<item name="android:windowBackground">#F5F5F5</item>
<item name="android:textColor">#1A1A2E</item>
</style>
<style name="Theme.JordanBot.Dark" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">#00D4AA</item>
<item name="colorPrimaryDark">#00B894</item>
<item name="colorAccent">#00D4AA</item>
<item name="colorSurface">#1A1A2E</item>
<item name="colorOnSurface">#FFFFFF</item>
<item name="android:windowBackground">#0F0F1A</item>
<item name="android:textColor">#FFFFFF</item>
</style>
</resources> </resources>