diff --git a/android/app/src/main/kotlin/com/umbrix/app/Settings.kt b/android/app/src/main/kotlin/com/umbrix/app/Settings.kt new file mode 100644 index 00000000..049747f4 --- /dev/null +++ b/android/app/src/main/kotlin/com/umbrix/app/Settings.kt @@ -0,0 +1,115 @@ +package com.umbrix.app + +import android.content.Context +import com.umbrix.app.bg.ProxyService +import com.umbrix.app.bg.VPNService +import com.umbrix.app.constant.PerAppProxyMode +import com.umbrix.app.constant.ServiceMode +import com.umbrix.app.constant.SettingsKey +import org.json.JSONObject +import java.io.File + +object Settings { + + private val preferences by lazy { + val context = Application.application.applicationContext + context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) + } + + var perAppProxyMode: String + get() = preferences.getString(SettingsKey.PER_APP_PROXY_MODE, PerAppProxyMode.OFF)!! + set(value) = preferences.edit().putString(SettingsKey.PER_APP_PROXY_MODE, value).apply() + + val perAppProxyEnabled: Boolean + get() = perAppProxyMode != PerAppProxyMode.OFF + + val perAppProxyList: List + get() { + val key = if (perAppProxyMode == PerAppProxyMode.INCLUDE) { + SettingsKey.PER_APP_PROXY_INCLUDE_LIST + } else { + SettingsKey.PER_APP_PROXY_EXCLUDE_LIST + } + // Flutter SharedPreferences plugin сохраняет List как StringSet + // Читаем напрямую без дополнительной сериализации + return preferences.getStringSet(key, emptySet())?.toList() ?: emptyList() + } + + var activeConfigPath: String + get() = preferences.getString(SettingsKey.ACTIVE_CONFIG_PATH, "")!! + set(value) = preferences.edit().putString(SettingsKey.ACTIVE_CONFIG_PATH, value).apply() + + var activeProfileName: String + get() = preferences.getString(SettingsKey.ACTIVE_PROFILE_NAME, "")!! + set(value) = preferences.edit().putString(SettingsKey.ACTIVE_PROFILE_NAME, value).apply() + + var serviceMode: String + get() = preferences.getString(SettingsKey.SERVICE_MODE, ServiceMode.VPN)!! + set(value) = preferences.edit().putString(SettingsKey.SERVICE_MODE, value).apply() + + var configOptions: String + get() = preferences.getString(SettingsKey.CONFIG_OPTIONS, "")!! + set(value) = preferences.edit().putString(SettingsKey.CONFIG_OPTIONS, value).apply() + + var debugMode: Boolean + get() = preferences.getBoolean(SettingsKey.DEBUG_MODE, false) + set(value) = preferences.edit().putBoolean(SettingsKey.DEBUG_MODE, value).apply() + + var disableMemoryLimit: Boolean + get() = preferences.getBoolean(SettingsKey.DISABLE_MEMORY_LIMIT, false) + set(value) = + preferences.edit().putBoolean(SettingsKey.DISABLE_MEMORY_LIMIT, value).apply() + + var dynamicNotification: Boolean + get() = preferences.getBoolean(SettingsKey.DYNAMIC_NOTIFICATION, true) + set(value) = + preferences.edit().putBoolean(SettingsKey.DYNAMIC_NOTIFICATION, value).apply() + + var systemProxyEnabled: Boolean + get() = preferences.getBoolean(SettingsKey.SYSTEM_PROXY_ENABLED, true) + set(value) = + preferences.edit().putBoolean(SettingsKey.SYSTEM_PROXY_ENABLED, value).apply() + + var startedByUser: Boolean + get() = preferences.getBoolean(SettingsKey.STARTED_BY_USER, false) + set(value) = preferences.edit().putBoolean(SettingsKey.STARTED_BY_USER, value).apply() + + fun serviceClass(): Class<*> { + return when (serviceMode) { + ServiceMode.VPN -> VPNService::class.java + else -> ProxyService::class.java + } + } + + private var currentServiceMode : String? = null + + suspend fun rebuildServiceMode(): Boolean { + var newMode = ServiceMode.NORMAL + try { + if (serviceMode == ServiceMode.VPN) { + newMode = ServiceMode.VPN + } + } catch (_: Exception) { + } + if (currentServiceMode == newMode) { + return false + } + currentServiceMode = newMode + return true + } + + private suspend fun needVPNService(): Boolean { + val filePath = activeConfigPath + if (filePath.isBlank()) return false + val content = JSONObject(File(filePath).readText()) + val inbounds = content.getJSONArray("inbounds") + for (index in 0 until inbounds.length()) { + val inbound = inbounds.getJSONObject(index) + if (inbound.getString("type") == "tun") { + return true + } + } + return false + } +} +