From 73df68021492a9f8cf7b01ed8672e042b422ff9c Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 12 Jul 2022 11:13:33 +0300 Subject: [PATCH] Add domain validation in source settings --- .../kotatsu/settings/DomainValidator.kt | 20 +++++++ .../kotatsu/settings/SourceSettingsExt.kt | 1 + .../settings/utils/EditTextBindListener.kt | 5 +- .../kotatsu/utils/EditTextValidator.kt | 54 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt b/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt new file mode 100644 index 000000000..6fc5adab3 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/settings/DomainValidator.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.settings + +import okhttp3.internal.toCanonicalHost +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.utils.EditTextValidator + +class DomainValidator : EditTextValidator() { + + override fun validate(text: String): ValidationResult { + if (text.isBlank()) { + return ValidationResult.Success + } + val host = text.trim().toCanonicalHost() + return if (host == null) { + ValidationResult.Failed(context.getString(R.string.invalid_domain_message)) + } else { + ValidationResult.Success + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsExt.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsExt.kt index 3a7c8843c..4776223d7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/SourceSettingsExt.kt @@ -28,6 +28,7 @@ fun PreferenceFragmentCompat.addPreferencesFromRepository(repository: RemoteMang EditTextBindListener( inputType = EditorInfo.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_URI, hint = key.defaultValue, + validator = DomainValidator(), ) ) setTitle(R.string.domain) diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt b/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt index 0390bceaa..50e93f24b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/settings/utils/EditTextBindListener.kt @@ -2,14 +2,17 @@ package org.koitharu.kotatsu.settings.utils import android.widget.EditText import androidx.preference.EditTextPreference +import org.koitharu.kotatsu.utils.EditTextValidator class EditTextBindListener( private val inputType: Int, - private val hint: String + private val hint: String, + private val validator: EditTextValidator?, ) : EditTextPreference.OnBindEditTextListener { override fun onBindEditText(editText: EditText) { editText.inputType = inputType editText.hint = hint + validator?.attachToEditText(editText) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt b/app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt new file mode 100644 index 000000000..37ca77618 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/utils/EditTextValidator.kt @@ -0,0 +1,54 @@ +package org.koitharu.kotatsu.utils + +import android.content.Context +import android.text.Editable +import android.text.TextWatcher +import android.widget.EditText +import androidx.annotation.CallSuper +import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import java.lang.ref.WeakReference + +abstract class EditTextValidator : TextWatcher { + + private var editTextRef: WeakReference? = null + + protected val context: Context + get() = checkNotNull(editTextRef?.get()?.context) { + "EditTextValidator is not attached to EditText" + } + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit + + @CallSuper + override fun afterTextChanged(s: Editable?) { + val editText = editTextRef?.get() ?: return + val newText = s?.toString().orEmpty() + val result = runCatching { + validate(newText) + }.getOrElse { e -> + ValidationResult.Failed(e.getDisplayMessage(editText.resources)) + } + editText.error = when (result) { + is ValidationResult.Failed -> result.message + ValidationResult.Success -> null + } + } + + fun attachToEditText(editText: EditText) { + editTextRef = WeakReference(editText) + editText.removeTextChangedListener(this) + editText.addTextChangedListener(this) + afterTextChanged(editText.text) + } + + abstract fun validate(text: String): ValidationResult + + sealed class ValidationResult { + + object Success : ValidationResult() + + class Failed(val message: CharSequence) : ValidationResult() + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6a4dfc4c5..4d234c7b7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -320,4 +320,5 @@ Manga marked as NSFW will never added to the history and your progress will not be saved Can help in case of some issues. All authorizations will be invalidated Show all + Invalid domain \ No newline at end of file