Compare commits

...

28 Commits

Author SHA1 Message Date
2dust cdb050b6c5 up 1.8.13 2024-01-08 09:13:42 +08:00
2dust 21f47b536d Bug fix 2024-01-07 17:15:09 +08:00
2dust f14484c986 Merge pull request #2733 from solokot/master
Russian translation
2024-01-07 16:31:38 +08:00
solokot 358dd78dc3 Russian translation
Small cosmetic fixes
2024-01-07 06:58:48 +00:00
2dust d79e072316 Merge pull request #2732 from admarty/master
Improve Vietnamese translation
2024-01-07 09:25:27 +08:00
2dust c24dee567a Modify background color 2024-01-07 09:24:48 +08:00
admarty 9f75bafcea Update strings.xml 2024-01-06 21:11:34 +07:00
admarty 2150452629 Update strings.xml 2024-01-06 20:50:50 +07:00
admarty 507a32a08e Improve Vietnamese translation 2024-01-06 20:22:52 +07:00
2dust 44dee8e850 Add main interface filter cache 2024-01-06 16:56:19 +08:00
2dust 5e4d9246c2 Merge pull request #2721 from mosayeb-a/fix-bug
fix a bug(ConcurrentModificationException)
2024-01-05 12:12:22 +08:00
mosayeb 9fe7419467 fix a bug(ConcurrentModificationException) 2024-01-03 11:15:00 -08:00
2dust 41b2251dfe Merge pull request #2718 from yuhan6665/wireguard
Wireguard can configure tun address
2024-01-02 12:06:08 +08:00
yuhan6665 73fad43573 Handle IPv6 address correctly 2024-01-01 22:16:07 -05:00
yuhan6665 4676717582 Wireguard can configure tun address
local tun address is also used by Wireguard server to check against its "allowedIPs" setting
2024-01-01 21:49:54 -05:00
2dust 834766e6e7 Merge pull request #2704 from yuhan6665/wireguard
Add Wireguard maunal config
2023-12-24 16:32:26 +08:00
yuhan6665 e304dce347 Add Wireguard maunal config
No support for export and import via links yet
2023-12-23 23:51:09 -05:00
2dust 61654aefeb Merge pull request #2690 from user09283/patch-1
Update strings.xml
2023-12-18 15:49:06 +08:00
user09283 1664aaa25b Update strings.xml
Update Vietnamese language
2023-12-18 00:41:47 +07:00
2dust 68f1f64f3d Merge pull request #2674 from mmrabbani/patch-1
Add HTTP3 to ALPN options
2023-12-14 09:20:11 +08:00
2dust 7bad57ca52 Merge pull request #2671 from solokot/master
Update Russian translation
2023-12-14 09:18:57 +08:00
MMR 1c8e1f0993 Add HTTP3 to ALPN options 2023-12-13 16:01:12 +03:30
solokot 6037ae6fc4 Update Russian translation 2023-12-09 18:59:33 +03:00
2dust dc1c5400b8 Add mux concurency setting 2023-12-07 17:49:09 +08:00
2dust 9ae4688171 Update build.yml 2023-12-05 17:52:45 +08:00
2dust e3f39234b2 Bug fix 2023-12-05 16:51:31 +08:00
2dust 0df0b2d6ac Merge pull request #2662 from solokot/master
Update Russian
2023-12-05 16:43:00 +08:00
solokot cc9b083e5d Update Russian 2023-12-04 10:00:31 +03:00
29 changed files with 520 additions and 130 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- name: Setup Golang
uses: actions/setup-go@v4
with:
go-version: '1.19.11'
go-version: '1.21.4'
- name: Install gomobile
run: |
+2 -2
View File
@@ -17,8 +17,8 @@ android {
minSdkVersion 21
targetSdkVersion Integer.parseInt("$targetSdkVer")
multiDexEnabled true
versionCode 532
versionName "1.8.12"
versionCode 538
versionName "1.8.13"
}
buildTypes {
+4
View File
@@ -178,11 +178,15 @@
android:name=".service.QSTileService"
android:icon="@drawable/ic_stat_name"
android:label="@string/app_tile_name"
android:foregroundServiceType="specialUse"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:process=":RunSoLibV2RayDaemon">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="tile" />
</service>
<!-- =====================Tasker===================== -->
<activity
@@ -41,6 +41,7 @@ object AppConfig {
const val PREF_CONFIRM_REMOVE = "pref_confirm_remove"
const val PREF_START_SCAN_IMMEDIATE = "pref_start_scan_immediate"
const val PREF_MUX_ENABLED = "pref_mux_enabled"
const val PREF_MUX_CONCURRENCY = "pref_mux_concurency"
const val PREF_MUX_XUDP_CONCURRENCY = "pref_mux_xudp_concurency"
const val PREF_MUX_XUDP_QUIC = "pref_mux_xudp_quic"
@@ -98,4 +99,6 @@ object AppConfig {
const val SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL = "1440" // 24 hours
const val SUBSCRIPTION_UPDATE_TASK_NAME = "subscription_updater"
const val CACHE_SUBSCRIPTION_ID = "cache_subscription_id"
const val CACHE_KEYWORD_FILTER = "cache_keyword_filter"
}
@@ -19,23 +19,32 @@ data class ServerConfig(
when(configType) {
EConfigType.VMESS, EConfigType.VLESS ->
return ServerConfig(
configType = configType,
outboundBean = V2rayConfig.OutboundBean(
protocol = configType.name.lowercase(),
settings = V2rayConfig.OutboundBean.OutSettingsBean(
vnext = listOf(V2rayConfig.OutboundBean.OutSettingsBean.VnextBean(
users = listOf(V2rayConfig.OutboundBean.OutSettingsBean.VnextBean.UsersBean())))),
streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean()))
EConfigType.CUSTOM, EConfigType.WIREGUARD ->
configType = configType,
outboundBean = V2rayConfig.OutboundBean(
protocol = configType.name.lowercase(),
settings = V2rayConfig.OutboundBean.OutSettingsBean(
vnext = listOf(V2rayConfig.OutboundBean.OutSettingsBean.VnextBean(
users = listOf(V2rayConfig.OutboundBean.OutSettingsBean.VnextBean.UsersBean())))),
streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean()))
EConfigType.CUSTOM ->
return ServerConfig(configType = configType)
EConfigType.SHADOWSOCKS, EConfigType.SOCKS, EConfigType.TROJAN ->
return ServerConfig(
configType = configType,
outboundBean = V2rayConfig.OutboundBean(
protocol = configType.name.lowercase(),
settings = V2rayConfig.OutboundBean.OutSettingsBean(
servers = listOf(V2rayConfig.OutboundBean.OutSettingsBean.ServersBean())),
streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean()))
configType = configType,
outboundBean = V2rayConfig.OutboundBean(
protocol = configType.name.lowercase(),
settings = V2rayConfig.OutboundBean.OutSettingsBean(
servers = listOf(V2rayConfig.OutboundBean.OutSettingsBean.ServersBean())),
streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean()))
EConfigType.WIREGUARD ->
return ServerConfig(
configType = configType,
outboundBean = V2rayConfig.OutboundBean(
protocol = configType.name.lowercase(),
settings = V2rayConfig.OutboundBean.OutSettingsBean(
secretKey = "",
peers = listOf(V2rayConfig.OutboundBean.OutSettingsBean.WireGuardBean())
)))
}
}
}
@@ -60,10 +69,6 @@ data class ServerConfig(
fun getV2rayPointDomainAndPort(): String {
val address = getProxyOutbound()?.getServerAddress().orEmpty()
val port = getProxyOutbound()?.getServerPort()
return if (Utils.isIpv6Address(address)) {
String.format("[%s]:%s", address, port)
} else {
String.format("%s:%s", address, port)
}
return Utils.getIpv6Address(address) + ":" + port
}
}
@@ -74,7 +74,7 @@ data class V2rayConfig(
var response: Response? = null,
/*DNS*/
val network: String? = null,
val address: Any? = null,
var address: Any? = null,
val port: Int? = null,
/*Freedom*/
var domainStrategy: String? = null,
@@ -83,8 +83,9 @@ data class V2rayConfig(
/*Loopback*/
val inboundTag: String? = null,
/*Wireguard*/
val secretKey: String? = null,
var secretKey: String? = null,
val peers: List<WireGuardBean>? = null,
var reserved: List<Int>? = null,
) {
data class VnextBean(var address: String = "",
@@ -36,7 +36,12 @@ class QSTileService : TileService() {
super.onStartListening()
setState(Tile.STATE_INACTIVE)
mMsgReceive = ReceiveMessageHandler(this)
registerReceiver(mMsgReceive, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(mMsgReceive, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY), Context.RECEIVER_EXPORTED)
} else {
registerReceiver(mMsgReceive, IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY))
}
MessageUtil.sendMsg2Service(this, AppConfig.MSG_REGISTER_CLIENT, "")
}
@@ -253,6 +253,10 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
importManually(EConfigType.TROJAN.value)
true
}
R.id.import_manually_wireguard -> {
importManually(EConfigType.WIREGUARD.value)
true
}
R.id.import_config_custom_clipboard -> {
importConfigCustomClipboard()
true
@@ -21,6 +21,7 @@ import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.MmkvManager.ID_MAIN
import com.v2ray.ang.util.MmkvManager.KEY_SELECTED_SERVER
import com.v2ray.ang.util.Utils
import com.v2ray.ang.util.Utils.getIpv6Address
class ServerActivity : BaseActivity() {
@@ -103,6 +104,12 @@ class ServerActivity : BaseActivity() {
private val container_short_id: LinearLayout? by lazy { findViewById(R.id.l7) }
private val et_spider_x: EditText? by lazy { findViewById(R.id.et_spider_x) }
private val container_spider_x: LinearLayout? by lazy { findViewById(R.id.l8) }
private val et_reserved1: EditText? by lazy { findViewById(R.id.et_reserved1) }
private val et_reserved2: EditText? by lazy { findViewById(R.id.et_reserved2) }
private val et_reserved3: EditText? by lazy { findViewById(R.id.et_reserved3) }
private val et_local_v4_address: EditText? by lazy { findViewById(R.id.et_local_v4_address) }
private val et_local_v6_address: EditText? by lazy { findViewById(R.id.et_local_v6_address) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -116,7 +123,7 @@ class ServerActivity : BaseActivity() {
EConfigType.SOCKS -> setContentView(R.layout.activity_server_socks)
EConfigType.VLESS -> setContentView(R.layout.activity_server_vless)
EConfigType.TROJAN -> setContentView(R.layout.activity_server_trojan)
else -> setContentView(R.layout.activity_server_vmess)
EConfigType.WIREGUARD -> setContentView(R.layout.activity_server_wireguard)
}
sp_network?.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
@@ -182,7 +189,6 @@ class ServerActivity : BaseActivity() {
*/
private fun bindingServer(config: ServerConfig): Boolean {
val outbound = config.getProxyOutbound() ?: return false
val streamSetting = config.outboundBean?.streamSettings ?: return false
et_remarks.text = Utils.getEditable(config.remarks)
et_address.text = Utils.getEditable(outbound.getServerAddress().orEmpty())
@@ -197,10 +203,24 @@ class ServerActivity : BaseActivity() {
if (flow >= 0) {
sp_flow?.setSelection(flow)
}
} else if (config.configType == EConfigType.TROJAN) {
val flow = Utils.arrayFind(flows, outbound.settings?.servers?.get(0)?.flow.orEmpty())
if (flow >= 0) {
sp_flow?.setSelection(flow)
} else if (config.configType == EConfigType.WIREGUARD) {
et_public_key?.text = Utils.getEditable(outbound.settings?.peers?.get(0)?.publicKey.orEmpty())
if (outbound.settings?.reserved == null) {
et_reserved1?.text = Utils.getEditable("0")
et_reserved2?.text = Utils.getEditable("0")
et_reserved3?.text = Utils.getEditable("0")
} else {
et_reserved1?.text = Utils.getEditable(outbound.settings?.reserved?.get(0).toString())
et_reserved2?.text = Utils.getEditable(outbound.settings?.reserved?.get(1).toString())
et_reserved3?.text = Utils.getEditable(outbound.settings?.reserved?.get(2).toString())
}
if (outbound.settings?.address == null) {
et_local_v4_address?.text = Utils.getEditable("172.16.0.2/32")
et_local_v6_address?.text = Utils.getEditable("2606:4700:110:8f81:d551:a0:532e:a2b3/128")
} else {
val list = outbound.settings?.address as List<*>
et_local_v4_address?.text = Utils.getEditable(list.get(0).toString())
et_local_v6_address?.text = Utils.getEditable(list.get(1).toString())
}
}
val securityEncryptions = if (config.configType == EConfigType.SHADOWSOCKS) shadowsocksSecuritys else securitys
@@ -209,6 +229,7 @@ class ServerActivity : BaseActivity() {
sp_security?.setSelection(security)
}
val streamSetting = config.outboundBean?.streamSettings ?: return true
val streamSecurity = Utils.arrayFind(streamSecuritys, streamSetting.security)
if (streamSecurity >= 0) {
sp_stream_security?.setSelection(streamSecurity)
@@ -282,6 +303,12 @@ class ServerActivity : BaseActivity() {
//et_security.text = null
sp_flow?.setSelection(0)
et_public_key?.text = null
et_reserved1?.text = Utils.getEditable("0")
et_reserved2?.text = Utils.getEditable("0")
et_reserved3?.text = Utils.getEditable("0")
et_local_v4_address?.text = Utils.getEditable("172.16.0.2/32")
et_local_v6_address?.text = Utils.getEditable("2606:4700:110:8f81:d551:a0:532e:a2b3/128")
return true
}
@@ -332,6 +359,10 @@ class ServerActivity : BaseActivity() {
config.outboundBean?.settings?.servers?.get(0)?.let { server ->
saveServers(server, port, config)
}
val wireguard = config.outboundBean?.settings
wireguard?.peers?.get(0)?.let { _ ->
savePeer(wireguard, port)
}
config.outboundBean?.streamSettings?.let {
saveStreamSettings(it)
}
@@ -378,6 +409,22 @@ class ServerActivity : BaseActivity() {
}
}
private fun savePeer(wireguard: V2rayConfig.OutboundBean.OutSettingsBean, port: Int) {
wireguard.secretKey = et_id.text.toString().trim()
wireguard.peers?.get(0)?.publicKey = et_public_key?.text.toString().trim()
wireguard.peers?.get(0)?.endpoint = getIpv6Address(et_address.text.toString().trim()) + ":" + port
val reserved1 = Utils.parseInt(et_reserved1?.text.toString())
val reserved2 = Utils.parseInt(et_reserved2?.text.toString())
val reserved3 = Utils.parseInt(et_reserved3?.text.toString())
if (reserved1 > 0 || reserved2 > 0 || reserved3 > 0) {
wireguard.reserved = listOf(reserved1, reserved2, reserved3)
}else {
wireguard.reserved = null
}
wireguard.address = listOf(et_local_v4_address?.text.toString().trim(),
et_local_v6_address?.text.toString().trim())
}
private fun saveStreamSettings(streamSetting: V2rayConfig.OutboundBean.StreamSettingsBean) {
val network = sp_network?.selectedItemPosition ?: return
val type = sp_header_type?.selectedItemPosition ?: return
@@ -6,9 +6,7 @@ import android.text.TextUtils
import android.view.View
import androidx.activity.viewModels
import androidx.preference.*
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequest
import androidx.work.multiprocess.RemoteWorkManager
import com.v2ray.ang.AngApplication
@@ -39,6 +37,7 @@ class SettingsActivity : BaseActivity() {
private val vpnDns by lazy { findPreference<EditTextPreference>(AppConfig.PREF_VPN_DNS) }
private val mux by lazy { findPreference<CheckBoxPreference>(AppConfig.PREF_MUX_ENABLED) }
private val muxConcurrency by lazy { findPreference<EditTextPreference>(AppConfig.PREF_MUX_CONCURRENCY) }
private val muxXudpConcurrency by lazy { findPreference<EditTextPreference>(AppConfig.PREF_MUX_XUDP_CONCURRENCY) }
private val muxXudpQuic by lazy { findPreference<ListPreference>(AppConfig.PREF_MUX_XUDP_QUIC) }
@@ -161,10 +160,14 @@ class SettingsActivity : BaseActivity() {
updateMux(newValue as Boolean)
true
}
muxXudpConcurrency?.setOnPreferenceChangeListener { _, newValue ->
muxConcurrency?.setOnPreferenceChangeListener { _, newValue ->
updateMuxConcurrency(newValue as String)
true
}
muxXudpConcurrency?.setOnPreferenceChangeListener { _, newValue ->
updateMuxXudpConcurrency(newValue as String)
true
}
}
override fun onStart() {
@@ -179,6 +182,7 @@ class SettingsActivity : BaseActivity() {
socksPort?.summary = defaultSharedPreferences.getString(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS)
httpPort?.summary = defaultSharedPreferences.getString(AppConfig.PREF_HTTP_PORT, AppConfig.PORT_HTTP)
updateMux(defaultSharedPreferences.getBoolean(AppConfig.PREF_MUX_ENABLED, false))
muxConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8")
muxXudpConcurrency?.summary = defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8")
autoUpdateInterval?.summary = defaultSharedPreferences.getString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL)
autoUpdateInterval?.isEnabled = defaultSharedPreferences.getBoolean(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false)
@@ -257,14 +261,24 @@ class SettingsActivity : BaseActivity() {
private fun updateMux(enabled: Boolean) {
val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity())
muxConcurrency?.isEnabled = enabled
muxXudpConcurrency?.isEnabled = enabled
muxXudpQuic?.isEnabled = enabled
if (enabled) {
updateMuxConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8"))
updateMuxConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_CONCURRENCY, "8"))
updateMuxXudpConcurrency(defaultSharedPreferences.getString(AppConfig.PREF_MUX_XUDP_CONCURRENCY, "8"))
}
}
private fun updateMuxConcurrency(value: String?) {
if (value == null) {
} else {
val concurrency = value.toIntOrNull() ?: 8
muxConcurrency?.summary = concurrency.toString()
}
}
private fun updateMuxXudpConcurrency(value: String?) {
if (value == null) {
muxXudpQuic?.isEnabled = true
} else {
@@ -617,10 +617,13 @@ object AngConfigManager {
EConfigType.SOCKS -> {
val remark = "#" + Utils.urlEncode(config.remarks)
val pw =
Utils.encode("${outbound.settings?.servers?.get(0)?.users?.get(0)?.user}:${outbound.getPassword()}")
if (outbound.settings?.servers?.get(0)?.users?.get(0)?.user != null)
"${outbound.settings?.servers?.get(0)?.users?.get(0)?.user}:${outbound.getPassword()}"
else
":"
val url = String.format(
"%s@%s:%s",
pw,
Utils.encode(pw),
Utils.getIpv6Address(outbound.getServerAddress()!!),
outbound.getServerPort()
)
@@ -366,7 +366,7 @@ object Utils {
}
fun getIpv6Address(address: String): String {
return if (isIpv6Address(address)) {
return if (isIpv6Address(address) && !address.contains('[') && !address.contains(']')) {
String.format("[%s]", address)
} else {
address
@@ -402,7 +402,6 @@ object V2rayConfigUtil {
private fun updateOutboundWithGlobalSettings(outbound: V2rayConfig.OutboundBean): Boolean {
try {
var muxEnabled = settingsStorage?.decodeBool(AppConfig.PREF_MUX_ENABLED, false)
val protocol = outbound.protocol
if (protocol.equals(EConfigType.SHADOWSOCKS.name, true)
|| protocol.equals(EConfigType.SOCKS.name, true)
@@ -414,10 +413,10 @@ object V2rayConfigUtil {
) {
muxEnabled = false
}
if (muxEnabled == true) {
outbound.mux?.enabled = true
outbound.mux?.concurrency = 8
outbound.mux?.concurrency =
settingsStorage?.decodeInt(AppConfig.PREF_MUX_CONCURRENCY) ?: 8
outbound.mux?.xudpConcurrency =
settingsStorage?.decodeInt(AppConfig.PREF_MUX_XUDP_CONCURRENCY) ?: 8
outbound.mux?.xudpProxyUDP443 =
@@ -427,6 +426,18 @@ object V2rayConfigUtil {
outbound.mux?.concurrency = -1
}
if (protocol.equals(EConfigType.WIREGUARD.name, true)) {
var localTunAddr = if (outbound.settings?.address == null) {
listOf("172.16.0.2/32", "2606:4700:110:8f81:d551:a0:532e:a2b3/128")
} else {
outbound.settings?.address as List<*>
}
if (settingsStorage?.decodeBool(AppConfig.PREF_PREFER_IPV6) != true) {
localTunAddr = listOf(localTunAddr.first())
}
outbound.settings?.address = localTunAddr
}
if (outbound.streamSettings?.network == DEFAULT_NETWORK
&& outbound.streamSettings?.tcpSettings?.header?.type == HTTP
) {
@@ -25,12 +25,28 @@ import kotlinx.coroutines.*
import java.util.*
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
private val mainStorage by lazy {
MMKV.mmkvWithID(
MmkvManager.ID_MAIN,
MMKV.MULTI_PROCESS_MODE
)
}
private val serverRawStorage by lazy {
MMKV.mmkvWithID(
MmkvManager.ID_SERVER_RAW,
MMKV.MULTI_PROCESS_MODE
)
}
private val settingsStorage by lazy {
MMKV.mmkvWithID(
MmkvManager.ID_SETTING,
MMKV.MULTI_PROCESS_MODE
)
}
var serverList = MmkvManager.decodeServerList()
var subscriptionId: String = ""
var keywordFilter: String = ""
var subscriptionId: String = settingsStorage.decodeString(AppConfig.CACHE_SUBSCRIPTION_ID, "")!!
var keywordFilter: String = settingsStorage.decodeString(AppConfig.CACHE_KEYWORD_FILTER, "")!!
private set
val serversCache = mutableListOf<ServersCache>()
val isRunning by lazy { MutableLiveData<Boolean>() }
@@ -74,7 +90,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
serverList.remove(guid)
MmkvManager.removeServer(guid)
val index = getPosition(guid)
if(index >= 0){
if (index >= 0) {
serversCache.removeAt(index)
}
}
@@ -87,7 +103,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, server)
serverList.add(0, key)
serversCache.add(0, ServersCache(key,config))
serversCache.add(0, ServersCache(key, config))
}
fun swapServer(fromPosition: Int, toPosition: Int) {
@@ -127,7 +143,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
val testResult = SpeedtestUtil.tcping(serverAddress, serverPort)
launch(Dispatchers.Main) {
MmkvManager.encodeServerTestDelayMillis(item.guid, testResult)
updateListAction.value = getPosition(item.guid)
updateListAction.value = getPosition(item.guid)
}
}
}
@@ -140,12 +156,18 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
MmkvManager.clearAllTestDelayResults()
updateListAction.value = -1 // update all
val serversCopy = serversCache.toList() // Create a copy of the list
getApplication<AngApplication>().toast(R.string.connection_test_testing)
viewModelScope.launch(Dispatchers.Default) { // without Dispatchers.Default viewModelScope will launch in main thread
for (item in serversCache) {
for (item in serversCopy) {
val config = V2rayConfigUtil.getV2rayConfig(getApplication(), item.guid)
if (config.status) {
MessageUtil.sendMsg2TestService(getApplication(), AppConfig.MSG_MEASURE_CONFIG, Pair(item.guid, config.content))
MessageUtil.sendMsg2TestService(
getApplication(),
AppConfig.MSG_MEASURE_CONFIG,
Pair(item.guid, config.content)
)
}
}
}
@@ -155,7 +177,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
MessageUtil.sendMsg2Service(getApplication(), AppConfig.MSG_MEASURE_DELAY, "")
}
fun filterConfig(context :Context) {
fun filterConfig(context: Context) {
val subscriptions = MmkvManager.decodeSubscriptions()
val listId = subscriptions.map { it.first }.toList().toMutableList()
val listRemarks = subscriptions.map { it.second.remarks }.toList().toMutableList()
@@ -167,7 +189,11 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
}
val ivBinding = DialogConfigFilterBinding.inflate(LayoutInflater.from(context))
ivBinding.spSubscriptionId.adapter = ArrayAdapter<String>( context, android.R.layout.simple_spinner_dropdown_item, listRemarks)
ivBinding.spSubscriptionId.adapter = ArrayAdapter<String>(
context,
android.R.layout.simple_spinner_dropdown_item,
listRemarks
)
ivBinding.spSubscriptionId.setSelection(checkedItem)
ivBinding.etKeyword.text = Utils.getEditable(keywordFilter)
val builder = AlertDialog.Builder(context).setView(ivBinding.root)
@@ -181,6 +207,8 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
subscriptions[position].first
}
keywordFilter = ivBinding.etKeyword.text.toString()
settingsStorage?.encode(AppConfig.CACHE_SUBSCRIPTION_ID, subscriptionId)
settingsStorage?.encode(AppConfig.CACHE_KEYWORD_FILTER, keywordFilter)
reloadServerList()
dialogInterface?.dismiss()
@@ -205,7 +233,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
// }.show()
}
fun getPosition(guid: String) : Int {
fun getPosition(guid: String): Int {
serversCache.forEachIndexed { index, it ->
if (it.guid == guid)
return index
@@ -218,20 +246,24 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
serversCache.forEachIndexed { index, it ->
val outbound = it.config.getProxyOutbound()
serversCache.forEachIndexed { index2, it2 ->
if(index2 > index){
if (index2 > index) {
val outbound2 = it2.config.getProxyOutbound()
if( outbound == outbound2 && !deleteServer.contains(it2.guid))
{
if (outbound == outbound2 && !deleteServer.contains(it2.guid)) {
deleteServer.add(it2.guid)
}
}
}
}
for(it in deleteServer){
for (it in deleteServer) {
MmkvManager.removeServer(it)
}
reloadServerList()
getApplication<AngApplication>().toast(getApplication<AngApplication>().getString(R.string.title_del_duplicate_config_count, deleteServer.count()))
getApplication<AngApplication>().toast(
getApplication<AngApplication>().getString(
R.string.title_del_duplicate_config_count,
deleteServer.count()
)
)
}
private val mMsgReceiver = object : BroadcastReceiver() {
@@ -240,23 +272,29 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
AppConfig.MSG_STATE_RUNNING -> {
isRunning.value = true
}
AppConfig.MSG_STATE_NOT_RUNNING -> {
isRunning.value = false
}
AppConfig.MSG_STATE_START_SUCCESS -> {
getApplication<AngApplication>().toast(R.string.toast_services_success)
isRunning.value = true
}
AppConfig.MSG_STATE_START_FAILURE -> {
getApplication<AngApplication>().toast(R.string.toast_services_failure)
isRunning.value = false
}
AppConfig.MSG_STATE_STOP_SUCCESS -> {
isRunning.value = false
}
AppConfig.MSG_MEASURE_DELAY_SUCCESS -> {
updateTestResultAction.value = intent.getStringExtra("content")
}
AppConfig.MSG_MEASURE_CONFIG_SUCCESS -> {
val resultPair = intent.getSerializableExtra("content") as Pair<String, Long>
MmkvManager.encodeServerTestDelayMillis(resultPair.first, resultPair.second)
@@ -61,6 +61,7 @@ class SettingsViewModel(application: Application) : AndroidViewModel(application
AppConfig.PREF_SNIFFING_ENABLED -> {
settingsStorage?.encode(key, sharedPreferences.getBoolean(key, true))
}
AppConfig.PREF_MUX_CONCURRENCY,
AppConfig.PREF_MUX_XUDP_CONCURRENCY -> {
settingsStorage?.encode(key, sharedPreferences.getString(key, "8")?.toIntOrNull() ?: 8)
}
@@ -48,7 +48,7 @@
android:id="@+id/layout_test"
android:layout_width="match_parent"
android:layout_height="@dimen/connection_test_height"
android:background="?attr/colorPrimary"
android:background="@color/colorMainTestBg"
android:gravity="center|start"
android:nextFocusRight="@+id/fab"
android:clickable="true"
@@ -0,0 +1,200 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.ServerActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/layout_margin_top_height">
<LinearLayout
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/title_server"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_remarks" />
<EditText
android:id="@+id/et_remarks"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/server_lab_address3" />
<EditText
android:id="@+id/et_address"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_port3" />
<EditText
android:id="@+id/et_port"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="number" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_public_key" />
<EditText
android:id="@+id/et_public_key"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_secret_key" />
<EditText
android:id="@+id/et_id"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/server_lab_reserved" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/et_reserved1"
android:layout_width="60dp"
android:layout_height="@dimen/edit_height"
android:inputType="number" />
<EditText
android:id="@+id/et_reserved2"
android:layout_width="60dp"
android:layout_height="@dimen/edit_height"
android:inputType="number" />
<EditText
android:id="@+id/et_reserved3"
android:layout_width="60dp"
android:layout_height="@dimen/edit_height"
android:inputType="number" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/server_lab_local_v4_address" />
<EditText
android:id="@+id/et_local_v4_address"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/server_lab_local_v6_address" />
<EditText
android:id="@+id/et_local_v6_address"
android:layout_width="match_parent"
android:layout_height="@dimen/edit_height"
android:inputType="text" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/layout_margin_top_height"
android:layout_marginTop="@dimen/layout_margin_top_height"
android:orientation="vertical" />
</LinearLayout>
</ScrollView>
@@ -34,6 +34,10 @@
android:id="@+id/import_manually_trojan"
android:title="@string/menu_item_import_config_manually_trojan"
app:showAsAction="never" />
<item
android:id="@+id/import_manually_wireguard"
android:title="@string/menu_item_import_config_manually_wireguard"
app:showAsAction="never" />
<item
android:title="@string/menu_item_import_config_custom"
@@ -28,6 +28,7 @@
<string name="menu_item_import_config_manually_ss">الكتابة يدويا [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">الكتابة يدويا [Socks]</string>
<string name="menu_item_import_config_manually_trojan">الكتابة يدويا [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">[Wireguard] الكتابة يدويا</string>
<string name="menu_item_import_config_custom">تكوين مخصص</string>
<string name="menu_item_import_config_custom_clipboard">استيراد التكوين المخصص من الحافظة</string>
<string name="menu_item_import_config_custom_local">استيراد التكوين المخصص من ملف محلي</string>
@@ -62,6 +63,9 @@
<string name="server_lab_public_key" translatable="false">مفتاح عام</string>
<string name="server_lab_short_id" translatable="false">ShortId</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_reserved">Reserved (اختياري)</string>
<string name="server_lab_local_v4_address">العنوان المحلي IPv4(اختياري)</string>
<string name="server_lab_local_v6_address">العنوان المحلي IPv6(اختياري, يستخدم فقط عندما تفضل IPv6)</string>
<string name="toast_success">نجاح</string>
<string name="toast_failure">فشل</string>
<string name="toast_none_data">لا يوجد شيء</string>
@@ -30,6 +30,7 @@
<string name="menu_item_import_config_manually_ss">تایپ دستی[Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">تایپ دستی[Socks]</string>
<string name="menu_item_import_config_manually_trojan">تایپ دستی[Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">[Wireguard]تایپ دستی</string>
<string name="menu_item_import_config_custom">پیکربندی سفارشی</string>
<string name="menu_item_import_config_custom_clipboard">پیکربندی سفارشی را از کلیپ‌بورد وارد کنید</string>
<string name="menu_item_import_config_custom_local">پیکربندی سفارشی را به صورت محلی وارد کنید</string>
@@ -59,6 +60,9 @@
<string name="server_lab_security4">نام‌کاربری (اختیاری)</string>
<string name="server_lab_encryption">رمزگذاری</string>
<string name="server_lab_flow">جریان</string>
<string name="server_lab_reserved">Reserved (اختیاری)</string>
<string name="server_lab_local_v4_address">آدرس محلی IPv4(اختیاری)</string>
<string name="server_lab_local_v6_address">آدرس محلی IPv6(اختیاری, فقط زمانی استفاده می شود که IPv6 را ترجیح می دهد)</string>
<string name="toast_success">موفقیت</string>
<string name="toast_failure">شکست</string>
<string name="toast_none_data">چیزی نیست</string>
@@ -11,4 +11,5 @@
<color name="colorAccent">#FFFFFF</color>
<color name="colorBg">#000000</color>
<color name="colorText">#FFFFFF</color>
<color name="colorMainTestBg">#222222</color>
</resources>
@@ -30,6 +30,7 @@
<string name="menu_item_import_config_manually_ss">Ручной ввод профиля Shadowsocks</string>
<string name="menu_item_import_config_manually_socks">Ручной ввод профиля Socks</string>
<string name="menu_item_import_config_manually_trojan">Ручной ввод профиля Trojan</string>
<string name="menu_item_import_config_manually_wireguard">Ручной ввод профиля Wireguard</string>
<string name="menu_item_import_config_custom">Пользовательский профиль</string>
<string name="menu_item_import_config_custom_clipboard">Импорт из буфера обмена</string>
<string name="menu_item_import_config_custom_local">Импорт из файла</string>
@@ -64,6 +65,9 @@
<string name="server_lab_public_key" translatable="false">PublicKey</string>
<string name="server_lab_short_id" translatable="false">ShortId</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_reserved">Reserved (необязательно)</string>
<string name="server_lab_local_v4_address">Локальный адрес IPv4 (необязательно)</string>
<string name="server_lab_local_v6_address">Локальный адрес IPv6 (необязательно, используется только если предпочитаете IPv6)</string>
<string name="toast_success">Успешно</string>
<string name="toast_failure">Ошибка</string>
<string name="toast_none_data">Ничего нет</string>
@@ -103,7 +107,8 @@
<string name="summary_pref_per_app_proxy">Основной: выделенное приложение соединяется через прокси, не выделенное — напрямую; \n\nРежим обхода: выделенное приложение соединяется напрямую, не выделенное — через прокси.\n\nЕсть возможность автоматического выбора проксируемых приложений в меню.</string>
<string name="title_pref_mux_enabled">Использовать мультиплексирование</string>
<string name="summary_pref_mux_enabled">Быстрее, но это может привести к нестабильному соединению.\nМультиплексирование TCP-трафика с 8 соединениями по умолчанию, ниже можно настроить обработку UDP и QUIC.</string>
<string name="summary_pref_mux_enabled">Быстрее, но это может привести к нестабильному соединению.\nНиже можно настроить обработку TCP, UDP и QUIC.</string>
<string name="title_pref_mux_concurency">TCP-соединения (диапазон от -1 до 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP-соединения (диапазон от -1 до 1024)</string>
<string name="title_pref_mux_xudp_quic">Обработка QUIC в мультиплексном туннеле</string>
<string-array name="mux_xudp_quic_entries">
@@ -166,14 +171,14 @@
<string name="summary_pref_feedback">Предложить улучшение или сообщить об ошибке на GitHub</string>
<string name="summary_pref_tg_group">Присоединиться к группе в Telegram</string>
<string name="toast_tg_app_not_found">Приложение Telegram не найдено</string>
<string name="title_privacy_policy">Политика конфиденциальности</string>
<string name="title_privacy_policy">Конфиденциальность</string>
<string name="title_pref_promotion">Содействие</string>
<string name="summary_pref_promotion">Содействие, нажмите для получения подробной информации (пожертвование может быть удалено)</string>
<string name="title_pref_auto_update_subscription">Автоматическое обновление подписок</string>
<string name="summary_pref_auto_update_subscription">Автоматическое обновление подписок в фоновом режиме с указанным интервалом. В зависимости от устройства эта функция может работать не всегда.</string>
<string name="title_pref_auto_update_interval">Интервал автообновления (мин.)</string>
<string name="title_pref_auto_update_interval">Интервал автообновления (мин., не менее 15)</string>
<string name="title_core_loglevel">Подробность ведения журнала</string>
<string name="title_mode">Режим</string>
+75 -65
View File
@@ -15,7 +15,7 @@
<string name="toast_services_start">Đang bắt đầu v2rayNG...</string>
<string name="toast_services_stop">Đã dừng v2rayNG!</string>
<string name="toast_services_success">Đã bắt đầu v2rayNG!</string>
<string name="toast_services_failure">Không thể bắt đầu v2rayNG, kiểm tra lại cấu hình hoặc khởi động lại thiết bị.</string>
<string name="toast_services_failure">Không thể bắt đầu v2rayNG, kiểm tra lại cấu hình.</string>
<!--ServerActivity-->
<string name="title_server">v2rayNG</string>
@@ -29,27 +29,28 @@
<string name="menu_item_import_config_manually_ss">Nhập thủ công [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">Nhập thủ công [Socks]</string>
<string name="menu_item_import_config_manually_trojan">Nhập thủ công [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Nhập thủ công [Wireguard]</string>
<string name="menu_item_import_config_custom">Nâng cao / Cấu hình tùy chỉnh</string>
<string name="menu_item_import_config_custom_clipboard">Nhập cấu hình tùy chỉnh từ Clipboard</string>
<string name="menu_item_import_config_custom_local">Nhập cấu hình tùy chỉnh từ Tệp</string>
<string name="menu_item_import_config_custom_url">Nhập cấu hình tùy chỉnh từ URL</string>
<string name="menu_item_import_config_custom_url_scan">Nhập cấu hình tùy chỉnh quét URL</string>
<string name="del_config_comfirm">Bạn có muốn xóa cấu hình không?</string>
<string name="del_config_comfirm">Xác nhận xóa?</string>
<string name="server_lab_remarks">Tên cấu hình</string>
<string name="server_lab_address">Địa chỉ</string>
<string name="server_lab_port">Cổng</string>
<string name="server_lab_id">ID</string>
<string name="server_lab_alterid">ID thay thế</string>
<string name="server_lab_security">Bảo mật</string>
<string name="server_lab_network">Kiểu kết nối</string>
<string name="server_lab_alterid">alterId</string>
<string name="server_lab_security">Phương thức mã hóa</string>
<string name="server_lab_network">Giao thức truyền tải (network)</string>
<string name="server_lab_more_function">Nâng cao</string>
<string name="server_lab_head_type">Loại Head</string>
<string name="server_lab_head_type">Kiểu ngụy trang (type)</string>
<string name="server_lab_mode_type">Chế độ gRPC</string>
<string name="server_lab_request_host">Yêu cầu host (Host/WS/H2) / Bảo mật QUIC</string>
<string name="server_lab_path">Đường dẫn (WS/H2) / Khóa QUIC / KCP seed / Dịch vụ gRPC</string>
<string name="server_lab_request_host">Yêu cầu host(host/ws host/h2 host)/QUIC security</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key/kcp seed/gRPC serviceName</string>
<string name="server_lab_stream_security">TLS</string>
<string name="server_lab_allow_insecure">Bỏ qua xác minh chứng chỉ</string>
<string name="server_lab_sni">Địa chỉ SNI</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
<string name="server_lab_sni">SNI</string>
<string name="server_lab_address3">Địa chỉ</string>
<string name="server_lab_port3">Cổng</string>
<string name="server_lab_id3">Mật khẩu</string>
@@ -58,6 +59,9 @@
<string name="server_lab_security4">Tên người dùng (Bổ sung)</string>
<string name="server_lab_encryption">Mã hoá</string>
<string name="server_lab_flow">Kiểm soát lưu lượng</string>
<string name="server_lab_reserved">Reserved (Bổ sung)</string>
<string name="server_lab_local_v4_address">địa chỉ cục bộ IPv4(Bổ sung)</string>
<string name="server_lab_local_v6_address">địa chỉ cục bộ IPv6(Bổ sung, chỉ được sử dụng khi thích IPv6)</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_none_data">Không có gì ở đây</string>
@@ -82,7 +86,7 @@
<string name="menu_item_search">Tìm kiếm</string>
<string name="menu_item_select_all">Chọn tất cả</string>
<string name="msg_enter_keywords">Nhập từ khoá</string>
<string name="switch_bypass_apps_mode">Bỏ qua kết nối VPN</string>
<string name="switch_bypass_apps_mode">Chế độ Bypass</string>
<string name="menu_item_select_proxy_app">Tự động chọn ứng dụng Proxy</string>
<string name="msg_downloading_content">Đang tải xuống nội dung...</string>
<string name="menu_item_export_proxy_app">Xuất và sao chép</string>
@@ -93,54 +97,55 @@
<string name="title_settings">Cài đặt</string>
<string name="title_advanced">Cài đặt nâng cao</string>
<string name="title_vpn_settings">Cài đặt VPN</string>
<string name="title_pref_per_app_proxy">Proxy ứng dụng</string>
<string name="summary_pref_per_app_proxy">- Chung: Ứng dụng đã chọn sẽ kết nối Proxy, chưa lựa chọn sẽ kết nối trực tiếp. \n- Bỏ qua kết nối: Ứng dụng được chọn sẽ trực tiếp kết nối, không lựa chọn sẽ kết nối qua Proxy. \n- Lựa chọn để tự động chọn ứng dụng Proxy trong Menu.</string>
<string name="title_pref_per_app_proxy">Proxy Theo Ứng Dụng</string>
<string name="summary_pref_per_app_proxy">- Bình thường: Ứng dụng đã chọn sẽ kết nối thông qua Proxy, chưa lựa chọn sẽ kết nối trực tiếp. \n- Chế độ Bypass: Ứng dụng được chọn sẽ kết nối trực tiếp, không lựa chọn sẽ kết nối qua Proxy. \n- Nếu bạn ở Trung Quốc thì chọn Tự động chọn ứng dụng Proxy trong Menu.</string>
<string name="title_pref_mux_enabled">Cho phép Mux</string>
<string name="summary_pref_mux_enabled">Nhanh hơn nhưng có thể khiến kết nối không ổn định\nMux lưu lượng TCP với 8 kết nối mặc định, tùy chỉnh cách xử lý UDP và QUIC bên dưới</string>
<string name="title_pref_mux_xudp_concurency">Kết nối XUDP (phạm vi -1 đến 1024)</string>
<string name="title_pref_mux_xudp_quic">Xử lý QUIC trong đường hầm mux</string>
<string name="title_pref_mux_enabled">Bật Mux</string>
<string name="summary_pref_mux_enabled">Dùng để giảm độ trễ trong bước bắt tay của kết nối TCP, Mux phân phối dữ liệu từ nhiều kết nối TCP trên một TCP duy nhất. Không nên sử dụng Mux để xem video, download file hoặc chạy speedtest vì thường không hiệu quả.</string>
<string name="title_pref_mux_concurency">TCP connections (từ 1 đến 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP connections (từ 1 đến 1024)</string>
<string name="title_pref_mux_xudp_quic">Handling of QUIC traffic in mux tunnel.</string>
<string-array name="mux_xudp_quic_entries">
<item>từ chối</item>
<item>cho phép</item>
<item>nhảy</item>
<item>Từ chối</item>
<item>Cho phép</item>
<item>Bỏ qua</item>
</string-array>
<string name="title_pref_speed_enabled">Cho phép hiển thị tốc độ mạng</string>
<string name="summary_pref_speed_enabled">Hiển thị tốc độ mạng hiện tại trên thanh thông báo.\nBiểu tượng trên thanh trạng thái có thể thay đổi tùy vào mức sử dụng.</string>
<string name="title_pref_speed_enabled">Bật Hiển thị tốc độ mạng</string>
<string name="summary_pref_speed_enabled">Hiển thị tốc độ mạng hiện tại trên thanh thông báo. \nBiểu tượng trên thanh trạng thái có thể thay đổi tùy vào mức sử dụng.</string>
<string name="title_pref_sniffing_enabled">Bật tính năng phát hiện luồng</string>
<string name="summary_pref_sniffing_enabled">Thử chuyển kết nối hiện tại của bạn qua trung gian để trung gian xử lý kết nối về lại cho bạn. (Mặc định là bật, hãy tắt nó nếu kết nối không ổn định)</string>
<string name="title_pref_sniffing_enabled">Bật Sniffing</string>
<string name="summary_pref_sniffing_enabled">Nhận diện tên miền từ gói tin để phục vụ định tuyến. \n(phải tắt để xài Zalo)</string>
<string name="title_pref_local_dns_enabled">Cho phép DNS cục bộ</string>
<string name="summary_pref_local_dns_enabled">DNS được xử lý bởi mô đun của lõi DNS. (Khuyến nghị, nếu cần định tuyến Bỏ qua mạng LAN và địa chỉ đất liền)</string>
<string name="title_pref_local_dns_enabled">Bật Local DNS</string>
<string name="summary_pref_local_dns_enabled">DNS được xử lý bởi mô-đun DNS của xray-core (dùng nếu cần định tuyến Bypassing LAN và địa chỉ nội địa)</string>
<string name="title_pref_fake_dns_enabled">Cho phép DNS giả</string>
<string name="summary_pref_fake_dns_enabled">DNS cục bộ trả về địa chỉ IP giả. (Nhanh hơn, nhưng có thể không hoạt động với một số ứng dụng)</string>
<string name="title_pref_fake_dns_enabled">Bật FakeDNS</string>
<string name="summary_pref_fake_dns_enabled">FakeDNS lấy tên miền mục tiêu bằng cách giả mạo DNS (nhanh hơn, nhưng có thể không hoạt động cho một số ứng dụng)</string>
<string name="title_pref_prefer_ipv6">Ưu tiên IPv6</string>
<string name="summary_pref_prefer_ipv6">Ưu tiên sử dụng địa chỉ IPv6 cho kết nối và lộ trình.</string>
<string name="summary_pref_prefer_ipv6">Ưu tiên sử dụng địa chỉ IPv6 cho kết nối và định tuyến.</string>
<string name="title_pref_routing">Lộ trình</string>
<string name="title_pref_routing_domain_strategy">Tùy chọn tên miền</string>
<string name="title_pref_routing_mode">Tùy chỉnh quy tắc lộ trình</string>
<string name="title_pref_routing_custom">Tùy chỉnh lộ trình</string>
<string name="title_pref_routing">Định tuyến</string>
<string name="title_pref_routing_domain_strategy">Chiến lược tên miền (domainStrategy)</string>
<string name="title_pref_routing_mode">Quy tắc được định nghĩa trước</string>
<string name="title_pref_routing_custom">Quy tắc tùy chỉnh</string>
<string name="title_pref_remote_dns">Điều khiển DNS (Bổ sung)</string>
<string name="title_pref_remote_dns">DNS ngoại quốc (không bắt buộc)</string>
<string name="summary_pref_remote_dns">DNS</string>
<string name="title_pref_vpn_dns">VPN DNS (Chỉ IPv4/IPv6)</string>
<string name="title_pref_domestic_dns">DNS trong nước (Bổ sung)</string>
<string name="title_pref_domestic_dns">DNS nội địa (không bắt buộc)</string>
<string name="summary_pref_domestic_dns">DNS</string>
<string name="title_pref_proxy_sharing_enabled">Cho phép kết nối từ mạng LAN</string>
<string name="summary_pref_proxy_sharing_enabled">Các thiết bị khác có thể kết nối đến Proxy bởi địa chỉ IP thông qua Socks/HTTP, chỉ bật khi bạn tin tưởng kết nối đó.</string>
<string name="toast_warning_pref_proxysharing_short">Cho phép kết nối từ mạng LAN, đảm bảo rằng bạn tin tưởng kết nối hiện tại!</string>
<string name="title_pref_allow_insecure">Cho phép đặt lại Bỏ qua xác minh chứng chỉ</string>
<string name="summary_pref_allow_insecure">Khi kết nối TLS, đặt cài đặt Bỏ qua xác minh chứng chỉ thành mặc định.</string>
<string name="title_pref_allow_insecure">allowInsecure</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ẽ bỏ qua xác minh chứng chỉ (allowInsecure: true).</string>
<string name="title_pref_socks_port">Cổng Proxy SOCKS5</string>
<string name="summary_pref_socks_port">Cổng Proxy SOCKS5</string>
@@ -148,13 +153,13 @@
<string name="title_pref_http_port">Cổng Proxy HTTP</string>
<string name="summary_pref_http_port">Cổng Proxy HTTP</string>
<string name="title_pref_local_dns_port">Cổng DNS cục bộ</string>
<string name="summary_pref_local_dns_port">Cổng DNS cục bộ</string>
<string name="title_pref_local_dns_port">Cổng Local DNS</string>
<string name="summary_pref_local_dns_port">Cổng Local DNS</string>
<string name="title_pref_confirm_remove">Hiển thị thông báo xác nhận xoá cấu hình</string>
<string name="summary_pref_confirm_remove">Hiển thị thông báo xác nhận xoá cấu hình khi bạn xoá một cấu hình.</string>
<string name="title_pref_confirm_remove">Xác nhận xóa tệp cấu hình</string>
<string name="summary_pref_confirm_remove">Yêu cầu xác nhận từ người dùng khi thực hiện xóa tệp cấu hình.</string>
<string name="title_pref_start_scan_immediate">Bắt đầu quét mã QR ngay lập tức</string>
<string name="title_pref_start_scan_immediate">Quét mã QR ngay lập tức</string>
<string name="summary_pref_start_scan_immediate">Mở camera để quét QR ngay khi khởi động, nếu không bạn có thể chọn quét mã hoặc chọn ảnh trên thanh công cụ.</string>
<string name="title_pref_feedback">Phản hồi lỗi</string>
@@ -162,30 +167,35 @@
<string name="summary_pref_tg_group">Tham gia nhóm Telegram</string>
<string name="toast_tg_app_not_found">Không tìm thấy ứng dụng Telegram</string>
<string name="title_pref_promotion">Quảng cáo Server</string>
<string name="title_pref_promotion">Quảng bá server</string>
<string name="summary_pref_promotion">Quảng cáo, nhấn để biết thêm (Ủng hộ có thể được gỡ bỏ)</string>
<string name="title_core_loglevel">Mức độ nhật ký</string>
<string name="title_pref_auto_update_subscription">Tự động cập nhật các gói đăng ký</string>
<string name="summary_pref_auto_update_subscription">Tự động cập nhật các gói đăng ký của bạn ở trong nền với khoảng thời gian cố định. Lưu ý rằng tùy thuộc vào thiết bị, tính năng này có thể không luôn hoạt động đúng như mong đợi.</string>
<string name="title_pref_auto_update_interval">Thời gian Cập nhật tự động (Phút, Giá trị tối thiểu 15)</string>
<string name="title_core_loglevel">Log level</string>
<string name="title_mode">Chế độ kết nối</string>
<string name="title_mode_help">Nhấn vào đây nếu bạn cần trợ giúp!</string>
<string name="title_language">Ngôn ngữ</string>
<string name="title_ui_settings">Cài đặt UI</string>
<string name="title_logcat">Nhật ký hoạt động</string>
<string name="logcat_copy">Sao chép nhật ký</string>
<string name="logcat_clear">Xoá nhật ký</string>
<string name="title_logcat">Logcat</string>
<string name="logcat_copy">Sao chép</string>
<string name="logcat_clear">Xoá</string>
<string name="title_service_restart">Kết nối lại v2rayNG</string>
<string name="title_del_all_config">Xoá tất cả cấu hình</string>
<string name="title_del_duplicate_config">Xoá cấu hình trùng lặp</string>
<string name="title_del_invalid_config">Xoá cấu hình lỗi (Kiểm tra trước)</string>
<string name="title_del_invalid_config">Xoá cấu hình lỗi</string>
<string name="title_export_all">Xuất và sao chép tất cả cấu hình</string>
<string name="title_sub_setting">Các gói đăng ký</string>
<string name="sub_setting_remarks">Tên các gói đăng ký</string>
<string name="sub_setting_remarks">Tên gói đăng ký</string>
<string name="sub_setting_url">URL gói đăng ký</string>
<string name="sub_setting_enable">Sử dụng gói đăng ký này</string>
<string name="sub_auto_update">Bật tự động cập nhật</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_real_ping_all_server">Kiểm tra máy chủ</string>
<string name="title_real_ping_all_server">Test HTTP tất cả máy chủ</string>
<string name="title_user_asset_setting">Tệp Geo asset</string>
<string name="title_sort_by_test_results">Sắp xếp lại theo lần kiểm tra cuối cùng</string>
<string name="title_filter_config">Lọc cấu hình theo các gói đăng ký</string>
@@ -195,25 +205,25 @@
<string name="tasker_start_service">Bắt đầu v2rayNG</string>
<string name="tasker_setting_confirm">Xác nhận</string>
<string name="routing_settings_title">Cài đặt lộ trình</string>
<string name="routing_settings_tips">Được phân cách bằng dấu phẩy (,). Hãy nhớ nó để lưu lại!</string>
<string name="routing_settings_title">Cài đặt định tuyến</string>
<string name="routing_settings_tips">Phân cách bằng dấu phẩy (,). Có thể tải xuống rules mặc định để tham khảo ở menu ba chấm</string>
<string name="routing_settings_save">Lưu lại</string>
<string name="routing_settings_delete">Xoá</string>
<string name="routing_settings_scan_replace">Quét và thay thế</string>
<string name="routing_settings_scan_append">Quét và nối</string>
<string name="routing_settings_default_rules">Đặt luật cho lộ trình mặc định</string>
<string name="routing_settings_scan_replace">Quét QR và thay thế</string>
<string name="routing_settings_scan_append">Quét QR nối thêm</string>
<string name="routing_settings_default_rules">Tải xuống rules mặc định cho China</string>
<string name="connection_test_pending">Kiểm tra kết nối</string>
<string name="connection_test_testing">Đang kiểm tra kết nối mạng...</string>
<string name="connection_test_available">Kiểm tra kết nối mạng thành công! Ping hiện tại là %d</string>
<string name="connection_test_available">Test thành công: kết nối đến Google.com mất %d ms</string>
<string name="connection_test_error">Lỗi kết nối mạng, hãy thử đổi cấu hình hoặc kiểm tra lại! Mã lỗi: %s</string>
<string name="connection_test_fail">Không có kết nối mạng!</string>
<string name="connection_test_error_status_code">Mã lỗi: #%d</string>
<string name="connection_connected">Đã kết nối, hãy nhấn vào đây để kiểm tra kết nối mạng!</string>
<string name="connection_not_connected">Chưa kết nối, hãy chọn một cấu hình để kết nối!</string>
<string name="connection_connected">Đã kết nối, nhấn vào đây để kiểm tra kết nối mạng!</string>
<string name="connection_not_connected">Chưa kết nối</string>
<string name="import_subscription_success">Đăng ký đã nhập thành công</string>
<string name="import_subscription_failure">Nhập đăng ký không thành công</string>
<string name="import_subscription_success">Nhập gói đăng ký thành công!</string>
<string name="import_subscription_failure">Nhập gói đăng ký không thành công!</string>
<string-array name="share_method">
<item>Xuất ra mã QR (Chụp màn hình để lưu)</item>
@@ -227,16 +237,16 @@
</string-array>
<string-array name="routing_tag">
<item>Proxy URL hoặc IP</item>
<item>Direct URL hoặc IP</item>
<item>URL đã chặn hoặc IP</item>
<item>Proxy</item>
<item>Direct</item>
<item>Blocked</item>
</string-array>
<string-array name="routing_mode">
<item>Proxy toàn cầu</item>
<item>Bỏ qua địa chỉ LAN rồi Proxy</item>
<item>Bỏ qua địa chỉ đất liền rồi Proxy</item>
<item>Bỏ qua LAN và địa chỉ đất liền rồi Proxy</item>
<item>Bỏ qua địa chỉ nội địa rồi Proxy</item>
<item>Bỏ qua LAN và địa chỉ nội địa rồi Proxy</item>
<item>Kết nối trực tiếp toàn cầu</item>
</string-array>
@@ -29,6 +29,7 @@
<string name="menu_item_import_config_manually_ss">手动输入[Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">手动输入[Socks]</string>
<string name="menu_item_import_config_manually_trojan">手动输入[Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">手动输入[Wireguard]</string>
<string name="menu_item_import_config_custom">自定义配置</string>
<string name="menu_item_import_config_custom_clipboard">从剪贴板导入自定义配置</string>
<string name="menu_item_import_config_custom_local">从本地导入自定义配置</string>
@@ -58,6 +59,9 @@
<string name="server_lab_security4">用户名(可选)</string>
<string name="server_lab_encryption">加密方式(encryption)</string>
<string name="server_lab_flow">流控(flow)</string>
<string name="server_lab_reserved">Reserved(可选)</string>
<string name="server_lab_local_v4_address">本地 IPv4 地址(可选)</string>
<string name="server_lab_local_v6_address">本地 IPv6 地址(可选, 仅 IPv6 优先时使用)</string>
<string name="toast_success">成功</string>
<string name="toast_failure">失败</string>
<string name="toast_none_data">没有数据</string>
@@ -97,7 +101,8 @@
<string name="summary_pref_per_app_proxy">常规:勾选的App被代理,未勾选的直连;\n绕行模式:勾选的App直连,未勾选的被代理.\n不明白者在菜单中选择自动选中需代理应用</string>
<string name="title_pref_mux_enabled">启用 Mux 多路复用</string>
<string name="summary_pref_mux_enabled">减低延时,但可能会断流,建议不要启用。\nTCP 默认复用 8 个子链接,UDP 及 QUIC 流量处理方式下方可选。</string>
<string name="summary_pref_mux_enabled">减低延时,但可能会断流,建议不要启用。\nTCP,UDP 及 QUIC 流量处理方式下方可选。</string>
<string name="title_pref_mux_concurency">TCP 复用子链接数(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP 复用子链接数(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_quic">QUIC 流量处理方式</string>
<string-array name="mux_xudp_quic_entries">
@@ -29,6 +29,7 @@
<string name="menu_item_import_config_manually_ss">手動鍵入 [Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">手動鍵入 [Socks]</string>
<string name="menu_item_import_config_manually_trojan">手動鍵入 [Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">手動鍵入 [Wireguard]</string>
<string name="menu_item_import_config_custom">自訂組態</string>
<string name="menu_item_import_config_custom_clipboard">從剪貼簿匯入自訂組態</string>
<string name="menu_item_import_config_custom_local">從本地匯入自訂組態</string>
@@ -58,6 +59,9 @@
<string name="server_lab_security4">使用者名稱 (可選)</string>
<string name="server_lab_encryption">加密 (encryption)</string>
<string name="server_lab_flow">流程 (flow)</string>
<string name="server_lab_reserved">Reserved (可選)</string>
<string name="server_lab_local_v4_address">本機 IPv4 位址(可選)</string>
<string name="server_lab_local_v6_address">本機 IPv6 位址(可選, 僅偏好 IPv6 時使用)</string>
<string name="toast_success">成功</string>
<string name="toast_failure">失敗</string>
<string name="toast_none_data">無資料</string>
@@ -97,7 +101,8 @@
<string name="summary_pref_per_app_proxy">常規:勾選的 App 啟用 Proxy,未勾選的直接連線;\n繞行模式:勾選的 App 直接連線,未勾選的啟用 Proxy。\n可在選單中選擇自動選中需 Proxy 應用</string>
<string name="title_pref_mux_enabled">啟用 Mux 多路復用</string>
<string name="summary_pref_mux_enabled">減低延時 但可能會斷流\nTCP 默認復用 8 個子鏈接,UDP 及 QUIC 流量處理方式下方可選</string>
<string name="summary_pref_mux_enabled">減低延時 但可能會斷流\nTCP,UDP 及 QUIC 流量處理方式下方可選</string>
<string name="title_pref_mux_concurency">TCP 復用子鏈接數(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP 復用子鏈接數(可填 -1 至 1024)</string>
<string name="title_pref_mux_xudp_quic">QUIC 流量處理方式</string>
<string-array name="mux_xudp_quic_entries">
@@ -76,8 +76,11 @@
<string-array name="streamsecurity_alpn" translatable="false">
<item></item>
<item>h3</item>
<item>h2</item>
<item>http/1.1</item>
<item>h3,h2,http/1.1</item>
<item>h3,h2</item>
<item>h2,http/1.1</item>
</string-array>
@@ -15,4 +15,5 @@
<color name="colorAccent">#000000</color>
<color name="colorBg">#FFFFFF</color>
<color name="colorText">#000000</color>
<color name="colorMainTestBg">#F0F1F6</color>
</resources>
+7 -1
View File
@@ -30,6 +30,7 @@
<string name="menu_item_import_config_manually_ss">Type manually[Shadowsocks]</string>
<string name="menu_item_import_config_manually_socks">Type manually[Socks]</string>
<string name="menu_item_import_config_manually_trojan">Type manually[Trojan]</string>
<string name="menu_item_import_config_manually_wireguard">Type manually[Wireguard]</string>
<string name="menu_item_import_config_custom">Custom config</string>
<string name="menu_item_import_config_custom_clipboard">Import custom config from Clipboard</string>
<string name="menu_item_import_config_custom_local">Import custom config from locally</string>
@@ -64,6 +65,10 @@
<string name="server_lab_public_key" translatable="false">PublicKey</string>
<string name="server_lab_short_id" translatable="false">ShortId</string>
<string name="server_lab_spider_x" translatable="false">SpiderX</string>
<string name="server_lab_secret_key" translatable="false">SecretKey</string>
<string name="server_lab_reserved">Reserved(Optional)</string>
<string name="server_lab_local_v4_address">local address IPv4(Optional)</string>
<string name="server_lab_local_v6_address">local address IPv6(Optional, only used when prefer IPv6)</string>
<string name="toast_success">Success</string>
<string name="toast_failure">Failure</string>
<string name="toast_none_data">There is nothing</string>
@@ -103,7 +108,8 @@
<string name="summary_pref_per_app_proxy">General: Checked App is proxy, unchecked direct connection; \nbypass mode: checked app directly connected, unchecked proxy. \nThe option to automatically select the proxy application in the menu</string>
<string name="title_pref_mux_enabled">Enable Mux</string>
<string name="summary_pref_mux_enabled">Faster, but it may cause unstable connectivity\nTCP traffic mux with default 8 connections,customize how to handle UDP and QUIC below</string>
<string name="summary_pref_mux_enabled">Faster, but it may cause unstable connectivity\ncustomize how to handle TCP, UDP and QUIC below</string>
<string name="title_pref_mux_concurency">TCP connections(range -1 to 1024)</string>
<string name="title_pref_mux_xudp_concurency">XUDP connections(range -1 to 1024)</string>
<string name="title_pref_mux_xudp_quic">Handling of QUIC in mux tunnel</string>
<string-array name="mux_xudp_quic_entries">
@@ -12,6 +12,12 @@
android:summary="@string/summary_pref_mux_enabled"
android:title="@string/title_pref_mux_enabled" />
<EditTextPreference
android:key="pref_mux_concurency"
android:summary="8"
android:inputType="number"
android:title="@string/title_pref_mux_concurency" />
<EditTextPreference
android:key="pref_mux_xudp_concurency"
android:summary="8"