diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt index a5e0da0b..824b1be8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/extension/_Ext.kt @@ -17,18 +17,38 @@ import java.net.URLConnection val Context.v2RayApplication: AngApplication? get() = applicationContext as? AngApplication +/** + * Shows a toast message with the given resource ID. + * + * @param message The resource ID of the message to show. + */ fun Context.toast(message: Int) { ToastCompat.makeText(this, message, Toast.LENGTH_SHORT).show() } +/** + * Shows a toast message with the given text. + * + * @param message The text of the message to show. + */ fun Context.toast(message: CharSequence) { ToastCompat.makeText(this, message, Toast.LENGTH_SHORT).show() } +/** + * Puts a key-value pair into the JSONObject. + * + * @param pair The key-value pair to put. + */ fun JSONObject.putOpt(pair: Pair) { put(pair.first, pair.second) } +/** + * Puts multiple key-value pairs into the JSONObject. + * + * @param pairs The map of key-value pairs to put. + */ fun JSONObject.putOpt(pairs: Map) { pairs.forEach { put(it.key, it.value) } } @@ -36,8 +56,18 @@ fun JSONObject.putOpt(pairs: Map) { const val THRESHOLD = 1000L const val DIVISOR = 1024.0 +/** + * Converts a Long value to a speed string. + * + * @return The speed string. + */ fun Long.toSpeedString(): String = this.toTrafficString() + "/s" +/** + * Converts a Long value to a traffic string. + * + * @return The traffic string. + */ fun Long.toTrafficString(): String { val units = arrayOf("B", "KB", "MB", "GB", "TB", "PB") var size = this.toDouble() @@ -59,10 +89,27 @@ val URLConnection.responseLength: Long val URI.idnHost: String get() = host?.replace("[", "")?.replace("]", "").orEmpty() +/** + * Removes all whitespace from the string. + * + * @return The string without whitespace. + */ fun String.removeWhiteSpace(): String = replace("\\s+".toRegex(), "") +/** + * Converts the string to a Long value, or returns 0 if the conversion fails. + * + * @return The Long value. + */ fun String.toLongEx(): Long = toLongOrNull() ?: 0 +/** + * Listens for package changes and executes a callback when a change occurs. + * + * @param onetime Whether to unregister the receiver after the first callback. + * @param callback The callback to execute when a package change occurs. + * @return The BroadcastReceiver that was registered. + */ fun Context.listenForPackageChanges(onetime: Boolean = true, callback: () -> Unit) = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { @@ -85,14 +132,31 @@ fun Context.listenForPackageChanges(onetime: Boolean = true, callback: () -> Uni } } +/** + * Retrieves a serializable object from the Bundle. + * + * @param key The key of the serializable object. + * @return The serializable object, or null if not found. + */ inline fun Bundle.serializable(key: String): T? = when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java) else -> @Suppress("DEPRECATION") getSerializable(key) as? T } +/** + * Retrieves a serializable object from the Intent. + * + * @param key The key of the serializable object. + * @return The serializable object, or null if not found. + */ inline fun Intent.serializable(key: String): T? = when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializableExtra(key, T::class.java) else -> @Suppress("DEPRECATION") getSerializableExtra(key) as? T } +/** + * Checks if the CharSequence is not null and not empty. + * + * @return True if the CharSequence is not null and not empty, false otherwise. + */ fun CharSequence?.isNotNullEmpty(): Boolean = (this != null && this.isNotEmpty()) \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/CustomFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/CustomFmt.kt index 7a873832..3bc20927 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/CustomFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/CustomFmt.kt @@ -6,6 +6,12 @@ import com.v2ray.ang.dto.V2rayConfig import com.v2ray.ang.util.JsonUtil object CustomFmt : FmtBase() { + /** + * Parses a JSON string into a ProfileItem object. + * + * @param str the JSON string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.CUSTOM) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt index 1ecfff47..0f6dbf1a 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt @@ -8,6 +8,14 @@ import com.v2ray.ang.util.Utils import java.net.URI open class FmtBase { + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @param userInfo the user information to include in the URI + * @param dicQuery the query parameters to include in the URI + * @return the converted URI string + */ fun toUri(config: ProfileItem, userInfo: String?, dicQuery: HashMap?): String { val query = if (dicQuery != null) ("?" + dicQuery.toList().joinToString( @@ -25,11 +33,24 @@ open class FmtBase { return "${url}${query}#${Utils.urlEncode(config.remarks)}" } + /** + * Extracts query parameters from a URI. + * + * @param uri the URI to extract query parameters from + * @return a map of query parameters + */ fun getQueryParam(uri: URI): Map { return uri.rawQuery.split("&") .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } } + /** + * Populates a ProfileItem object with values from query parameters. + * + * @param config the ProfileItem object to populate + * @param queryParam the query parameters to use for populating the ProfileItem + * @param allowInsecure whether to allow insecure connections + */ fun getItemFormQuery(config: ProfileItem, queryParam: Map, allowInsecure: Boolean) { config.network = queryParam["type"] ?: NetworkType.TCP.type config.headerType = queryParam["headerType"] @@ -63,6 +84,12 @@ open class FmtBase { config.flow = queryParam["flow"] } + /** + * Creates a map of query parameters from a ProfileItem object. + * + * @param config the ProfileItem object to create query parameters from + * @return a map of query parameters + */ fun getQueryDic(config: ProfileItem): HashMap { val dicQuery = HashMap() dicQuery["security"] = config.security?.ifEmpty { "none" }.orEmpty() @@ -121,5 +148,4 @@ open class FmtBase { return dicQuery } - } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/HttpFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/HttpFmt.kt index e9ebc53e..faac0230 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/HttpFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/HttpFmt.kt @@ -6,6 +6,12 @@ import com.v2ray.ang.dto.V2rayConfig.OutboundBean import com.v2ray.ang.extension.isNotNullEmpty object HttpFmt : FmtBase() { + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.HTTP) @@ -22,6 +28,4 @@ object HttpFmt : FmtBase() { return outboundBean } - - } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/Hysteria2Fmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/Hysteria2Fmt.kt index 1c5dc99d..7a6abe08 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/Hysteria2Fmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/Hysteria2Fmt.kt @@ -13,6 +13,12 @@ import com.v2ray.ang.util.Utils import java.net.URI object Hysteria2Fmt : FmtBase() { + /** + * Parses a Hysteria2 URI string into a ProfileItem object. + * + * @param str the Hysteria2 URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { var allowInsecure = MmkvManager.decodeSettingsBool(AppConfig.PREF_ALLOW_INSECURE, false) val config = ProfileItem.create(EConfigType.HYSTERIA2) @@ -45,6 +51,12 @@ object Hysteria2Fmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val dicQuery = HashMap() @@ -67,6 +79,13 @@ object Hysteria2Fmt : FmtBase() { return toUri(config, config.password, dicQuery) } + /** + * Converts a ProfileItem object to a Hysteria2Bean object. + * + * @param config the ProfileItem object to convert + * @param socksPort the port number for the socks5 proxy + * @return the converted Hysteria2Bean object, or null if conversion fails + */ fun toNativeConfig(config: ProfileItem, socksPort: Int): Hysteria2Bean? { val obfs = if (config.obfsPassword.isNullOrEmpty()) null else @@ -118,10 +137,14 @@ object Hysteria2Fmt : FmtBase() { return bean } - + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.HYSTERIA2) return outboundBean } - } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt index c4edc5bd..d32eeef7 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt @@ -9,10 +9,22 @@ import com.v2ray.ang.util.Utils import java.net.URI object ShadowsocksFmt : FmtBase() { + /** + * Parses a Shadowsocks URI string into a ProfileItem object. + * + * @param str the Shadowsocks URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { return parseSip002(str) ?: parseLegacy(str) } + /** + * Parses a SIP002 Shadowsocks URI string into a ProfileItem object. + * + * @param str the SIP002 Shadowsocks URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parseSip002(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.SHADOWSOCKS) @@ -55,6 +67,12 @@ object ShadowsocksFmt : FmtBase() { return config } + /** + * Parses a legacy Shadowsocks URI string into a ProfileItem object. + * + * @param str the legacy Shadowsocks URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parseLegacy(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.SHADOWSOCKS) var result = str.replace(EConfigType.SHADOWSOCKS.protocolScheme, "") @@ -92,12 +110,24 @@ object ShadowsocksFmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val pw = "${config.method}:${config.password}" return toUri(config, Utils.encode(pw), null) } + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.SHADOWSOCKS) @@ -134,6 +164,4 @@ object ShadowsocksFmt : FmtBase() { return outboundBean } - - } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/SocksFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/SocksFmt.kt index 3b47bf3e..f37030c2 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/SocksFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/SocksFmt.kt @@ -9,6 +9,12 @@ import com.v2ray.ang.util.Utils import java.net.URI object SocksFmt : FmtBase() { + /** + * Parses a Socks URI string into a ProfileItem object. + * + * @param str the Socks URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.SOCKS) @@ -31,6 +37,12 @@ object SocksFmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val pw = if (config.username.isNotNullEmpty()) @@ -41,6 +53,12 @@ object SocksFmt : FmtBase() { return toUri(config, Utils.encode(pw), null) } + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.SOCKS) @@ -57,5 +75,4 @@ object SocksFmt : FmtBase() { return outboundBean } - } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt index db0c907d..56883cd8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt @@ -11,6 +11,12 @@ import com.v2ray.ang.util.Utils import java.net.URI object TrojanFmt : FmtBase() { + /** + * Parses a Trojan URI string into a ProfileItem object. + * + * @param str the Trojan URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { var allowInsecure = MmkvManager.decodeSettingsBool(AppConfig.PREF_ALLOW_INSECURE, false) val config = ProfileItem.create(EConfigType.TROJAN) @@ -35,12 +41,24 @@ object TrojanFmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val dicQuery = getQueryDic(config) return toUri(config, config.password, dicQuery) } + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.TROJAN) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt index a4ca34c5..77d2f2a3 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt @@ -12,6 +12,12 @@ import java.net.URI object VlessFmt : FmtBase() { + /** + * Parses a Vless URI string into a ProfileItem object. + * + * @param str the Vless URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { var allowInsecure = MmkvManager.decodeSettingsBool(AppConfig.PREF_ALLOW_INSECURE, false) val config = ProfileItem.create(EConfigType.VLESS) @@ -31,6 +37,12 @@ object VlessFmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val dicQuery = getQueryDic(config) dicQuery["encryption"] = config.method ?: "none" @@ -38,7 +50,12 @@ object VlessFmt : FmtBase() { return toUri(config, config.password, dicQuery) } - + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.VLESS) @@ -78,6 +95,4 @@ object VlessFmt : FmtBase() { return outboundBean } - - } \ No newline at end of file diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt index e566f5fa..c5cba993 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt @@ -16,6 +16,12 @@ import com.v2ray.ang.util.Utils import java.net.URI object VmessFmt : FmtBase() { + /** + * Parses a Vmess string into a ProfileItem object. + * + * @param str the Vmess string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { if (str.indexOf('?') > 0 && str.indexOf('&') > 0) { return parseVmessStd(str) @@ -79,6 +85,12 @@ object VmessFmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val vmessQRCode = VmessQRCode() @@ -122,6 +134,12 @@ object VmessFmt : FmtBase() { return Utils.encode(json) } + /** + * Parses a standard Vmess URI string into a ProfileItem object. + * + * @param str the standard Vmess URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parseVmessStd(str: String): ProfileItem? { val allowInsecure = MmkvManager.decodeSettingsBool(AppConfig.PREF_ALLOW_INSECURE, false) val config = ProfileItem.create(EConfigType.VMESS) @@ -141,7 +159,12 @@ object VmessFmt : FmtBase() { return config } - + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.VMESS) diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt index 2bce4d24..2e6b0df8 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/WireguardFmt.kt @@ -10,6 +10,12 @@ import com.v2ray.ang.util.Utils import java.net.URI object WireguardFmt : FmtBase() { + /** + * Parses a URI string into a ProfileItem object. + * + * @param str the URI string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parse(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.WIREGUARD) @@ -31,6 +37,12 @@ object WireguardFmt : FmtBase() { return config } + /** + * Parses a Wireguard configuration file string into a ProfileItem object. + * + * @param str the Wireguard configuration file string to parse + * @return the parsed ProfileItem object, or null if parsing fails + */ fun parseWireguardConfFile(str: String): ProfileItem? { val config = ProfileItem.create(EConfigType.WIREGUARD) @@ -85,6 +97,12 @@ object WireguardFmt : FmtBase() { return config } + /** + * Converts a ProfileItem object to an OutboundBean object. + * + * @param profileItem the ProfileItem object to convert + * @return the converted OutboundBean object, or null if conversion fails + */ fun toOutbound(profileItem: ProfileItem): OutboundBean? { val outboundBean = OutboundBean.create(EConfigType.WIREGUARD) @@ -103,6 +121,12 @@ object WireguardFmt : FmtBase() { return outboundBean } + /** + * Converts a ProfileItem object to a URI string. + * + * @param config the ProfileItem object to convert + * @return the converted URI string + */ fun toUri(config: ProfileItem): String { val dicQuery = HashMap()