Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf33391785 | |||
| a35ba5dfbd | |||
| 3b4d895c1d | |||
| e8585a82c6 | |||
| 087c08f95a | |||
| 6612ca8256 | |||
| 487692deb7 | |||
| e9332168bf | |||
| 15fcfec4c8 | |||
| a4baeeb0fa | |||
| 093e51186d | |||
| 14a29884e7 | |||
| 30b0bd8d0d | |||
| ae84df7367 | |||
| b673167731 |
@@ -84,7 +84,7 @@ jobs:
|
|||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|
||||||
- name: Decode Keystore
|
- name: Decode Keystore
|
||||||
uses: timheuer/base64-to-file@v1.2.4
|
uses: timheuer/base64-to-file@v2.0.0
|
||||||
id: android_keystore
|
id: android_keystore
|
||||||
with:
|
with:
|
||||||
fileName: "android_keystore.jks"
|
fileName: "android_keystore.jks"
|
||||||
|
|||||||
+1
-1
Submodule AndroidLibXrayLite updated: 071ff37317...d8bfc35e93
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "com.v2ray.ang"
|
applicationId = "com.v2ray.ang"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 722
|
versionCode = 724
|
||||||
versionName = "2.1.2"
|
versionName = "2.1.4"
|
||||||
multiDexEnabled = true
|
multiDexEnabled = true
|
||||||
|
|
||||||
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
||||||
|
|||||||
@@ -273,6 +273,11 @@
|
|||||||
|
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name="androidx.work.multiprocess.RemoteWorkManagerService"
|
||||||
|
android:exported="false"
|
||||||
|
android:process=":bg" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.cache"
|
android:authorities="${applicationId}.cache"
|
||||||
|
|||||||
@@ -43,10 +43,8 @@ object AppConfig {
|
|||||||
const val PREF_FRAGMENT_PACKETS = "pref_fragment_packets"
|
const val PREF_FRAGMENT_PACKETS = "pref_fragment_packets"
|
||||||
const val PREF_FRAGMENT_LENGTH = "pref_fragment_length"
|
const val PREF_FRAGMENT_LENGTH = "pref_fragment_length"
|
||||||
const val PREF_FRAGMENT_INTERVAL = "pref_fragment_interval"
|
const val PREF_FRAGMENT_INTERVAL = "pref_fragment_interval"
|
||||||
const val SUBSCRIPTION_AUTO_UPDATE = "pref_auto_update_subscription"
|
|
||||||
const val SUBSCRIPTION_AUTO_UPDATE_INTERVAL = "pref_auto_update_interval"
|
|
||||||
const val SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL = "1440" // Default is 24 hours
|
|
||||||
const val SUBSCRIPTION_UPDATE_TASK_NAME = "subscription_updater"
|
const val SUBSCRIPTION_UPDATE_TASK_NAME = "subscription_updater"
|
||||||
|
const val SUBSCRIPTION_MIN_INTERVAL_MINUTES = 15L
|
||||||
const val PREF_SPEED_ENABLED = "pref_speed_enabled"
|
const val PREF_SPEED_ENABLED = "pref_speed_enabled"
|
||||||
const val PREF_CONFIRM_REMOVE = "pref_confirm_remove"
|
const val PREF_CONFIRM_REMOVE = "pref_confirm_remove"
|
||||||
const val PREF_START_SCAN_IMMEDIATE = "pref_start_scan_immediate"
|
const val PREF_START_SCAN_IMMEDIATE = "pref_start_scan_immediate"
|
||||||
@@ -58,10 +56,12 @@ object AppConfig {
|
|||||||
const val PREF_PREFER_IPV6 = "pref_prefer_ipv6"
|
const val PREF_PREFER_IPV6 = "pref_prefer_ipv6"
|
||||||
const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled"
|
const val PREF_PROXY_SHARING = "pref_proxy_sharing_enabled"
|
||||||
const val PREF_ALLOW_INSECURE = "pref_allow_insecure"
|
const val PREF_ALLOW_INSECURE = "pref_allow_insecure"
|
||||||
|
const val PREF_ENABLE_LOCAL_PROXY = "pref_enable_local_proxy"
|
||||||
const val PREF_SOCKS_PORT = "pref_socks_port"
|
const val PREF_SOCKS_PORT = "pref_socks_port"
|
||||||
const val PREF_DYNAMIC_SOCKS_PORT = "pref_dynamic_socks_port"
|
const val PREF_DYNAMIC_SOCKS_PORT = "pref_dynamic_socks_port"
|
||||||
const val PREF_SOCKS_USERNAME = "pref_socks_username"
|
const val PREF_SOCKS_USERNAME = "pref_socks_username"
|
||||||
const val PREF_SOCKS_PASSWORD = "pref_socks_password"
|
const val PREF_SOCKS_PASSWORD = "pref_socks_password"
|
||||||
|
const val PREF_SOCKS_ENABLE_UDP = "pref_socks_enable_udp"
|
||||||
const val PREF_REMOTE_DNS = "pref_remote_dns"
|
const val PREF_REMOTE_DNS = "pref_remote_dns"
|
||||||
const val PREF_DOMESTIC_DNS = "pref_domestic_dns"
|
const val PREF_DOMESTIC_DNS = "pref_domestic_dns"
|
||||||
const val PREF_DNS_HOSTS = "pref_dns_hosts"
|
const val PREF_DNS_HOSTS = "pref_dns_hosts"
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ data class ProfileItem(
|
|||||||
var host: String? = null,
|
var host: String? = null,
|
||||||
var path: String? = null,
|
var path: String? = null,
|
||||||
var seed: String? = null,
|
var seed: String? = null,
|
||||||
|
var kcpMtu: Int? = null,
|
||||||
|
var kcpTti: Int? = null,
|
||||||
|
|
||||||
var quicSecurity: String? = null,
|
var quicSecurity: String? = null,
|
||||||
var quicKey: String? = null,
|
var quicKey: String? = null,
|
||||||
var mode: String? = null,
|
var mode: String? = null,
|
||||||
@@ -43,7 +46,6 @@ data class ProfileItem(
|
|||||||
var fingerPrint: String? = null,
|
var fingerPrint: String? = null,
|
||||||
var insecure: Boolean? = null,
|
var insecure: Boolean? = null,
|
||||||
var echConfigList: String? = null,
|
var echConfigList: String? = null,
|
||||||
var echForceQuery: String? = null,
|
|
||||||
var pinnedCA256: String? = null,
|
var pinnedCA256: String? = null,
|
||||||
|
|
||||||
var publicKey: String? = null,
|
var publicKey: String? = null,
|
||||||
@@ -102,6 +104,8 @@ data class ProfileItem(
|
|||||||
&& this.host == obj.host
|
&& this.host == obj.host
|
||||||
&& this.path == obj.path
|
&& this.path == obj.path
|
||||||
&& this.seed == obj.seed
|
&& this.seed == obj.seed
|
||||||
|
&& this.kcpMtu == obj.kcpMtu
|
||||||
|
&& this.kcpTti == obj.kcpTti
|
||||||
&& this.quicSecurity == obj.quicSecurity
|
&& this.quicSecurity == obj.quicSecurity
|
||||||
&& this.quicKey == obj.quicKey
|
&& this.quicKey == obj.quicKey
|
||||||
&& this.mode == obj.mode
|
&& this.mode == obj.mode
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ data class SubscriptionItem(
|
|||||||
val addedTime: Long = System.currentTimeMillis(),
|
val addedTime: Long = System.currentTimeMillis(),
|
||||||
var lastUpdated: Long = -1,
|
var lastUpdated: Long = -1,
|
||||||
var autoUpdate: Boolean = false,
|
var autoUpdate: Boolean = false,
|
||||||
val updateInterval: Int? = null,
|
var updateInterval: Long = 1440, // in minutes, default to 24 hours
|
||||||
var prevProfile: String? = null,
|
var prevProfile: String? = null,
|
||||||
var nextProfile: String? = null,
|
var nextProfile: String? = null,
|
||||||
var filter: String? = null,
|
var filter: String? = null,
|
||||||
|
|||||||
@@ -256,7 +256,6 @@ data class V2rayConfig(
|
|||||||
val disableSystemRoot: Boolean? = null,
|
val disableSystemRoot: Boolean? = null,
|
||||||
val enableSessionResumption: Boolean? = null,
|
val enableSessionResumption: Boolean? = null,
|
||||||
var echConfigList: String? = null,
|
var echConfigList: String? = null,
|
||||||
var echForceQuery: String? = null,
|
|
||||||
var pinnedPeerCertSha256: String? = null,
|
var pinnedPeerCertSha256: String? = null,
|
||||||
// REALITY settings
|
// REALITY settings
|
||||||
val show: Boolean = false,
|
val show: Boolean = false,
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ open class FmtBase {
|
|||||||
config.path = queryParam["path"]
|
config.path = queryParam["path"]
|
||||||
|
|
||||||
config.seed = queryParam["seed"]
|
config.seed = queryParam["seed"]
|
||||||
|
config.kcpMtu = queryParam["mtu"]?.toIntOrNull()
|
||||||
|
config.kcpTti = queryParam["tti"]?.toIntOrNull()
|
||||||
config.quicSecurity = queryParam["quicSecurity"]
|
config.quicSecurity = queryParam["quicSecurity"]
|
||||||
config.quicKey = queryParam["key"]
|
config.quicKey = queryParam["key"]
|
||||||
config.mode = queryParam["mode"]
|
config.mode = queryParam["mode"]
|
||||||
@@ -112,6 +114,8 @@ open class FmtBase {
|
|||||||
config.mldsa65Verify?.nullIfBlank()?.let { dicQuery["pqv"] = it }
|
config.mldsa65Verify?.nullIfBlank()?.let { dicQuery["pqv"] = it }
|
||||||
config.flow?.nullIfBlank()?.let { dicQuery["flow"] = it }
|
config.flow?.nullIfBlank()?.let { dicQuery["flow"] = it }
|
||||||
config.finalMask?.nullIfBlank()?.let { dicQuery["fm"] = it }
|
config.finalMask?.nullIfBlank()?.let { dicQuery["fm"] = it }
|
||||||
|
config.kcpMtu?.let { dicQuery["mtu"] = it.toString() }
|
||||||
|
config.kcpTti?.let { dicQuery["tti"] = it.toString() }
|
||||||
// Add two keys for compatibility: "insecure" and "allowInsecure"
|
// Add two keys for compatibility: "insecure" and "allowInsecure"
|
||||||
if (config.security == AppConfig.TLS) {
|
if (config.security == AppConfig.TLS) {
|
||||||
val insecureFlag = if (config.insecure == true) "1" else "0"
|
val insecureFlag = if (config.insecure == true) "1" else "0"
|
||||||
|
|||||||
@@ -679,6 +679,7 @@ object MmkvManager {
|
|||||||
return settingsStorage.decodeStringSet(key)
|
return settingsStorage.decodeStringSet(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes the start on boot setting.
|
* Encodes the start on boot setting.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -252,12 +252,7 @@ object SettingsManager {
|
|||||||
* it creates a new default subscription to ensure that ungroup
|
* it creates a new default subscription to ensure that ungroup
|
||||||
**/
|
**/
|
||||||
fun removeSubscriptionWithDefault(subid: String) {
|
fun removeSubscriptionWithDefault(subid: String) {
|
||||||
// val subsList = decodeSubsList()
|
SubscriptionUpdater.cancelOne(subId = subid)
|
||||||
// if (subsList.size == 1 && subsList.first() == DEFAULT_SUBSCRIPTION_ID) {
|
|
||||||
// LogUtil.i(ANG_PACKAGE,"Attempted to remove the only existing default subscription, operation ignored.")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Remove the subscription
|
// Remove the subscription
|
||||||
removeSubscription(subid)
|
removeSubscription(subid)
|
||||||
|
|
||||||
@@ -499,7 +494,6 @@ object SettingsManager {
|
|||||||
ensureDefaultValue(AppConfig.PREF_MODE, VPN)
|
ensureDefaultValue(AppConfig.PREF_MODE, VPN)
|
||||||
ensureDefaultValue(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN)
|
ensureDefaultValue(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN)
|
||||||
ensureDefaultValue(AppConfig.PREF_VPN_MTU, AppConfig.VPN_MTU.toString())
|
ensureDefaultValue(AppConfig.PREF_VPN_MTU, AppConfig.VPN_MTU.toString())
|
||||||
ensureDefaultValue(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL, AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
|
|
||||||
ensureDefaultValue(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS)
|
ensureDefaultValue(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS)
|
||||||
ensureDefaultValue(AppConfig.PREF_REMOTE_DNS, AppConfig.DNS_PROXY)
|
ensureDefaultValue(AppConfig.PREF_REMOTE_DNS, AppConfig.DNS_PROXY)
|
||||||
ensureDefaultValue(AppConfig.PREF_DOMESTIC_DNS, AppConfig.DNS_DIRECT)
|
ensureDefaultValue(AppConfig.PREF_DOMESTIC_DNS, AppConfig.DNS_DIRECT)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.v2ray.ang.handler
|
package com.v2ray.ang.handler
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
@@ -90,6 +89,7 @@ object SpeedtestManager {
|
|||||||
val proxyUsername = SettingsManager.getSocksUsername()
|
val proxyUsername = SettingsManager.getSocksUsername()
|
||||||
val proxyPassword = SettingsManager.getSocksPassword()
|
val proxyPassword = SettingsManager.getSocksPassword()
|
||||||
val httpPort = SettingsManager.getHttpPort()
|
val httpPort = SettingsManager.getHttpPort()
|
||||||
|
if (httpPort == 0) return null
|
||||||
val content = HttpUtil.getUrlContent(url, 5000, httpPort, proxyUsername, proxyPassword) ?: return null
|
val content = HttpUtil.getUrlContent(url, 5000, httpPort, proxyUsername, proxyPassword) ?: return null
|
||||||
val ipInfo = JsonUtil.fromJson(content, IPAPIInfo::class.java) ?: return null
|
val ipInfo = JsonUtil.fromJson(content, IPAPIInfo::class.java) ?: return null
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,149 @@ import android.content.Context
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.work.Constraints
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
|
import androidx.work.NetworkType
|
||||||
|
import androidx.work.PeriodicWorkRequestBuilder
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
|
import androidx.work.multiprocess.RemoteWorkManager
|
||||||
|
import androidx.work.workDataOf
|
||||||
|
import com.v2ray.ang.AngApplication
|
||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
|
import com.v2ray.ang.dto.SubscriptionCache
|
||||||
import com.v2ray.ang.util.LogUtil
|
import com.v2ray.ang.util.LogUtil
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
object SubscriptionUpdater {
|
object SubscriptionUpdater {
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Public API — the only methods external callers should ever use
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync all subscription tasks with current settings.
|
||||||
|
*
|
||||||
|
* Startup/boot callers should use the default mode so existing periodic work is kept.
|
||||||
|
* Use forceReschedule=true only when the next run time needs to be recalculated from
|
||||||
|
* the latest persisted subscription state (for example after a manual refresh).
|
||||||
|
* Call from: MainActivity.onCreate(), BootReceiver.onReceive().
|
||||||
|
*/
|
||||||
|
fun sync(
|
||||||
|
context: Context = AngApplication.application,
|
||||||
|
forceReschedule: Boolean = false
|
||||||
|
) {
|
||||||
|
val existingWorkPolicy =
|
||||||
|
if (forceReschedule) {
|
||||||
|
ExistingPeriodicWorkPolicy.REPLACE
|
||||||
|
} else {
|
||||||
|
ExistingPeriodicWorkPolicy.KEEP
|
||||||
|
}
|
||||||
|
|
||||||
|
MmkvManager.decodeSubscriptions().forEach { sub ->
|
||||||
|
scheduleOne(
|
||||||
|
context = context,
|
||||||
|
subId = sub.guid,
|
||||||
|
shouldRun = sub.subscription.autoUpdate,
|
||||||
|
existingWorkPolicy = existingWorkPolicy
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LogUtil.i(
|
||||||
|
AppConfig.TAG,
|
||||||
|
"SubscriptionUpdater: sync complete forceReschedule=$forceReschedule"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync a single subscription's task.
|
||||||
|
* Call from: SubEditActivity after saving, after a manual update (to reset the timer).
|
||||||
|
*/
|
||||||
|
fun syncOne(context: Context = AngApplication.application, subId: String) {
|
||||||
|
val subItem = MmkvManager.decodeSubscription(subId) ?: return
|
||||||
|
scheduleOne(
|
||||||
|
context = context,
|
||||||
|
subId = subId,
|
||||||
|
shouldRun = subItem.autoUpdate,
|
||||||
|
existingWorkPolicy = ExistingPeriodicWorkPolicy.REPLACE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel the auto-update task for a single subscription.
|
||||||
|
* Call from: when a subscription is deleted.
|
||||||
|
*/
|
||||||
|
fun cancelOne(context: Context = AngApplication.application, subId: String) {
|
||||||
|
RemoteWorkManager.getInstance(context)
|
||||||
|
.cancelUniqueWork(taskName(subId))
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Internal scheduling logic
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private fun taskName(subId: String) = "${AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME}_$subId"
|
||||||
|
|
||||||
|
private fun scheduleOne(
|
||||||
|
context: Context,
|
||||||
|
subId: String,
|
||||||
|
shouldRun: Boolean,
|
||||||
|
existingWorkPolicy: ExistingPeriodicWorkPolicy
|
||||||
|
) {
|
||||||
|
val rw = RemoteWorkManager.getInstance(context)
|
||||||
|
if (!shouldRun) {
|
||||||
|
rw.cancelUniqueWork(taskName(subId))
|
||||||
|
LogUtil.d(AppConfig.TAG, "SubscriptionUpdater: cancelled task for $subId")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val subItem = MmkvManager.decodeSubscription(subId) ?: return
|
||||||
|
|
||||||
|
val intervalMinutes = maxOf(
|
||||||
|
AppConfig.SUBSCRIPTION_MIN_INTERVAL_MINUTES,
|
||||||
|
subItem.updateInterval
|
||||||
|
)
|
||||||
|
|
||||||
|
// Base initial delay on the last successful update time persisted in subscription.
|
||||||
|
val lastUpdated = subItem.lastUpdated
|
||||||
|
val intervalMillis = intervalMinutes * 60 * 1000L
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
val initialDelayMillis = if (lastUpdated <= 0L) {
|
||||||
|
0L
|
||||||
|
} else {
|
||||||
|
maxOf(0L, lastUpdated + intervalMillis - now)
|
||||||
|
}
|
||||||
|
|
||||||
|
val request = PeriodicWorkRequestBuilder<UpdateTask>(intervalMinutes, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(
|
||||||
|
Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.setInputData(workDataOf(KEY_SUB_ID to subId))
|
||||||
|
.setInitialDelay(initialDelayMillis, TimeUnit.MILLISECONDS)
|
||||||
|
.addTag(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
rw.enqueueUniquePeriodicWork(
|
||||||
|
taskName(subId),
|
||||||
|
existingWorkPolicy,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
LogUtil.i(
|
||||||
|
AppConfig.TAG,
|
||||||
|
"SubscriptionUpdater: scheduled [$subId] interval=${intervalMinutes}min " +
|
||||||
|
"initialDelay=${initialDelayMillis / 1000}s policy=$existingWorkPolicy"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Worker
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
private const val KEY_SUB_ID = "subId"
|
||||||
|
|
||||||
class UpdateTask(context: Context, params: WorkerParameters) :
|
class UpdateTask(context: Context, params: WorkerParameters) :
|
||||||
CoroutineWorker(context, params) {
|
CoroutineWorker(context, params) {
|
||||||
|
|
||||||
@@ -23,39 +158,50 @@ object SubscriptionUpdater {
|
|||||||
NotificationCompat.Builder(applicationContext, AppConfig.SUBSCRIPTION_UPDATE_CHANNEL)
|
NotificationCompat.Builder(applicationContext, AppConfig.SUBSCRIPTION_UPDATE_CHANNEL)
|
||||||
.setWhen(0)
|
.setWhen(0)
|
||||||
.setTicker("Update")
|
.setTicker("Update")
|
||||||
.setContentTitle(context.getString(R.string.title_pref_auto_update_subscription))
|
.setContentTitle(applicationContext.getString(R.string.title_pref_auto_update_subscription))
|
||||||
.setSmallIcon(R.drawable.ic_stat_name)
|
.setSmallIcon(R.drawable.ic_stat_name)
|
||||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the subscription update work.
|
|
||||||
* @return The result of the work.
|
|
||||||
*/
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
LogUtil.i(AppConfig.TAG, "subscription automatic update starting")
|
val subId = inputData.getString(KEY_SUB_ID)
|
||||||
|
LogUtil.i(AppConfig.TAG, "SubscriptionUpdater automatic update starting: $subId")
|
||||||
|
|
||||||
val subs = MmkvManager.decodeSubscriptions().filter { it.subscription.autoUpdate }
|
if (subId.isNullOrEmpty()) {
|
||||||
|
LogUtil.w(AppConfig.TAG, "SubscriptionUpdater: missing subId in worker input")
|
||||||
for (sub in subs) {
|
return Result.success()
|
||||||
val subItem = sub.subscription
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
notification.setChannelId(AppConfig.SUBSCRIPTION_UPDATE_CHANNEL)
|
|
||||||
val channel =
|
|
||||||
NotificationChannel(
|
|
||||||
AppConfig.SUBSCRIPTION_UPDATE_CHANNEL,
|
|
||||||
AppConfig.SUBSCRIPTION_UPDATE_CHANNEL_NAME,
|
|
||||||
NotificationManager.IMPORTANCE_MIN
|
|
||||||
)
|
|
||||||
notificationManager.createNotificationChannel(channel)
|
|
||||||
}
|
|
||||||
notificationManager.notify(3, notification.build())
|
|
||||||
LogUtil.i(AppConfig.TAG, "subscription automatic update: ---${subItem.remarks}")
|
|
||||||
AngConfigManager.updateConfigViaSub(sub)
|
|
||||||
notification.setContentText("Updating ${subItem.remarks}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val subItem = MmkvManager.decodeSubscription(subId)
|
||||||
|
if (subItem == null) {
|
||||||
|
LogUtil.w(AppConfig.TAG, "SubscriptionUpdater: no subscription found for $subId")
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subItem.autoUpdate) {
|
||||||
|
LogUtil.i(AppConfig.TAG, "SubscriptionUpdater: auto-update disabled for $subId, skip")
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
val sub = SubscriptionCache(subId, subItem)
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
notificationManager.createNotificationChannel(
|
||||||
|
NotificationChannel(
|
||||||
|
AppConfig.SUBSCRIPTION_UPDATE_CHANNEL,
|
||||||
|
AppConfig.SUBSCRIPTION_UPDATE_CHANNEL_NAME,
|
||||||
|
NotificationManager.IMPORTANCE_MIN
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationManager.notify(3, notification.build())
|
||||||
|
LogUtil.i(AppConfig.TAG, "SubscriptionUpdater automatic update: ---${sub.subscription.remarks}")
|
||||||
|
AngConfigManager.updateConfigViaSub(sub)
|
||||||
|
notification.setContentText("Updating ${sub.subscription.remarks}")
|
||||||
|
|
||||||
notificationManager.cancel(3)
|
notificationManager.cancel(3)
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -384,6 +384,12 @@ object V2rayConfigManager {
|
|||||||
*/
|
*/
|
||||||
private fun getInbounds(v2rayConfig: V2rayConfig): Boolean {
|
private fun getInbounds(v2rayConfig: V2rayConfig): Boolean {
|
||||||
try {
|
try {
|
||||||
|
val vpn = SettingsManager.isVpnMode()
|
||||||
|
val useHev = SettingsManager.isUsingHevTun()
|
||||||
|
val forcedByHev = vpn && useHev
|
||||||
|
|
||||||
|
val enableLocalProxy = forcedByHev || MmkvManager.decodeSettingsBool(AppConfig.PREF_ENABLE_LOCAL_PROXY, true)
|
||||||
|
|
||||||
val socksPort = SettingsManager.getSocksPort()
|
val socksPort = SettingsManager.getSocksPort()
|
||||||
val socksUsername = SettingsManager.getSocksUsername()
|
val socksUsername = SettingsManager.getSocksUsername()
|
||||||
val socksPassword = SettingsManager.getSocksPassword()
|
val socksPassword = SettingsManager.getSocksPassword()
|
||||||
@@ -396,6 +402,7 @@ object V2rayConfigManager {
|
|||||||
inbound1.listen = AppConfig.LOOPBACK
|
inbound1.listen = AppConfig.LOOPBACK
|
||||||
}
|
}
|
||||||
inbound1.port = socksPort
|
inbound1.port = socksPort
|
||||||
|
inbound1.settings?.udp = MmkvManager.decodeSettingsBool(AppConfig.PREF_SOCKS_ENABLE_UDP, true)
|
||||||
if (socksUsername != null && socksPassword != null) {
|
if (socksUsername != null && socksPassword != null) {
|
||||||
inbound1.settings?.auth = "password"
|
inbound1.settings?.auth = "password"
|
||||||
inbound1.settings?.accounts = listOf(
|
inbound1.settings?.accounts = listOf(
|
||||||
@@ -431,6 +438,10 @@ object V2rayConfigManager {
|
|||||||
v2rayConfig.inbounds.add(inbound2)
|
v2rayConfig.inbounds.add(inbound2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!enableLocalProxy) {
|
||||||
|
v2rayConfig.inbounds.removeIf { it.protocol == "socks" || it.protocol == "http" }
|
||||||
|
}
|
||||||
|
|
||||||
if (needTun()) {
|
if (needTun()) {
|
||||||
val inboundTun = v2rayConfig.inbounds.firstOrNull { e -> e.tag == "tun" }
|
val inboundTun = v2rayConfig.inbounds.firstOrNull { e -> e.tag == "tun" }
|
||||||
inboundTun?.settings?.mtu = SettingsManager.getVpnMtu()
|
inboundTun?.settings?.mtu = SettingsManager.getVpnMtu()
|
||||||
@@ -1305,7 +1316,10 @@ object V2rayConfigManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NetworkType.KCP.type -> {
|
NetworkType.KCP.type -> {
|
||||||
streamSettings.kcpSettings = StreamSettingsBean.KcpSettingsBean()
|
val kcpSetting = StreamSettingsBean.KcpSettingsBean()
|
||||||
|
profileItem.kcpMtu?.let { kcpSetting.mtu = it }
|
||||||
|
profileItem.kcpTti?.let { kcpSetting.tti = it }
|
||||||
|
streamSettings.kcpSettings = kcpSetting
|
||||||
val udpMaskList = mutableListOf<StreamSettingsBean.FinalMaskBean.MaskBean>()
|
val udpMaskList = mutableListOf<StreamSettingsBean.FinalMaskBean.MaskBean>()
|
||||||
if (!headerType.isNullOrEmpty() && headerType != "none") {
|
if (!headerType.isNullOrEmpty() && headerType != "none") {
|
||||||
val kcpHeaderType = when {
|
val kcpHeaderType = when {
|
||||||
@@ -1502,7 +1516,6 @@ object V2rayConfigManager {
|
|||||||
fingerprint = profileItem.fingerPrint.nullIfBlank(),
|
fingerprint = profileItem.fingerPrint.nullIfBlank(),
|
||||||
alpn = profileItem.alpn?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }.takeIf { !it.isNullOrEmpty() },
|
alpn = profileItem.alpn?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }.takeIf { !it.isNullOrEmpty() },
|
||||||
echConfigList = profileItem.echConfigList.nullIfBlank(),
|
echConfigList = profileItem.echConfigList.nullIfBlank(),
|
||||||
echForceQuery = profileItem.echForceQuery.nullIfBlank(),
|
|
||||||
pinnedPeerCertSha256 = profileItem.pinnedCA256.nullIfBlank(),
|
pinnedPeerCertSha256 = profileItem.pinnedCA256.nullIfBlank(),
|
||||||
publicKey = profileItem.publicKey.nullIfBlank(),
|
publicKey = profileItem.publicKey.nullIfBlank(),
|
||||||
shortId = profileItem.shortId.nullIfBlank(),
|
shortId = profileItem.shortId.nullIfBlank(),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.handler.MmkvManager
|
import com.v2ray.ang.handler.MmkvManager
|
||||||
|
import com.v2ray.ang.handler.SubscriptionUpdater
|
||||||
import com.v2ray.ang.handler.V2RayServiceManager
|
import com.v2ray.ang.handler.V2RayServiceManager
|
||||||
import com.v2ray.ang.util.LogUtil
|
import com.v2ray.ang.util.LogUtil
|
||||||
|
|
||||||
@@ -37,5 +38,6 @@ class BootReceiver : BroadcastReceiver() {
|
|||||||
|
|
||||||
LogUtil.i(AppConfig.TAG, "BootReceiver: Starting V2Ray service")
|
LogUtil.i(AppConfig.TAG, "BootReceiver: Starting V2Ray service")
|
||||||
V2RayServiceManager.startVService(context)
|
V2RayServiceManager.startVService(context)
|
||||||
|
SubscriptionUpdater.sync(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.setSession(V2RayServiceManager.getRunningServerName())
|
//builder.setSession(V2RayServiceManager.getRunningServerName())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import com.v2ray.ang.handler.AngConfigManager
|
|||||||
import com.v2ray.ang.handler.MmkvManager
|
import com.v2ray.ang.handler.MmkvManager
|
||||||
import com.v2ray.ang.handler.SettingsChangeManager
|
import com.v2ray.ang.handler.SettingsChangeManager
|
||||||
import com.v2ray.ang.handler.SettingsManager
|
import com.v2ray.ang.handler.SettingsManager
|
||||||
|
import com.v2ray.ang.handler.SubscriptionUpdater
|
||||||
import com.v2ray.ang.handler.V2RayServiceManager
|
import com.v2ray.ang.handler.V2RayServiceManager
|
||||||
import com.v2ray.ang.util.LogUtil
|
import com.v2ray.ang.util.LogUtil
|
||||||
import com.v2ray.ang.util.Utils
|
import com.v2ray.ang.util.Utils
|
||||||
@@ -98,6 +99,7 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
|||||||
|
|
||||||
setupGroupTab()
|
setupGroupTab()
|
||||||
setupViewModel()
|
setupViewModel()
|
||||||
|
SubscriptionUpdater.sync()
|
||||||
mainViewModel.reloadServerList()
|
mainViewModel.reloadServerList()
|
||||||
|
|
||||||
checkAndRequestPermission(PermissionType.POST_NOTIFICATIONS) {
|
checkAndRequestPermission(PermissionType.POST_NOTIFICATIONS) {
|
||||||
|
|||||||
@@ -84,9 +84,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
private val xhttpMode: Array<out String> by lazy {
|
private val xhttpMode: Array<out String> by lazy {
|
||||||
resources.getStringArray(R.array.xhttp_mode)
|
resources.getStringArray(R.array.xhttp_mode)
|
||||||
}
|
}
|
||||||
private val echForceQuerys: Array<out String> by lazy {
|
|
||||||
resources.getStringArray(R.array.ech_force_query_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Kotlin synthetics was used, but since it is removed in 1.8. We switch to old manual approach.
|
// Kotlin synthetics was used, but since it is removed in 1.8. We switch to old manual approach.
|
||||||
@@ -132,13 +129,14 @@ class ServerActivity : BaseActivity() {
|
|||||||
private val et_port_hop_interval: EditText? by lazy { findViewById(R.id.et_port_hop_interval) }
|
private val et_port_hop_interval: EditText? by lazy { findViewById(R.id.et_port_hop_interval) }
|
||||||
private val et_bandwidth_down: EditText? by lazy { findViewById(R.id.et_bandwidth_down) }
|
private val et_bandwidth_down: EditText? by lazy { findViewById(R.id.et_bandwidth_down) }
|
||||||
private val et_bandwidth_up: EditText? by lazy { findViewById(R.id.et_bandwidth_up) }
|
private val et_bandwidth_up: EditText? by lazy { findViewById(R.id.et_bandwidth_up) }
|
||||||
|
private val et_kcp_mtu: EditText? by lazy { findViewById(R.id.et_kcp_mtu) }
|
||||||
|
private val et_kcp_tti: EditText? by lazy { findViewById(R.id.et_kcp_tti) }
|
||||||
|
private val layout_kcp: LinearLayout? by lazy { findViewById(R.id.layout_kcp) }
|
||||||
private val et_extra: EditText? by lazy { findViewById(R.id.et_extra) }
|
private val et_extra: EditText? by lazy { findViewById(R.id.et_extra) }
|
||||||
private val et_fm: EditText? by lazy { findViewById(R.id.et_fm) }
|
private val et_fm: EditText? by lazy { findViewById(R.id.et_fm) }
|
||||||
private val layout_extra: LinearLayout? by lazy { findViewById(R.id.layout_extra) }
|
private val layout_extra: LinearLayout? by lazy { findViewById(R.id.layout_extra) }
|
||||||
private val et_ech_config_list: EditText? by lazy { findViewById(R.id.et_ech_config_list) }
|
private val et_ech_config_list: EditText? by lazy { findViewById(R.id.et_ech_config_list) }
|
||||||
private val container_ech_config_list: LinearLayout? by lazy { findViewById(R.id.lay_ech_config_list) }
|
private val container_ech_config_list: LinearLayout? by lazy { findViewById(R.id.lay_ech_config_list) }
|
||||||
private val sp_ech_force_query: Spinner? by lazy { findViewById(R.id.sp_ech_force_query) }
|
|
||||||
private val container_ech_force_query: LinearLayout? by lazy { findViewById(R.id.lay_ech_force_query) }
|
|
||||||
private val et_pinned_ca256: EditText? by lazy { findViewById(R.id.et_pinned_ca256) }
|
private val et_pinned_ca256: EditText? by lazy { findViewById(R.id.et_pinned_ca256) }
|
||||||
private val container_pinned_ca256: LinearLayout? by lazy { findViewById(R.id.lay_pinned_ca256) }
|
private val container_pinned_ca256: LinearLayout? by lazy { findViewById(R.id.lay_pinned_ca256) }
|
||||||
|
|
||||||
@@ -245,6 +243,14 @@ class ServerActivity : BaseActivity() {
|
|||||||
)
|
)
|
||||||
et_fm?.text = Utils.getEditable(config?.finalMask)
|
et_fm?.text = Utils.getEditable(config?.finalMask)
|
||||||
|
|
||||||
|
layout_kcp?.visibility =
|
||||||
|
when (networks[position]) {
|
||||||
|
NetworkType.KCP.type -> View.VISIBLE
|
||||||
|
else -> View.GONE
|
||||||
|
}
|
||||||
|
et_kcp_mtu?.text = Utils.getEditable(config?.kcpMtu?.toString().orEmpty())
|
||||||
|
et_kcp_tti?.text = Utils.getEditable(config?.kcpTti?.toString().orEmpty())
|
||||||
|
|
||||||
layout_extra?.visibility =
|
layout_extra?.visibility =
|
||||||
when (networks[position]) {
|
when (networks[position]) {
|
||||||
NetworkType.XHTTP.type -> View.VISIBLE
|
NetworkType.XHTTP.type -> View.VISIBLE
|
||||||
@@ -279,7 +285,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
container_spider_x,
|
container_spider_x,
|
||||||
container_mldsa65_verify,
|
container_mldsa65_verify,
|
||||||
container_ech_config_list,
|
container_ech_config_list,
|
||||||
container_ech_force_query,
|
|
||||||
container_pinned_ca256
|
container_pinned_ca256
|
||||||
).forEach { it?.visibility = View.GONE }
|
).forEach { it?.visibility = View.GONE }
|
||||||
}
|
}
|
||||||
@@ -292,7 +297,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
container_alpn,
|
container_alpn,
|
||||||
container_allow_insecure,
|
container_allow_insecure,
|
||||||
container_ech_config_list,
|
container_ech_config_list,
|
||||||
container_ech_force_query,
|
|
||||||
container_pinned_ca256
|
container_pinned_ca256
|
||||||
).forEach { it?.visibility = View.VISIBLE }
|
).forEach { it?.visibility = View.VISIBLE }
|
||||||
listOf(
|
listOf(
|
||||||
@@ -313,7 +317,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
container_alpn,
|
container_alpn,
|
||||||
container_allow_insecure,
|
container_allow_insecure,
|
||||||
container_ech_config_list,
|
container_ech_config_list,
|
||||||
container_ech_force_query,
|
|
||||||
container_pinned_ca256
|
container_pinned_ca256
|
||||||
).forEach { it?.visibility = View.GONE }
|
).forEach { it?.visibility = View.GONE }
|
||||||
listOf(
|
listOf(
|
||||||
@@ -397,10 +400,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
sp_allow_insecure?.setSelection(allowinsecure)
|
sp_allow_insecure?.setSelection(allowinsecure)
|
||||||
}
|
}
|
||||||
et_ech_config_list?.text = Utils.getEditable(config.echConfigList)
|
et_ech_config_list?.text = Utils.getEditable(config.echConfigList)
|
||||||
config.echForceQuery?.let { it ->
|
|
||||||
val index = Utils.arrayFind(echForceQuerys, it)
|
|
||||||
index.let { sp_ech_force_query?.setSelection(if (it >= 0) it else 0) }
|
|
||||||
}
|
|
||||||
et_pinned_ca256?.text = Utils.getEditable(config.pinnedCA256)
|
et_pinned_ca256?.text = Utils.getEditable(config.pinnedCA256)
|
||||||
} else if (config.security == REALITY) {
|
} else if (config.security == REALITY) {
|
||||||
et_public_key?.text = Utils.getEditable(config.publicKey.orEmpty())
|
et_public_key?.text = Utils.getEditable(config.publicKey.orEmpty())
|
||||||
@@ -569,6 +568,8 @@ class ServerActivity : BaseActivity() {
|
|||||||
profileItem.xhttpMode = transportTypes(networks[network])[type]
|
profileItem.xhttpMode = transportTypes(networks[network])[type]
|
||||||
profileItem.xhttpExtra = et_extra?.text?.toString()?.trim().nullIfBlank()
|
profileItem.xhttpExtra = et_extra?.text?.toString()?.trim().nullIfBlank()
|
||||||
profileItem.finalMask = et_fm?.text?.toString()?.trim()?.nullIfBlank()
|
profileItem.finalMask = et_fm?.text?.toString()?.trim()?.nullIfBlank()
|
||||||
|
profileItem.kcpMtu = et_kcp_mtu?.text?.toString()?.toIntOrNull()
|
||||||
|
profileItem.kcpTti = et_kcp_tti?.text?.toString()?.toIntOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveTls(config: ProfileItem) {
|
private fun saveTls(config: ProfileItem) {
|
||||||
@@ -582,7 +583,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
val spiderX = et_spider_x?.text?.toString()
|
val spiderX = et_spider_x?.text?.toString()
|
||||||
val mldsa65Verify = et_mldsa65_verify?.text?.toString()
|
val mldsa65Verify = et_mldsa65_verify?.text?.toString()
|
||||||
val echConfigList = et_ech_config_list?.text?.toString()
|
val echConfigList = et_ech_config_list?.text?.toString()
|
||||||
val echForceQueryIndex = sp_ech_force_query?.selectedItemPosition ?: 0
|
|
||||||
val pinnedCA256 = et_pinned_ca256?.text?.toString()
|
val pinnedCA256 = et_pinned_ca256?.text?.toString()
|
||||||
|
|
||||||
val allowInsecure =
|
val allowInsecure =
|
||||||
@@ -602,7 +602,6 @@ class ServerActivity : BaseActivity() {
|
|||||||
config.spiderX = spiderX
|
config.spiderX = spiderX
|
||||||
config.mldsa65Verify = mldsa65Verify
|
config.mldsa65Verify = mldsa65Verify
|
||||||
config.echConfigList = echConfigList
|
config.echConfigList = echConfigList
|
||||||
config.echForceQuery = echForceQuerys[echForceQueryIndex]
|
|
||||||
config.pinnedCA256 = pinnedCA256
|
config.pinnedCA256 = pinnedCA256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,12 @@ import androidx.preference.CheckBoxPreference
|
|||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
|
||||||
import androidx.work.PeriodicWorkRequest
|
|
||||||
import androidx.work.multiprocess.RemoteWorkManager
|
|
||||||
import com.v2ray.ang.AngApplication
|
|
||||||
import com.v2ray.ang.AppConfig
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.AppConfig.VPN
|
import com.v2ray.ang.AppConfig.VPN
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
import com.v2ray.ang.extension.toLongEx
|
|
||||||
import com.v2ray.ang.handler.MmkvManager
|
import com.v2ray.ang.handler.MmkvManager
|
||||||
import com.v2ray.ang.handler.SubscriptionUpdater
|
|
||||||
import com.v2ray.ang.helper.MmkvPreferenceDataStore
|
import com.v2ray.ang.helper.MmkvPreferenceDataStore
|
||||||
import com.v2ray.ang.util.Utils
|
import com.v2ray.ang.util.Utils
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class SettingsActivity : BaseActivity() {
|
class SettingsActivity : BaseActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@@ -48,16 +41,20 @@ class SettingsActivity : BaseActivity() {
|
|||||||
private val fragmentLength by lazy { findPreference<EditTextPreference>(AppConfig.PREF_FRAGMENT_LENGTH) }
|
private val fragmentLength by lazy { findPreference<EditTextPreference>(AppConfig.PREF_FRAGMENT_LENGTH) }
|
||||||
private val fragmentInterval by lazy { findPreference<EditTextPreference>(AppConfig.PREF_FRAGMENT_INTERVAL) }
|
private val fragmentInterval by lazy { findPreference<EditTextPreference>(AppConfig.PREF_FRAGMENT_INTERVAL) }
|
||||||
|
|
||||||
private val autoUpdateCheck by lazy { findPreference<CheckBoxPreference>(AppConfig.SUBSCRIPTION_AUTO_UPDATE) }
|
|
||||||
private val autoUpdateInterval by lazy { findPreference<EditTextPreference>(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL) }
|
|
||||||
private val mode by lazy { findPreference<ListPreference>(AppConfig.PREF_MODE) }
|
private val mode by lazy { findPreference<ListPreference>(AppConfig.PREF_MODE) }
|
||||||
private val socksPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_PORT) }
|
|
||||||
private val dynamicSocksPort by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_DYNAMIC_SOCKS_PORT) }
|
|
||||||
|
|
||||||
private val hevTunLogLevel by lazy { findPreference<ListPreference>(AppConfig.PREF_HEV_TUNNEL_LOGLEVEL) }
|
private val hevTunLogLevel by lazy { findPreference<ListPreference>(AppConfig.PREF_HEV_TUNNEL_LOGLEVEL) }
|
||||||
private val hevTunRwTimeout by lazy { findPreference<EditTextPreference>(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT) }
|
private val hevTunRwTimeout by lazy { findPreference<EditTextPreference>(AppConfig.PREF_HEV_TUNNEL_RW_TIMEOUT) }
|
||||||
private val useHevTun by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_USE_HEV_TUNNEL) }
|
private val useHevTun by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_USE_HEV_TUNNEL) }
|
||||||
|
|
||||||
|
private val enableLocalProxy by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_ENABLE_LOCAL_PROXY) }
|
||||||
|
private val socksPort by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_PORT) }
|
||||||
|
private val dynamicSocksPort by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_DYNAMIC_SOCKS_PORT) }
|
||||||
|
private val socksUsername by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_USERNAME) }
|
||||||
|
private val socksPassword by lazy { findPreference<EditTextPreference>(AppConfig.PREF_SOCKS_PASSWORD) }
|
||||||
|
private val socksEnableUdp by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_SOCKS_ENABLE_UDP) }
|
||||||
|
private val proxySharing by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_PROXY_SHARING) }
|
||||||
|
|
||||||
override fun onCreatePreferences(bundle: Bundle?, s: String?) {
|
override fun onCreatePreferences(bundle: Bundle?, s: String?) {
|
||||||
// Use MMKV as the storage backend for all Preferences
|
// Use MMKV as the storage backend for all Preferences
|
||||||
// This prevents inconsistencies between SharedPreferences and MMKV
|
// This prevents inconsistencies between SharedPreferences and MMKV
|
||||||
@@ -90,15 +87,6 @@ class SettingsActivity : BaseActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
autoUpdateCheck?.setOnPreferenceChangeListener { _, newValue ->
|
|
||||||
val value = newValue as Boolean
|
|
||||||
autoUpdateCheck?.isChecked = value
|
|
||||||
autoUpdateInterval?.isEnabled = value
|
|
||||||
autoUpdateInterval?.text?.toLongEx()?.let {
|
|
||||||
if (newValue) configureUpdateTask(it) else cancelUpdateTask()
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
mode?.setOnPreferenceChangeListener { pref, newValue ->
|
mode?.setOnPreferenceChangeListener { pref, newValue ->
|
||||||
val valueStr = newValue.toString()
|
val valueStr = newValue.toString()
|
||||||
(pref as? ListPreference)?.let { lp ->
|
(pref as? ListPreference)?.let { lp ->
|
||||||
@@ -115,6 +103,11 @@ class SettingsActivity : BaseActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableLocalProxy?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
|
updateEnableLocalProxy(newValue as Boolean)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
dynamicSocksPort?.setOnPreferenceChangeListener { _, newValue ->
|
dynamicSocksPort?.setOnPreferenceChangeListener { _, newValue ->
|
||||||
updateDynamicSocksPort(newValue as Boolean)
|
updateDynamicSocksPort(newValue as Boolean)
|
||||||
true
|
true
|
||||||
@@ -174,15 +167,15 @@ class SettingsActivity : BaseActivity() {
|
|||||||
// Initialize mode-dependent UI states
|
// Initialize mode-dependent UI states
|
||||||
updateMode(MmkvManager.decodeSettingsString(AppConfig.PREF_MODE, VPN))
|
updateMode(MmkvManager.decodeSettingsString(AppConfig.PREF_MODE, VPN))
|
||||||
|
|
||||||
|
// Initialize local proxy state
|
||||||
|
updateEnableLocalProxy(MmkvManager.decodeSettingsBool(AppConfig.PREF_ENABLE_LOCAL_PROXY, true))
|
||||||
|
|
||||||
// Initialize mux-dependent UI states
|
// Initialize mux-dependent UI states
|
||||||
updateMux(MmkvManager.decodeSettingsBool(AppConfig.PREF_MUX_ENABLED, false))
|
updateMux(MmkvManager.decodeSettingsBool(AppConfig.PREF_MUX_ENABLED, false))
|
||||||
|
|
||||||
// Initialize fragment-dependent UI states
|
// Initialize fragment-dependent UI states
|
||||||
updateFragment(MmkvManager.decodeSettingsBool(AppConfig.PREF_FRAGMENT_ENABLED, false))
|
updateFragment(MmkvManager.decodeSettingsBool(AppConfig.PREF_FRAGMENT_ENABLED, false))
|
||||||
|
|
||||||
// Initialize auto-update interval state
|
|
||||||
autoUpdateInterval?.isEnabled = MmkvManager.decodeSettingsBool(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
|
|
||||||
|
|
||||||
updateDynamicSocksPort(MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_SOCKS_PORT, false))
|
updateDynamicSocksPort(MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_SOCKS_PORT, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,29 +213,6 @@ class SettingsActivity : BaseActivity() {
|
|||||||
vpnDns?.isEnabled = !enabled
|
vpnDns?.isEnabled = !enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configureUpdateTask(interval: Long) {
|
|
||||||
val rw = RemoteWorkManager.getInstance(AngApplication.application)
|
|
||||||
rw.cancelUniqueWork(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
|
|
||||||
rw.enqueueUniquePeriodicWork(
|
|
||||||
AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME,
|
|
||||||
ExistingPeriodicWorkPolicy.UPDATE,
|
|
||||||
PeriodicWorkRequest.Builder(
|
|
||||||
SubscriptionUpdater.UpdateTask::class.java,
|
|
||||||
interval,
|
|
||||||
TimeUnit.MINUTES
|
|
||||||
)
|
|
||||||
.apply {
|
|
||||||
setInitialDelay(interval, TimeUnit.MINUTES)
|
|
||||||
}
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cancelUpdateTask() {
|
|
||||||
val rw = RemoteWorkManager.getInstance(AngApplication.application)
|
|
||||||
rw.cancelUniqueWork(AppConfig.SUBSCRIPTION_UPDATE_TASK_NAME)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMux(enabled: Boolean) {
|
private fun updateMux(enabled: Boolean) {
|
||||||
muxConcurrency?.isEnabled = enabled
|
muxConcurrency?.isEnabled = enabled
|
||||||
muxXudpConcurrency?.isEnabled = enabled
|
muxXudpConcurrency?.isEnabled = enabled
|
||||||
@@ -276,12 +246,44 @@ class SettingsActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDynamicSocksPort(enabled: Boolean) {
|
private fun updateDynamicSocksPort(enabled: Boolean) {
|
||||||
socksPort?.isEnabled = !enabled
|
socksPort?.isEnabled = (enableLocalProxy?.isChecked == true) && !enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateEnableLocalProxy(enabled: Boolean) {
|
||||||
|
val dynamic = MmkvManager.decodeSettingsBool(AppConfig.PREF_DYNAMIC_SOCKS_PORT, false)
|
||||||
|
socksPort?.isEnabled = enabled && !dynamic
|
||||||
|
dynamicSocksPort?.isEnabled = enabled
|
||||||
|
socksUsername?.isEnabled = enabled
|
||||||
|
socksPassword?.isEnabled = enabled
|
||||||
|
socksEnableUdp?.isEnabled = enabled
|
||||||
|
proxySharing?.isEnabled = enabled
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
if (appendHttpProxy?.isChecked == true) {
|
||||||
|
appendHttpProxy?.isChecked = false
|
||||||
|
MmkvManager.encodeSettings(AppConfig.PREF_APPEND_HTTP_PROXY, false)
|
||||||
|
}
|
||||||
|
appendHttpProxy?.isEnabled = false
|
||||||
|
} else {
|
||||||
|
val vpn = MmkvManager.decodeSettingsString(AppConfig.PREF_MODE) == VPN
|
||||||
|
appendHttpProxy?.isEnabled = vpn
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateHevTunSettings(enabled: Boolean) {
|
private fun updateHevTunSettings(enabled: Boolean) {
|
||||||
hevTunLogLevel?.isEnabled = enabled
|
hevTunLogLevel?.isEnabled = enabled
|
||||||
hevTunRwTimeout?.isEnabled = enabled
|
hevTunRwTimeout?.isEnabled = enabled
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
if (enableLocalProxy?.isChecked == false) {
|
||||||
|
enableLocalProxy?.isChecked = true
|
||||||
|
MmkvManager.encodeSettings(AppConfig.PREF_ENABLE_LOCAL_PROXY, true)
|
||||||
|
}
|
||||||
|
enableLocalProxy?.isEnabled = false
|
||||||
|
} else {
|
||||||
|
enableLocalProxy?.isEnabled = true
|
||||||
|
}
|
||||||
|
updateEnableLocalProxy(enableLocalProxy?.isChecked == true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.v2ray.ang.extension.toastSuccess
|
|||||||
import com.v2ray.ang.handler.MmkvManager
|
import com.v2ray.ang.handler.MmkvManager
|
||||||
import com.v2ray.ang.handler.SettingsChangeManager
|
import com.v2ray.ang.handler.SettingsChangeManager
|
||||||
import com.v2ray.ang.handler.SettingsManager
|
import com.v2ray.ang.handler.SettingsManager
|
||||||
|
import com.v2ray.ang.handler.SubscriptionUpdater
|
||||||
import com.v2ray.ang.util.Utils
|
import com.v2ray.ang.util.Utils
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -51,6 +52,7 @@ class SubEditActivity : BaseActivity() {
|
|||||||
binding.etFilter.text = Utils.getEditable(subItem.filter)
|
binding.etFilter.text = Utils.getEditable(subItem.filter)
|
||||||
binding.chkEnable.isChecked = subItem.enabled
|
binding.chkEnable.isChecked = subItem.enabled
|
||||||
binding.autoUpdateCheck.isChecked = subItem.autoUpdate
|
binding.autoUpdateCheck.isChecked = subItem.autoUpdate
|
||||||
|
binding.etUpdateInterval.text = Utils.getEditable(subItem.updateInterval.toString())
|
||||||
binding.allowInsecureUrl.isChecked = subItem.allowInsecureUrl
|
binding.allowInsecureUrl.isChecked = subItem.allowInsecureUrl
|
||||||
binding.etPreProfile.text = Utils.getEditable(subItem.prevProfile)
|
binding.etPreProfile.text = Utils.getEditable(subItem.prevProfile)
|
||||||
binding.etNextProfile.text = Utils.getEditable(subItem.nextProfile)
|
binding.etNextProfile.text = Utils.getEditable(subItem.nextProfile)
|
||||||
@@ -65,6 +67,7 @@ class SubEditActivity : BaseActivity() {
|
|||||||
binding.etUrl.text = null
|
binding.etUrl.text = null
|
||||||
binding.etFilter.text = null
|
binding.etFilter.text = null
|
||||||
binding.chkEnable.isChecked = true
|
binding.chkEnable.isChecked = true
|
||||||
|
binding.etUpdateInterval.text = null
|
||||||
binding.etPreProfile.text = null
|
binding.etPreProfile.text = null
|
||||||
binding.etNextProfile.text = null
|
binding.etNextProfile.text = null
|
||||||
return true
|
return true
|
||||||
@@ -82,6 +85,27 @@ class SubEditActivity : BaseActivity() {
|
|||||||
subItem.filter = binding.etFilter.text.toString()
|
subItem.filter = binding.etFilter.text.toString()
|
||||||
subItem.enabled = binding.chkEnable.isChecked
|
subItem.enabled = binding.chkEnable.isChecked
|
||||||
subItem.autoUpdate = binding.autoUpdateCheck.isChecked
|
subItem.autoUpdate = binding.autoUpdateCheck.isChecked
|
||||||
|
|
||||||
|
val intervalInput = binding.etUpdateInterval.text.toString().trim()
|
||||||
|
val intervalMinutes = intervalInput.toLongOrNull()
|
||||||
|
if (subItem.autoUpdate) {
|
||||||
|
// autoUpdate is enabled: interval must be valid
|
||||||
|
if (intervalMinutes == null) {
|
||||||
|
// field is empty, reset to default
|
||||||
|
subItem.updateInterval = SubscriptionItem().updateInterval
|
||||||
|
} else if (intervalMinutes < AppConfig.SUBSCRIPTION_MIN_INTERVAL_MINUTES) {
|
||||||
|
toast(R.string.toast_invalid_update_interval)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
subItem.updateInterval = intervalMinutes
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// autoUpdate is disabled: save only if the value is valid, otherwise keep the existing value
|
||||||
|
if (intervalMinutes != null && intervalMinutes >= AppConfig.SUBSCRIPTION_MIN_INTERVAL_MINUTES) {
|
||||||
|
subItem.updateInterval = intervalMinutes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subItem.prevProfile = binding.etPreProfile.text.toString()
|
subItem.prevProfile = binding.etPreProfile.text.toString()
|
||||||
subItem.nextProfile = binding.etNextProfile.text.toString()
|
subItem.nextProfile = binding.etNextProfile.text.toString()
|
||||||
subItem.allowInsecureUrl = binding.allowInsecureUrl.isChecked
|
subItem.allowInsecureUrl = binding.allowInsecureUrl.isChecked
|
||||||
@@ -105,6 +129,7 @@ class SubEditActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MmkvManager.encodeSubscription(editSubId, subItem)
|
MmkvManager.encodeSubscription(editSubId, subItem)
|
||||||
|
SubscriptionUpdater.syncOne(subId = editSubId)
|
||||||
toastSuccess(R.string.toast_success)
|
toastSuccess(R.string.toast_success)
|
||||||
finish()
|
finish()
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -146,7 +146,6 @@
|
|||||||
android:layout_weight="1.0"
|
android:layout_weight="1.0"
|
||||||
android:text="@string/sub_auto_update" />
|
android:text="@string/sub_auto_update" />
|
||||||
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/auto_update_check"
|
android:id="@+id/auto_update_check"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -157,6 +156,26 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/padding_spacing_dp16"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/title_pref_auto_update_interval" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_update_interval"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="number"
|
||||||
|
tools:ignore="TextFields" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -134,30 +134,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:nextFocusDown="@+id/sp_ech_force_query" />
|
android:nextFocusDown="@+id/et_pinned_ca256" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/lay_ech_force_query"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/server_lab_ech_force_query" />
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/sp_ech_force_query"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/padding_spacing_dp8"
|
|
||||||
android:layout_marginBottom="@dimen/padding_spacing_dp8"
|
|
||||||
android:entries="@array/ech_force_query_value" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/lay_pinned_ca256"
|
android:id="@+id/lay_pinned_ca256"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -175,7 +155,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:nextFocusDown="@+id/sp_ech_force_query" />
|
android:nextFocusDown="@+id/et_public_key" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,49 @@
|
|||||||
android:inputType="text" />
|
android:inputType="text" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_kcp"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/padding_spacing_dp16"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/server_lab_kcp_mtu" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_kcp_mtu"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="number" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/padding_spacing_dp16"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/server_lab_kcp_tti" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/et_kcp_tti"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="number" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_extra"
|
android:id="@+id/layout_extra"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -89,6 +89,8 @@
|
|||||||
<string name="server_lab_reserved">محجوز (اختياري)</string>
|
<string name="server_lab_reserved">محجوز (اختياري)</string>
|
||||||
<string name="server_lab_local_address">العنوان المحلي (اختياري IPv4/IPv6، مفصولة بفواصل)</string>
|
<string name="server_lab_local_address">العنوان المحلي (اختياري IPv4/IPv6، مفصولة بفواصل)</string>
|
||||||
<string name="server_lab_local_mtu">Mtu (اختياري، الافتراضي 1420)</string>
|
<string name="server_lab_local_mtu">Mtu (اختياري، الافتراضي 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (اختياري، الافتراضي في النواة 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (اختياري، الافتراضي في النواة 50)</string>
|
||||||
<string name="toast_success">نجاح</string>
|
<string name="toast_success">نجاح</string>
|
||||||
<string name="toast_failure">فشل</string>
|
<string name="toast_failure">فشل</string>
|
||||||
<string name="toast_none_data">لا يوجد شيء</string>
|
<string name="toast_none_data">لا يوجد شيء</string>
|
||||||
@@ -115,7 +117,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -221,6 +222,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">عند TLS، الافتراضي هو السماح غير الآمن</string>
|
<string name="summary_pref_allow_insecure">عند TLS، الافتراضي هو السماح غير الآمن</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">منفذ بروكسي Local</string>
|
<string name="title_pref_socks_port">منفذ بروكسي Local</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">تفعيل الوكيل المحلي</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">مصادقة socks5 ليست آمنة تمامًا عند استخدام UDP</string>
|
||||||
<string name="summary_pref_socks_port">منفذ بروكسي Local</string>
|
<string name="summary_pref_socks_port">منفذ بروكسي Local</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
||||||
@@ -295,6 +300,7 @@
|
|||||||
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
|
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
|
||||||
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
|
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
|
||||||
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
|
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
|
||||||
|
<string name="toast_invalid_update_interval">فاصل التحديث غير صالح. الحد الأدنى هو 15 دقيقة.</string>
|
||||||
<string name="title_sub_update">تحديث الاشتراك (أول خطوة)</string>
|
<string name="title_sub_update">تحديث الاشتراك (أول خطوة)</string>
|
||||||
<string name="title_ping_all_server">Tcping لجميع الإعدادات</string>
|
<string name="title_ping_all_server">Tcping لجميع الإعدادات</string>
|
||||||
<string name="title_real_ping_all_server"> اختبر جميع الإعدادات (3)</string>
|
<string name="title_real_ping_all_server"> اختبر جميع الإعدادات (3)</string>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">সংরক্ষিত (ঐচ্ছিক)</string>
|
<string name="server_lab_reserved">সংরক্ষিত (ঐচ্ছিক)</string>
|
||||||
<string name="server_lab_local_address">স্থানীয় ঠিকানা (ঐচ্ছিক IPv4/IPv6, কমা দ্বারা পৃথক করা)</string>
|
<string name="server_lab_local_address">স্থানীয় ঠিকানা (ঐচ্ছিক IPv4/IPv6, কমা দ্বারা পৃথক করা)</string>
|
||||||
<string name="server_lab_local_mtu">MTU (ঐচ্ছিক, ডিফল্ট 1420)</string>
|
<string name="server_lab_local_mtu">MTU (ঐচ্ছিক, ডিফল্ট 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (ঐচ্ছিক, কোর ডিফল্ট 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (ঐচ্ছিক, কোর ডিফল্ট 50)</string>
|
||||||
<string name="toast_success">সফল</string>
|
<string name="toast_success">সফল</string>
|
||||||
<string name="toast_failure">ব্যর্থ</string>
|
<string name="toast_failure">ব্যর্থ</string>
|
||||||
<string name="toast_none_data">কোনও তথ্য নেই</string>
|
<string name="toast_none_data">কোনও তথ্য নেই</string>
|
||||||
@@ -114,7 +116,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -221,6 +222,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">যখন TLS, ডিফল্টভাবে allowInsecure</string>
|
<string name="summary_pref_allow_insecure">যখন TLS, ডিফল্টভাবে allowInsecure</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">Local প্রক্সি পোর্ট</string>
|
<string name="title_pref_socks_port">Local প্রক্সি পোর্ট</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">লোকাল প্রক্সি সক্ষম করুন</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">UDP ব্যবহার করার সময় socks5 প্রমাণীকরণ সম্পূর্ণরূপে নিরাপদ নয়</string>
|
||||||
<string name="summary_pref_socks_port">Local প্রক্সি পোর্ট</string>
|
<string name="summary_pref_socks_port">Local প্রক্সি পোর্ট</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
||||||
@@ -295,6 +300,7 @@
|
|||||||
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
|
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
|
||||||
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
|
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
|
||||||
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
|
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
|
||||||
|
<string name="toast_invalid_update_interval">আপডেটের বিরতি সঠিক নয়। সর্বনিম্ন ১৫ মিনিট।</string>
|
||||||
<string name="title_sub_update">সাবস্ক্রিপশন আপডেট</string>
|
<string name="title_sub_update">সাবস্ক্রিপশন আপডেট</string>
|
||||||
<string name="title_ping_all_server">সব কনফিগারেশন TCPing</string>
|
<string name="title_ping_all_server">সব কনফিগারেশন TCPing</string>
|
||||||
<string name="title_real_ping_all_server">সব কনফিগারেশন প্রকৃত বিলম্ব</string>
|
<string name="title_real_ping_all_server">সব কনফিগারেশন প্রকৃত বিলম্ব</string>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved(اختیاری، وا کاما ز یک جوڌا ابۊن)</string>
|
<string name="server_lab_reserved">Reserved(اختیاری، وا کاما ز یک جوڌا ابۊن)</string>
|
||||||
<string name="server_lab_local_address">نشۊوی مهلی (اختیاری IPv4/IPv6، وا کاما ز یک جوڌا ابۊن)</string>
|
<string name="server_lab_local_address">نشۊوی مهلی (اختیاری IPv4/IPv6، وا کاما ز یک جوڌا ابۊن)</string>
|
||||||
<string name="server_lab_local_mtu">Mtu(اختیاری، پؽش فرز 1420)</string>
|
<string name="server_lab_local_mtu">Mtu(اختیاری، پؽش فرز 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (اختیاری، پؽش فرز هسته 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (اختیاری، پؽش فرز هسته 50)</string>
|
||||||
<string name="toast_success">وا مووفقیت ٱنجوم وابی</string>
|
<string name="toast_success">وا مووفقیت ٱنجوم وابی</string>
|
||||||
<string name="toast_failure">شکست خرد</string>
|
<string name="toast_failure">شکست خرد</string>
|
||||||
<string name="toast_none_data">هیچ داده ای وۊجۊڌ نڌاره</string>
|
<string name="toast_none_data">هیچ داده ای وۊجۊڌ نڌاره</string>
|
||||||
@@ -112,9 +114,8 @@
|
|||||||
<string name="server_lab_bandwidth_up">وا روء رئڌن پئنا باند (واهڌ)</string>
|
<string name="server_lab_bandwidth_up">وا روء رئڌن پئنا باند (واهڌ)</string>
|
||||||
<string name="server_lab_xhttp_mode">هالت XHTTP</string>
|
<string name="server_lab_xhttp_mode">هالت XHTTP</string>
|
||||||
<string name="server_lab_xhttp_extra">XHTTP Extra خام JSON، قالوو: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra خام JSON، قالوو: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">finalMask خام JSON، قالوو: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">نومگه کانفیگ Ech</string>
|
<string name="server_lab_ech_config_list">نومگه کانفیگ Ech</string>
|
||||||
<string name="server_lab_ech_force_query">پورس وو جۊ اجباری Ech</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -135,8 +136,8 @@
|
|||||||
<string name="menu_item_search">پیتینیڌن</string>
|
<string name="menu_item_search">پیتینیڌن</string>
|
||||||
<string name="menu_item_select_all">پسند پوی</string>
|
<string name="menu_item_select_all">پسند پوی</string>
|
||||||
<string name="menu_item_invert_selection">پسند چواسه</string>
|
<string name="menu_item_invert_selection">پسند چواسه</string>
|
||||||
<string name="msg_enter_keywords">کلمه کلیدی را وارد کنید</string>
|
<string name="msg_enter_keywords">کلمه کلیدی ن بزنین</string>
|
||||||
<string name="switch_bypass_apps_mode">هالت Bypass</string>
|
<string name="switch_bypass_apps_mode">هالت دور زیڌن</string>
|
||||||
<string name="menu_item_select_proxy_app">پسند خوتکار پروکسی برنومه</string>
|
<string name="menu_item_select_proxy_app">پسند خوتکار پروکسی برنومه</string>
|
||||||
<string name="msg_downloading_content">موئتوا هونی دانلود ابۊن</string>
|
<string name="msg_downloading_content">موئتوا هونی دانلود ابۊن</string>
|
||||||
<string name="menu_item_export_proxy_app">و در کشیڌن من کلیپ بورد</string>
|
<string name="menu_item_export_proxy_app">و در کشیڌن من کلیپ بورد</string>
|
||||||
@@ -151,7 +152,7 @@
|
|||||||
<string name="title_core_settings">سامووا هسته</string>
|
<string name="title_core_settings">سامووا هسته</string>
|
||||||
<string name="title_vpn_settings">سامووا VPN</string>
|
<string name="title_vpn_settings">سامووا VPN</string>
|
||||||
<string name="title_pref_per_app_proxy">پروکسی و ری برنومه</string>
|
<string name="title_pref_per_app_proxy">پروکسی و ری برنومه</string>
|
||||||
<string name="summary_pref_per_app_proxy">پوی وولاتی: برنومه واجۊری بیڌه پروکسی هڌ، منپیز موستقیم بؽ نشووه هڌ. هالت دور زیڌن: برنومه نشووک ناڌه موستقیمن منپیز هڌ، پروکسی نشووک زیڌه نؽڌ. گۊزینه پسند خوتکار برنومه پروکسی من نومگه</string>
|
<string name="summary_pref_per_app_proxy">پوی وولاتی: برنومه پسند وابیڌه وا ی پروکسی منپیز ابۊ، برنومه پسند نوابیڌه موستقیمن منپیز ابۊ. \nحالت دور زیڌن: برنومه پسند وابیڌه موستقیمن منپیز ابۊ، برنومه پسند نوابیڌه وا ی پروکسی منپیز ابۊ. \nپسند خوتکار برنومه یل پروکسی من نومگه امکووݩ پزیر هڌ.</string>
|
||||||
<string name="title_pref_is_booted">منپیز خوتکار مجال ره ونی</string>
|
<string name="title_pref_is_booted">منپیز خوتکار مجال ره ونی</string>
|
||||||
<string name="summary_pref_is_booted">مجال ره وندن، خوساخوس و سرور پسند بیڌه منپیز ابۊ که گاشڌ نا مووفق بۊ.</string>
|
<string name="summary_pref_is_booted">مجال ره وندن، خوساخوس و سرور پسند بیڌه منپیز ابۊ که گاشڌ نا مووفق بۊ.</string>
|
||||||
|
|
||||||
@@ -187,10 +188,10 @@
|
|||||||
<string name="summary_pref_fake_dns_enabled">DNS مهلی نشۊویا IP جئلی ن وورگنه (زل تر، ٱما گاشڌ من یقرد ز برنومه یل کار نکونه)</string>
|
<string name="summary_pref_fake_dns_enabled">DNS مهلی نشۊویا IP جئلی ن وورگنه (زل تر، ٱما گاشڌ من یقرد ز برنومه یل کار نکونه)</string>
|
||||||
|
|
||||||
<string name="title_pref_ipv6_enabled">ره وندن IPv6</string>
|
<string name="title_pref_ipv6_enabled">ره وندن IPv6</string>
|
||||||
<string name="summary_pref_ipv6_enabled">نشۊویا IPv6 وو تورا IPv6 ن ز رابط VPN ره وند کۊنین</string>
|
<string name="summary_pref_ipv6_enabled">نشۊویا IPv6 وو تورا IPv6 ن ز رابت VPN ره ونین</string>
|
||||||
|
|
||||||
<string name="title_pref_prefer_ipv6">ترجی داڌن IPv6</string>
|
<string name="title_pref_prefer_ipv6">ترجی داڌن IPv6</string>
|
||||||
<string name="summary_pref_prefer_ipv6">مون حل کردن نوم دامنه، نشۊویا IPv6 ن ترجی بڌین</string>
|
<string name="summary_pref_prefer_ipv6">مجال هل وو فسل نوم دامنه، نشۊویا IPv6 ن ترجی بڌین</string>
|
||||||
|
|
||||||
<string name="title_pref_remote_dns">DNS ز ره دیر (اختیاری) (udp/tcp/https/quic) (اختیاری)</string>
|
<string name="title_pref_remote_dns">DNS ز ره دیر (اختیاری) (udp/tcp/https/quic) (اختیاری)</string>
|
||||||
<string name="summary_pref_remote_dns">DNS</string>
|
<string name="summary_pref_remote_dns">DNS</string>
|
||||||
@@ -221,13 +222,17 @@
|
|||||||
<string name="summary_pref_allow_insecure">مجال و کار بوردن TLS ب تۉر پؽش فرز، موجوز نا ٱمن فعال هڌ.</string>
|
<string name="summary_pref_allow_insecure">مجال و کار بوردن TLS ب تۉر پؽش فرز، موجوز نا ٱمن فعال هڌ.</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">پورت پروکسی مهلی</string>
|
<string name="title_pref_socks_port">پورت پروکسی مهلی</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">ره وندن پروکسی مهلی</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">هرسا قیرفعال بۊ، هیچ پروکسی SOCKS من دسرس نؽ، سی دل هیمو ورۊ رسۊوی یل اشتراک وو کارا جۊر یو نترن ز پروکسی استفاڌه کونن.</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">ائراز هۊویت socks5 مجال استفاڌه ز UDP کاملن ایمن نؽ</string>
|
||||||
<string name="summary_pref_socks_port">پورت پروکسی مهلی</string>
|
<string name="summary_pref_socks_port">پورت پروکسی مهلی</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
<string name="title_pref_dynamic_socks_port">ره وندن پورت پروکسی مهلی پۊیا</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
<string name="summary_pref_dynamic_socks_port">هر کرت ک و من ٱووڌنی وورکل ابۊ، ی پورت پروکسی مهلی تساڌۊفی وورکل کۊنین</string>
|
||||||
<string name="title_pref_socks_username">Local proxy username (optional)</string>
|
<string name="title_pref_socks_username">نوم منتوری پروکسی مهلی (اختیاری)</string>
|
||||||
<string name="summary_pref_socks_username">Username</string>
|
<string name="summary_pref_socks_username">نوم منتوری</string>
|
||||||
<string name="title_pref_socks_password">Local proxy password (optional)</string>
|
<string name="title_pref_socks_password">رزم پروکسی مهلی (اختیاری)</string>
|
||||||
<string name="summary_pref_socks_password">Password</string>
|
<string name="summary_pref_socks_password">رزم</string>
|
||||||
|
|
||||||
<string name="title_pref_local_dns_port">پورت DNS مهلی</string>
|
<string name="title_pref_local_dns_port">پورت DNS مهلی</string>
|
||||||
<string name="summary_pref_local_dns_port">پورت DNS مهلی</string>
|
<string name="summary_pref_local_dns_port">پورت DNS مهلی</string>
|
||||||
@@ -245,7 +250,7 @@
|
|||||||
<string name="summary_pref_double_column_display">نومگه نمایه یل من دو سۊتۊن نشووݩ داڌه ابۊن وو چینۉ ترین موئتوا بیشتری ن سیل کۊنین. سی ره وستن، وا برنومه ن ز نۊ ره ونین.</string>
|
<string name="summary_pref_double_column_display">نومگه نمایه یل من دو سۊتۊن نشووݩ داڌه ابۊن وو چینۉ ترین موئتوا بیشتری ن سیل کۊنین. سی ره وستن، وا برنومه ن ز نۊ ره ونین.</string>
|
||||||
|
|
||||||
<string name="title_pref_group_all_display">نشووݩ داڌن پوی بونکۊ یل ن فعال کۊنین</string>
|
<string name="title_pref_group_all_display">نشووݩ داڌن پوی بونکۊ یل ن فعال کۊنین</string>
|
||||||
<string name="summary_pref_group_all_display">ی بلگه «پوی بلگه یل» ازاف کۊنین</string>
|
<string name="summary_pref_group_all_display">ی بلگه «پوی بونکۊ یل کانفیگ» ازاف کۊنین</string>
|
||||||
<!-- AboutActivity -->
|
<!-- AboutActivity -->
|
||||||
<string name="title_pref_feedback">فشناڌن منشڌ</string>
|
<string name="title_pref_feedback">فشناڌن منشڌ</string>
|
||||||
<string name="summary_pref_feedback">فشناڌن منشڌ یا گوزارش موشکلا من Github</string>
|
<string name="summary_pref_feedback">فشناڌن منشڌ یا گوزارش موشکلا من Github</string>
|
||||||
@@ -295,6 +300,7 @@
|
|||||||
<string name="sub_setting_pre_profile">نوم موستعار پروکسی دیندایی</string>
|
<string name="sub_setting_pre_profile">نوم موستعار پروکسی دیندایی</string>
|
||||||
<string name="sub_setting_next_profile">نوم موستعار پروکسی نیایی</string>
|
<string name="sub_setting_next_profile">نوم موستعار پروکسی نیایی</string>
|
||||||
<string name="sub_setting_pre_profile_tip">موتمعن بۊ ک نوم موستعار هڌس وو جۊرس نی</string>
|
<string name="sub_setting_pre_profile_tip">موتمعن بۊ ک نوم موستعار هڌس وو جۊرس نی</string>
|
||||||
|
<string name="toast_invalid_update_interval">فاسله ورۊ کردن نا موئتبر هڌ. اقل مقدار 15 دؽقه هڌ.</string>
|
||||||
<string name="title_sub_update">ورۊ کردن اشتراک بونکۊ سکویی</string>
|
<string name="title_sub_update">ورۊ کردن اشتراک بونکۊ سکویی</string>
|
||||||
<string name="title_ping_all_server">Tcping کانفیگا بونکۊ سکویی</string>
|
<string name="title_ping_all_server">Tcping کانفیگا بونکۊ سکویی</string>
|
||||||
<string name="title_real_ping_all_server">تئخیر واقعی کانفیگا بونکۊ سکویی</string>
|
<string name="title_real_ping_all_server">تئخیر واقعی کانفیگا بونکۊ سکویی</string>
|
||||||
@@ -310,9 +316,9 @@
|
|||||||
<string name="title_update_config_count">ورۊ کردن %d کانفیگ</string>
|
<string name="title_update_config_count">ورۊ کردن %d کانفیگ</string>
|
||||||
<string name="title_update_subscription_result">%1$d کانفیگ ورۊ وابی (مووفق: %2$d، شکست خرده: %3$d، رڌ وابیڌه: %4$d)</string>
|
<string name="title_update_subscription_result">%1$d کانفیگ ورۊ وابی (مووفق: %2$d، شکست خرده: %3$d، رڌ وابیڌه: %4$d)</string>
|
||||||
<string name="title_update_subscription_no_subscription">بؽ اشتراک</string>
|
<string name="title_update_subscription_no_subscription">بؽ اشتراک</string>
|
||||||
<string name="toast_server_not_found_in_group">Selected server not found in current group</string>
|
<string name="toast_server_not_found_in_group">سرور پسند وابیڌه من بونکۊ سکویی نجۊرست</string>
|
||||||
<string name="toast_fragment_not_available">Unable to locate current view</string>
|
<string name="toast_fragment_not_available">نتره نما سکویی ن بجۊره</string>
|
||||||
<string name="title_locate_selected_config">Locate the selected config</string>
|
<string name="title_locate_selected_config">کانفیگ پسند وابیڌه ن بجۊرین</string>
|
||||||
|
|
||||||
<string name="tasker_start_service">ره وندن خدمات</string>
|
<string name="tasker_start_service">ره وندن خدمات</string>
|
||||||
<string name="tasker_setting_confirm">قوۊل</string>
|
<string name="tasker_setting_confirm">قوۊل</string>
|
||||||
@@ -320,7 +326,7 @@
|
|||||||
<!-- RoutingSettingActivity -->
|
<!-- RoutingSettingActivity -->
|
||||||
<string name="routing_settings_domain_strategy">نشقه دامنه</string>
|
<string name="routing_settings_domain_strategy">نشقه دامنه</string>
|
||||||
<string name="routing_settings_title">سامووا تور جوستن</string>
|
<string name="routing_settings_title">سامووا تور جوستن</string>
|
||||||
<string name="routing_settings_tips">وا کاما ز یک جوڌا ابۊن (،)؛ یکی را وارد کنید: domain، ip یا process</string>
|
<string name="routing_settings_tips">وا کاما ز یک جوڌا ابۊن (,)؛ یکی ن بزنین: domain، ip یا process</string>
|
||||||
<string name="routing_settings_save">زفت کردن</string>
|
<string name="routing_settings_save">زفت کردن</string>
|
||||||
<string name="routing_settings_delete">روفتن</string>
|
<string name="routing_settings_delete">روفتن</string>
|
||||||
<string name="routing_settings_rule_title">سامووا قانۉݩ تور جوستن</string>
|
<string name="routing_settings_rule_title">سامووا قانۉݩ تور جوستن</string>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved (اختیاری، جدا شده با کاما)</string>
|
<string name="server_lab_reserved">Reserved (اختیاری، جدا شده با کاما)</string>
|
||||||
<string name="server_lab_local_address">آدرس محلی (IPv4/IPv6 اختیاری، جدا شده با کاما)</string>
|
<string name="server_lab_local_address">آدرس محلی (IPv4/IPv6 اختیاری، جدا شده با کاما)</string>
|
||||||
<string name="server_lab_local_mtu">MTU (اختیاری، پیشفرض 1420)</string>
|
<string name="server_lab_local_mtu">MTU (اختیاری، پیشفرض 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (اختیاری، پیشفرض هسته 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (اختیاری، پیشفرض هسته 50)</string>
|
||||||
<string name="toast_success">با موفقیت انجام شد</string>
|
<string name="toast_success">با موفقیت انجام شد</string>
|
||||||
<string name="toast_failure">شکست</string>
|
<string name="toast_failure">شکست</string>
|
||||||
<string name="toast_none_data">هیچ داده ای وجود ندارد</string>
|
<string name="toast_none_data">هیچ داده ای وجود ندارد</string>
|
||||||
@@ -114,7 +116,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">خام JSON XHTTP Extra، قالب: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">خام JSON XHTTP Extra، قالب: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">لیست کانفیگ Ech</string>
|
<string name="server_lab_ech_config_list">لیست کانفیگ Ech</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -219,6 +220,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">هنگام استفاده از TLS، به طور پیش فرض مجوز ناامن فعال است.</string>
|
<string name="summary_pref_allow_insecure">هنگام استفاده از TLS، به طور پیش فرض مجوز ناامن فعال است.</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">پورت پروکسی محلی</string>
|
<string name="title_pref_socks_port">پورت پروکسی محلی</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">فعالسازی پروکسی محلی</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">احراز هویت socks5 هنگام استفاده از UDP کاملاً ایمن نیست</string>
|
||||||
<string name="summary_pref_socks_port">پورت پروکسی محلی</string>
|
<string name="summary_pref_socks_port">پورت پروکسی محلی</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
||||||
@@ -292,6 +297,7 @@
|
|||||||
<string name="sub_setting_pre_profile">نام مستعار پروکسی قبلی</string>
|
<string name="sub_setting_pre_profile">نام مستعار پروکسی قبلی</string>
|
||||||
<string name="sub_setting_next_profile">نام مستعار پروکسی بعدی</string>
|
<string name="sub_setting_next_profile">نام مستعار پروکسی بعدی</string>
|
||||||
<string name="sub_setting_pre_profile_tip">لطفاً مطمئن شوید که نام مستعار وجود دارد و منحصر به فرد است</string>
|
<string name="sub_setting_pre_profile_tip">لطفاً مطمئن شوید که نام مستعار وجود دارد و منحصر به فرد است</string>
|
||||||
|
<string name="toast_invalid_update_interval">بازه بروزرسانی نامعتبر است. حداقل مقدار 15 دقیقه است.</string>
|
||||||
<string name="title_sub_update">بهروزرسانی گروه فعلی اشتراک</string>
|
<string name="title_sub_update">بهروزرسانی گروه فعلی اشتراک</string>
|
||||||
<string name="title_ping_all_server">TCPING کانفیگ های گروه فعلی</string>
|
<string name="title_ping_all_server">TCPING کانفیگ های گروه فعلی</string>
|
||||||
<string name="title_real_ping_all_server">تاخیر واقعی کانفیگ های گروه فعلی</string>
|
<string name="title_real_ping_all_server">تاخیر واقعی کانفیگ های گروه فعلی</string>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_widget_name">v2rayNG</string>
|
<string name="app_widget_name">v2rayNG</string>
|
||||||
<string name="app_tile_name">v2rayNG</string>
|
<string name="app_tile_name">v2rayNG</string>
|
||||||
<string name="app_tile_first_use">Первое использование этой функции, пожалуйста, используйте приложение, чтобы добавить сервер</string>
|
<string name="app_tile_first_use">Первое использование этой функции, пожалуйста, используйте приложение, чтобы добавить профиль</string>
|
||||||
<string name="navigation_drawer_open">Открыть панель навигации</string>
|
<string name="navigation_drawer_open">Открыть панель навигации</string>
|
||||||
<string name="navigation_drawer_close">Закрыть панель навигации</string>
|
<string name="navigation_drawer_close">Закрыть панель навигации</string>
|
||||||
<string name="migration_success">Успешный перенос данных!</string>
|
<string name="migration_success">Успешный перенос данных!</string>
|
||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved (необязательно, через запятую)</string>
|
<string name="server_lab_reserved">Reserved (необязательно, через запятую)</string>
|
||||||
<string name="server_lab_local_address">Локальный адрес (необязательно, IPv4/IPv6 через запятую)</string>
|
<string name="server_lab_local_address">Локальный адрес (необязательно, IPv4/IPv6 через запятую)</string>
|
||||||
<string name="server_lab_local_mtu">MTU (необязательно, по умолчанию 1420)</string>
|
<string name="server_lab_local_mtu">MTU (необязательно, по умолчанию 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (необязательно, по умолчанию 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (необязательно, по умолчанию 50)</string>
|
||||||
<string name="toast_success">Успешно</string>
|
<string name="toast_success">Успешно</string>
|
||||||
<string name="toast_failure">Ошибка</string>
|
<string name="toast_failure">Ошибка</string>
|
||||||
<string name="toast_none_data">Ничего нет</string>
|
<string name="toast_none_data">Ничего нет</string>
|
||||||
@@ -114,7 +116,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">Необработанный JSON XHTTP Extra, формат: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">Необработанный JSON XHTTP Extra, формат: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">Необработанный JSON FinalMask, формат: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">Необработанный JSON FinalMask, формат: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Отпечаток сертификата (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Отпечаток сертификата (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -143,6 +144,7 @@
|
|||||||
<string name="menu_item_import_proxy_app">Импорт из буфера обмена</string>
|
<string name="menu_item_import_proxy_app">Импорт из буфера обмена</string>
|
||||||
<string name="per_app_proxy_settings">Выбор приложений</string>
|
<string name="per_app_proxy_settings">Выбор приложений</string>
|
||||||
<string name="per_app_proxy_settings_enable">Использовать выбор приложений</string>
|
<string name="per_app_proxy_settings_enable">Использовать выбор приложений</string>
|
||||||
|
<string name="app_picker_unknown_app">Неизвестное приложение (неопознанный UID)</string>
|
||||||
|
|
||||||
<!-- Preferences -->
|
<!-- Preferences -->
|
||||||
<string name="title_settings">Настройки</string>
|
<string name="title_settings">Настройки</string>
|
||||||
@@ -222,6 +224,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">Для TLS по умолчанию разрешены небезопасные соединения</string>
|
<string name="summary_pref_allow_insecure">Для TLS по умолчанию разрешены небезопасные соединения</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">Порт локального прокси</string>
|
<string name="title_pref_socks_port">Порт локального прокси</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">Использовать локальный прокси</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">Если отключено, SOCKS-прокси недоступен, поэтому обновления подписки и подобные действия не смогут использовать прокси</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">Аутентификация SOCKS5 не полностью безопасна при использовании UDP</string>
|
||||||
<string name="summary_pref_socks_port">Порт локального прокси</string>
|
<string name="summary_pref_socks_port">Порт локального прокси</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Динамически менять порт локального прокси</string>
|
<string name="title_pref_dynamic_socks_port">Динамически менять порт локального прокси</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Использовать случайный порт локального прокси при каждом создании соединения</string>
|
<string name="summary_pref_dynamic_socks_port">Использовать случайный порт локального прокси при каждом создании соединения</string>
|
||||||
@@ -297,6 +303,7 @@
|
|||||||
<string name="sub_setting_pre_profile">Предыдущий профиль прокси</string>
|
<string name="sub_setting_pre_profile">Предыдущий профиль прокси</string>
|
||||||
<string name="sub_setting_next_profile">Следующий профиль прокси</string>
|
<string name="sub_setting_next_profile">Следующий профиль прокси</string>
|
||||||
<string name="sub_setting_pre_profile_tip">Профиль должен быть уникальным</string>
|
<string name="sub_setting_pre_profile_tip">Профиль должен быть уникальным</string>
|
||||||
|
<string name="toast_invalid_update_interval">Неверный интервал обновления. Минимум 15 минут.</string>
|
||||||
<string name="title_sub_update">Обновить подписку</string>
|
<string name="title_sub_update">Обновить подписку</string>
|
||||||
<string name="title_ping_all_server">Проверить профили</string>
|
<string name="title_ping_all_server">Проверить профили</string>
|
||||||
<string name="title_real_ping_all_server">Проверить задержку профилей</string>
|
<string name="title_real_ping_all_server">Проверить задержку профилей</string>
|
||||||
@@ -321,7 +328,7 @@
|
|||||||
<!-- RoutingSettingActivity -->
|
<!-- RoutingSettingActivity -->
|
||||||
<string name="routing_settings_domain_strategy">Доменная стратегия</string>
|
<string name="routing_settings_domain_strategy">Доменная стратегия</string>
|
||||||
<string name="routing_settings_title">Маршрутизация</string>
|
<string name="routing_settings_title">Маршрутизация</string>
|
||||||
<string name="routing_settings_tips">Через запятую (,)\nТолько что-то одно: домен, IP или процесс</string>
|
<string name="routing_settings_tips">Через запятую (,)\nЧто-то одно: домен, IP или процесс</string>
|
||||||
<string name="routing_settings_save">Сохранить</string>
|
<string name="routing_settings_save">Сохранить</string>
|
||||||
<string name="routing_settings_delete">Очистить</string>
|
<string name="routing_settings_delete">Очистить</string>
|
||||||
<string name="routing_settings_rule_title">Настройка правил маршрутизации</string>
|
<string name="routing_settings_rule_title">Настройка правил маршрутизации</string>
|
||||||
@@ -334,7 +341,7 @@
|
|||||||
<string name="routing_settings_locked">Постоянное (сохранится при импорте правил)</string>
|
<string name="routing_settings_locked">Постоянное (сохранится при импорте правил)</string>
|
||||||
<string name="routing_settings_domain">Домен</string>
|
<string name="routing_settings_domain">Домен</string>
|
||||||
<string name="routing_settings_ip">IP</string>
|
<string name="routing_settings_ip">IP</string>
|
||||||
<string name="routing_settings_process">Процесс (название пакета — поддерживается только при использовании Xray TUN, включённой функции routeOnly и ОС Android 10+)</string>
|
<string name="routing_settings_process">Процесс (название пакета; поддерживается только при использовании Xray TUN, включённой функции routeOnly и ОС Android 10+)</string>
|
||||||
<string name="routing_settings_port">Порт</string>
|
<string name="routing_settings_port">Порт</string>
|
||||||
<string name="routing_settings_protocol">Протокол</string>
|
<string name="routing_settings_protocol">Протокол</string>
|
||||||
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
|
<string name="routing_settings_protocol_tip">[http,tls,bittorrent]</string>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved (Không bắt buộc)</string>
|
<string name="server_lab_reserved">Reserved (Không bắt buộc)</string>
|
||||||
<string name="server_lab_local_address">Địa chỉ cục bộ (IPv4 / IPv6, phân cách bằng dấu phẩy)</string>
|
<string name="server_lab_local_address">Địa chỉ cục bộ (IPv4 / IPv6, phân cách bằng dấu phẩy)</string>
|
||||||
<string name="server_lab_local_mtu">MTU (Không bắt buộc, mặc định là 1420)</string>
|
<string name="server_lab_local_mtu">MTU (Không bắt buộc, mặc định là 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (Không bắt buộc, mặc định core là 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (Không bắt buộc, mặc định core là 50)</string>
|
||||||
<string name="toast_success">Thành công!</string>
|
<string name="toast_success">Thành công!</string>
|
||||||
<string name="toast_failure">Đã xảy ra lỗi, vui lòng thử lại!</string>
|
<string name="toast_failure">Đã xảy ra lỗi, vui lòng thử lại!</string>
|
||||||
<string name="toast_none_data">Không có gì ở đây!</string>
|
<string name="toast_none_data">Không có gì ở đây!</string>
|
||||||
@@ -114,7 +116,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -221,6 +222,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">Khi nhập những cấu hình có bảo mật TLS, mặc định sẽ không xác minh chứng chỉ.</string>
|
<string name="summary_pref_allow_insecure">Khi nhập những cấu hình có bảo mật TLS, mặc định sẽ không xác minh chứng chỉ.</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">Cổng Proxy Local</string>
|
<string name="title_pref_socks_port">Cổng Proxy Local</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">Bật proxy cục bộ</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">Xác thực socks5 không hoàn toàn an toàn khi sử dụng UDP</string>
|
||||||
<string name="summary_pref_socks_port">Cổng Proxy Local</string>
|
<string name="summary_pref_socks_port">Cổng Proxy Local</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
||||||
@@ -295,6 +300,7 @@
|
|||||||
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
|
<string name="sub_setting_pre_profile">Previous proxy configuration remarks</string>
|
||||||
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
|
<string name="sub_setting_next_profile">Next proxy configuration remarks</string>
|
||||||
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
|
<string name="sub_setting_pre_profile_tip">The configuration remarks exists and is unique</string>
|
||||||
|
<string name="toast_invalid_update_interval">Khoảng thời gian cập nhật không hợp lệ. Giá trị tối thiểu là 15 phút.</string>
|
||||||
<string name="title_sub_update">Cập nhật các gói đăng ký</string>
|
<string name="title_sub_update">Cập nhật các gói đăng ký</string>
|
||||||
<string name="title_ping_all_server">Ping tất cả máy chủ</string>
|
<string name="title_ping_all_server">Ping tất cả máy chủ</string>
|
||||||
<string name="title_real_ping_all_server">Kiểm tra HTTP tất cả máy chủ</string>
|
<string name="title_real_ping_all_server">Kiểm tra HTTP tất cả máy chủ</string>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved (可选,逗号隔开)</string>
|
<string name="server_lab_reserved">Reserved (可选,逗号隔开)</string>
|
||||||
<string name="server_lab_local_address">本地地址 (可选 IPv4/IPv6,逗号隔开)</string>
|
<string name="server_lab_local_address">本地地址 (可选 IPv4/IPv6,逗号隔开)</string>
|
||||||
<string name="server_lab_local_mtu">Mtu (可选, 默认 1420)</string>
|
<string name="server_lab_local_mtu">Mtu (可选, 默认 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (可选, 默认 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (可选, 默认 50)</string>
|
||||||
<string name="toast_success">成功</string>
|
<string name="toast_success">成功</string>
|
||||||
<string name="toast_failure">失败</string>
|
<string name="toast_failure">失败</string>
|
||||||
<string name="toast_none_data">没有数据</string>
|
<string name="toast_none_data">没有数据</string>
|
||||||
@@ -114,7 +116,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">XHTTP Extra 原始 JSON,格式: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra 原始 JSON,格式: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">FinalMask 原始 JSON 格式: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">FinalMask 原始 JSON 格式: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">证书指纹 (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">证书指纹 (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -218,6 +219,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">传输层安全选 tls 时,默认跳过证书验证 (allowInsecure)</string>
|
<string name="summary_pref_allow_insecure">传输层安全选 tls 时,默认跳过证书验证 (allowInsecure)</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">本地代理端口</string>
|
<string name="title_pref_socks_port">本地代理端口</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">启用本地代理</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">不开启时没有 socks 代理,无法通过代理更新订阅等</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">使用 UDP 时,socks5 认证并不完全安全</string>
|
||||||
<string name="summary_pref_socks_port">本地代理端口</string>
|
<string name="summary_pref_socks_port">本地代理端口</string>
|
||||||
<string name="title_pref_dynamic_socks_port">启用动态本地代理端口</string>
|
<string name="title_pref_dynamic_socks_port">启用动态本地代理端口</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">每次生成 inbound 时随机生成一个本地代理端口</string>
|
<string name="summary_pref_dynamic_socks_port">每次生成 inbound 时随机生成一个本地代理端口</string>
|
||||||
@@ -293,6 +298,7 @@
|
|||||||
<string name="sub_setting_pre_profile">前置代理配置别名</string>
|
<string name="sub_setting_pre_profile">前置代理配置别名</string>
|
||||||
<string name="sub_setting_next_profile">落地代理配置別名</string>
|
<string name="sub_setting_next_profile">落地代理配置別名</string>
|
||||||
<string name="sub_setting_pre_profile_tip">请确保配置别名存在并唯一</string>
|
<string name="sub_setting_pre_profile_tip">请确保配置别名存在并唯一</string>
|
||||||
|
<string name="toast_invalid_update_interval">更新间隔无效,最小值为 15 分钟。</string>
|
||||||
<string name="title_sub_update">更新订阅</string>
|
<string name="title_sub_update">更新订阅</string>
|
||||||
<string name="title_ping_all_server">测试配置 Tcping</string>
|
<string name="title_ping_all_server">测试配置 Tcping</string>
|
||||||
<string name="title_real_ping_all_server">测试配置真连接</string>
|
<string name="title_real_ping_all_server">测试配置真连接</string>
|
||||||
|
|||||||
@@ -88,6 +88,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved (可選,逗號隔開)</string>
|
<string name="server_lab_reserved">Reserved (可選,逗號隔開)</string>
|
||||||
<string name="server_lab_local_address">本機位址 (可選 IPv4/IPv6,逗號隔開)</string>
|
<string name="server_lab_local_address">本機位址 (可選 IPv4/IPv6,逗號隔開)</string>
|
||||||
<string name="server_lab_local_mtu">MTU (可選, 預設 1420)</string>
|
<string name="server_lab_local_mtu">MTU (可選, 預設 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (可選, 預設 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (可選, 預設 50)</string>
|
||||||
<string name="toast_success">成功</string>
|
<string name="toast_success">成功</string>
|
||||||
<string name="toast_failure">失敗</string>
|
<string name="toast_failure">失敗</string>
|
||||||
<string name="toast_none_data">無資料</string>
|
<string name="toast_none_data">無資料</string>
|
||||||
@@ -114,7 +116,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">XHTTP Extra 原始 JSON,格式: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra 原始 JSON,格式: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">FinalMask 原始 JSON 格式: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">FinalMask 原始 JSON 格式: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">證書指紋 (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">證書指紋 (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -219,6 +220,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">傳輸層安全選 tls 時,預設跳過憑證驗證 (allowInsecure)</string>
|
<string name="summary_pref_allow_insecure">傳輸層安全選 tls 時,預設跳過憑證驗證 (allowInsecure)</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">本地代理埠</string>
|
<string name="title_pref_socks_port">本地代理埠</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">啟用本地代理</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">未開啟時沒有 socks 代理,無法透過代理更新訂閱等</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">使用 UDP 時,socks5 認證並不完全安全</string>
|
||||||
<string name="summary_pref_socks_port">本地代理埠</string>
|
<string name="summary_pref_socks_port">本地代理埠</string>
|
||||||
<string name="title_pref_dynamic_socks_port">啟用動態本地代理埠</string>
|
<string name="title_pref_dynamic_socks_port">啟用動態本地代理埠</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">每次產生 inbound 時隨機產生一個本地代理埠</string>
|
<string name="summary_pref_dynamic_socks_port">每次產生 inbound 時隨機產生一個本地代理埠</string>
|
||||||
@@ -294,6 +299,7 @@
|
|||||||
<string name="sub_setting_pre_profile">前置代理設定檔别名</string>
|
<string name="sub_setting_pre_profile">前置代理設定檔别名</string>
|
||||||
<string name="sub_setting_next_profile">落地代理設定檔別名</string>
|
<string name="sub_setting_next_profile">落地代理設定檔別名</string>
|
||||||
<string name="sub_setting_pre_profile_tip">请确保設定檔别名存在并唯一</string>
|
<string name="sub_setting_pre_profile_tip">请确保設定檔别名存在并唯一</string>
|
||||||
|
<string name="toast_invalid_update_interval">更新間隔無效,最小值為 15 分鐘。</string>
|
||||||
<string name="title_sub_update">更新訂閱</string>
|
<string name="title_sub_update">更新訂閱</string>
|
||||||
<string name="title_ping_all_server">偵測設定 Tcping</string>
|
<string name="title_ping_all_server">偵測設定 Tcping</string>
|
||||||
<string name="title_real_ping_all_server">偵測設定真延遲</string>
|
<string name="title_real_ping_all_server">偵測設定真延遲</string>
|
||||||
|
|||||||
@@ -215,11 +215,5 @@
|
|||||||
<item>2</item>
|
<item>2</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="ech_force_query_value" translatable="false">
|
|
||||||
<item />
|
|
||||||
<item>none</item>
|
|
||||||
<item>half</item>
|
|
||||||
<item>full</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -89,6 +89,8 @@
|
|||||||
<string name="server_lab_reserved">Reserved(Optional, separated by commas)</string>
|
<string name="server_lab_reserved">Reserved(Optional, separated by commas)</string>
|
||||||
<string name="server_lab_local_address">Local address (optional IPv4/IPv6, separated by commas)</string>
|
<string name="server_lab_local_address">Local address (optional IPv4/IPv6, separated by commas)</string>
|
||||||
<string name="server_lab_local_mtu">Mtu(optional, default 1420)</string>
|
<string name="server_lab_local_mtu">Mtu(optional, default 1420)</string>
|
||||||
|
<string name="server_lab_kcp_mtu">mKCP MTU (Optional, core default 1350)</string>
|
||||||
|
<string name="server_lab_kcp_tti">mKCP TTI (Optional, core default 50)</string>
|
||||||
<string name="toast_success">Success</string>
|
<string name="toast_success">Success</string>
|
||||||
<string name="toast_failure">Failure</string>
|
<string name="toast_failure">Failure</string>
|
||||||
<string name="toast_none_data">There is nothing</string>
|
<string name="toast_none_data">There is nothing</string>
|
||||||
@@ -115,7 +117,6 @@
|
|||||||
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
<string name="server_lab_xhttp_extra">XHTTP Extra raw JSON, format: { XHTTPObject }</string>
|
||||||
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
<string name="server_lab_final_mask">finalMask raw JSON, format: { FinalMaskObject }</string>
|
||||||
<string name="server_lab_ech_config_list">EchConfigList</string>
|
<string name="server_lab_ech_config_list">EchConfigList</string>
|
||||||
<string name="server_lab_ech_force_query">EchForceQuery</string>
|
|
||||||
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
<string name="server_lab_pinned_ca256">Certificate fingerprint (SHA-256)</string>
|
||||||
|
|
||||||
<!-- UserAssetActivity -->
|
<!-- UserAssetActivity -->
|
||||||
@@ -225,6 +226,10 @@
|
|||||||
<string name="summary_pref_allow_insecure">When TLS is selected, allow insecure connections by default</string>
|
<string name="summary_pref_allow_insecure">When TLS is selected, allow insecure connections by default</string>
|
||||||
|
|
||||||
<string name="title_pref_socks_port">Local proxy port</string>
|
<string name="title_pref_socks_port">Local proxy port</string>
|
||||||
|
<string name="title_pref_enable_local_proxy">Enable local proxy</string>
|
||||||
|
<string name="summary_pref_enable_local_proxy">When disabled, no SOCKS proxy is available, so subscription updates and similar actions cannot use the proxy</string>
|
||||||
|
<string name="title_pref_socks_enable_udp">SOCKS5 UDP</string>
|
||||||
|
<string name="summary_pref_socks_enable_udp">SOCKS5 authentication is not fully secure when using UDP.</string>
|
||||||
<string name="summary_pref_socks_port">Local proxy port</string>
|
<string name="summary_pref_socks_port">Local proxy port</string>
|
||||||
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
<string name="title_pref_dynamic_socks_port">Enable dynamic local proxy port</string>
|
||||||
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
<string name="summary_pref_dynamic_socks_port">Generate a random local proxy port each time the inbound is created</string>
|
||||||
@@ -300,6 +305,7 @@
|
|||||||
<string name="sub_setting_pre_profile">Previous proxy config remarks</string>
|
<string name="sub_setting_pre_profile">Previous proxy config remarks</string>
|
||||||
<string name="sub_setting_next_profile">Next proxy config remarks</string>
|
<string name="sub_setting_next_profile">Next proxy config remarks</string>
|
||||||
<string name="sub_setting_pre_profile_tip">The config remarks exist and are unique</string>
|
<string name="sub_setting_pre_profile_tip">The config remarks exist and are unique</string>
|
||||||
|
<string name="toast_invalid_update_interval">Invalid update interval. Minimum is 15 minutes.</string>
|
||||||
<string name="title_sub_update">Update subscription</string>
|
<string name="title_sub_update">Update subscription</string>
|
||||||
<string name="title_ping_all_server">Tcping config</string>
|
<string name="title_ping_all_server">Tcping config</string>
|
||||||
<string name="title_real_ping_all_server">Real delay config</string>
|
<string name="title_real_ping_all_server">Real delay config</string>
|
||||||
|
|||||||
@@ -146,15 +146,20 @@
|
|||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="pref_proxy_sharing_enabled"
|
android:key="pref_allow_insecure"
|
||||||
android:summary="@string/summary_pref_proxy_sharing_enabled"
|
android:title="@string/title_pref_allow_insecure" />
|
||||||
android:title="@string/title_pref_proxy_sharing_enabled" />
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="pref_enable_local_proxy"
|
||||||
|
android:summary="@string/summary_pref_enable_local_proxy"
|
||||||
|
android:title="@string/title_pref_enable_local_proxy" />
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="pref_allow_insecure"
|
android:key="pref_proxy_sharing_enabled"
|
||||||
android:summary="@string/summary_pref_allow_insecure"
|
android:summary="@string/summary_pref_proxy_sharing_enabled"
|
||||||
android:title="@string/title_pref_allow_insecure" />
|
android:title="@string/title_pref_proxy_sharing_enabled" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
@@ -179,6 +184,12 @@
|
|||||||
android:summary="@string/summary_pref_socks_password"
|
android:summary="@string/summary_pref_socks_password"
|
||||||
android:title="@string/title_pref_socks_password" />
|
android:title="@string/title_pref_socks_password" />
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="pref_socks_enable_udp"
|
||||||
|
android:summary="@string/summary_pref_socks_enable_udp"
|
||||||
|
android:title="@string/title_pref_socks_enable_udp" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="pref_remote_dns"
|
android:key="pref_remote_dns"
|
||||||
android:summary="@string/summary_pref_remote_dns"
|
android:summary="@string/summary_pref_remote_dns"
|
||||||
@@ -267,19 +278,6 @@
|
|||||||
android:title="@string/title_pref_fragment_packets" />
|
android:title="@string/title_pref_fragment_packets" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
|
||||||
android:title="@string/title_sub_setting"
|
|
||||||
app:initialExpandedChildrenCount="0">
|
|
||||||
<CheckBoxPreference
|
|
||||||
android:key="pref_auto_update_subscription"
|
|
||||||
android:summary="@string/summary_pref_auto_update_subscription"
|
|
||||||
android:title="@string/title_pref_auto_update_subscription" />
|
|
||||||
<EditTextPreference
|
|
||||||
android:inputType="number"
|
|
||||||
android:key="pref_auto_update_interval"
|
|
||||||
android:summary="1440"
|
|
||||||
android:title="@string/title_pref_auto_update_interval" />
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/title_advanced">
|
<PreferenceCategory android:title="@string/title_advanced">
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "9.1.1"
|
agp = "9.2.0"
|
||||||
desugarJdkLibs = "2.1.5"
|
desugarJdkLibs = "2.1.5"
|
||||||
gradleLicensePlugin = "0.9.8"
|
gradleLicensePlugin = "0.9.8"
|
||||||
kotlin = "2.3.10"
|
kotlin = "2.3.10"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
#Thu Nov 14 12:42:51 BDT 2024
|
#Thu Nov 14 12:42:51 BDT 2024
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Reference in New Issue
Block a user