2952/proxy (#2961)
* replace hard-coded strings with existing constants * proxy port * * custom proxy port and hostname inputs * typesafety, refactor, linting, unit tests * relocate ProxyConfiguration in app structure * remove unused editTextPreference fn * allow preference category to have no title * refactor proxy prefs hierarchy/dependency
This commit is contained in:
parent
59c24381a3
commit
25443217c2
6 changed files with 143 additions and 21 deletions
|
|
@ -0,0 +1,32 @@
|
|||
package com.keylesspalace.tusky.settings
|
||||
|
||||
import java.net.IDN
|
||||
|
||||
class ProxyConfiguration private constructor(
|
||||
val hostname: String,
|
||||
val port: Int
|
||||
) {
|
||||
companion object {
|
||||
fun create(hostname: String, port: Int): ProxyConfiguration? {
|
||||
if (isValidHostname(IDN.toASCII(hostname)) && isValidProxyPort(port)) {
|
||||
return ProxyConfiguration(hostname, port)
|
||||
}
|
||||
return null
|
||||
}
|
||||
fun isValidProxyPort(value: Any): Boolean = when (value) {
|
||||
is String -> if (value == "") true else value.runCatching(String::toInt).map(
|
||||
PROXY_RANGE::contains
|
||||
).getOrDefault(false)
|
||||
is Int -> PROXY_RANGE.contains(value)
|
||||
else -> false
|
||||
}
|
||||
fun isValidHostname(hostname: String): Boolean =
|
||||
IP_ADDRESS_REGEX.matches(hostname) || HOSTNAME_REGEX.matches(hostname)
|
||||
const val MIN_PROXY_PORT = 0
|
||||
const val MAX_PROXY_PORT = 65535
|
||||
}
|
||||
}
|
||||
|
||||
private val PROXY_RANGE = IntRange(ProxyConfiguration.MIN_PROXY_PORT, ProxyConfiguration.MAX_PROXY_PORT)
|
||||
private val IP_ADDRESS_REGEX = Regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
|
||||
private val HOSTNAME_REGEX = Regex("^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$")
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
package com.keylesspalace.tusky.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.widget.Button
|
||||
import androidx.activity.result.ActivityResultRegistryOwner
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import androidx.preference.EditTextPreference
|
||||
|
|
@ -50,10 +52,25 @@ inline fun PreferenceParent.switchPreference(
|
|||
return pref
|
||||
}
|
||||
|
||||
inline fun PreferenceParent.editTextPreference(
|
||||
inline fun PreferenceParent.validatedEditTextPreference(
|
||||
errorMessage: String?,
|
||||
crossinline isValid: (a: String) -> Boolean,
|
||||
builder: EditTextPreference.() -> Unit
|
||||
): EditTextPreference {
|
||||
val pref = EditTextPreference(context)
|
||||
pref.setOnBindEditTextListener { editText ->
|
||||
editText.doAfterTextChanged { editable ->
|
||||
requireNotNull(editable)
|
||||
val btn = editText.rootView.findViewById<Button>(android.R.id.button1)
|
||||
if (isValid(editable.toString())) {
|
||||
editText.error = null
|
||||
btn.isEnabled = true
|
||||
} else {
|
||||
editText.error = errorMessage
|
||||
btn.isEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
builder(pref)
|
||||
addPref(pref)
|
||||
return pref
|
||||
|
|
@ -69,12 +86,12 @@ inline fun PreferenceParent.checkBoxPreference(
|
|||
}
|
||||
|
||||
inline fun PreferenceParent.preferenceCategory(
|
||||
@StringRes title: Int,
|
||||
@StringRes title: Int? = null,
|
||||
builder: PreferenceParent.(PreferenceCategory) -> Unit
|
||||
) {
|
||||
val category = PreferenceCategory(context)
|
||||
addPref(category)
|
||||
category.setTitle(title)
|
||||
title?.run(category::setTitle)
|
||||
val newParent = PreferenceParent(context) { category.addPreference(it) }
|
||||
builder(newParent, category)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue