This commit is contained in:
arm64v8a 2023-03-16 13:41:25 +09:00
parent 48a2776f9c
commit fafe14b7c6
22 changed files with 118 additions and 106 deletions

View File

@ -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"

View File

@ -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

View File

@ -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) {

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
)

View File

@ -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
}

View File

@ -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/")
}
}
}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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"