diff --git a/src/all/mangadex/build.gradle b/src/all/mangadex/build.gradle index a10f7a7df..0dea04520 100644 --- a/src/all/mangadex/build.gradle +++ b/src/all/mangadex/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'MangaDex' pkgNameSuffix = 'all.mangadex' extClass = '.MangaDexFactory' - extVersionCode = 167 + extVersionCode = 168 isNsfw = true } diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt index 7bd954526..479b6fd4f 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MDConstants.kt @@ -6,8 +6,10 @@ import java.util.TimeZone object MDConstants { - val uuidRegex = - Regex("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}") + const val UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}" + + val uuidRegex = UUID_REGEX.toRegex() + val onlyUuidRegex = "^$UUID_REGEX$".toRegex() const val mangaLimit = 20 const val latestChapterLimit = 100 @@ -103,6 +105,11 @@ object MDConstants { return "${blockedUploaderPref}_$dexLang" } + private const val hasSanitizedUuidsPref = "hasSanitizedUuids" + fun getHasSanitizedUuidsPrefKey(dexLang: String): String { + return "${hasSanitizedUuidsPref}_$dexLang" + } + const val tagGroupContent = "content" const val tagGroupFormat = "format" const val tagGroupGenre = "genre" diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt index 11841693d..5f8ca93aa 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDex.kt @@ -64,6 +64,10 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St .addInterceptor(MdAtHomeReportInterceptor(network.client, headers)) .build() + init { + preferences.sanitizeExistingUuidPrefs() + } + // POPULAR Manga Section override fun popularMangaRequest(page: Int): Request { @@ -745,15 +749,11 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St title = helper.intl.blockGroupByUuid summary = helper.intl.blockGroupByUuidSummary - setOnPreferenceChangeListener { _, newValue -> - val groupsBlocked = newValue.toString() - .split(",") - .map { it.trim() } - .filter { helper.containsUuid(it) } - .joinToString(", ") + setOnBindEditTextListener(helper::setupEditTextUuidValidator) + setOnPreferenceChangeListener { _, newValue -> preferences.edit() - .putString(MDConstants.getBlockedGroupsPrefKey(dexLang), groupsBlocked) + .putString(MDConstants.getBlockedGroupsPrefKey(dexLang), newValue.toString()) .commit() } } @@ -763,15 +763,11 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St title = helper.intl.blockUploaderByUuid summary = helper.intl.blockUploaderByUuidSummary - setOnPreferenceChangeListener { _, newValue -> - val uploaderBlocked = newValue.toString() - .split(",") - .map { it.trim() } - .filter { helper.containsUuid(it) } - .joinToString(", ") + setOnBindEditTextListener(helper::setupEditTextUuidValidator) + setOnPreferenceChangeListener { _, newValue -> preferences.edit() - .putString(MDConstants.getBlockedUploaderPrefKey(dexLang), uploaderBlocked) + .putString(MDConstants.getBlockedUploaderPrefKey(dexLang), newValue.toString()) .commit() } } @@ -795,4 +791,28 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St private inline fun Response.parseAs(): T = use { helper.json.decodeFromString(body?.string().orEmpty()) } + + private fun SharedPreferences.sanitizeExistingUuidPrefs() { + if (getBoolean(MDConstants.getHasSanitizedUuidsPrefKey(dexLang), false)) { + return + } + + val blockedGroups = getString(MDConstants.getBlockedGroupsPrefKey(dexLang), "")!! + .split(",") + .map(String::trim) + .filter(helper::isUuid) + .joinToString(", ") + + val blockedUploaders = getString(MDConstants.getBlockedUploaderPrefKey(dexLang), "")!! + .split(",") + .map(String::trim) + .filter(helper::isUuid) + .joinToString(", ") + + edit() + .putString(MDConstants.getBlockedGroupsPrefKey(dexLang), blockedGroups) + .putString(MDConstants.getBlockedUploaderPrefKey(dexLang), blockedUploaders) + .putBoolean(MDConstants.getHasSanitizedUuidsPrefKey(dexLang), true) + .apply() + } } diff --git a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDexHelper.kt b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDexHelper.kt index bfb91b06d..346b98961 100644 --- a/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDexHelper.kt +++ b/src/all/mangadex/src/eu/kanade/tachiyomi/extension/all/mangadex/MangaDexHelper.kt @@ -1,6 +1,10 @@ package eu.kanade.tachiyomi.extension.all.mangadex +import android.text.Editable +import android.text.TextWatcher import android.util.Log +import android.widget.Button +import android.widget.EditText import eu.kanade.tachiyomi.extension.all.mangadex.dto.AtHomeDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterDataDto import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaAttributesDto @@ -19,7 +23,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.Request import org.jsoup.parser.Parser -import uy.kohesive.injekt.api.get import java.util.Date import java.util.Locale import java.util.concurrent.TimeUnit @@ -62,6 +65,11 @@ class MangaDexHelper(private val lang: String) { */ fun containsUuid(url: String) = url.contains(MDConstants.uuidRegex) + /** + * Check if the string is a valid uuid + */ + fun isUuid(text: String) = text.matches(MDConstants.onlyUuidRegex) + /** * Get the manga offset pages are 1 based, so subtract 1 */ @@ -394,4 +402,33 @@ class MangaDexHelper(private val lang: String) { currentSlug } } + + /** + * Adds a custom [TextWatcher] to the preference's [EditText] that show an + * error if the input value contains invalid UUIDs. If the validation fails, + * the Ok button is disabled to prevent the user from saving the value. + */ + fun setupEditTextUuidValidator(editText: EditText) { + editText.addTextChangedListener(object : TextWatcher { + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} + + override fun afterTextChanged(editable: Editable?) { + requireNotNull(editable) + + val text = editable.toString() + + val isValid = text.isBlank() || text + .split(",") + .map(String::trim) + .all(::isUuid) + + editText.error = if (!isValid) intl.invalidUuids else null + editText.rootView.findViewById