diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt index 914fab11..db48cb38 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt @@ -37,7 +37,7 @@ import be.mygod.vpnhotspot.net.monitor.TrafficRecorder import be.mygod.vpnhotspot.room.AppDatabase import be.mygod.vpnhotspot.room.ClientStats import be.mygod.vpnhotspot.room.TrafficRecord -import be.mygod.vpnhotspot.util.SpanFormatter +import be.mygod.vpnhotspot.util.format import be.mygod.vpnhotspot.util.showAllowingStateLoss import be.mygod.vpnhotspot.util.toPluralInt import be.mygod.vpnhotspot.widget.SmartSnackbar @@ -82,10 +82,11 @@ class ClientsFragment : Fragment() { data class StatsArg(val title: CharSequence, val stats: ClientStats) : Parcelable class StatsDialogFragment : AlertDialogFragment() { override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) { - setTitle(SpanFormatter.format(getText(R.string.clients_stats_title), arg.title)) val context = context val resources = resources - val format = NumberFormat.getIntegerInstance(resources.configuration.locale) + val locale = resources.configuration.locale + setTitle(getText(R.string.clients_stats_title).format(locale, arg.title)) + val format = NumberFormat.getIntegerInstance(locale) setMessage("%s\n%s\n%s".format( resources.getQuantityString(R.plurals.clients_stats_message_1, arg.stats.count.toPluralInt(), format.format(arg.stats.count), DateUtils.formatDateTime(context, arg.stats.timestamp, diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt index a5b2056a..bc6e7fec 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/preference/UpstreamsPreference.kt @@ -13,8 +13,8 @@ import androidx.preference.Preference import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor -import be.mygod.vpnhotspot.util.SpanFormatter import be.mygod.vpnhotspot.util.allRoutes +import be.mygod.vpnhotspot.util.format import be.mygod.vpnhotspot.util.parseNumericAddress import timber.log.Timber @@ -72,7 +72,7 @@ class UpstreamsPreference(context: Context, attrs: AttributeSet) : Preference(co } private fun onUpdate() = (context as LifecycleOwner).lifecycleScope.launchWhenStarted { - summary = SpanFormatter.format(context.getText(R.string.settings_service_upstream_monitor_summary), - primary.charSequence, fallback.charSequence) + summary = context.getText(R.string.settings_service_upstream_monitor_summary).format( + context.resources.configuration.locale, primary.charSequence, fallback.charSequence) } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/util/SpanFormatter.kt b/mobile/src/main/java/be/mygod/vpnhotspot/util/SpanFormatter.kt deleted file mode 100644 index e3d056fe..00000000 --- a/mobile/src/main/java/be/mygod/vpnhotspot/util/SpanFormatter.kt +++ /dev/null @@ -1,84 +0,0 @@ -package be.mygod.vpnhotspot.util - -import android.text.Spannable -import android.text.SpannableStringBuilder -import android.text.Spanned -import android.text.SpannedString -import java.util.* - -/** - * Provides [String.format] style functions that work with [Spanned] strings and preserve formatting. - * - * https://github.com/george-steel/android-utils/blob/289aff11e53593a55d780f9f5986e49343a79e55/src/org/oshkimaadziig/george/androidutils/SpanFormatter.java - * - * @author George T. Steel - */ -object SpanFormatter { - private val formatSequence = "%([0-9]+\\$| "%" - "n" -> "\n" - else -> { - val argItem = args[when (argTerm) { - "" -> ++argAt - "<" -> argAt - else -> Integer.parseInt(argTerm.substring(0, argTerm.length - 1)) - 1 - }] - if (typeTerm == "s" && argItem is Spanned) argItem else { - String.format(locale, "%$modTerm$typeTerm", argItem) - } - } - } - - out.replace(i, exprEnd, cookedArg) - i += cookedArg.length - } - - return SpannedString(out) - } -} diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/util/Utils.kt b/mobile/src/main/java/be/mygod/vpnhotspot/util/Utils.kt index 2b024db6..998b464e 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/util/Utils.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/util/Utils.kt @@ -12,9 +12,7 @@ import android.os.RemoteException import android.system.ErrnoException import android.system.Os import android.system.OsConstants -import android.text.Spannable -import android.text.SpannableString -import android.text.SpannableStringBuilder +import android.text.* import android.view.MenuItem import android.view.View import android.widget.ImageView @@ -39,6 +37,7 @@ import java.lang.reflect.Method import java.net.InetAddress import java.net.NetworkInterface import java.net.SocketException +import java.util.* tailrec fun Throwable.getRootCause(): Throwable { if (this is InvocationTargetException || this is RemoteException) return (cause ?: return this).getRootCause() @@ -80,6 +79,53 @@ fun setVisibility(view: View, value: Boolean) { view.isVisible = value } +private val formatSequence = "%([0-9]+\\$| "%" + "n" -> "\n" + else -> { + val argItem = args[when (argTerm) { + "" -> ++argAt + "<" -> argAt + else -> Integer.parseInt(argTerm.substring(0, argTerm.length - 1)) - 1 + }] + if (typeTerm == "s" && argItem is Spanned) argItem else { + String.format(locale, "%$modTerm$typeTerm", argItem) + } + } + } + replace(i, exprEnd, cookedArg) + i += cookedArg.length + } +} + fun makeIpSpan(ip: InetAddress) = ip.hostAddress.let { // exclude all bogon IP addresses supported by Android APIs if (!app.hasTouch || ip.isMulticastAddress || ip.isAnyLocalAddress || ip.isLoopbackAddress ||