mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-19 06:30:05 +08:00
fix
This commit is contained in:
parent
48a2776f9c
commit
fafe14b7c6
@ -33,7 +33,7 @@ object Key {
|
||||
const val RESOLVE_DESTINATION = "resolveDestination"
|
||||
|
||||
const val BYPASS_LAN = "bypassLan"
|
||||
const val BYPASS_LAN_IN_CORE_ONLY = "bypassLanInCoreOnly"
|
||||
const val BYPASS_LAN_IN_CORE = "bypassLanInCore"
|
||||
|
||||
const val MIXED_PORT = "mixedPort"
|
||||
const val ALLOW_ACCESS = "allowAccess"
|
||||
|
||||
@ -42,13 +42,11 @@ class ServiceNotification(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
|
||||
}
|
||||
|
||||
val trafficStatistics = DataStore.profileTrafficStatistics
|
||||
val showDirectSpeed = DataStore.showDirectSpeed
|
||||
|
||||
private val callback: ISagerNetServiceCallback by lazy {
|
||||
object : ISagerNetServiceCallback.Stub() {
|
||||
override fun cbSpeedUpdate(stats: SpeedDisplayData) {
|
||||
if (!trafficStatistics) return
|
||||
builder.apply {
|
||||
if (showDirectSpeed) {
|
||||
val speedDetail = (service as Context).getString(
|
||||
@ -180,7 +178,7 @@ class ServiceNotification(
|
||||
}
|
||||
|
||||
private fun updateCallback(screenOn: Boolean) {
|
||||
if (!trafficStatistics) return
|
||||
if (DataStore.speedInterval == 0) return
|
||||
if (screenOn) {
|
||||
service.data.binder.registerCallback(callback)
|
||||
callbackRegistered = true
|
||||
|
||||
@ -109,7 +109,7 @@ class VpnService : BaseVpnService(),
|
||||
builder.addDnsServer(PRIVATE_VLAN4_ROUTER)
|
||||
|
||||
// route
|
||||
if (DataStore.bypassLan && !DataStore.bypassLanInCoreOnly) {
|
||||
if (DataStore.bypassLan) {
|
||||
resources.getStringArray(R.array.bypass_private_route).forEach {
|
||||
val subnet = Subnet.fromString(it)!!
|
||||
builder.addRoute(subnet.address.hostAddress!!, subnet.prefixSize)
|
||||
@ -142,7 +142,7 @@ class VpnService : BaseVpnService(),
|
||||
var bypass = DataStore.bypass
|
||||
var workaroundSYSTEM = false /* DataStore.tunImplementation == TunImplementation.SYSTEM */
|
||||
var needBypassRootUid = workaroundSYSTEM || data.proxy!!.config.trafficMap.values.any {
|
||||
it.nekoBean?.needBypassRootUid() == true || it.hysteriaBean?.protocol == HysteriaBean.PROTOCOL_FAKETCP
|
||||
it[0].nekoBean?.needBypassRootUid() == true || it[0].hysteriaBean?.protocol == HysteriaBean.PROTOCOL_FAKETCP
|
||||
}
|
||||
|
||||
if (proxyApps || needBypassRootUid) {
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
package io.nekohasekai.sagernet.bg.proto
|
||||
|
||||
import io.nekohasekai.sagernet.BuildConfig
|
||||
import io.nekohasekai.sagernet.bg.BaseService
|
||||
import io.nekohasekai.sagernet.database.ProxyEntity
|
||||
import io.nekohasekai.sagernet.ktx.Logs
|
||||
import io.nekohasekai.sagernet.ktx.runOnIoDispatcher
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import moe.matsuri.nb4a.utils.JavaUtil
|
||||
|
||||
class ProxyInstance(profile: ProxyEntity, val service: BaseService.Interface) :
|
||||
BoxInstance(profile) {
|
||||
@ -15,6 +17,7 @@ class ProxyInstance(profile: ProxyEntity, val service: BaseService.Interface) :
|
||||
override fun buildConfig() {
|
||||
super.buildConfig()
|
||||
Logs.d(config.config)
|
||||
if (BuildConfig.DEBUG) Logs.d(JavaUtil.gson.toJson(config.trafficMap))
|
||||
}
|
||||
|
||||
override suspend fun init() {
|
||||
|
||||
@ -16,22 +16,25 @@ class TrafficLooper
|
||||
) {
|
||||
|
||||
private var job: Job? = null
|
||||
private val items = mutableMapOf<String, TrafficUpdater.TrafficLooperData>()
|
||||
private val items = mutableMapOf<Long, TrafficUpdater.TrafficLooperData>()
|
||||
|
||||
suspend fun stop() {
|
||||
job?.cancel()
|
||||
// finally
|
||||
// finally traffic post
|
||||
if (!DataStore.profileTrafficStatistics) return
|
||||
val traffic = mutableMapOf<Long, TrafficData>()
|
||||
data.proxy?.config?.trafficMap?.forEach { (tag, ent) ->
|
||||
val item = items[tag] ?: return@forEach
|
||||
ent.rx = item.rx
|
||||
ent.tx = item.tx
|
||||
ProfileManager.updateProfile(ent) // update DB
|
||||
traffic[ent.id] = TrafficData(
|
||||
id = ent.id,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
)
|
||||
data.proxy?.config?.trafficMap?.forEach { (_, ents) ->
|
||||
for (ent in ents) {
|
||||
val item = items[ent.id] ?: return@forEach
|
||||
ent.rx = item.rx
|
||||
ent.tx = item.tx
|
||||
ProfileManager.updateProfile(ent) // update DB
|
||||
traffic[ent.id] = TrafficData(
|
||||
id = ent.id,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
)
|
||||
}
|
||||
}
|
||||
data.binder.broadcast { b ->
|
||||
for (t in traffic) {
|
||||
@ -64,31 +67,35 @@ class TrafficLooper
|
||||
if (!proxy.isInitialized()) continue
|
||||
items.clear()
|
||||
itemBypass = TrafficUpdater.TrafficLooperData(tag = "bypass")
|
||||
items["bypass"] = itemBypass
|
||||
// proxy.config.trafficMap.forEach { (tag, ent) ->
|
||||
proxy.config.outboundTags.forEach { tag ->
|
||||
// TODO g-xx query traffic return 0?
|
||||
val ent = proxy.config.trafficMap[tag] ?: return@forEach
|
||||
val item = TrafficUpdater.TrafficLooperData(
|
||||
tag = tag,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
)
|
||||
if (tag == proxy.config.outboundTagMain) {
|
||||
itemMain = item
|
||||
itemMainBase = TrafficUpdater.TrafficLooperData(
|
||||
items[-1] = itemBypass
|
||||
//
|
||||
val tags = hashSetOf("bypass")
|
||||
proxy.config.trafficMap.forEach { (tag, ents) ->
|
||||
for (ent in ents) {
|
||||
val item = TrafficUpdater.TrafficLooperData(
|
||||
tag = tag,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
)
|
||||
if (ent.id == proxy.config.mainEntId) {
|
||||
itemMain = item
|
||||
itemMainBase = TrafficUpdater.TrafficLooperData(
|
||||
tag = tag,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
)
|
||||
Logs.d("traffic count $tag to main")
|
||||
}
|
||||
items[ent.id] = item
|
||||
tags.add(tag)
|
||||
Logs.d("traffic count $tag to ${ent.id}")
|
||||
}
|
||||
items[tag] = item
|
||||
Logs.d("traffic count $tag to ${ent.id}")
|
||||
}
|
||||
//
|
||||
trafficUpdater = TrafficUpdater(
|
||||
box = proxy.box, items = items
|
||||
box = proxy.box, items = items.values.toList()
|
||||
)
|
||||
proxy.box.setV2rayStats(items.keys.joinToString("\n"))
|
||||
proxy.box.setV2rayStats(tags.joinToString("\n"))
|
||||
}
|
||||
|
||||
trafficUpdater.updateAll()
|
||||
@ -106,16 +113,20 @@ class TrafficLooper
|
||||
|
||||
// traffic
|
||||
val traffic = mutableMapOf<Long, TrafficData>()
|
||||
proxy.config.trafficMap.forEach { (tag, ent) ->
|
||||
val item = items[tag] ?: return@forEach
|
||||
ent.rx = item.rx
|
||||
ent.tx = item.tx
|
||||
if (DataStore.profileTrafficStatistics) {
|
||||
proxy.config.trafficMap.forEach { (tag, ents) ->
|
||||
for (ent in ents) {
|
||||
val item = items[ent.id] ?: return@forEach
|
||||
ent.rx = item.rx
|
||||
ent.tx = item.tx
|
||||
// ProfileManager.updateProfile(ent) // update DB
|
||||
traffic[ent.id] = TrafficData(
|
||||
id = ent.id,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
) // display
|
||||
traffic[ent.id] = TrafficData(
|
||||
id = ent.id,
|
||||
rx = ent.rx,
|
||||
tx = ent.tx,
|
||||
) // display
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast
|
||||
|
||||
@ -4,10 +4,11 @@ import io.nekohasekai.sagernet.ktx.onIoDispatcher
|
||||
|
||||
class TrafficUpdater(
|
||||
private val box: libcore.BoxInstance,
|
||||
val items: Map<String, TrafficLooperData>, // contain "bypass"
|
||||
val items: List<TrafficLooperData>, // contain "bypass"
|
||||
) {
|
||||
|
||||
class TrafficLooperData(
|
||||
// Don't associate proxyEntity
|
||||
var tag: String,
|
||||
var tx: Long = 0,
|
||||
var rx: Long = 0,
|
||||
@ -52,12 +53,12 @@ class TrafficUpdater(
|
||||
|
||||
suspend fun updateAll() {
|
||||
val updated = mutableMapOf<String, TrafficLooperData>() // diffs
|
||||
items.forEach { (tag, item) ->
|
||||
var diff = updated[tag]
|
||||
items.forEach { item ->
|
||||
var diff = updated[item.tag]
|
||||
// query a tag only once
|
||||
if (diff == null) {
|
||||
diff = updateOne(item)
|
||||
updated[tag] = diff
|
||||
updated[item.tag] = diff
|
||||
} else {
|
||||
item.rx += diff.rx
|
||||
item.tx += diff.tx
|
||||
|
||||
@ -93,7 +93,7 @@ object DataStore : OnPreferenceDataStoreChangeListener {
|
||||
var mtu by configurationStore.stringToInt(Key.MTU) { 9000 }
|
||||
|
||||
var bypassLan by configurationStore.boolean(Key.BYPASS_LAN)
|
||||
var bypassLanInCoreOnly by configurationStore.boolean(Key.BYPASS_LAN_IN_CORE_ONLY)
|
||||
var bypassLanInCore by configurationStore.boolean(Key.BYPASS_LAN_IN_CORE)
|
||||
|
||||
var allowAccess by configurationStore.boolean(Key.ALLOW_ACCESS)
|
||||
var speedInterval by configurationStore.stringToInt(Key.SPEED_INTERVAL)
|
||||
|
||||
@ -51,16 +51,15 @@ const val LOCAL_DNS_SERVER = "underlying://0.0.0.0"
|
||||
class ConfigBuildResult(
|
||||
var config: String,
|
||||
var externalIndex: List<IndexEntity>,
|
||||
var outboundTags: List<String>,
|
||||
var outboundTagMain: String,
|
||||
var trafficMap: Map<String, ProxyEntity>,
|
||||
var mainEntId: Long,
|
||||
var trafficMap: Map<String, List<ProxyEntity>>,
|
||||
val alerts: List<Pair<Int, String>>,
|
||||
) {
|
||||
data class IndexEntity(var chain: LinkedHashMap<Int, ProxyEntity>)
|
||||
}
|
||||
|
||||
fun mergeJSON(j: String, to: MutableMap<String, Any>) {
|
||||
if (j.isNullOrBlank()) return
|
||||
if (j.isBlank()) return
|
||||
val m = gson.fromJson(j, to.javaClass)
|
||||
m.forEach { (k, v) ->
|
||||
if (v is Map<*, *> && to[k] is Map<*, *>) {
|
||||
@ -83,19 +82,14 @@ fun buildConfig(
|
||||
return ConfigBuildResult(
|
||||
bean.config,
|
||||
listOf(),
|
||||
listOf(TAG_PROXY), //
|
||||
TAG_PROXY, //
|
||||
mapOf(
|
||||
TAG_PROXY to proxy
|
||||
),
|
||||
proxy.id, //
|
||||
mapOf(TAG_PROXY to listOf(proxy)), //
|
||||
listOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val outboundTags = ArrayList<String>()
|
||||
var outboundTagMain = TAG_BYPASS
|
||||
val trafficMap = HashMap<String, ProxyEntity>()
|
||||
val trafficMap = HashMap<String, MutableList<ProxyEntity>>()
|
||||
val globalOutbounds = ArrayList<Long>()
|
||||
|
||||
fun ProxyEntity.resolveChain(): MutableList<ProxyEntity> {
|
||||
@ -141,7 +135,7 @@ fun buildConfig(
|
||||
val resolveDestination = DataStore.resolveDestination
|
||||
val alerts = mutableListOf<Pair<Int, String>>()
|
||||
|
||||
var optionsToMerge: String = ""
|
||||
var optionsToMerge = ""
|
||||
|
||||
return MyOptions().apply {
|
||||
if (!forTest && DataStore.enableClashAPI) experimental = ExperimentalOptions().apply {
|
||||
@ -254,7 +248,7 @@ fun buildConfig(
|
||||
|
||||
// chainTagOut: v2ray outbound tag for this chain
|
||||
var chainTagOut = ""
|
||||
var chainTag = "c-$chainId"
|
||||
val chainTag = "c-$chainId"
|
||||
var muxApplied = false
|
||||
|
||||
fun genDomainStrategy(noAsIs: Boolean): String {
|
||||
@ -307,8 +301,6 @@ fun buildConfig(
|
||||
} else {
|
||||
// index == 0 means last profile in chain / not chain
|
||||
chainTagOut = tagOut
|
||||
outboundTags.add(tagOut)
|
||||
if (chainId == 0L) outboundTagMain = tagOut
|
||||
}
|
||||
|
||||
if (needGlobal) {
|
||||
@ -318,8 +310,10 @@ fun buildConfig(
|
||||
globalOutbounds.add(proxyEntity.id)
|
||||
}
|
||||
|
||||
// include g-xx
|
||||
trafficMap[tagOut] = proxyEntity
|
||||
// include g-xx & chain ent
|
||||
val mapList = mutableListOf(proxyEntity)
|
||||
if (index == 0 && profileList.size > 1) mapList.add(proxy) // chain ent
|
||||
trafficMap[tagOut] = mapList
|
||||
|
||||
// Chain outbound
|
||||
if (proxyEntity.needExternal()) {
|
||||
@ -474,10 +468,26 @@ fun buildConfig(
|
||||
makeSingBoxRule(rule.ip.split("\n"), true)
|
||||
}
|
||||
if (rule.port.isNotBlank()) {
|
||||
port = rule.port.split("\n").map { it.toIntOrNull() ?: 0 }
|
||||
port = mutableListOf<Int>()
|
||||
port_range = mutableListOf<String>()
|
||||
rule.port.split(",").map {
|
||||
if (it.contains(":")) {
|
||||
port_range.add(it)
|
||||
} else {
|
||||
it.toIntOrNull()?.apply { port.add(this) }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rule.sourcePort.isNotBlank()) {
|
||||
source_port = rule.sourcePort.split("\n").map { it.toIntOrNull() ?: 0 }
|
||||
source_port = mutableListOf<Int>()
|
||||
source_port_range = mutableListOf<String>()
|
||||
rule.sourcePort.split(",").map {
|
||||
if (it.contains(":")) {
|
||||
source_port_range.add(it)
|
||||
} else {
|
||||
it.toIntOrNull()?.apply { source_port.add(this) }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rule.network.isNotBlank()) {
|
||||
network = rule.network
|
||||
@ -656,15 +666,15 @@ fun buildConfig(
|
||||
}
|
||||
|
||||
if (!forTest) {
|
||||
route.rules.add(Rule_DefaultOptions().apply {
|
||||
route.rules.add(0, Rule_DefaultOptions().apply {
|
||||
inbound = listOf(TAG_DNS_IN)
|
||||
outbound = TAG_DNS_OUT
|
||||
})
|
||||
route.rules.add(Rule_DefaultOptions().apply {
|
||||
route.rules.add(0, Rule_DefaultOptions().apply {
|
||||
port = listOf(53)
|
||||
outbound = TAG_DNS_OUT
|
||||
}) // TODO new mode use system dns?
|
||||
if (DataStore.bypassLan && DataStore.bypassLanInCoreOnly) {
|
||||
if (DataStore.bypassLanInCore) {
|
||||
route.rules.add(Rule_DefaultOptions().apply {
|
||||
outbound = TAG_BYPASS
|
||||
geoip = listOf("private")
|
||||
@ -700,8 +710,7 @@ fun buildConfig(
|
||||
mergeJSON(optionsToMerge, this)
|
||||
}),
|
||||
externalIndexMap,
|
||||
outboundTags,
|
||||
outboundTagMain,
|
||||
proxy.id,
|
||||
trafficMap,
|
||||
alerts
|
||||
)
|
||||
|
||||
@ -103,7 +103,7 @@ class AssetsActivity : ThemedActivity() {
|
||||
.substringAfterLast('/')
|
||||
.substringAfter(':')
|
||||
|
||||
if (!fileName.endsWith(".dat")) {
|
||||
if (!fileName.endsWith(".db")) {
|
||||
alert(getString(R.string.route_not_asset, fileName)).show()
|
||||
return@registerForActivityResult
|
||||
}
|
||||
|
||||
@ -264,7 +264,7 @@ class RouteFragment : ToolbarFragment(R.layout.layout_route), Toolbar.OnMenuItem
|
||||
inner class DocumentHolder(binding: LayoutEmptyRouteBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind() {
|
||||
itemView.setOnClickListener {
|
||||
it.context.launchCustomTab("https://sing-box.sagernet.org/configuration/route/rule/")
|
||||
it.context.launchCustomTab("https://matsuridayo.github.io/nb4a-route/")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,6 @@ import io.nekohasekai.sagernet.database.preference.EditTextPreferenceModifiers
|
||||
import io.nekohasekai.sagernet.ktx.*
|
||||
import io.nekohasekai.sagernet.utils.Theme
|
||||
import io.nekohasekai.sagernet.widget.AppListPreference
|
||||
import libcore.Libcore
|
||||
import moe.matsuri.nb4a.Protocols
|
||||
import moe.matsuri.nb4a.ui.ColorPickerPreference
|
||||
import moe.matsuri.nb4a.ui.LongClickSwitchPreference
|
||||
@ -39,7 +38,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
listView.layoutManager = FixedLinearLayoutManager(listView)
|
||||
}
|
||||
|
||||
val reloadListener = Preference.OnPreferenceChangeListener { _, _ ->
|
||||
private val reloadListener = Preference.OnPreferenceChangeListener { _, _ ->
|
||||
needReload()
|
||||
true
|
||||
}
|
||||
@ -50,7 +49,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
addPreferencesFromResource(R.xml.global_preferences)
|
||||
|
||||
DataStore.routePackages = DataStore.nekoPlugins
|
||||
nekoPlugins = findPreference<AppListPreference>(Key.NEKO_PLUGIN_MANAGED)!!
|
||||
nekoPlugins = findPreference(Key.NEKO_PLUGIN_MANAGED)!!
|
||||
nekoPlugins.setOnPreferenceClickListener {
|
||||
// borrow from route app settings
|
||||
startActivity(Intent(
|
||||
@ -80,7 +79,6 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
true
|
||||
}
|
||||
val mixedPort = findPreference<EditTextPreference>(Key.MIXED_PORT)!!
|
||||
val speedInterval = findPreference<Preference>(Key.SPEED_INTERVAL)!!
|
||||
val serviceMode = findPreference<Preference>(Key.SERVICE_MODE)!!
|
||||
val allowAccess = findPreference<Preference>(Key.ALLOW_ACCESS)!!
|
||||
val appendHttpProxy = findPreference<SwitchPreference>(Key.APPEND_HTTP_PROXY)!!
|
||||
@ -96,14 +94,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
tcpKeepAliveInterval.isVisible = false
|
||||
|
||||
val bypassLan = findPreference<SwitchPreference>(Key.BYPASS_LAN)!!
|
||||
val bypassLanInCoreOnly = findPreference<SwitchPreference>(Key.BYPASS_LAN_IN_CORE_ONLY)!!
|
||||
|
||||
bypassLanInCoreOnly.isEnabled = bypassLan.isChecked
|
||||
bypassLan.setOnPreferenceChangeListener { _, newValue ->
|
||||
bypassLanInCoreOnly.isEnabled = newValue as Boolean
|
||||
needReload()
|
||||
true
|
||||
}
|
||||
val bypassLanInCore = findPreference<SwitchPreference>(Key.BYPASS_LAN_IN_CORE)!!
|
||||
|
||||
val remoteDns = findPreference<EditTextPreference>(Key.REMOTE_DNS)!!
|
||||
val directDns = findPreference<EditTextPreference>(Key.DIRECT_DNS)!!
|
||||
@ -192,9 +183,10 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
|
||||
val profileTrafficStatistics =
|
||||
findPreference<SwitchPreference>(Key.PROFILE_TRAFFIC_STATISTICS)!!
|
||||
speedInterval.isEnabled = profileTrafficStatistics.isChecked
|
||||
profileTrafficStatistics.setOnPreferenceChangeListener { _, newValue ->
|
||||
speedInterval.isEnabled = newValue as Boolean
|
||||
val speedInterval = findPreference<SimpleMenuPreference>(Key.SPEED_INTERVAL)!!
|
||||
profileTrafficStatistics.isEnabled = speedInterval.value.toString() != "0"
|
||||
speedInterval.setOnPreferenceChangeListener { _, newValue ->
|
||||
profileTrafficStatistics.isEnabled = newValue.toString() != "0"
|
||||
needReload()
|
||||
true
|
||||
}
|
||||
@ -209,7 +201,6 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
val acquireWakeLock = findPreference<SwitchPreference>(Key.ACQUIRE_WAKE_LOCK)!!
|
||||
val enableClashAPI = findPreference<SwitchPreference>(Key.ENABLE_CLASH_API)!!
|
||||
|
||||
speedInterval.onPreferenceChangeListener = reloadListener
|
||||
mixedPort.onPreferenceChangeListener = reloadListener
|
||||
appendHttpProxy.onPreferenceChangeListener = reloadListener
|
||||
showDirectSpeed.onPreferenceChangeListener = reloadListener
|
||||
@ -217,7 +208,8 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
|
||||
trafficSniffing.onPreferenceChangeListener = reloadListener
|
||||
muxConcurrency.onPreferenceChangeListener = reloadListener
|
||||
tcpKeepAliveInterval.onPreferenceChangeListener = reloadListener
|
||||
bypassLanInCoreOnly.onPreferenceChangeListener = reloadListener
|
||||
bypassLan.onPreferenceChangeListener = reloadListener
|
||||
bypassLanInCore.onPreferenceChangeListener = reloadListener
|
||||
mtu.onPreferenceChangeListener = reloadListener
|
||||
|
||||
enableFakeDns.onPreferenceChangeListener = reloadListener
|
||||
|
||||
@ -220,7 +220,7 @@
|
||||
<string name="domain_strategy">استراتيجية حل المجال</string>
|
||||
<string name="route_opt_block_ads">إعلانات كتلة</string>
|
||||
<string name="route_opt_bypass_lan">جانبا LAN</string>
|
||||
<string name="route_not_asset">ليس ملف أصل: استثناء .dat، لكن %s</string>
|
||||
<string name="route_not_asset">ليس ملف أصل: استثناء .db، لكن %s</string>
|
||||
<string name="hysteria_download_mbps">أقصى سرعة تنزيل (بالميجابت في الثانية)</string>
|
||||
<string name="hysteria_upload_mbps">أقصى سرعة تحميل (بالميجابت في الثانية)</string>
|
||||
<string name="hysteria_auth_payload">حمولة المصادقة</string>
|
||||
|
||||
@ -154,7 +154,7 @@
|
||||
<string name="route_asset_status">Versión local: %s</string>
|
||||
<string name="route_asset_no_update">Sin actualización</string>
|
||||
<string name="route_asset_updated">Actualizado</string>
|
||||
<string name="route_not_asset">No es un archivo de activos: excepto .dat, pero %s</string>
|
||||
<string name="route_not_asset">No es un archivo de activos: excepto .db, pero %s</string>
|
||||
<string name="route_opt_bypass_lan">Omitir LAN</string>
|
||||
<string name="route_opt_block_ads">Bloquear anuncios</string>
|
||||
<string name="route_opt_block_analysis">Bloquear analítica</string>
|
||||
|
||||
@ -152,7 +152,7 @@
|
||||
<string name="route_asset_status">نسخه محلی: %s</string>
|
||||
<string name="route_asset_no_update">بدون آپدیت</string>
|
||||
<string name="route_asset_updated">به روز رسانی</string>
|
||||
<string name="route_not_asset">نه یک فایل پشتیبان: به جز .dat، اما %s</string>
|
||||
<string name="route_not_asset">نه یک فایل پشتیبان: به جز .db، اما %s</string>
|
||||
<string name="route_opt_bypass_lan">دور زدن LAN</string>
|
||||
<string name="route_opt_block_ads">مسدود کردن تبلیغات</string>
|
||||
<string name="route_opt_block_analysis">بلاک کردن انالیز ها</string>
|
||||
|
||||
@ -181,7 +181,7 @@
|
||||
<string name="mux_sum">Mux dirancang untuk mengurangi latensi handshake TCP, bukan untuk meningkatkan throughput koneksi. Menggunakan Mux untuk menonton video, mengunduh, atau uji kecepatan biasanya kontra produktif</string>
|
||||
<string name="domain_strategy">Strategi Resolusi Domain</string>
|
||||
<string name="route_opt_bypass_lan">Lewati LAN</string>
|
||||
<string name="route_not_asset">Bukan file aset: kecuali .dat, tapi %s</string>
|
||||
<string name="route_not_asset">Bukan file aset: kecuali .db, tapi %s</string>
|
||||
<string name="route_rules_provider">Penyedia Aset Aturan</string>
|
||||
<string name="route_reverse_redirect">Pengalihan Terbalik</string>
|
||||
<string name="route_bypass_domain">Aturan domain untuk %s</string>
|
||||
|
||||
@ -237,7 +237,7 @@
|
||||
<string name="domain_strategy">Domeneløsningsstrategi</string>
|
||||
<string name="route_opt_block_ads">Blokker annonser</string>
|
||||
<string name="route_opt_bypass_lan">Omgå LAN</string>
|
||||
<string name="route_not_asset">Ikke en ressursfil: unntatt .dat, men %s</string>
|
||||
<string name="route_not_asset">Ikke en ressursfil: unntatt .db, men %s</string>
|
||||
<string name="route_asset_updated">Oppdatert</string>
|
||||
<string name="route_asset_no_update">Ingen oppdatering</string>
|
||||
<string name="route_asset_status">Lokal versjon: %s</string>
|
||||
|
||||
@ -296,7 +296,7 @@
|
||||
<string name="domain_strategy">Стратегия разрешения доменов</string>
|
||||
<string name="route_opt_block_ads">Блокировать рекламу</string>
|
||||
<string name="route_opt_bypass_lan">Обход LAN</string>
|
||||
<string name="route_not_asset">Не файл ресурса: ожидался .dat, а не %s</string>
|
||||
<string name="route_not_asset">Не файл ресурса: ожидался .db, а не %s</string>
|
||||
<string name="route_asset_updated">Обновлено</string>
|
||||
<string name="route_asset_no_update">Обновлений нет</string>
|
||||
<string name="route_asset_status">Локальная версия: %s</string>
|
||||
|
||||
@ -369,7 +369,7 @@
|
||||
<string name="alter_id">Alternatif ID</string>
|
||||
<string name="obfs">Şaşırtmaca</string>
|
||||
<string name="tcp_keep_alive_interval">TCP aktif paket teslim koruma aralığı</string>
|
||||
<string name="route_not_asset">Varlık dosyası değil: .dat beklendi ama %s</string>
|
||||
<string name="route_not_asset">Varlık dosyası değil: .db beklendi ama %s</string>
|
||||
<string name="route_rules_provider">Rota Varlıkları Sağlayıcısı</string>
|
||||
<string name="route_assets">Varlıklar</string>
|
||||
<string name="route_manage_assets">Rota Varlıklarını Yönet</string>
|
||||
|
||||
@ -262,7 +262,7 @@
|
||||
<string name="lines">%d 行</string>
|
||||
<string name="only">仅</string>
|
||||
<string name="prefer">优先</string>
|
||||
<string name="route_not_asset">不是资源文件: 预期 .dat 为扩展名, 但 %s</string>
|
||||
<string name="route_not_asset">不是资源文件: 预期 .db 为扩展名, 但 %s</string>
|
||||
<string name="route_asset_no_update">已为最新</string>
|
||||
<string name="route_asset_updated">已更新</string>
|
||||
<string name="route_asset_status">本地版本: %s</string>
|
||||
|
||||
@ -234,7 +234,7 @@
|
||||
<string name="route_asset_status">本地版本:%s</string>
|
||||
<string name="route_asset_no_update">無更新</string>
|
||||
<string name="route_asset_updated">已更新</string>
|
||||
<string name="route_not_asset">非資源檔案:預期副檔名為 .dat,但 %s</string>
|
||||
<string name="route_not_asset">非資源檔案:預期副檔名為 .db,但 %s</string>
|
||||
<string name="route_opt_bypass_lan">略過區域網路位址</string>
|
||||
<string name="route_opt_block_ads">封鎖廣告</string>
|
||||
<string name="domain_strategy">網域解析策略</string>
|
||||
|
||||
@ -157,7 +157,7 @@
|
||||
<string name="route_asset_status">Local version: %s</string>
|
||||
<string name="route_asset_no_update">No update</string>
|
||||
<string name="route_asset_updated">Updated</string>
|
||||
<string name="route_not_asset">Not an asset file: excepted .dat, but %s</string>
|
||||
<string name="route_not_asset">Not an asset file: excepted .db, but %s</string>
|
||||
<string name="route_opt_bypass_lan">Bypass LAN</string>
|
||||
<string name="route_opt_block_ads">Block ADs</string>
|
||||
<string name="route_opt_block_analysis">Block analysis</string>
|
||||
@ -331,7 +331,6 @@
|
||||
<string name="append_http_proxy">Append HTTP Proxy to VPN</string>
|
||||
<string name="append_http_proxy_sum">HTTP proxy will be used directly from (browser/ some supported apps), without going through the virtual NIC device (Android 10+)</string>
|
||||
<string name="bypass_lan_in_core_only">Bypass LAN in Core Only</string>
|
||||
<string name="bypass_lan_in_core_only_sum">If Lineage\'s "Allow hotspot clients to use VPNs" does not work, try this.</string>
|
||||
<string name="protocol_settings">Protocol Settings</string>
|
||||
<string name="trojan_provider">Trojan Provider</string>
|
||||
<string name="group_basic">Basic</string>
|
||||
|
||||
@ -89,8 +89,7 @@
|
||||
app:key="bypassLan"
|
||||
app:title="@string/route_opt_bypass_lan" />
|
||||
<SwitchPreference
|
||||
android:summary="@string/bypass_lan_in_core_only_sum"
|
||||
app:key="bypassLanInCoreOnly"
|
||||
app:key="bypassLanInCore"
|
||||
app:title="@string/bypass_lan_in_core_only" />
|
||||
<SwitchPreference
|
||||
app:defaultValue="true"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user