From 51adca8568745ce94431cb200c7b9ba46a70f356 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sat, 17 Aug 2024 19:40:04 +0800 Subject: [PATCH] Format code --- V2rayNG/app/build.gradle.kts | 9 +- V2rayNG/app/src/main/AndroidManifest.xml | 92 ++- .../ang/helper/ItemTouchHelperAdapter.java | 4 +- .../helper/SimpleItemTouchHelperCallback.java | 3 +- .../kotlin/com/v2ray/ang/AngApplication.kt | 12 +- .../main/kotlin/com/v2ray/ang/AppConfig.kt | 1 + .../main/kotlin/com/v2ray/ang/dto/AppInfo.kt | 12 +- .../kotlin/com/v2ray/ang/dto/EConfigType.kt | 2 +- .../kotlin/com/v2ray/ang/dto/ERoutingMode.kt | 2 +- .../kotlin/com/v2ray/ang/dto/ServerConfig.kt | 46 +- .../kotlin/com/v2ray/ang/dto/ServersCache.kt | 6 +- .../kotlin/com/v2ray/ang/dto/V2rayConfig.kt | 664 ++++++++++-------- .../kotlin/com/v2ray/ang/dto/VmessQRCode.kt | 32 +- .../kotlin/com/v2ray/ang/extension/_Ext.kt | 2 - .../com/v2ray/ang/receiver/WidgetProvider.kt | 16 +- .../com/v2ray/ang/service/QSTileService.kt | 5 + .../v2ray/ang/service/SubscriptionUpdater.kt | 1 - .../ang/service/V2RayProxyOnlyService.kt | 2 +- .../v2ray/ang/service/V2RayServiceManager.kt | 125 ++-- .../com/v2ray/ang/service/V2RayTestService.kt | 7 +- .../com/v2ray/ang/service/V2RayVpnService.kt | 55 +- .../kotlin/com/v2ray/ang/ui/AboutActivity.kt | 2 +- .../kotlin/com/v2ray/ang/ui/BaseActivity.kt | 3 +- .../com/v2ray/ang/ui/FragmentAdapter.kt | 2 +- .../kotlin/com/v2ray/ang/ui/LogcatActivity.kt | 2 + .../kotlin/com/v2ray/ang/ui/MainActivity.kt | 1 - .../com/v2ray/ang/ui/MainRecyclerAdapter.kt | 5 +- .../com/v2ray/ang/ui/PerAppProxyActivity.kt | 71 +- .../com/v2ray/ang/ui/PerAppProxyAdapter.kt | 13 +- .../v2ray/ang/ui/RoutingSettingsActivity.kt | 2 +- .../v2ray/ang/ui/RoutingSettingsFragment.kt | 44 +- .../com/v2ray/ang/ui/ScScannerActivity.kt | 14 +- .../com/v2ray/ang/ui/ScSwitchActivity.kt | 4 +- .../com/v2ray/ang/ui/ScannerActivity.kt | 13 +- .../kotlin/com/v2ray/ang/ui/ServerActivity.kt | 20 +- .../ang/ui/ServerCustomConfigActivity.kt | 18 +- .../com/v2ray/ang/ui/SettingsActivity.kt | 8 +- .../com/v2ray/ang/ui/SubEditActivity.kt | 24 +- .../kotlin/com/v2ray/ang/ui/TaskerActivity.kt | 22 +- .../com/v2ray/ang/ui/UserAssetActivity.kt | 57 +- .../com/v2ray/ang/ui/UserAssetUrlActivity.kt | 4 +- .../com/v2ray/ang/util/AngConfigManager.kt | 2 +- .../main/kotlin/com/v2ray/ang/util/Utils.kt | 25 +- .../com/v2ray/ang/util/fmt/ShadowsocksFmt.kt | 4 +- .../com/v2ray/ang/util/fmt/TrojanFmt.kt | 8 +- .../kotlin/com/v2ray/ang/util/fmt/VlessFmt.kt | 6 +- .../kotlin/com/v2ray/ang/util/fmt/VmessFmt.kt | 4 +- .../com/v2ray/ang/util/fmt/WireguardFmt.kt | 2 +- .../res/drawable-night/ic_action_done.xml | 12 +- .../main/res/drawable-night/ic_add_24dp.xml | 10 +- .../src/main/res/drawable-night/ic_copy.xml | 10 +- .../res/drawable-night/ic_delete_24dp.xml | 10 +- .../drawable-night/ic_description_24dp.xml | 10 +- .../main/res/drawable-night/ic_edit_24dp.xml | 10 +- .../main/res/drawable-night/ic_file_24dp.xml | 6 +- .../res/drawable-night/ic_logcat_24dp.xml | 6 +- .../ic_outline_filter_alt_24.xml | 13 +- .../res/drawable-night/ic_promotion_24dp.xml | 4 +- .../main/res/drawable-night/ic_save_24dp.xml | 10 +- .../main/res/drawable-night/ic_share_24dp.xml | 10 +- .../res/drawable-night/ic_telegram_24dp.xml | 6 +- .../src/main/res/drawable/ic_action_done.xml | 12 +- .../app/src/main/res/drawable/ic_add_24dp.xml | 10 +- V2rayNG/app/src/main/res/drawable/ic_copy.xml | 10 +- .../src/main/res/drawable/ic_delete_24dp.xml | 10 +- .../main/res/drawable/ic_description_24dp.xml | 10 +- .../src/main/res/drawable/ic_edit_24dp.xml | 10 +- .../src/main/res/drawable/ic_file_24dp.xml | 6 +- .../src/main/res/drawable/ic_logcat_24dp.xml | 18 +- .../res/drawable/ic_outline_filter_alt_24.xml | 13 +- .../main/res/drawable/ic_promotion_24dp.xml | 12 +- .../src/main/res/drawable/ic_save_24dp.xml | 10 +- .../src/main/res/drawable/ic_share_24dp.xml | 10 +- .../main/res/drawable/ic_source_code_24dp.xml | 11 +- .../app/src/main/res/layout/activity_main.xml | 6 +- .../app/src/main/res/layout/activity_none.xml | 3 +- .../res/layout/activity_routing_settings.xml | 1 - .../layout/activity_server_custom_config.xml | 10 +- .../layout/activity_server_shadowsocks.xml | 4 +- .../res/layout/activity_server_trojan.xml | 2 +- .../main/res/layout/activity_server_vless.xml | 12 +- .../main/res/layout/activity_server_vmess.xml | 2 +- .../res/layout/activity_server_wireguard.xml | 3 + .../main/res/layout/activity_sub_setting.xml | 3 +- .../res/layout/activity_user_asset_url.xml | 128 ++-- .../main/res/layout/dialog_config_filter.xml | 2 +- .../src/main/res/layout/layout_progress.xml | 10 +- .../app/src/main/res/layout/nav_header.xml | 1 - .../res/layout/preference_with_help_link.xml | 12 +- .../app/src/main/res/layout/tls_layout.xml | 18 +- V2rayNG/app/src/main/res/menu/menu_asset.xml | 2 +- .../src/main/res/menu/menu_bypass_list.xml | 2 +- V2rayNG/app/src/main/res/menu/menu_drawer.xml | 9 +- V2rayNG/app/src/main/res/menu/menu_main.xml | 2 +- .../main/res/mipmap-anydpi-v26/ic_banner.xml | 6 +- .../res/mipmap-anydpi-v26/ic_launcher.xml | 4 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 4 +- .../app/src/main/res/values-ar/strings.xml | 4 +- V2rayNG/app/src/main/res/values/arrays.xml | 2 +- V2rayNG/app/src/main/res/values/attrs.xml | 1 + V2rayNG/app/src/main/res/xml/cache_paths.xml | 4 +- .../java/com/v2ray/ang/ExampleUnitTest.java | 4 +- .../kotlin/com/v2ray/ang/ExampleUnitTest.kt | 66 +- 103 files changed, 1151 insertions(+), 913 deletions(-) diff --git a/V2rayNG/app/build.gradle.kts b/V2rayNG/app/build.gradle.kts index 1fb6789f..ffb2c46c 100644 --- a/V2rayNG/app/build.gradle.kts +++ b/V2rayNG/app/build.gradle.kts @@ -68,12 +68,9 @@ android { "universal" output.outputFileName = "v2rayNG_${variant.versionName}_${abi}.apk" - if(versionCodes.containsKey(abi)) - { + if (versionCodes.containsKey(abi)) { output.versionCodeOverride = (1000000 * versionCodes[abi]!!).plus(variant.versionCode) - } - else - { + } else { return@forEach } } @@ -92,7 +89,7 @@ android { } dependencies { - implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar","*.jar")))) + implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar", "*.jar")))) testImplementation(libs.junit) implementation(libs.flexbox) diff --git a/V2rayNG/app/src/main/AndroidManifest.xml b/V2rayNG/app/src/main/AndroidManifest.xml index 42cfc261..d5301680 100644 --- a/V2rayNG/app/src/main/AndroidManifest.xml +++ b/V2rayNG/app/src/main/AndroidManifest.xml @@ -8,18 +8,29 @@ android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" - android:xlargeScreens="true"/> + android:xlargeScreens="true" /> - + - - - - + + + + - + @@ -31,7 +42,7 @@ android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" android:minSdkVersion="34" /> - + @@ -53,12 +64,14 @@ android:theme="@style/AppThemeDayNight.NoActionBar"> + - + + @@ -119,12 +132,14 @@ - - - - - - + + + + + + + + - + - - + android:process=":RunSoLibV2RayDaemon"> + android:exported="true" + android:name=".receiver.WidgetProvider" + android:process=":RunSoLibV2RayDaemon"> + android:name="android.appwidget.provider" + android:resource="@xml/app_widget_provider" /> @@ -180,13 +196,13 @@ + android:exported="true" + 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"> @@ -208,7 +224,7 @@ + android:process=":RunSoLibV2RayDaemon"> @@ -234,7 +250,7 @@ android:grantUriPermissions="true"> + android:resource="@xml/cache_paths" /> diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/helper/ItemTouchHelperAdapter.java b/V2rayNG/app/src/main/java/com/v2ray/ang/helper/ItemTouchHelperAdapter.java index 2de0c74a..566feffc 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/helper/ItemTouchHelperAdapter.java +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/helper/ItemTouchHelperAdapter.java @@ -16,8 +16,8 @@ package com.v2ray.ang.helper; -import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; /** * Interface to listen for a move or dismissal event from a {@link ItemTouchHelper.Callback}. @@ -36,7 +36,6 @@ public interface ItemTouchHelperAdapter { * @param fromPosition The start position of the moved item. * @param toPosition Then resolved position of the moved item. * @return True if the item was moved to the new adapter position. - * * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder) * @see RecyclerView.ViewHolder#getAdapterPosition() */ @@ -52,7 +51,6 @@ public interface ItemTouchHelperAdapter { * adjusting the underlying data to reflect this removal. * * @param position The position of the item dismissed. - * * @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder) * @see RecyclerView.ViewHolder#getAdapterPosition() */ diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java b/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java index 97fceab7..e3686921 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/helper/SimpleItemTouchHelperCallback.java @@ -17,9 +17,10 @@ package com.v2ray.ang.helper; import android.graphics.Canvas; + import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; import org.jetbrains.annotations.NotNull; diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt index 0a900e0d..a07e7f99 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AngApplication.kt @@ -7,16 +7,13 @@ import androidx.work.WorkManager import com.tencent.mmkv.MMKV import com.v2ray.ang.util.Utils -class AngApplication : MultiDexApplication() -{ - companion object - { +class AngApplication : MultiDexApplication() { + companion object { //const val PREF_LAST_VERSION = "pref_last_version" lateinit var application: AngApplication } - override fun attachBaseContext(base: Context?) - { + override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) application = this } @@ -25,8 +22,7 @@ class AngApplication : MultiDexApplication() .setDefaultProcessName("${BuildConfig.APPLICATION_ID}:bg") .build() - override fun onCreate() - { + override fun onCreate() { super.onCreate() // LeakCanary.install(this) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt index 786b1db7..b564a41b 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/AppConfig.kt @@ -140,6 +140,7 @@ object AppConfig { const val RAY_NG_CHANNEL_NAME = "V2rayNG Background Service" const val SUBSCRIPTION_UPDATE_CHANNEL = "subscription_update_channel" const val SUBSCRIPTION_UPDATE_CHANNEL_NAME = "Subscription Update Service" + /** Protocols Scheme **/ const val VMESS = "vmess://" const val CUSTOM = "" diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/AppInfo.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/AppInfo.kt index f99655a8..219e35e9 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/AppInfo.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/AppInfo.kt @@ -2,8 +2,10 @@ package com.v2ray.ang.dto import android.graphics.drawable.Drawable -data class AppInfo(val appName: String, - val packageName: String, - val appIcon: Drawable, - val isSystemApp: Boolean, - var isSelected: Int) \ No newline at end of file +data class AppInfo( + val appName: String, + val packageName: String, + val appIcon: Drawable, + val isSystemApp: Boolean, + var isSelected: Int +) \ No newline at end of file diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt index 3db803de..0cde22f0 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/EConfigType.kt @@ -6,7 +6,7 @@ import com.v2ray.ang.AppConfig enum class EConfigType(val value: Int, val protocolScheme: String) { VMESS(1, AppConfig.VMESS), CUSTOM(2, AppConfig.CUSTOM), - SHADOWSOCKS(3,AppConfig.SHADOWSOCKS), + SHADOWSOCKS(3, AppConfig.SHADOWSOCKS), SOCKS(4, AppConfig.SOCKS), VLESS(5, AppConfig.VLESS), TROJAN(6, AppConfig.TROJAN), diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ERoutingMode.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ERoutingMode.kt index 96d77397..8d882ed6 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ERoutingMode.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ERoutingMode.kt @@ -1,6 +1,6 @@ package com.v2ray.ang.dto -enum class ERoutingMode(val value: String ) { +enum class ERoutingMode(val value: String) { GLOBAL_PROXY("0"), BYPASS_LAN("1"), BYPASS_MAINLAND("2"), diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt index 1999c977..f2a91e2e 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServerConfig.kt @@ -1,50 +1,64 @@ package com.v2ray.ang.dto -import com.v2ray.ang.AppConfig.TAG_PROXY import com.v2ray.ang.AppConfig.TAG_BLOCKED import com.v2ray.ang.AppConfig.TAG_DIRECT +import com.v2ray.ang.AppConfig.TAG_PROXY import com.v2ray.ang.util.Utils data class ServerConfig( - val configVersion: Int = 3, - val configType: EConfigType, - var subscriptionId: String = "", - val addedTime: Long = System.currentTimeMillis(), - var remarks: String = "", - val outboundBean: V2rayConfig.OutboundBean? = null, - var fullConfig: V2rayConfig? = null + val configVersion: Int = 3, + val configType: EConfigType, + var subscriptionId: String = "", + val addedTime: Long = System.currentTimeMillis(), + var remarks: String = "", + val outboundBean: V2rayConfig.OutboundBean? = null, + var fullConfig: V2rayConfig? = null ) { companion object { fun create(configType: EConfigType): ServerConfig { - when(configType) { + 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())) + 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())) + servers = listOf(V2rayConfig.OutboundBean.OutSettingsBean.ServersBean()) + ), + streamSettings = V2rayConfig.OutboundBean.StreamSettingsBean() + ) + ) + EConfigType.WIREGUARD -> return ServerConfig( configType = configType, - outboundBean = V2rayConfig.OutboundBean( + outboundBean = V2rayConfig.OutboundBean( protocol = configType.name.lowercase(), settings = V2rayConfig.OutboundBean.OutSettingsBean( secretKey = "", peers = listOf(V2rayConfig.OutboundBean.OutSettingsBean.WireGuardBean()) - ))) + ) + ) + ) } } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServersCache.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServersCache.kt index 82cea587..7ea3e6a3 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServersCache.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/ServersCache.kt @@ -1,4 +1,6 @@ package com.v2ray.ang.dto -data class ServersCache(val guid: String, - val profile: ProfileItem) \ No newline at end of file +data class ServersCache( + val guid: String, + val profile: ProfileItem +) \ No newline at end of file diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt index 4224debe..13cbab0e 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt @@ -10,21 +10,22 @@ import com.google.gson.reflect.TypeToken import java.lang.reflect.Type data class V2rayConfig( - var remarks: String? = null, - var stats: Any? = null, - val log: LogBean, - var policy: PolicyBean?, - val inbounds: ArrayList, - var outbounds: ArrayList, - var dns: DnsBean, - val routing: RoutingBean, - val api: Any? = null, - val transport: Any? = null, - val reverse: Any? = null, - var fakedns: Any? = null, - val browserForwarder: Any? = null, - var observatory: Any? = null, - var burstObservatory: Any? = null) { + var remarks: String? = null, + var stats: Any? = null, + val log: LogBean, + var policy: PolicyBean?, + val inbounds: ArrayList, + var outbounds: ArrayList, + var dns: DnsBean, + val routing: RoutingBean, + val api: Any? = null, + val transport: Any? = null, + val reverse: Any? = null, + var fakedns: Any? = null, + val browserForwarder: Any? = null, + var observatory: Any? = null, + var burstObservatory: Any? = null +) { companion object { const val DEFAULT_PORT = 443 const val DEFAULT_SECURITY = "auto" @@ -36,210 +37,261 @@ data class V2rayConfig( const val HTTP = "http" } - data class LogBean(val access: String, - val error: String, - var loglevel: String?, - val dnsLog: Boolean? = null) + data class LogBean( + val access: String, + val error: String, + var loglevel: String?, + val dnsLog: Boolean? = null + ) data class InboundBean( - var tag: String, - var port: Int, - var protocol: String, - var listen: String? = null, - val settings: Any? = null, - val sniffing: SniffingBean?, - val streamSettings: Any? = null, - val allocate: Any? = null) { + var tag: String, + var port: Int, + var protocol: String, + var listen: String? = null, + val settings: Any? = null, + val sniffing: SniffingBean?, + val streamSettings: Any? = null, + val allocate: Any? = null + ) { - data class InSettingsBean(val auth: String? = null, - val udp: Boolean? = null, - val userLevel: Int? = null, - val address: String? = null, - val port: Int? = null, - val network: String? = null) + data class InSettingsBean( + val auth: String? = null, + val udp: Boolean? = null, + val userLevel: Int? = null, + val address: String? = null, + val port: Int? = null, + val network: String? = null + ) - data class SniffingBean(var enabled: Boolean, - val destOverride: ArrayList, - val metadataOnly: Boolean? = null, - var routeOnly: Boolean? = null) + data class SniffingBean( + var enabled: Boolean, + val destOverride: ArrayList, + val metadataOnly: Boolean? = null, + var routeOnly: Boolean? = null + ) } - data class OutboundBean(var tag: String = "proxy", - var protocol: String, - var settings: OutSettingsBean? = null, - var streamSettings: StreamSettingsBean? = null, - val proxySettings: Any? = null, - val sendThrough: String? = null, - var mux: MuxBean? = MuxBean(false)) { + data class OutboundBean( + var tag: String = "proxy", + var protocol: String, + var settings: OutSettingsBean? = null, + var streamSettings: StreamSettingsBean? = null, + val proxySettings: Any? = null, + val sendThrough: String? = null, + var mux: MuxBean? = MuxBean(false) + ) { - data class OutSettingsBean(var vnext: List? = null, - var fragment: FragmentBean? = null, - var servers: List? = null, - /*Blackhole*/ - var response: Response? = null, - /*DNS*/ - val network: String? = null, - var address: Any? = null, - val port: Int? = null, - /*Freedom*/ - var domainStrategy: String? = null, - val redirect: String? = null, - val userLevel: Int? = null, - /*Loopback*/ - val inboundTag: String? = null, - /*Wireguard*/ - var secretKey: String? = null, - val peers: List? = null, - var reserved: List? = null, - var mtu :Int? = null + data class OutSettingsBean( + var vnext: List? = null, + var fragment: FragmentBean? = null, + var servers: List? = null, + /*Blackhole*/ + var response: Response? = null, + /*DNS*/ + val network: String? = null, + var address: Any? = null, + val port: Int? = null, + /*Freedom*/ + var domainStrategy: String? = null, + val redirect: String? = null, + val userLevel: Int? = null, + /*Loopback*/ + val inboundTag: String? = null, + /*Wireguard*/ + var secretKey: String? = null, + val peers: List? = null, + var reserved: List? = null, + var mtu: Int? = null ) { - data class VnextBean(var address: String = "", - var port: Int = DEFAULT_PORT, - var users: List) { + data class VnextBean( + var address: String = "", + var port: Int = DEFAULT_PORT, + var users: List + ) { - data class UsersBean(var id: String = "", - var alterId: Int? = null, - var security: String = DEFAULT_SECURITY, - var level: Int = DEFAULT_LEVEL, - var encryption: String = "", - var flow: String = "") + data class UsersBean( + var id: String = "", + var alterId: Int? = null, + var security: String = DEFAULT_SECURITY, + var level: Int = DEFAULT_LEVEL, + var encryption: String = "", + var flow: String = "" + ) } - data class FragmentBean(var packets: String? = null, - var length: String? = null, - var interval: String? = null) + data class FragmentBean( + var packets: String? = null, + var length: String? = null, + var interval: String? = null + ) - data class ServersBean(var address: String = "", - var method: String = "chacha20-poly1305", - var ota: Boolean = false, - var password: String = "", - var port: Int = DEFAULT_PORT, - var level: Int = DEFAULT_LEVEL, - val email: String? = null, - var flow: String? = null, - val ivCheck: Boolean? = null, - var users: List? = null) { + data class ServersBean( + var address: String = "", + var method: String = "chacha20-poly1305", + var ota: Boolean = false, + var password: String = "", + var port: Int = DEFAULT_PORT, + var level: Int = DEFAULT_LEVEL, + val email: String? = null, + var flow: String? = null, + val ivCheck: Boolean? = null, + var users: List? = null + ) { - data class SocksUsersBean(var user: String = "", - var pass: String = "", - var level: Int = DEFAULT_LEVEL) + data class SocksUsersBean( + var user: String = "", + var pass: String = "", + var level: Int = DEFAULT_LEVEL + ) } data class Response(var type: String) - data class WireGuardBean(var publicKey: String = "", - var endpoint: String = "") + data class WireGuardBean( + var publicKey: String = "", + var endpoint: String = "" + ) } - data class StreamSettingsBean(var network: String = DEFAULT_NETWORK, - var security: String = "", - var tcpSettings: TcpSettingsBean? = null, - var kcpSettings: KcpSettingsBean? = null, - var wsSettings: WsSettingsBean? = null, - var httpupgradeSettings: HttpupgradeSettingsBean? = null, - var splithttpSettings: SplithttpSettingsBean? = null, - var httpSettings: HttpSettingsBean? = null, - var tlsSettings: TlsSettingsBean? = null, - var quicSettings: QuicSettingBean? = null, - var realitySettings: TlsSettingsBean? = null, - var grpcSettings: GrpcSettingsBean? = null, - val dsSettings: Any? = null, - var sockopt: SockoptBean? = null + data class StreamSettingsBean( + var network: String = DEFAULT_NETWORK, + var security: String = "", + var tcpSettings: TcpSettingsBean? = null, + var kcpSettings: KcpSettingsBean? = null, + var wsSettings: WsSettingsBean? = null, + var httpupgradeSettings: HttpupgradeSettingsBean? = null, + var splithttpSettings: SplithttpSettingsBean? = null, + var httpSettings: HttpSettingsBean? = null, + var tlsSettings: TlsSettingsBean? = null, + var quicSettings: QuicSettingBean? = null, + var realitySettings: TlsSettingsBean? = null, + var grpcSettings: GrpcSettingsBean? = null, + val dsSettings: Any? = null, + var sockopt: SockoptBean? = null ) { - data class TcpSettingsBean(var header: HeaderBean = HeaderBean(), - val acceptProxyProtocol: Boolean? = null) { - data class HeaderBean(var type: String = "none", - var request: RequestBean? = null, - var response: Any? = null) { - data class RequestBean(var path: List = ArrayList(), - var headers: HeadersBean = HeadersBean(), - val version: String? = null, - val method: String? = null) { - data class HeadersBean(var Host: List? = ArrayList(), - @SerializedName("User-Agent") - val userAgent: List? = null, - @SerializedName("Accept-Encoding") - val acceptEncoding: List? = null, - val Connection: List? = null, - val Pragma: String? = null) + data class TcpSettingsBean( + var header: HeaderBean = HeaderBean(), + val acceptProxyProtocol: Boolean? = null + ) { + data class HeaderBean( + var type: String = "none", + var request: RequestBean? = null, + var response: Any? = null + ) { + data class RequestBean( + var path: List = ArrayList(), + var headers: HeadersBean = HeadersBean(), + val version: String? = null, + val method: String? = null + ) { + data class HeadersBean( + var Host: List? = ArrayList(), + @SerializedName("User-Agent") + val userAgent: List? = null, + @SerializedName("Accept-Encoding") + val acceptEncoding: List? = null, + val Connection: List? = null, + val Pragma: String? = null + ) } } } - data class KcpSettingsBean(var mtu: Int = 1350, - var tti: Int = 50, - var uplinkCapacity: Int = 12, - var downlinkCapacity: Int = 100, - var congestion: Boolean = false, - var readBufferSize: Int = 1, - var writeBufferSize: Int = 1, - var header: HeaderBean = HeaderBean(), - var seed: String? = null) { + data class KcpSettingsBean( + var mtu: Int = 1350, + var tti: Int = 50, + var uplinkCapacity: Int = 12, + var downlinkCapacity: Int = 100, + var congestion: Boolean = false, + var readBufferSize: Int = 1, + var writeBufferSize: Int = 1, + var header: HeaderBean = HeaderBean(), + var seed: String? = null + ) { data class HeaderBean(var type: String = "none") } - data class WsSettingsBean(var path: String = "", - var headers: HeadersBean = HeadersBean(), - val maxEarlyData: Int? = null, - val useBrowserForwarding: Boolean? = null, - val acceptProxyProtocol: Boolean? = null) { + data class WsSettingsBean( + var path: String = "", + var headers: HeadersBean = HeadersBean(), + val maxEarlyData: Int? = null, + val useBrowserForwarding: Boolean? = null, + val acceptProxyProtocol: Boolean? = null + ) { data class HeadersBean(var Host: String = "") } - data class HttpupgradeSettingsBean(var path: String = "", - var host: String = "", - val acceptProxyProtocol: Boolean? = null) + data class HttpupgradeSettingsBean( + var path: String = "", + var host: String = "", + val acceptProxyProtocol: Boolean? = null + ) - data class SplithttpSettingsBean(var path: String = "", - var host: String = "", - val maxUploadSize: Int? = null, - val maxConcurrentUploads: Int? = null) - data class HttpSettingsBean(var host: List = ArrayList(), - var path: String = "") + data class SplithttpSettingsBean( + var path: String = "", + var host: String = "", + val maxUploadSize: Int? = null, + val maxConcurrentUploads: Int? = null + ) - data class SockoptBean(var TcpNoDelay: Boolean? = null, - var tcpKeepAliveIdle: Int? = null, - var tcpFastOpen: Boolean? = null, - var tproxy: String? = null, - var mark: Int? = null, - var dialerProxy: String? = null) + data class HttpSettingsBean( + var host: List = ArrayList(), + var path: String = "" + ) - data class TlsSettingsBean(var allowInsecure: Boolean = false, - var serverName: String = "", - val alpn: List? = null, - val minVersion: String? = null, - val maxVersion: String? = null, - val preferServerCipherSuites: Boolean? = null, - val cipherSuites: String? = null, - val fingerprint: String? = null, - val certificates: List? = null, - val disableSystemRoot: Boolean? = null, - val enableSessionResumption: Boolean? = null, - // REALITY settings - val show: Boolean = false, - var publicKey: String? = null, - var shortId: String? = null, - var spiderX: String? = null) + data class SockoptBean( + var TcpNoDelay: Boolean? = null, + var tcpKeepAliveIdle: Int? = null, + var tcpFastOpen: Boolean? = null, + var tproxy: String? = null, + var mark: Int? = null, + var dialerProxy: String? = null + ) - data class QuicSettingBean(var security: String = "none", - var key: String = "", - var header: HeaderBean = HeaderBean()) { + data class TlsSettingsBean( + var allowInsecure: Boolean = false, + var serverName: String = "", + val alpn: List? = null, + val minVersion: String? = null, + val maxVersion: String? = null, + val preferServerCipherSuites: Boolean? = null, + val cipherSuites: String? = null, + val fingerprint: String? = null, + val certificates: List? = null, + val disableSystemRoot: Boolean? = null, + val enableSessionResumption: Boolean? = null, + // REALITY settings + val show: Boolean = false, + var publicKey: String? = null, + var shortId: String? = null, + var spiderX: String? = null + ) + + data class QuicSettingBean( + var security: String = "none", + var key: String = "", + var header: HeaderBean = HeaderBean() + ) { data class HeaderBean(var type: String = "none") } - data class GrpcSettingsBean(var serviceName: String = "", - var authority: String? = null, - var multiMode: Boolean? = null, - var idle_timeout: Int? = null, - var health_check_timeout: Int? = null - ) + data class GrpcSettingsBean( + var serviceName: String = "", + var authority: String? = null, + var multiMode: Boolean? = null, + var idle_timeout: Int? = null, + var health_check_timeout: Int? = null + ) - fun populateTransportSettings(transport: String, headerType: String?, host: String?, path: String?, seed: String?, - quicSecurity: String?, key: String?, mode: String?, serviceName: String?, - authority: String?): String { + fun populateTransportSettings( + transport: String, headerType: String?, host: String?, path: String?, seed: String?, + quicSecurity: String?, key: String?, mode: String?, serviceName: String?, + authority: String? + ): String { var sni = "" network = transport when (network) { @@ -249,8 +301,8 @@ data class V2rayConfig( tcpSetting.header.type = HTTP if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(path)) { val requestObj = TcpSettingsBean.HeaderBean.RequestBean() - requestObj.headers.Host = (host .orEmpty()).split(",").map { it.trim() }.filter { it.isNotEmpty() } - requestObj.path = (path .orEmpty()).split(",").map { it.trim() }.filter { it.isNotEmpty() } + requestObj.headers.Host = (host.orEmpty()).split(",").map { it.trim() }.filter { it.isNotEmpty() } + requestObj.path = (path.orEmpty()).split(",").map { it.trim() }.filter { it.isNotEmpty() } tcpSetting.header.request = requestObj sni = requestObj.headers.Host?.getOrNull(0) ?: sni } @@ -260,6 +312,7 @@ data class V2rayConfig( } tcpSettings = tcpSetting } + "kcp" -> { val kcpsetting = KcpSettingsBean() kcpsetting.header.type = headerType ?: "none" @@ -270,6 +323,7 @@ data class V2rayConfig( } kcpSettings = kcpsetting } + "ws" -> { val wssetting = WsSettingsBean() wssetting.headers.Host = host.orEmpty() @@ -277,6 +331,7 @@ data class V2rayConfig( wssetting.path = path ?: "/" wsSettings = wssetting } + "httpupgrade" -> { val httpupgradeSetting = HttpupgradeSettingsBean() httpupgradeSetting.host = host.orEmpty() @@ -284,6 +339,7 @@ data class V2rayConfig( httpupgradeSetting.path = path ?: "/" httpupgradeSettings = httpupgradeSetting } + "splithttp" -> { val splithttpSetting = SplithttpSettingsBean() splithttpSetting.host = host.orEmpty() @@ -291,14 +347,16 @@ data class V2rayConfig( splithttpSetting.path = path ?: "/" splithttpSettings = splithttpSetting } + "h2", "http" -> { network = "h2" val h2Setting = HttpSettingsBean() - h2Setting.host = (host .orEmpty()).split(",").map { it.trim() }.filter { it.isNotEmpty() } + h2Setting.host = (host.orEmpty()).split(",").map { it.trim() }.filter { it.isNotEmpty() } sni = h2Setting.host.getOrNull(0) ?: sni h2Setting.path = path ?: "/" httpSettings = h2Setting } + "quic" -> { val quicsetting = QuicSettingBean() quicsetting.security = quicSecurity ?: "none" @@ -306,6 +364,7 @@ data class V2rayConfig( quicsetting.header.type = headerType ?: "none" quicSettings = quicsetting } + "grpc" -> { val grpcSetting = GrpcSettingsBean() grpcSetting.multiMode = mode == "multi" @@ -320,17 +379,19 @@ data class V2rayConfig( return sni } - fun populateTlsSettings(streamSecurity: String, allowInsecure: Boolean, sni: String, fingerprint: String?, alpns: String?, - publicKey: String?, shortId: String?, spiderX: String?) { + fun populateTlsSettings( + streamSecurity: String, allowInsecure: Boolean, sni: String, fingerprint: String?, alpns: String?, + publicKey: String?, shortId: String?, spiderX: String? + ) { security = streamSecurity val tlsSetting = TlsSettingsBean( - allowInsecure = allowInsecure, - serverName = sni, - fingerprint = fingerprint, - alpn = if (alpns.isNullOrEmpty()) null else alpns.split(",").map { it.trim() }.filter { it.isNotEmpty() }, - publicKey = publicKey, - shortId = shortId, - spiderX = spiderX + allowInsecure = allowInsecure, + serverName = sni, + fingerprint = fingerprint, + alpn = if (alpns.isNullOrEmpty()) null else alpns.split(",").map { it.trim() }.filter { it.isNotEmpty() }, + publicKey = publicKey, + shortId = shortId, + spiderX = spiderX ) if (security == TLS) { tlsSettings = tlsSetting @@ -342,18 +403,22 @@ data class V2rayConfig( } } - data class MuxBean(var enabled: Boolean, - var concurrency: Int = 8, - var xudpConcurrency: Int = 8, - var xudpProxyUDP443: String = "",) + data class MuxBean( + var enabled: Boolean, + var concurrency: Int = 8, + var xudpConcurrency: Int = 8, + var xudpProxyUDP443: String = "", + ) fun getServerAddress(): String? { if (protocol.equals(EConfigType.VMESS.name, true) - || protocol.equals(EConfigType.VLESS.name, true)) { + || protocol.equals(EConfigType.VLESS.name, true) + ) { return settings?.vnext?.get(0)?.address } else if (protocol.equals(EConfigType.SHADOWSOCKS.name, true) - || protocol.equals(EConfigType.SOCKS.name, true) - || protocol.equals(EConfigType.TROJAN.name, true)) { + || protocol.equals(EConfigType.SOCKS.name, true) + || protocol.equals(EConfigType.TROJAN.name, true) + ) { return settings?.servers?.get(0)?.address } else if (protocol.equals(EConfigType.WIREGUARD.name, true)) { return settings?.peers?.get(0)?.endpoint?.substringBeforeLast(":") @@ -363,11 +428,13 @@ data class V2rayConfig( fun getServerPort(): Int? { if (protocol.equals(EConfigType.VMESS.name, true) - || protocol.equals(EConfigType.VLESS.name, true)) { + || protocol.equals(EConfigType.VLESS.name, true) + ) { return settings?.vnext?.get(0)?.port } else if (protocol.equals(EConfigType.SHADOWSOCKS.name, true) - || protocol.equals(EConfigType.SOCKS.name, true) - || protocol.equals(EConfigType.TROJAN.name, true)) { + || protocol.equals(EConfigType.SOCKS.name, true) + || protocol.equals(EConfigType.TROJAN.name, true) + ) { return settings?.servers?.get(0)?.port } else if (protocol.equals(EConfigType.WIREGUARD.name, true)) { return settings?.peers?.get(0)?.endpoint?.substringAfterLast(":")?.toInt() @@ -377,10 +444,12 @@ data class V2rayConfig( fun getPassword(): String? { if (protocol.equals(EConfigType.VMESS.name, true) - || protocol.equals(EConfigType.VLESS.name, true)) { + || protocol.equals(EConfigType.VLESS.name, true) + ) { return settings?.vnext?.get(0)?.users?.get(0)?.id } else if (protocol.equals(EConfigType.SHADOWSOCKS.name, true) - || protocol.equals(EConfigType.TROJAN.name, true)) { + || protocol.equals(EConfigType.TROJAN.name, true) + ) { return settings?.servers?.get(0)?.password } else if (protocol.equals(EConfigType.SOCKS.name, true)) { return settings?.servers?.get(0)?.users?.get(0)?.pass @@ -401,59 +470,84 @@ data class V2rayConfig( fun getTransportSettingDetails(): List? { if (protocol.equals(EConfigType.VMESS.name, true) - || protocol.equals(EConfigType.VLESS.name, true) - || protocol.equals(EConfigType.TROJAN.name, true) - || protocol.equals(EConfigType.SHADOWSOCKS.name, true)) { + || protocol.equals(EConfigType.VLESS.name, true) + || protocol.equals(EConfigType.TROJAN.name, true) + || protocol.equals(EConfigType.SHADOWSOCKS.name, true) + ) { val transport = streamSettings?.network ?: return null return when (transport) { "tcp" -> { val tcpSetting = streamSettings?.tcpSettings ?: return null - listOf(tcpSetting.header.type, - tcpSetting.header.request?.headers?.Host?.joinToString().orEmpty(), - tcpSetting.header.request?.path?.joinToString().orEmpty()) + listOf( + tcpSetting.header.type, + tcpSetting.header.request?.headers?.Host?.joinToString().orEmpty(), + tcpSetting.header.request?.path?.joinToString().orEmpty() + ) } + "kcp" -> { val kcpSetting = streamSettings?.kcpSettings ?: return null - listOf(kcpSetting.header.type, - "", - kcpSetting.seed.orEmpty()) + listOf( + kcpSetting.header.type, + "", + kcpSetting.seed.orEmpty() + ) } + "ws" -> { val wsSetting = streamSettings?.wsSettings ?: return null - listOf("", - wsSetting.headers.Host, - wsSetting.path) + listOf( + "", + wsSetting.headers.Host, + wsSetting.path + ) } + "httpupgrade" -> { val httpupgradeSetting = streamSettings?.httpupgradeSettings ?: return null - listOf("", + listOf( + "", httpupgradeSetting.host, - httpupgradeSetting.path) + httpupgradeSetting.path + ) } + "splithttp" -> { val splithttpSetting = streamSettings?.splithttpSettings ?: return null - listOf("", + listOf( + "", splithttpSetting.host, - splithttpSetting.path) + splithttpSetting.path + ) } + "h2" -> { val h2Setting = streamSettings?.httpSettings ?: return null - listOf("", - h2Setting.host.joinToString(), - h2Setting.path) + listOf( + "", + h2Setting.host.joinToString(), + h2Setting.path + ) } + "quic" -> { val quicSetting = streamSettings?.quicSettings ?: return null - listOf(quicSetting.header.type, - quicSetting.security, - quicSetting.key) + listOf( + quicSetting.header.type, + quicSetting.security, + quicSetting.key + ) } + "grpc" -> { val grpcSetting = streamSettings?.grpcSettings ?: return null - listOf(if (grpcSetting.multiMode == true) "multi" else "gun", - grpcSetting.authority.orEmpty(), - grpcSetting.serviceName) + listOf( + if (grpcSetting.multiMode == true) "multi" else "gun", + grpcSetting.authority.orEmpty(), + grpcSetting.serviceName + ) } + else -> null } } @@ -461,59 +555,69 @@ data class V2rayConfig( } } - data class DnsBean(var servers: ArrayList? = null, - var hosts: Map? = null, - val clientIp: String? = null, - val disableCache: Boolean? = null, - val queryStrategy: String? = null, - val tag: String? = null + data class DnsBean( + var servers: ArrayList? = null, + var hosts: Map? = null, + val clientIp: String? = null, + val disableCache: Boolean? = null, + val queryStrategy: String? = null, + val tag: String? = null ) { - data class ServersBean(var address: String = "", - var port: Int? = null, - var domains: List? = null, - var expectIPs: List? = null, - val clientIp: String? = null) - } - - data class RoutingBean(var domainStrategy: String, - var domainMatcher: String? = null, - var rules: ArrayList, - val balancers: List? = null) { - - data class RulesBean( - var ip: ArrayList? = null, - var domain: ArrayList? = null, - var outboundTag: String = "", - var balancerTag: String? = null, - var port: String? = null, - val sourcePort: String? = null, - val network: String? = null, - val source: List? = null, - val user: List? = null, - var inboundTag: List? = null, - val protocol: List? = null, - val attrs: String? = null, - val domainMatcher: String? = null + data class ServersBean( + var address: String = "", + var port: Int? = null, + var domains: List? = null, + var expectIPs: List? = null, + val clientIp: String? = null ) } - data class PolicyBean(var levels: Map, - var system: Any? = null) { - data class LevelBean( - var handshake: Int? = null, - var connIdle: Int? = null, - var uplinkOnly: Int? = null, - var downlinkOnly: Int? = null, - val statsUserUplink: Boolean? = null, - val statsUserDownlink: Boolean? = null, - var bufferSize: Int? = null) + data class RoutingBean( + var domainStrategy: String, + var domainMatcher: String? = null, + var rules: ArrayList, + val balancers: List? = null + ) { + + data class RulesBean( + var ip: ArrayList? = null, + var domain: ArrayList? = null, + var outboundTag: String = "", + var balancerTag: String? = null, + var port: String? = null, + val sourcePort: String? = null, + val network: String? = null, + val source: List? = null, + val user: List? = null, + var inboundTag: List? = null, + val protocol: List? = null, + val attrs: String? = null, + val domainMatcher: String? = null + ) } - data class FakednsBean(var ipPool: String = "198.18.0.0/15", - var poolSize: Int = 10000) // roughly 10 times smaller than total ip pool + data class PolicyBean( + var levels: Map, + var system: Any? = null + ) { + data class LevelBean( + var handshake: Int? = null, + var connIdle: Int? = null, + var uplinkOnly: Int? = null, + var downlinkOnly: Int? = null, + val statsUserUplink: Boolean? = null, + val statsUserDownlink: Boolean? = null, + var bufferSize: Int? = null + ) + } + + data class FakednsBean( + var ipPool: String = "198.18.0.0/15", + var poolSize: Int = 10000 + ) // roughly 10 times smaller than total ip pool fun getProxyOutbound(): OutboundBean? { - outbounds?.forEach { outbound -> + outbounds.forEach { outbound -> EConfigType.entries.forEach { if (outbound.protocol.equals(it.name, true)) { return outbound @@ -525,13 +629,13 @@ data class V2rayConfig( fun toPrettyPrinting(): String { return GsonBuilder() - .setPrettyPrinting() - .disableHtmlEscaping() - .registerTypeAdapter( // custom serialiser is needed here since JSON by default parse number as Double, core will fail to start - object : TypeToken() {}.type, - JsonSerializer { src: Double?, _: Type?, _: JsonSerializationContext? -> JsonPrimitive(src?.toInt()) } - ) - .create() - .toJson(this) + .setPrettyPrinting() + .disableHtmlEscaping() + .registerTypeAdapter( // custom serialiser is needed here since JSON by default parse number as Double, core will fail to start + object : TypeToken() {}.type, + JsonSerializer { src: Double?, _: Type?, _: JsonSerializationContext? -> JsonPrimitive(src?.toInt()) } + ) + .create() + .toJson(this) } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt index 54b7dd74..779c7e3c 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/VmessQRCode.kt @@ -1,17 +1,19 @@ package com.v2ray.ang.dto -data class VmessQRCode(var v: String = "", - var ps: String = "", - var add: String = "", - var port: String = "", - var id: String = "", - var aid: String = "0", - var scy: String = "", - var net: String = "", - var type: String = "", - var host: String = "", - var path: String = "", - var tls: String = "", - var sni: String = "", - var alpn: String = "", - var fp: String = "") \ No newline at end of file +data class VmessQRCode( + var v: String = "", + var ps: String = "", + var add: String = "", + var port: String = "", + var id: String = "", + var aid: String = "0", + var scy: String = "", + var net: String = "", + var type: String = "", + var host: String = "", + var path: String = "", + var tls: String = "", + var sni: String = "", + var alpn: String = "", + var fp: String = "" +) \ No newline at end of file diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt index 87fa3260..f4c3a6f4 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/extension/_Ext.kt @@ -1,8 +1,6 @@ package com.v2ray.ang.extension import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkCapabilities import android.os.Build import android.widget.Toast import com.v2ray.ang.AngApplication diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/receiver/WidgetProvider.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/receiver/WidgetProvider.kt index 52dacf04..5aa6c2de 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/receiver/WidgetProvider.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/receiver/WidgetProvider.kt @@ -35,7 +35,8 @@ class WidgetProvider : AppWidgetProvider() { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT } else { PendingIntent.FLAG_UPDATE_CURRENT - }) + } + ) remoteViews.setOnClickPendingIntent(R.id.layout_switch, pendingIntent) if (isRunning) { remoteViews.setInt(R.id.image_switch, "setImageResource", R.drawable.ic_stop_24dp) @@ -65,12 +66,17 @@ class WidgetProvider : AppWidgetProvider() { AppWidgetManager.getInstance(context)?.let { manager -> when (intent.getIntExtra("key", 0)) { AppConfig.MSG_STATE_RUNNING, AppConfig.MSG_STATE_START_SUCCESS -> { - updateWidgetBackground(context, manager, manager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)), - true) + updateWidgetBackground( + context, manager, manager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)), + true + ) } + AppConfig.MSG_STATE_NOT_RUNNING, AppConfig.MSG_STATE_START_FAILURE, AppConfig.MSG_STATE_STOP_SUCCESS -> { - updateWidgetBackground(context, manager, manager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)), - false) + updateWidgetBackground( + context, manager, manager.getAppWidgetIds(ComponentName(context, WidgetProvider::class.java)), + false + ) } } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/QSTileService.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/QSTileService.kt index ecbae70e..1c9afe6c 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/QSTileService.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/QSTileService.kt @@ -58,6 +58,7 @@ class QSTileService : TileService() { Tile.STATE_INACTIVE -> { Utils.startVServiceFromToggle(this) } + Tile.STATE_ACTIVE -> { Utils.stopVService(this) } @@ -74,15 +75,19 @@ class QSTileService : TileService() { AppConfig.MSG_STATE_RUNNING -> { context?.setState(Tile.STATE_ACTIVE) } + AppConfig.MSG_STATE_NOT_RUNNING -> { context?.setState(Tile.STATE_INACTIVE) } + AppConfig.MSG_STATE_START_SUCCESS -> { context?.setState(Tile.STATE_ACTIVE) } + AppConfig.MSG_STATE_START_FAILURE -> { context?.setState(Tile.STATE_INACTIVE) } + AppConfig.MSG_STATE_STOP_SUCCESS -> { context?.setState(Tile.STATE_INACTIVE) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt index a1e8a5ac..449b8835 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/SubscriptionUpdater.kt @@ -21,7 +21,6 @@ import com.v2ray.ang.util.Utils object SubscriptionUpdater { - class UpdateTask(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayProxyOnlyService.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayProxyOnlyService.kt index d3f6a296..4d387a45 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayProxyOnlyService.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayProxyOnlyService.kt @@ -49,7 +49,7 @@ class V2RayProxyOnlyService : Service(), ServiceControl { @RequiresApi(Build.VERSION_CODES.N) override fun attachBaseContext(newBase: Context?) { val context = newBase?.let { - MyContextWrapper.wrap(newBase, Utils.getLocale()) + MyContextWrapper.wrap(newBase, Utils.getLocale()) } super.attachBaseContext(context) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt index 4324f45c..1f6dfa6f 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayServiceManager.kt @@ -27,14 +27,14 @@ import com.v2ray.ang.util.MmkvManager import com.v2ray.ang.util.Utils import com.v2ray.ang.util.V2rayConfigUtil import go.Seq +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.disposables.Disposable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import libv2ray.Libv2ray import libv2ray.V2RayPoint import libv2ray.V2RayVPNServiceSupportsSet -import io.reactivex.rxjava3.core.Observable -import io.reactivex.rxjava3.disposables.Disposable import java.lang.ref.SoftReference import kotlin.math.min @@ -206,18 +206,23 @@ object V2RayServiceManager { MessageUtil.sendMsg2UI(serviceControl.getService(), AppConfig.MSG_STATE_NOT_RUNNING, "") } } + AppConfig.MSG_UNREGISTER_CLIENT -> { // nothing to do } + AppConfig.MSG_STATE_START -> { // nothing to do } + AppConfig.MSG_STATE_STOP -> { serviceControl.stopService() } + AppConfig.MSG_STATE_RESTART -> { startV2rayPoint() } + AppConfig.MSG_MEASURE_DELAY -> { measureV2rayDelay() } @@ -228,6 +233,7 @@ object V2RayServiceManager { Log.d(ANG_PACKAGE, "SCREEN_OFF, stop querying stats") stopSpeedNotification() } + Intent.ACTION_SCREEN_ON -> { Log.d(ANG_PACKAGE, "SCREEN_ON, start querying stats") startSpeedNotification() @@ -270,46 +276,52 @@ object V2RayServiceManager { private fun showNotification() { val service = serviceControl?.get()?.getService() ?: return val startMainIntent = Intent(service, MainActivity::class.java) - val contentPendingIntent = PendingIntent.getActivity(service, - NOTIFICATION_PENDING_INTENT_CONTENT, startMainIntent, + val contentPendingIntent = PendingIntent.getActivity( + service, + NOTIFICATION_PENDING_INTENT_CONTENT, startMainIntent, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT } else { PendingIntent.FLAG_UPDATE_CURRENT - }) + } + ) val stopV2RayIntent = Intent(AppConfig.BROADCAST_ACTION_SERVICE) stopV2RayIntent.`package` = ANG_PACKAGE stopV2RayIntent.putExtra("key", AppConfig.MSG_STATE_STOP) - val stopV2RayPendingIntent = PendingIntent.getBroadcast(service, - NOTIFICATION_PENDING_INTENT_STOP_V2RAY, stopV2RayIntent, + val stopV2RayPendingIntent = PendingIntent.getBroadcast( + service, + NOTIFICATION_PENDING_INTENT_STOP_V2RAY, stopV2RayIntent, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT } else { PendingIntent.FLAG_UPDATE_CURRENT - }) + } + ) val channelId = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - createNotificationChannel() - } else { - // If earlier version channel ID is not used - // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context) - "" - } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + createNotificationChannel() + } else { + // If earlier version channel ID is not used + // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context) + "" + } mBuilder = NotificationCompat.Builder(service, channelId) - .setSmallIcon(R.drawable.ic_stat_name) - .setContentTitle(currentConfig?.remarks) - .setPriority(NotificationCompat.PRIORITY_MIN) - .setOngoing(true) - .setShowWhen(false) - .setOnlyAlertOnce(true) - .setContentIntent(contentPendingIntent) - .addAction(R.drawable.ic_delete_24dp, - service.getString(R.string.notification_action_stop_v2ray), - stopV2RayPendingIntent) + .setSmallIcon(R.drawable.ic_stat_name) + .setContentTitle(currentConfig?.remarks) + .setPriority(NotificationCompat.PRIORITY_MIN) + .setOngoing(true) + .setShowWhen(false) + .setOnlyAlertOnce(true) + .setContentIntent(contentPendingIntent) + .addAction( + R.drawable.ic_delete_24dp, + service.getString(R.string.notification_action_stop_v2ray), + stopV2RayPendingIntent + ) //.build() //mBuilder?.setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE) //取消震动,铃声其他都不好使 @@ -321,8 +333,10 @@ object V2RayServiceManager { private fun createNotificationChannel(): String { val channelId = AppConfig.RAY_NG_CHANNEL_ID val channelName = AppConfig.RAY_NG_CHANNEL_NAME - val chan = NotificationChannel(channelId, - channelName, NotificationManager.IMPORTANCE_HIGH) + val chan = NotificationChannel( + channelId, + channelName, NotificationManager.IMPORTANCE_HIGH + ) chan.lightColor = Color.DKGRAY chan.importance = NotificationManager.IMPORTANCE_NONE chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE @@ -363,40 +377,43 @@ object V2RayServiceManager { private fun startSpeedNotification() { if (mDisposable == null && - v2rayPoint.isRunning && - settingsStorage?.decodeBool(AppConfig.PREF_SPEED_ENABLED) == true) { + v2rayPoint.isRunning && + settingsStorage?.decodeBool(AppConfig.PREF_SPEED_ENABLED) == true + ) { var lastZeroSpeed = false val outboundTags = currentConfig?.getAllOutboundTags() outboundTags?.remove(TAG_DIRECT) mDisposable = Observable.interval(3, java.util.concurrent.TimeUnit.SECONDS) - .subscribe { - val queryTime = System.currentTimeMillis() - val sinceLastQueryInSeconds = (queryTime - lastQueryTime) / 1000.0 - var proxyTotal = 0L - val text = StringBuilder() - outboundTags?.forEach { - val up = v2rayPoint.queryStats(it, AppConfig.UPLINK) - val down = v2rayPoint.queryStats(it, AppConfig.DOWNLINK) - if (up + down > 0) { - appendSpeedString(text, it, up / sinceLastQueryInSeconds, down / sinceLastQueryInSeconds) - proxyTotal += up + down - } + .subscribe { + val queryTime = System.currentTimeMillis() + val sinceLastQueryInSeconds = (queryTime - lastQueryTime) / 1000.0 + var proxyTotal = 0L + val text = StringBuilder() + outboundTags?.forEach { + val up = v2rayPoint.queryStats(it, AppConfig.UPLINK) + val down = v2rayPoint.queryStats(it, AppConfig.DOWNLINK) + if (up + down > 0) { + appendSpeedString(text, it, up / sinceLastQueryInSeconds, down / sinceLastQueryInSeconds) + proxyTotal += up + down } - val directUplink = v2rayPoint.queryStats(TAG_DIRECT, AppConfig.UPLINK) - val directDownlink = v2rayPoint.queryStats(TAG_DIRECT, AppConfig.DOWNLINK) - val zeroSpeed = proxyTotal == 0L && directUplink == 0L && directDownlink == 0L - if (!zeroSpeed || !lastZeroSpeed) { - if (proxyTotal == 0L) { - appendSpeedString(text, outboundTags?.firstOrNull(), 0.0, 0.0) - } - appendSpeedString(text, TAG_DIRECT, directUplink / sinceLastQueryInSeconds, - directDownlink / sinceLastQueryInSeconds) - updateNotification(text.toString(), proxyTotal, directDownlink + directUplink) - } - lastZeroSpeed = zeroSpeed - lastQueryTime = queryTime } + val directUplink = v2rayPoint.queryStats(TAG_DIRECT, AppConfig.UPLINK) + val directDownlink = v2rayPoint.queryStats(TAG_DIRECT, AppConfig.DOWNLINK) + val zeroSpeed = proxyTotal == 0L && directUplink == 0L && directDownlink == 0L + if (!zeroSpeed || !lastZeroSpeed) { + if (proxyTotal == 0L) { + appendSpeedString(text, outboundTags?.firstOrNull(), 0.0, 0.0) + } + appendSpeedString( + text, TAG_DIRECT, directUplink / sinceLastQueryInSeconds, + directDownlink / sinceLastQueryInSeconds + ) + updateNotification(text.toString(), proxyTotal, directDownlink + directUplink) + } + lastZeroSpeed = zeroSpeed + lastQueryTime = queryTime + } } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayTestService.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayTestService.kt index d8414000..6d6dc0aa 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayTestService.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayTestService.kt @@ -10,7 +10,11 @@ import com.v2ray.ang.util.MessageUtil import com.v2ray.ang.util.SpeedtestUtil import com.v2ray.ang.util.Utils import go.Seq -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.cancelChildren +import kotlinx.coroutines.launch import libv2ray.Libv2ray import java.util.concurrent.Executors @@ -32,6 +36,7 @@ class V2RayTestService : Service() { MessageUtil.sendMsg2UI(this@V2RayTestService, MSG_MEASURE_CONFIG_SUCCESS, Pair(contentPair.first, result)) } } + MSG_MEASURE_CONFIG_CANCEL -> { realTestScope.coroutineContext[Job]?.cancelChildren() } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt index d3f675a6..c5f3ea99 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/service/V2RayVpnService.kt @@ -4,7 +4,13 @@ import android.app.Service import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.net.* +import android.net.ConnectivityManager +import android.net.LocalSocket +import android.net.LocalSocketAddress +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.net.VpnService import android.os.Build import android.os.ParcelFileDescriptor import android.os.StrictMode @@ -19,7 +25,6 @@ import com.v2ray.ang.util.MyContextWrapper import com.v2ray.ang.util.Utils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import java.io.File import java.lang.ref.SoftReference @@ -54,9 +59,9 @@ class V2RayVpnService : VpnService(), ServiceControl { @delegate:RequiresApi(Build.VERSION_CODES.P) private val defaultNetworkRequest by lazy { NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) - .build() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .build() } private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager } @@ -140,11 +145,11 @@ class V2RayVpnService : VpnService(), ServiceControl { builder.addDnsServer(PRIVATE_VLAN4_ROUTER) } else { Utils.getVpnDnsServers() - .forEach { - if (Utils.isPureIpAddress(it)) { - builder.addDnsServer(it) - } + .forEach { + if (Utils.isPureIpAddress(it)) { + builder.addDnsServer(it) } + } } builder.setSession(V2RayServiceManager.currentConfig?.remarks.orEmpty()) @@ -197,14 +202,16 @@ class V2RayVpnService : VpnService(), ServiceControl { private fun runTun2socks() { val socksPort = Utils.parseInt(settingsStorage?.decodeString(AppConfig.PREF_SOCKS_PORT), AppConfig.PORT_SOCKS.toInt()) - val cmd = arrayListOf(File(applicationContext.applicationInfo.nativeLibraryDir, TUN2SOCKS).absolutePath, - "--netif-ipaddr", PRIVATE_VLAN4_ROUTER, - "--netif-netmask", "255.255.255.252", - "--socks-server-addr", "127.0.0.1:${socksPort}", - "--tunmtu", VPN_MTU.toString(), - "--sock-path", "sock_path",//File(applicationContext.filesDir, "sock_path").absolutePath, - "--enable-udprelay", - "--loglevel", "notice") + val cmd = arrayListOf( + File(applicationContext.applicationInfo.nativeLibraryDir, TUN2SOCKS).absolutePath, + "--netif-ipaddr", PRIVATE_VLAN4_ROUTER, + "--netif-netmask", "255.255.255.252", + "--socks-server-addr", "127.0.0.1:${socksPort}", + "--tunmtu", VPN_MTU.toString(), + "--sock-path", "sock_path",//File(applicationContext.filesDir, "sock_path").absolutePath, + "--enable-udprelay", + "--loglevel", "notice" + ) if (settingsStorage?.decodeBool(AppConfig.PREF_PREFER_IPV6) == true) { cmd.add("--netif-ip6addr") @@ -221,14 +228,14 @@ class V2RayVpnService : VpnService(), ServiceControl { val proBuilder = ProcessBuilder(cmd) proBuilder.redirectErrorStream(true) process = proBuilder - .directory(applicationContext.filesDir) - .start() + .directory(applicationContext.filesDir) + .start() Thread(Runnable { - Log.d(packageName,"$TUN2SOCKS check") + Log.d(packageName, "$TUN2SOCKS check") process.waitFor() - Log.d(packageName,"$TUN2SOCKS exited") + Log.d(packageName, "$TUN2SOCKS exited") if (isRunning) { - Log.d(packageName,"$TUN2SOCKS restart") + Log.d(packageName, "$TUN2SOCKS restart") runTun2socks() } }).start() @@ -275,7 +282,7 @@ class V2RayVpnService : VpnService(), ServiceControl { // val emptyInfo = VpnNetworkInfo() // val info = loadVpnNetworkInfo(configName, emptyInfo)!! + (lastNetworkInfo ?: emptyInfo) // saveVpnNetworkInfo(configName, info) - isRunning = false; + isRunning = false if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { try { connectivity.unregisterNetworkCallback(defaultNetworkCallback) @@ -328,7 +335,7 @@ class V2RayVpnService : VpnService(), ServiceControl { @RequiresApi(Build.VERSION_CODES.N) override fun attachBaseContext(newBase: Context?) { val context = newBase?.let { - MyContextWrapper.wrap(newBase, Utils.getLocale()) + MyContextWrapper.wrap(newBase, Utils.getLocale()) } super.attachBaseContext(context) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/AboutActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/AboutActivity.kt index 8d2682a0..8f0f1bf0 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/AboutActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/AboutActivity.kt @@ -21,7 +21,7 @@ import java.text.SimpleDateFormat import java.util.Locale class AboutActivity : BaseActivity() { - private val binding by lazy {ActivityAboutBinding.inflate(layoutInflater)} + private val binding by lazy { ActivityAboutBinding.inflate(layoutInflater) } private val extDir by lazy { File(Utils.backupPath(this)) } override fun onCreate(savedInstanceState: Bundle?) { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/BaseActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/BaseActivity.kt index db9e1d3f..8a2c7fda 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/BaseActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/BaseActivity.kt @@ -28,13 +28,14 @@ abstract class BaseActivity : AppCompatActivity() { onBackPressedDispatcher.onBackPressed() true } + else -> super.onOptionsItemSelected(item) } @RequiresApi(Build.VERSION_CODES.N) override fun attachBaseContext(newBase: Context?) { val context = newBase?.let { - MyContextWrapper.wrap(newBase, Utils.getLocale()) + MyContextWrapper.wrap(newBase, Utils.getLocale()) } super.attachBaseContext(context) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/FragmentAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/FragmentAdapter.kt index d9d12992..deeb43c3 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/FragmentAdapter.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/FragmentAdapter.kt @@ -5,7 +5,7 @@ import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter class FragmentAdapter(fragmentActivity: FragmentActivity, private val mFragments: List) : - FragmentStateAdapter(fragmentActivity) { + FragmentStateAdapter(fragmentActivity) { override fun createFragment(position: Int): Fragment { return mFragments[position] diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/LogcatActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/LogcatActivity.kt index 5ae0f357..c71294eb 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/LogcatActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/LogcatActivity.kt @@ -84,10 +84,12 @@ class LogcatActivity : BaseActivity() { toast(R.string.toast_success) true } + R.id.clear_all -> { logcat(true) true } + else -> super.onOptionsItemSelected(item) } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt index 20d4df33..8dd873de 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainActivity.kt @@ -32,7 +32,6 @@ import com.v2ray.ang.AppConfig import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivityMainBinding import com.v2ray.ang.dto.EConfigType -import com.v2ray.ang.extension.isNetworkConnected import com.v2ray.ang.extension.toast import com.v2ray.ang.helper.SimpleItemTouchHelperCallback import com.v2ray.ang.service.V2RayServiceManager diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt index c0141c9b..4d7ebc1f 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/MainRecyclerAdapter.kt @@ -29,8 +29,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Observable import java.util.concurrent.TimeUnit -class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter() - , ItemTouchHelperAdapter { +class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter(), ItemTouchHelperAdapter { companion object { private const val VIEW_TYPE_ITEM = 1 private const val VIEW_TYPE_FOOTER = 2 @@ -95,7 +94,7 @@ class MainRecyclerAdapter(val activity: MainActivity) : RecyclerView.Adapter - if (blacklist.contains(one.packageName)) { - one.isSelected = 1 - } else { - one.isSelected = 0 - } + .subscribeOn(Schedulers.io()) + .map { + if (blacklist != null) { + it.forEach { one -> + if (blacklist.contains(one.packageName)) { + one.isSelected = 1 + } else { + one.isSelected = 0 } - val comparator = Comparator { p1, p2 -> - when { - p1.isSelected > p2.isSelected -> -1 - p1.isSelected == p2.isSelected -> 0 - else -> 1 - } - } - it.sortedWith(comparator) - } else { - val comparator = object : Comparator { - val collator = Collator.getInstance() - override fun compare(o1: AppInfo, o2: AppInfo) = collator.compare(o1.appName, o2.appName) - } - it.sortedWith(comparator) } + val comparator = Comparator { p1, p2 -> + when { + p1.isSelected > p2.isSelected -> -1 + p1.isSelected == p2.isSelected -> 0 + else -> 1 + } + } + it.sortedWith(comparator) + } else { + val comparator = object : Comparator { + val collator = Collator.getInstance() + override fun compare(o1: AppInfo, o2: AppInfo) = collator.compare(o1.appName, o2.appName) + } + it.sortedWith(comparator) } + } // .map { // val comparator = object : Comparator { // val collator = Collator.getInstance() @@ -79,13 +79,13 @@ class PerAppProxyActivity : BaseActivity() { // } // it.sortedWith(comparator) // } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { - appsAll = it - adapter = PerAppProxyAdapter(this, it, blacklist) - binding.recyclerView.adapter = adapter - binding.pbWaiting.visibility = View.GONE - } + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + appsAll = it + adapter = PerAppProxyAdapter(this, it, blacklist) + binding.recyclerView.adapter = adapter + binding.pbWaiting.visibility = View.GONE + } /*** recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() { var dst = 0 @@ -218,18 +218,22 @@ class PerAppProxyActivity : BaseActivity() { it.notifyDataSetChanged() true } ?: false + R.id.select_proxy_app -> { selectProxyApp() true } + R.id.import_proxy_app -> { importProxyApp() true } + R.id.export_proxy_app -> { exportProxyApp() true } + else -> super.onOptionsItemSelected(item) } @@ -324,7 +328,8 @@ class PerAppProxyActivity : BaseActivity() { if (key.isNotEmpty()) { appsAll?.forEach { if (it.appName.uppercase().indexOf(key) >= 0 - || it.packageName.uppercase().indexOf(key) >= 0) { + || it.packageName.uppercase().indexOf(key) >= 0 + ) { apps.add(it) } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/PerAppProxyAdapter.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/PerAppProxyAdapter.kt index 040e9b9c..7e5dcddd 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/PerAppProxyAdapter.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/PerAppProxyAdapter.kt @@ -1,16 +1,15 @@ package com.v2ray.ang.ui import android.view.LayoutInflater -import androidx.recyclerview.widget.RecyclerView import android.view.View import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView import com.v2ray.ang.R import com.v2ray.ang.databinding.ItemRecyclerBypassListBinding import com.v2ray.ang.dto.AppInfo -import java.util.* class PerAppProxyAdapter(val activity: BaseActivity, val apps: List, blacklist: MutableSet?) : - RecyclerView.Adapter() { + RecyclerView.Adapter() { companion object { private const val VIEW_TYPE_HEADER = 0 @@ -34,8 +33,10 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List, bl return when (viewType) { VIEW_TYPE_HEADER -> { val view = View(ctx) - view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ctx.resources.getDimensionPixelSize(R.dimen.bypass_list_header_height) * 0) + view.layoutParams = ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ctx.resources.getDimensionPixelSize(R.dimen.bypass_list_header_height) * 0 + ) BaseViewHolder(view) } // VIEW_TYPE_ITEM -> AppViewHolder(ctx.layoutInflater @@ -51,7 +52,7 @@ class PerAppProxyAdapter(val activity: BaseActivity, val apps: List, bl open class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) inner class AppViewHolder(private val itemBypassBinding: ItemRecyclerBypassListBinding) : BaseViewHolder(itemBypassBinding.root), - View.OnClickListener { + View.OnClickListener { private val inBlacklist: Boolean get() = blacklist.contains(appInfo.packageName) private lateinit var appInfo: AppInfo diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsActivity.kt index 9eab7935..c8d84ab0 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsActivity.kt @@ -1,10 +1,10 @@ package com.v2ray.ang.ui import android.os.Bundle -import com.v2ray.ang.R import androidx.fragment.app.Fragment import com.google.android.material.tabs.TabLayoutMediator import com.v2ray.ang.AppConfig +import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivityRoutingSettingsBinding class RoutingSettingsActivity : BaseActivity() { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt index 02a690d0..4904a69c 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/RoutingSettingsFragment.kt @@ -1,15 +1,19 @@ package com.v2ray.ang.ui import android.Manifest -import androidx.appcompat.app.AppCompatActivity.RESULT_OK import android.content.Intent import android.os.Bundle import android.text.TextUtils -import android.view.* +import android.view.LayoutInflater +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity.RESULT_OK import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope -import androidx.preference.PreferenceManager import com.tbruyelle.rxpermissions3.RxPermissions import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig @@ -24,14 +28,17 @@ import kotlinx.coroutines.launch class RoutingSettingsFragment : Fragment() { private val binding by lazy { FragmentRoutingSettingsBinding.inflate(layoutInflater) } + companion object { private const val routing_arg = "routing_arg" } - private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } + private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { // Inflate the layout for this fragment return binding.root// inflater.inflate(R.layout.fragment_routing_settings, container, false) } @@ -63,22 +70,27 @@ class RoutingSettingsFragment : Fragment() { saveRouting() true } + R.id.del_routing -> { binding.etRoutingContent.text = null true } + R.id.scan_replace -> { scanQRcode(true) true } + R.id.scan_append -> { scanQRcode(false) true } + R.id.default_rules -> { setDefaultRules() true } + else -> super.onOptionsItemSelected(item) } @@ -95,16 +107,16 @@ class RoutingSettingsFragment : Fragment() { // .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP), requestCode) // } catch (e: Exception) { RxPermissions(requireActivity()) - .request(Manifest.permission.CAMERA) - .subscribe { - if (it) - if (forReplace) - scanQRCodeForReplace.launch(Intent(activity, ScannerActivity::class.java)) - else - scanQRCodeForAppend.launch(Intent(activity, ScannerActivity::class.java)) + .request(Manifest.permission.CAMERA) + .subscribe { + if (it) + if (forReplace) + scanQRCodeForReplace.launch(Intent(activity, ScannerActivity::class.java)) else - activity?.toast(R.string.toast_permission_denied) - } + scanQRCodeForAppend.launch(Intent(activity, ScannerActivity::class.java)) + else + activity?.toast(R.string.toast_permission_denied) + } // } return true } @@ -130,9 +142,11 @@ class RoutingSettingsFragment : Fragment() { AppConfig.PREF_V2RAY_ROUTING_AGENT -> { tag = AppConfig.TAG_PROXY } + AppConfig.PREF_V2RAY_ROUTING_DIRECT -> { tag = AppConfig.TAG_DIRECT } + AppConfig.PREF_V2RAY_ROUTING_BLOCKED -> { tag = AppConfig.TAG_BLOCKED } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScScannerActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScScannerActivity.kt index c8508553..17090b75 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScScannerActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScScannerActivity.kt @@ -19,13 +19,13 @@ class ScScannerActivity : BaseActivity() { fun importQRcode(): Boolean { RxPermissions(this) - .request(Manifest.permission.CAMERA) - .subscribe { - if (it) - scanQRCode.launch(Intent(this, ScannerActivity::class.java)) - else - toast(R.string.toast_permission_denied) - } + .request(Manifest.permission.CAMERA) + .subscribe { + if (it) + scanQRCode.launch(Intent(this, ScannerActivity::class.java)) + else + toast(R.string.toast_permission_denied) + } return true } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScSwitchActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScSwitchActivity.kt index 3d3101ef..7f536971 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScSwitchActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScSwitchActivity.kt @@ -1,9 +1,9 @@ package com.v2ray.ang.ui -import com.v2ray.ang.R -import com.v2ray.ang.util.Utils import android.os.Bundle +import com.v2ray.ang.R import com.v2ray.ang.service.V2RayServiceManager +import com.v2ray.ang.util.Utils class ScSwitchActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScannerActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScannerActivity.kt index c38d5362..029f023b 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScannerActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ScannerActivity.kt @@ -1,11 +1,10 @@ package com.v2ray.ang.ui import android.Manifest -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle import android.content.Intent import android.graphics.BitmapFactory import android.os.Build +import android.os.Bundle import android.view.Menu import android.view.MenuItem import androidx.activity.result.contract.ActivityResultContracts @@ -20,7 +19,7 @@ import io.github.g00fy2.quickie.QRResult import io.github.g00fy2.quickie.ScanCustomCode import io.github.g00fy2.quickie.config.ScannerConfig -class ScannerActivity : BaseActivity(){ +class ScannerActivity : BaseActivity() { private val scanQrCode = registerForActivityResult(ScanCustomCode(), ::handleResult) private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) } @@ -33,7 +32,7 @@ class ScannerActivity : BaseActivity(){ } } - private fun launchScan(){ + private fun launchScan() { scanQrCode.launch( ScannerConfig.build { setHapticSuccessFeedback(true) // enable (default) or disable haptic feedback when a barcode was detected @@ -44,7 +43,7 @@ class ScannerActivity : BaseActivity(){ } private fun handleResult(result: QRResult) { - if (result is QRResult.QRSuccess ) { + if (result is QRResult.QRSuccess) { finished(result.content.rawValue.orEmpty()) } else { finish() @@ -54,7 +53,7 @@ class ScannerActivity : BaseActivity(){ private fun finished(text: String) { val intent = Intent() intent.putExtra("SCAN_RESULT", text) - setResult(AppCompatActivity.RESULT_OK, intent) + setResult(RESULT_OK, intent) finish() } @@ -68,6 +67,7 @@ class ScannerActivity : BaseActivity(){ launchScan() true } + R.id.select_photo -> { val permission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { Manifest.permission.READ_MEDIA_IMAGES @@ -88,6 +88,7 @@ class ScannerActivity : BaseActivity(){ } true } + else -> super.onOptionsItemSelected(item) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt index 0b5391bb..fbfe8d1e 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerActivity.kt @@ -533,16 +533,16 @@ class ServerActivity : BaseActivity() { val spiderX = et_spider_x?.text?.toString()?.trim() ?: return var sni = streamSetting.populateTransportSettings( - transport = networks[network], - headerType = transportTypes(networks[network])[type], - host = requestHost, - path = path, - seed = path, - quicSecurity = requestHost, - key = path, - mode = transportTypes(networks[network])[type], - serviceName = path, - authority = requestHost, + transport = networks[network], + headerType = transportTypes(networks[network])[type], + host = requestHost, + path = path, + seed = path, + quicSecurity = requestHost, + key = path, + mode = transportTypes(networks[network])[type], + serviceName = path, + authority = requestHost, ) if (sniField.isNotBlank()) { sni = sniField diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt index f760b3f3..3df4d3a0 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/ServerCustomConfigActivity.kt @@ -105,14 +105,14 @@ class ServerCustomConfigActivity : BaseActivity() { private fun deleteServer(): Boolean { if (editGuid.isNotEmpty()) { AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) - .setPositiveButton(android.R.string.ok) { _, _ -> - MmkvManager.removeServer(editGuid) - finish() - } - .setNegativeButton(android.R.string.no) {_, _ -> - // do nothing - } - .show() + .setPositiveButton(android.R.string.ok) { _, _ -> + MmkvManager.removeServer(editGuid) + finish() + } + .setNegativeButton(android.R.string.no) { _, _ -> + // do nothing + } + .show() } return true } @@ -139,10 +139,12 @@ class ServerCustomConfigActivity : BaseActivity() { deleteServer() true } + R.id.save_config -> { saveServer() true } + else -> super.onOptionsItemSelected(item) } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt index a025909a..305ed274 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SettingsActivity.kt @@ -184,7 +184,7 @@ class SettingsActivity : BaseActivity() { localDns?.isChecked = settingsStorage.getBoolean(AppConfig.PREF_LOCAL_DNS_ENABLED, false) fakeDns?.isChecked = settingsStorage.getBoolean(AppConfig.PREF_FAKE_DNS_ENABLED, false) localDnsPort?.summary = settingsStorage.decodeString(AppConfig.PREF_LOCAL_DNS_PORT, AppConfig.PORT_LOCAL_DNS) - vpnDns?.summary = settingsStorage.decodeString(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN) + vpnDns?.summary = settingsStorage.decodeString(AppConfig.PREF_VPN_DNS, AppConfig.DNS_VPN) updateMux(settingsStorage.getBoolean(AppConfig.PREF_MUX_ENABLED, false)) mux?.isChecked = settingsStorage.getBoolean(AppConfig.PREF_MUX_ENABLED, false) @@ -198,7 +198,8 @@ class SettingsActivity : BaseActivity() { fragmentInterval?.summary = settingsStorage.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20") autoUpdateCheck?.isChecked = settingsStorage.getBoolean(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false) - autoUpdateInterval?.summary = settingsStorage.decodeString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL,AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL) + autoUpdateInterval?.summary = + settingsStorage.decodeString(AppConfig.SUBSCRIPTION_AUTO_UPDATE_INTERVAL, AppConfig.SUBSCRIPTION_DEFAULT_UPDATE_INTERVAL) autoUpdateInterval?.isEnabled = settingsStorage.getBoolean(AppConfig.SUBSCRIPTION_AUTO_UPDATE, false) socksPort?.summary = settingsStorage.decodeString(AppConfig.PREF_SOCKS_PORT, AppConfig.PORT_SOCKS) @@ -350,12 +351,15 @@ class SettingsActivity : BaseActivity() { updateFragmentInterval(settingsStorage.decodeString(AppConfig.PREF_FRAGMENT_INTERVAL, "10-20")) } } + private fun updateFragmentPackets(value: String?) { fragmentPackets?.summary = value.toString() } + private fun updateFragmentLength(value: String?) { fragmentLength?.summary = value.toString() } + private fun updateFragmentInterval(value: String?) { fragmentInterval?.summary = value.toString() } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt index 1f52f6d2..d9546f34 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/SubEditActivity.kt @@ -18,7 +18,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class SubEditActivity : BaseActivity() { - private val binding by lazy {ActivitySubEditBinding.inflate(layoutInflater)} + private val binding by lazy { ActivitySubEditBinding.inflate(layoutInflater) } var del_config: MenuItem? = null var save_config: MenuItem? = null @@ -100,18 +100,18 @@ class SubEditActivity : BaseActivity() { private fun deleteServer(): Boolean { if (editSubId.isNotEmpty()) { AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) - .setPositiveButton(android.R.string.ok) { _, _ -> - lifecycleScope.launch(Dispatchers.IO) { - MmkvManager.removeSubscription(editSubId) - launch(Dispatchers.Main) { - finish() - } + .setPositiveButton(android.R.string.ok) { _, _ -> + lifecycleScope.launch(Dispatchers.IO) { + MmkvManager.removeSubscription(editSubId) + launch(Dispatchers.Main) { + finish() } } - .setNegativeButton(android.R.string.no) {_, _ -> - // do nothing - } - .show() + } + .setNegativeButton(android.R.string.no) { _, _ -> + // do nothing + } + .show() } return true } @@ -133,10 +133,12 @@ class SubEditActivity : BaseActivity() { deleteServer() true } + R.id.save_config -> { saveServer() true } + else -> super.onOptionsItemSelected(item) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/TaskerActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/TaskerActivity.kt index 872607d3..edf352f7 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/TaskerActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/TaskerActivity.kt @@ -1,18 +1,16 @@ package com.v2ray.ang.ui -import androidx.appcompat.app.AppCompatActivity -import android.os.Bundle -import android.view.View -import android.widget.ArrayAdapter -import android.widget.ListView -import java.util.ArrayList -import com.v2ray.ang.R import android.content.Intent +import android.os.Bundle import android.text.TextUtils import android.view.Menu import android.view.MenuItem +import android.view.View +import android.widget.ArrayAdapter +import android.widget.ListView import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig +import com.v2ray.ang.R import com.v2ray.ang.databinding.ActivityTaskerBinding import com.v2ray.ang.util.MmkvManager @@ -39,8 +37,10 @@ class TaskerActivity : BaseActivity() { lstGuid.add(key) } } - val adapter = ArrayAdapter(this, - android.R.layout.simple_list_item_single_choice, lstData) + val adapter = ArrayAdapter( + this, + android.R.layout.simple_list_item_single_choice, lstData + ) listview = findViewById(R.id.listview) as ListView listview?.adapter = adapter @@ -88,7 +88,7 @@ class TaskerActivity : BaseActivity() { intent.putExtra(AppConfig.TASKER_EXTRA_BUNDLE, extraBundle) intent.putExtra(AppConfig.TASKER_EXTRA_STRING_BLURB, blurb) - setResult(AppCompatActivity.RESULT_OK, intent) + setResult(RESULT_OK, intent) finish() } @@ -103,10 +103,12 @@ class TaskerActivity : BaseActivity() { R.id.del_config -> { true } + R.id.save_config -> { confirmFinish() true } + else -> super.onOptionsItemSelected(item) } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetActivity.kt index 9cd441cd..5a8f814e 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetActivity.kt @@ -83,6 +83,7 @@ class UserAssetActivity : BaseActivity() { startActivity(intent) true } + R.id.download_file -> { downloadGeoFiles() true @@ -100,24 +101,24 @@ class UserAssetActivity : BaseActivity() { RxPermissions(this) .request(permission) .subscribe { - if (it) { - val intent = Intent(Intent.ACTION_GET_CONTENT) - intent.type = "*/*" - intent.addCategory(Intent.CATEGORY_OPENABLE) + if (it) { + val intent = Intent(Intent.ACTION_GET_CONTENT) + intent.type = "*/*" + intent.addCategory(Intent.CATEGORY_OPENABLE) - try { - chooseFile.launch( - Intent.createChooser( - intent, - getString(R.string.title_file_chooser) + try { + chooseFile.launch( + Intent.createChooser( + intent, + getString(R.string.title_file_chooser) + ) ) - ) - } catch (ex: android.content.ActivityNotFoundException) { - toast(R.string.toast_require_file_manager) - } - } else - toast(R.string.toast_permission_denied) - } + } catch (ex: android.content.ActivityNotFoundException) { + toast(R.string.toast_require_file_manager) + } + } else + toast(R.string.toast_permission_denied) + } } private val chooseFile = @@ -237,15 +238,18 @@ class UserAssetActivity : BaseActivity() { conn?.disconnect() } } + private fun addBuiltInGeoItems(assets: List>): List> { val list = mutableListOf>() builtInGeoFiles .filter { geoFile -> assets.none { it.second.remarks == geoFile } } - .forEach { - list.add(Utils.getUuid() to AssetUrlItem( - it, - AppConfig.GeoUrl + it - )) + .forEach { + list.add( + Utils.getUuid() to AssetUrlItem( + it, + AppConfig.GeoUrl + it + ) + ) } return list + assets @@ -257,14 +261,15 @@ class UserAssetActivity : BaseActivity() { ItemRecyclerUserAssetBinding.inflate( LayoutInflater.from(parent.context), parent, - false) + false + ) ) } @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: UserAssetViewHolder, position: Int) { - var assets = MmkvManager.decodeAssetUrls(); - assets = addBuiltInGeoItems(assets); + var assets = MmkvManager.decodeAssetUrls() + assets = addBuiltInGeoItems(assets) val item = assets.getOrNull(position) ?: return // file with name == item.second.remarks val file = extDir.listFiles()?.find { it.name == item.second.remarks } @@ -300,8 +305,8 @@ class UserAssetActivity : BaseActivity() { } override fun getItemCount(): Int { - var assets = MmkvManager.decodeAssetUrls(); - assets = addBuiltInGeoItems(assets); + var assets = MmkvManager.decodeAssetUrls() + assets = addBuiltInGeoItems(assets) return assets.size } } diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetUrlActivity.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetUrlActivity.kt index 1d5d66f5..63dba839 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetUrlActivity.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/ui/UserAssetUrlActivity.kt @@ -112,7 +112,7 @@ class UserAssetUrlActivity : BaseActivity() { MmkvManager.removeAssetUrl(editAssetId) finish() } - .setNegativeButton(android.R.string.no) {_, _ -> + .setNegativeButton(android.R.string.no) { _, _ -> // do nothing } .show() @@ -137,10 +137,12 @@ class UserAssetUrlActivity : BaseActivity() { deleteServer() true } + R.id.save_config -> { saveServer() true } + else -> super.onOptionsItemSelected(item) } } \ No newline at end of file diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt index 37bf1fd8..beda150f 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt @@ -386,7 +386,7 @@ object AngConfigManager { // } // } - fun importBatchConfig(server: String?, subid: String, append: Boolean): Pair { + fun importBatchConfig(server: String?, subid: String, append: Boolean): Pair { var count = parseBatchConfig(Utils.decode(server), subid, append) if (count <= 0) { count = parseBatchConfig(server, subid, append) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt index a01ee24a..7be5024a 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/Utils.kt @@ -140,7 +140,7 @@ object Utils { } fun getVpnDnsServers(): List { - val vpnDns = settingsStorage?.decodeString(AppConfig.PREF_VPN_DNS)?:AppConfig.DNS_VPN + val vpnDns = settingsStorage?.decodeString(AppConfig.PREF_VPN_DNS) ?: AppConfig.DNS_VPN return vpnDns.split(",").filter { isPureIpAddress(it) } // allow empty, in that case dns will use system default } @@ -204,7 +204,8 @@ object Utils { } fun isIpv4Address(value: String): Boolean { - val regV4 = Regex("^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$") + val regV4 = + Regex("^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$") return regV4.matches(value) } @@ -214,7 +215,8 @@ object Utils { addr = addr.drop(1) addr = addr.dropLast(addr.count() - addr.lastIndexOf("]")) } - val regV6 = Regex("^((?:[0-9A-Fa-f]{1,4}))?((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))?((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7}$") + val regV6 = + Regex("^((?:[0-9A-Fa-f]{1,4}))?((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))?((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7}$") return regV6.matches(addr) } @@ -300,8 +302,7 @@ object Utils { * readTextFromAssets */ fun readTextFromAssets(context: Context?, fileName: String): String { - if(context == null) - { + if (context == null) { return "" } val content = context.assets.open(fileName).bufferedReader().use { @@ -314,7 +315,7 @@ object Utils { if (context == null) return "" val extDir = context.getExternalFilesDir(AppConfig.DIR_ASSETS) - ?: return context.getDir(AppConfig.DIR_ASSETS, 0).absolutePath + ?: return context.getDir(AppConfig.DIR_ASSETS, 0).absolutePath return extDir.absolutePath } @@ -370,8 +371,10 @@ object Utils { conn.setRequestProperty("Connection", "close") conn.setRequestProperty("User-agent", "v2rayNG/${BuildConfig.VERSION_NAME}") url.userInfo?.let { - conn.setRequestProperty("Authorization", - "Basic ${encode(urlDecode(it))}") + conn.setRequestProperty( + "Authorization", + "Basic ${encode(urlDecode(it))}" + ) } conn.useCaches = false return conn.inputStream.use { @@ -393,7 +396,7 @@ object Utils { } fun getIpv6Address(address: String?): String { - if(address == null){ + if (address == null) { return "" } return if (isIpv6Address(address) && !address.contains('[') && !address.contains(']')) { @@ -427,8 +430,8 @@ object Utils { fun fixIllegalUrl(str: String): String { return str - .replace(" ","%20") - .replace("|","%7C") + .replace(" ", "%20") + .replace("|", "%7C") } fun removeWhiteSpace(str: String?): String? { diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/ShadowsocksFmt.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/ShadowsocksFmt.kt index 749e67d3..40e068ee 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/ShadowsocksFmt.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/ShadowsocksFmt.kt @@ -67,7 +67,7 @@ object ShadowsocksFmt { private fun tryResolveResolveSip002(str: String, config: ServerConfig): Boolean { try { val uri = URI(Utils.fixIllegalUrl(str)) - config.remarks = Utils.urlDecode(uri.fragment .orEmpty()) + config.remarks = Utils.urlDecode(uri.fragment.orEmpty()) val method: String val password: String @@ -88,7 +88,7 @@ object ShadowsocksFmt { password = base64Decode.substringAfter(":") } - val query = Utils.urlDecode(uri.query .orEmpty()) + val query = Utils.urlDecode(uri.query.orEmpty()) if (query != "") { val queryPairs = HashMap() val pairs = query.split(";") diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/TrojanFmt.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/TrojanFmt.kt index 90fa9412..cc76272e 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/TrojanFmt.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/TrojanFmt.kt @@ -19,12 +19,12 @@ object TrojanFmt { ) } - fun parseTrojan(str: String): ServerConfig? { + fun parseTrojan(str: String): ServerConfig { var allowInsecure = settingsStorage?.decodeBool(AppConfig.PREF_ALLOW_INSECURE) ?: false val config = ServerConfig.create(EConfigType.TROJAN) val uri = URI(Utils.fixIllegalUrl(str)) - config.remarks = Utils.urlDecode(uri.fragment .orEmpty()) + config.remarks = Utils.urlDecode(uri.fragment.orEmpty()) var flow = "" var fingerprint = config.outboundBean?.streamSettings?.tlsSettings?.fingerprint @@ -56,7 +56,7 @@ object TrojanFmt { queryParam["authority"] ) fingerprint = queryParam["fp"].orEmpty() - allowInsecure = if ((queryParam["allowInsecure"] .orEmpty()) == "1") true else allowInsecure + allowInsecure = if ((queryParam["allowInsecure"].orEmpty()) == "1") true else allowInsecure config.outboundBean?.streamSettings?.populateTlsSettings( queryParam["security"] ?: V2rayConfig.TLS, allowInsecure, @@ -111,7 +111,7 @@ object TrojanFmt { dicQuery["sid"] = tlsSetting.shortId.orEmpty() } if (!TextUtils.isEmpty(tlsSetting.spiderX)) { - dicQuery["spx"] = Utils.urlEncode(tlsSetting.spiderX .orEmpty()) + dicQuery["spx"] = Utils.urlEncode(tlsSetting.spiderX.orEmpty()) } } dicQuery["type"] = diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VlessFmt.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VlessFmt.kt index 3196305a..ef442401 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VlessFmt.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VlessFmt.kt @@ -30,7 +30,7 @@ object VlessFmt { val streamSetting = config.outboundBean?.streamSettings ?: return null - config.remarks = Utils.urlDecode(uri.fragment .orEmpty()) + config.remarks = Utils.urlDecode(uri.fragment.orEmpty()) config.outboundBean.settings?.vnext?.get(0)?.let { vnext -> vnext.address = uri.idnHost vnext.port = uri.port @@ -51,7 +51,7 @@ object VlessFmt { queryParam["serviceName"], queryParam["authority"] ) - allowInsecure = if ((queryParam["allowInsecure"] .orEmpty()) == "1") true else allowInsecure + allowInsecure = if ((queryParam["allowInsecure"].orEmpty()) == "1") true else allowInsecure streamSetting.populateTlsSettings( queryParam["security"].orEmpty(), allowInsecure, @@ -102,7 +102,7 @@ object VlessFmt { dicQuery["sid"] = tlsSetting.shortId.orEmpty() } if (!TextUtils.isEmpty(tlsSetting.spiderX)) { - dicQuery["spx"] = Utils.urlEncode(tlsSetting.spiderX .orEmpty()) + dicQuery["spx"] = Utils.urlEncode(tlsSetting.spiderX.orEmpty()) } } dicQuery["type"] = diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VmessFmt.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VmessFmt.kt index 313700a6..d191c6d0 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VmessFmt.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/VmessFmt.kt @@ -121,7 +121,7 @@ object VmessFmt { val streamSetting = config.outboundBean?.streamSettings ?: return null - config.remarks = Utils.urlDecode(uri.fragment .orEmpty()) + config.remarks = Utils.urlDecode(uri.fragment.orEmpty()) config.outboundBean.settings?.vnext?.get(0)?.let { vnext -> vnext.address = uri.idnHost vnext.port = uri.port @@ -143,7 +143,7 @@ object VmessFmt { queryParam["authority"] ) - allowInsecure = if ((queryParam["allowInsecure"] .orEmpty()) == "1") true else allowInsecure + allowInsecure = if ((queryParam["allowInsecure"].orEmpty()) == "1") true else allowInsecure streamSetting.populateTlsSettings( queryParam["security"].orEmpty(), allowInsecure, diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/WireguardFmt.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/WireguardFmt.kt index 8375870a..34fb2eff 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/WireguardFmt.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/fmt/WireguardFmt.kt @@ -13,7 +13,7 @@ object WireguardFmt { val uri = URI(Utils.fixIllegalUrl(str)) if (uri.rawQuery != null) { val config = ServerConfig.create(EConfigType.WIREGUARD) - config.remarks = Utils.urlDecode(uri.fragment .orEmpty()) + config.remarks = Utils.urlDecode(uri.fragment.orEmpty()) val queryParam = uri.rawQuery.split("&") .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_action_done.xml b/V2rayNG/app/src/main/res/drawable-night/ic_action_done.xml index 33a117f6..c3fb8a47 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_action_done.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_action_done.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:fillColor="#FFFFFFFF" + android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_add_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_add_24dp.xml index b9b8eca8..d2948026 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_add_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_add_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_copy.xml b/V2rayNG/app/src/main/res/drawable-night/ic_copy.xml index e50927b2..9cafc852 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_copy.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_copy.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_delete_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_delete_24dp.xml index ab38bb6d..4c803eca 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_delete_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_delete_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_description_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_description_24dp.xml index 7e0d28e3..6f55b8de 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_description_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_description_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M14,2L6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM16,18L8,18v-2h8v2zM16,14L8,14v-2h8v2zM13,9L13,3.5L18.5,9L13,9z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_edit_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_edit_24dp.xml index 35a774a5..85d32985 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_edit_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_edit_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_file_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_file_24dp.xml index 3ddbb298..30595842 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_file_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_file_24dp.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="1024" android:viewportHeight="1024"> - + diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_logcat_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_logcat_24dp.xml index c60b6062..1c1a9c94 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_logcat_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_logcat_24dp.xml @@ -5,11 +5,11 @@ android:viewportHeight="1024"> + android:fillColor="#FFFFFFFF" /> + android:fillColor="#FFFFFFFF" /> + android:fillColor="#FFFFFFFF" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_outline_filter_alt_24.xml b/V2rayNG/app/src/main/res/drawable-night/ic_outline_filter_alt_24.xml index 6cb82eff..9d0d5910 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_outline_filter_alt_24.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_outline_filter_alt_24.xml @@ -1,5 +1,10 @@ - - + + diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_promotion_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_promotion_24dp.xml index e5c48df8..014a5021 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_promotion_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_promotion_24dp.xml @@ -5,8 +5,8 @@ android:viewportHeight="1024"> + android:fillColor="#FFFFFFFF" /> + android:fillColor="#FFFFFFFF" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_save_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_save_24dp.xml index a7a81a25..47a92519 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_save_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_save_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_share_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_share_24dp.xml index 90406663..b09d63e8 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_share_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_share_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" /> diff --git a/V2rayNG/app/src/main/res/drawable-night/ic_telegram_24dp.xml b/V2rayNG/app/src/main/res/drawable-night/ic_telegram_24dp.xml index 98373510..b35b623c 100644 --- a/V2rayNG/app/src/main/res/drawable-night/ic_telegram_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable-night/ic_telegram_24dp.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="1024" android:viewportHeight="1024"> - + diff --git a/V2rayNG/app/src/main/res/drawable/ic_action_done.xml b/V2rayNG/app/src/main/res/drawable/ic_action_done.xml index 5635bead..bda675f1 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_action_done.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_action_done.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:fillColor="#FF000000" + android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_add_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_add_24dp.xml index 0258249c..fedd077d 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_add_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_add_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_copy.xml b/V2rayNG/app/src/main/res/drawable/ic_copy.xml index 8a894a3b..380c8783 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_copy.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_copy.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_delete_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_delete_24dp.xml index 2f5557af..c3027b2e 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_delete_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_delete_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8.46,11.88l1.41,-1.41L12,12.59l2.12,-2.12 1.41,1.41L13.41,14l2.12,2.12 -1.41,1.41L12,15.41l-2.12,2.12 -1.41,-1.41L10.59,14l-2.13,-2.12zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_description_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_description_24dp.xml index 38c33351..a30bc6ca 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_description_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_description_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M14,2L6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM16,18L8,18v-2h8v2zM16,14L8,14v-2h8v2zM13,9L13,3.5L18.5,9L13,9z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_edit_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_edit_24dp.xml index 2ab2fb75..5505cc77 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_edit_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_edit_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_file_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_file_24dp.xml index cb5193f6..c14b248f 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_file_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_file_24dp.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="1024" android:viewportHeight="1024"> - + diff --git a/V2rayNG/app/src/main/res/drawable/ic_logcat_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_logcat_24dp.xml index 86562d04..b8a544ef 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_logcat_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_logcat_24dp.xml @@ -3,13 +3,13 @@ android:height="24dp" android:viewportWidth="1024" android:viewportHeight="1024"> - - - + + + diff --git a/V2rayNG/app/src/main/res/drawable/ic_outline_filter_alt_24.xml b/V2rayNG/app/src/main/res/drawable/ic_outline_filter_alt_24.xml index d574422c..3a12237a 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_outline_filter_alt_24.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_outline_filter_alt_24.xml @@ -1,5 +1,10 @@ - - + + diff --git a/V2rayNG/app/src/main/res/drawable/ic_promotion_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_promotion_24dp.xml index 58505a6b..079a2197 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_promotion_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_promotion_24dp.xml @@ -3,10 +3,10 @@ android:height="24dp" android:viewportWidth="1024" android:viewportHeight="1024"> - - + + diff --git a/V2rayNG/app/src/main/res/drawable/ic_save_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_save_24dp.xml index a561d632..0651fcc6 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_save_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_save_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_share_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_share_24dp.xml index e3fe874d..338d95ad 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_share_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_share_24dp.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" /> diff --git a/V2rayNG/app/src/main/res/drawable/ic_source_code_24dp.xml b/V2rayNG/app/src/main/res/drawable/ic_source_code_24dp.xml index 73879a2a..dc13d1c8 100644 --- a/V2rayNG/app/src/main/res/drawable/ic_source_code_24dp.xml +++ b/V2rayNG/app/src/main/res/drawable/ic_source_code_24dp.xml @@ -1,4 +1,9 @@ - - + + diff --git a/V2rayNG/app/src/main/res/layout/activity_main.xml b/V2rayNG/app/src/main/res/layout/activity_main.xml index 25c6189e..7c5ff6e3 100644 --- a/V2rayNG/app/src/main/res/layout/activity_main.xml +++ b/V2rayNG/app/src/main/res/layout/activity_main.xml @@ -51,7 +51,7 @@ app:tabTextAppearance="@style/TabLayoutTextStyle" app:tabIndicatorFullWidth="false" android:layout_height="wrap_content" - android:layout_width="match_parent"/> + android:layout_width="match_parent" /> + android:textAppearance="@style/TextAppearance.AppCompat.Small" /> @@ -120,7 +120,7 @@ android:layout_gravity="start" app:headerLayout="@layout/nav_header" app:itemIconTint="@color/colorAccent" - app:menu="@menu/menu_drawer" > + app:menu="@menu/menu_drawer"> diff --git a/V2rayNG/app/src/main/res/layout/activity_none.xml b/V2rayNG/app/src/main/res/layout/activity_none.xml index d7681698..c7d9548b 100644 --- a/V2rayNG/app/src/main/res/layout/activity_none.xml +++ b/V2rayNG/app/src/main/res/layout/activity_none.xml @@ -1,5 +1,4 @@ - + android:layout_height="match_parent"> diff --git a/V2rayNG/app/src/main/res/layout/activity_routing_settings.xml b/V2rayNG/app/src/main/res/layout/activity_routing_settings.xml index 7052cc5f..a77a8062 100644 --- a/V2rayNG/app/src/main/res/layout/activity_routing_settings.xml +++ b/V2rayNG/app/src/main/res/layout/activity_routing_settings.xml @@ -1,7 +1,6 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="top|start" + android:id="@+id/editor" + android:layout_marginTop="@dimen/layout_margin_top_height" /> diff --git a/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml b/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml index 1cf58010..926a09f3 100644 --- a/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml +++ b/V2rayNG/app/src/main/res/layout/activity_server_shadowsocks.xml @@ -205,9 +205,9 @@ android:inputType="text" /> - + + - - + + android:id="@+id/et_security" + android:layout_width="match_parent" + android:layout_height="@dimen/edit_height" + android:inputType="text" + android:text="none" /> @@ -225,7 +225,7 @@ android:inputType="text" /> - + - + + + + + tools:listitem="@layout/item_recycler_sub_setting" /> \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/layout/activity_user_asset_url.xml b/V2rayNG/app/src/main/res/layout/activity_user_asset_url.xml index bc378009..15247c42 100644 --- a/V2rayNG/app/src/main/res/layout/activity_user_asset_url.xml +++ b/V2rayNG/app/src/main/res/layout/activity_user_asset_url.xml @@ -1,86 +1,86 @@ - - + android:layout_height="match_parent" + tools:context=".ui.UserAssetUrlActivity"> + android:orientation="vertical"> + android:orientation="vertical" + android:padding="@dimen/layout_margin_top_height"> - + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + android:orientation="vertical" /> - - - - \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/layout/dialog_config_filter.xml b/V2rayNG/app/src/main/res/layout/dialog_config_filter.xml index 115371df..1c043f4f 100644 --- a/V2rayNG/app/src/main/res/layout/dialog_config_filter.xml +++ b/V2rayNG/app/src/main/res/layout/dialog_config_filter.xml @@ -18,7 +18,7 @@ + android:layout_height="@dimen/edit_height" /> diff --git a/V2rayNG/app/src/main/res/layout/layout_progress.xml b/V2rayNG/app/src/main/res/layout/layout_progress.xml index 78ff04c7..8c699420 100644 --- a/V2rayNG/app/src/main/res/layout/layout_progress.xml +++ b/V2rayNG/app/src/main/res/layout/layout_progress.xml @@ -1,11 +1,11 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="16dp"> diff --git a/V2rayNG/app/src/main/res/layout/tls_layout.xml b/V2rayNG/app/src/main/res/layout/tls_layout.xml index dcbf2e17..2f29d782 100644 --- a/V2rayNG/app/src/main/res/layout/tls_layout.xml +++ b/V2rayNG/app/src/main/res/layout/tls_layout.xml @@ -1,10 +1,9 @@ - + android:orientation="vertical"> + + + + + android:orientation="vertical"> + + + + app:showAsAction="ifRoom"> + app:showAsAction="always" /> - + + android:id="@+id/user_asset_setting" + android:icon="@drawable/ic_file_24dp" + android:title="@string/title_user_asset_setting" /> diff --git a/V2rayNG/app/src/main/res/menu/menu_main.xml b/V2rayNG/app/src/main/res/menu/menu_main.xml index 5bcba5e7..7894237b 100644 --- a/V2rayNG/app/src/main/res/menu/menu_main.xml +++ b/V2rayNG/app/src/main/res/menu/menu_main.xml @@ -6,7 +6,7 @@ android:icon="@drawable/ic_outline_filter_alt_24" android:title="@string/menu_item_search" app:actionViewClass="androidx.appcompat.widget.SearchView" - app:showAsAction="always|collapseActionView"/> + app:showAsAction="always|collapseActionView" /> - + - + \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index e202e4be..c46314ad 100644 --- a/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,6 @@ - - + + \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 036d09bc..c9ad5f98 100644 --- a/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/V2rayNG/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/values-ar/strings.xml b/V2rayNG/app/src/main/res/values-ar/strings.xml index 4f31bde9..7370804c 100644 --- a/V2rayNG/app/src/main/res/values-ar/strings.xml +++ b/V2rayNG/app/src/main/res/values-ar/strings.xml @@ -42,7 +42,7 @@ العنوان المنفذ المعرف - AlterId + AlterId الأمان الشبكة @@ -110,7 +110,7 @@ الملف غير موجود الملاحظات موجودة بالفعل الإجراء غير مسموح به - + جار التحميل بحث diff --git a/V2rayNG/app/src/main/res/values/arrays.xml b/V2rayNG/app/src/main/res/values/arrays.xml index 684c44a5..721aae04 100644 --- a/V2rayNG/app/src/main/res/values/arrays.xml +++ b/V2rayNG/app/src/main/res/values/arrays.xml @@ -49,7 +49,7 @@ gun multi - + diff --git a/V2rayNG/app/src/main/res/values/attrs.xml b/V2rayNG/app/src/main/res/values/attrs.xml index 52069cfb..0df1370f 100644 --- a/V2rayNG/app/src/main/res/values/attrs.xml +++ b/V2rayNG/app/src/main/res/values/attrs.xml @@ -1,5 +1,6 @@ + diff --git a/V2rayNG/app/src/main/res/xml/cache_paths.xml b/V2rayNG/app/src/main/res/xml/cache_paths.xml index f9649fc7..c782c283 100644 --- a/V2rayNG/app/src/main/res/xml/cache_paths.xml +++ b/V2rayNG/app/src/main/res/xml/cache_paths.xml @@ -1,4 +1,6 @@ - + diff --git a/V2rayNG/app/src/test/java/com/v2ray/ang/ExampleUnitTest.java b/V2rayNG/app/src/test/java/com/v2ray/ang/ExampleUnitTest.java index 5c6cdaa6..3e28d640 100644 --- a/V2rayNG/app/src/test/java/com/v2ray/ang/ExampleUnitTest.java +++ b/V2rayNG/app/src/test/java/com/v2ray/ang/ExampleUnitTest.java @@ -1,9 +1,9 @@ package com.v2ray.ang; -import org.junit.Test; - import static org.junit.Assert.assertEquals; +import org.junit.Test; + /** * To work on unit tests, switch the Test Artifact in the Build Variants view. */ diff --git a/V2rayNG/app/src/test/kotlin/com/v2ray/ang/ExampleUnitTest.kt b/V2rayNG/app/src/test/kotlin/com/v2ray/ang/ExampleUnitTest.kt index 8e7961ff..7cda0075 100644 --- a/V2rayNG/app/src/test/kotlin/com/v2ray/ang/ExampleUnitTest.kt +++ b/V2rayNG/app/src/test/kotlin/com/v2ray/ang/ExampleUnitTest.kt @@ -1,39 +1,41 @@ -import org.junit.Assert.* -import org.junit.Test import com.v2ray.ang.util.Utils +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test class UtilTest { - @Test - fun test_parseInt() { - assertEquals(Utils.parseInt("1234"), 1234) - } - - @Test - fun test_isIpAddress() { - assertFalse(Utils.isIpAddress("114.113.112.266")) - assertFalse(Utils.isIpAddress("666.666.666.666")) - assertFalse(Utils.isIpAddress("256.0.0.0" )) - assertFalse(Utils.isIpAddress("::ffff:127.0.0.0.1" )) - assertFalse(Utils.isIpAddress("baidu.com")) - assertFalse(Utils.isIpAddress("")) + @Test + fun test_parseInt() { + assertEquals(Utils.parseInt("1234"), 1234) + } - assertTrue(Utils.isIpAddress("127.0.0.1" )) - assertTrue(Utils.isIpAddress("127.0.0.1:80" )) - assertTrue(Utils.isIpAddress("0.0.0.0/0" )) - assertTrue(Utils.isIpAddress("::1" )) - assertTrue(Utils.isIpAddress("[::1]:80" )) - assertTrue(Utils.isIpAddress("2605:2700:0:3::4713:93e3" )) - assertTrue(Utils.isIpAddress("[2605:2700:0:3::4713:93e3]:80" )) - assertTrue(Utils.isIpAddress("::ffff:192.168.173.22" )) - assertTrue(Utils.isIpAddress("[::ffff:192.168.173.22]:80" )) - assertTrue(Utils.isIpAddress("1::" )) - assertTrue(Utils.isIpAddress("::" )) - assertTrue(Utils.isIpAddress("::/0" )) - assertTrue(Utils.isIpAddress("10.24.56.0/24" )) - assertTrue(Utils.isIpAddress("2001:4321::1" )) - assertTrue(Utils.isIpAddress("240e:1234:abcd:12::6666" )) - assertTrue(Utils.isIpAddress("240e:1234:abcd:12::/64" )) - } + @Test + fun test_isIpAddress() { + assertFalse(Utils.isIpAddress("114.113.112.266")) + assertFalse(Utils.isIpAddress("666.666.666.666")) + assertFalse(Utils.isIpAddress("256.0.0.0")) + assertFalse(Utils.isIpAddress("::ffff:127.0.0.0.1")) + assertFalse(Utils.isIpAddress("baidu.com")) + assertFalse(Utils.isIpAddress("")) + + assertTrue(Utils.isIpAddress("127.0.0.1")) + assertTrue(Utils.isIpAddress("127.0.0.1:80")) + assertTrue(Utils.isIpAddress("0.0.0.0/0")) + assertTrue(Utils.isIpAddress("::1")) + assertTrue(Utils.isIpAddress("[::1]:80")) + assertTrue(Utils.isIpAddress("2605:2700:0:3::4713:93e3")) + assertTrue(Utils.isIpAddress("[2605:2700:0:3::4713:93e3]:80")) + assertTrue(Utils.isIpAddress("::ffff:192.168.173.22")) + assertTrue(Utils.isIpAddress("[::ffff:192.168.173.22]:80")) + assertTrue(Utils.isIpAddress("1::")) + assertTrue(Utils.isIpAddress("::")) + assertTrue(Utils.isIpAddress("::/0")) + assertTrue(Utils.isIpAddress("10.24.56.0/24")) + assertTrue(Utils.isIpAddress("2001:4321::1")) + assertTrue(Utils.isIpAddress("240e:1234:abcd:12::6666")) + assertTrue(Utils.isIpAddress("240e:1234:abcd:12::/64")) + } }