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 2e66d6fd..4b7ff2a0 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,7 +1,6 @@ package com.v2ray.ang.extension import android.content.Context -import android.os.Build import android.widget.Toast import com.v2ray.ang.AngApplication import me.drakeet.support.toast.ToastCompat @@ -9,63 +8,48 @@ import org.json.JSONObject import java.net.URI import java.net.URLConnection -/** - * Some extensions for the AngApplication - */ - -// Extension property to retrieve AngApplication instance from Context val Context.v2RayApplication: AngApplication - get() = applicationContext as AngApplication + get() = applicationContext as? AngApplication ?: throw IllegalStateException("Not an AngApplication") -// Extension functions to show a toast message for Int and CharSequence types -fun Context.toast(message: Int, duration: Int = Toast.LENGTH_SHORT) = - ToastCompat.makeText(this, message, duration).show() +fun Context.toast(message: Int) = showToast(message) +fun Context.toast(message: CharSequence) = showToast(message) -fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) = - ToastCompat.makeText(this, message, duration).show() - -// JSONObject Extensions to put a Pair or Map of data -fun JSONObject.putOpt(pair: Pair) = putOpt(pair.first, pair.second) - -fun JSONObject.putOpt(pairs: Map) = pairs.forEach { (key, value) -> - putOpt(key to value) +private fun Context.showToast(message: Any) { + ToastCompat.makeText(this, message.toString(), Toast.LENGTH_SHORT).apply { show() } } -// Constants for traffic and speed conversions -const val threshold = 1000 -const val divisor = 1024F - -// Extension function to convert Long byte value to a string with speed units -fun Long.toSpeedString() = "${toTrafficString()}/s" - -// Extension function to convert Long byte value to a string with traffic units -fun Long.toTrafficString(): String = when { - this == 0L -> "0 B" - this < threshold -> "${this.formatBytes()} B" - else -> { - val (value, unit) = listOf( - divisor to "KB", - divisor * divisor to "MB", - divisor * divisor * divisor to "GB", - divisor * divisor * divisor * divisor to "TB", - divisor * divisor * divisor * divisor * divisor to "PB" - ).fold(this to "B") { (value, _), (div, unit) -> - if (value < threshold * divisor) return@fold value to unit - (value / divisor) to unit - } - "${value.formatBytes()} $unit" +fun JSONObject.putOpt(pair: Pair) { + pair.second?.let { + put(pair.first, it) } } -private fun Long.formatBytes() = "%.2f".format(this / divisor).trimEnd('0').trimEnd('.') +fun JSONObject.putOpt(pairs: Map) { + pairs.forEach { (key, value) -> + putOpt(key to value) + } +} + +private const val KILOBYTE = 1024.0 +private const val THRESHOLD = 1024 + +fun Long.toTrafficString(): String { + var value = this.toDouble() + val units = listOf("B", "KB", "MB", "GB", "TB", "PB") + var unitIndex = 0 + + while (value >= THRESHOLD && unitIndex < units.lastIndex) { + value /= KILOBYTE + unitIndex++ + } + + return String.format("%.2f %s", value, units[unitIndex]) +} -// URLConnection extension property to return the response length with backward compatibility val URLConnection.responseLength: Long - get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) contentLengthLong else contentLength.toLong() + get() = if (Build.VERSION.SDK_INT >= 23) contentLengthLong else contentLength.toLong() -// URI extension property to return an IDN Hostname val URI.idnHost: String get() = host?.replace("[", "")?.replace("]", "") ?: "" -// String extension function to remove all white spaces -fun String.removeWhiteSpace() = replace(" ", "") +fun String.removeWhiteSpace() = replace("\\s+".toRegex(), "")