|
1 | 1 | package eu.kanade.tachiyomi.extension.en.hiperdex |
2 | 2 |
|
| 3 | +import android.text.Editable |
| 4 | +import android.text.TextWatcher |
| 5 | +import android.widget.Button |
| 6 | +import android.widget.Toast |
| 7 | +import androidx.preference.CheckBoxPreference |
| 8 | +import androidx.preference.EditTextPreference |
| 9 | +import androidx.preference.PreferenceScreen |
3 | 10 | import eu.kanade.tachiyomi.multisrc.hiper.Hiper |
| 11 | +import eu.kanade.tachiyomi.source.ConfigurableSource |
| 12 | +import eu.kanade.tachiyomi.source.model.MangasPage |
| 13 | +import eu.kanade.tachiyomi.source.model.SManga |
4 | 14 | import keiyoushi.annotation.Source |
5 | 15 | import keiyoushi.network.rateLimit |
| 16 | +import keiyoushi.utils.getPreferences |
| 17 | +import okhttp3.Response |
6 | 18 |
|
7 | 19 | @Source |
8 | | -abstract class Hiperdex : Hiper() { |
| 20 | +abstract class Hiperdex : |
| 21 | + Hiper(), |
| 22 | + ConfigurableSource { |
9 | 23 |
|
10 | 24 | override fun headersBuilder() = super.headersBuilder() |
11 | | - .set("x-hpx-nexus", "hpx-block-f91") |
| 25 | + .set("x-svc-gate", "f5pabmx7sdek") |
12 | 26 |
|
13 | 27 | override val client = super.client.newBuilder() |
14 | 28 | .rateLimit(3) |
15 | 29 | .build() |
| 30 | + |
| 31 | + private val preferences = getPreferences() |
| 32 | + |
| 33 | + override fun setupPreferenceScreen(screen: PreferenceScreen) { |
| 34 | + val noRemoveTitleBrowsingPref = CheckBoxPreference(screen.context).apply { |
| 35 | + key = NO_REMOVE_TITLE_BROWSING_PREF |
| 36 | + title = "Don't apply title cleaning in browsing/search results" |
| 37 | + summary = "Don't apply the 2 options above when browsing or searching for manga, but still apply them in manga details." |
| 38 | + setVisible(isRemoveTitleVersion() || customRemoveTitle().isNotEmpty()) |
| 39 | + setDefaultValue(false) |
| 40 | + } |
| 41 | + |
| 42 | + CheckBoxPreference(screen.context).apply { |
| 43 | + key = "${REMOVE_TITLE_VERSION_PREF}_$lang" |
| 44 | + title = "Remove version information from entry titles" |
| 45 | + summary = "This removes version tags like '(Official)' or '(Uncensored)' from entry titles " + |
| 46 | + "and helps identify duplicate entries in your library. " + |
| 47 | + "To update existing entries, remove them from your library (unfavorite) and refresh manually. " + |
| 48 | + "You might also want to clear the database in advanced settings." |
| 49 | + setDefaultValue(false) |
| 50 | + setOnPreferenceChangeListener { _, newValue -> |
| 51 | + val enabled = newValue as Boolean |
| 52 | + noRemoveTitleBrowsingPref.setVisible(enabled || customRemoveTitle().isNotEmpty()) |
| 53 | + true |
| 54 | + } |
| 55 | + }.also { screen.addPreference(it) } |
| 56 | + |
| 57 | + EditTextPreference(screen.context).apply { |
| 58 | + key = "${REMOVE_TITLE_CUSTOM_PREF}_$lang" |
| 59 | + title = "Custom regex to be removed from title" |
| 60 | + summary = customRemoveTitle() |
| 61 | + setDefaultValue("") |
| 62 | + |
| 63 | + val validate = { str: String -> |
| 64 | + runCatching { Regex(str) } |
| 65 | + .map { true to "" } |
| 66 | + .getOrElse { false to it.message } |
| 67 | + } |
| 68 | + |
| 69 | + setOnBindEditTextListener { editText -> |
| 70 | + editText.addTextChangedListener( |
| 71 | + object : TextWatcher { |
| 72 | + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} |
| 73 | + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} |
| 74 | + |
| 75 | + override fun afterTextChanged(editable: Editable?) { |
| 76 | + editable ?: return |
| 77 | + val text = editable.toString() |
| 78 | + val valid = validate(text) |
| 79 | + editText.error = if (!valid.first) valid.second else null |
| 80 | + editText.rootView.findViewById<Button>(android.R.id.button1)?.isEnabled = editText.error == null |
| 81 | + } |
| 82 | + }, |
| 83 | + ) |
| 84 | + } |
| 85 | + |
| 86 | + setOnPreferenceChangeListener { _, newValue -> |
| 87 | + val (isValid, message) = validate(newValue as String) |
| 88 | + if (isValid) { |
| 89 | + summary = newValue |
| 90 | + noRemoveTitleBrowsingPref.setVisible(isRemoveTitleVersion() || newValue.isNotEmpty()) |
| 91 | + } else { |
| 92 | + Toast.makeText(screen.context, message, Toast.LENGTH_LONG).show() |
| 93 | + } |
| 94 | + isValid |
| 95 | + } |
| 96 | + }.also { screen.addPreference(it) } |
| 97 | + |
| 98 | + screen.addPreference(noRemoveTitleBrowsingPref) |
| 99 | + } |
| 100 | + |
| 101 | + override fun searchMangaParse(response: Response): MangasPage { |
| 102 | + val (manga, hasNextPage) = super.searchMangaParse(response) |
| 103 | + return MangasPage( |
| 104 | + manga.map { |
| 105 | + if (!noCleanTitlesWhileBrowsing()) { |
| 106 | + it.title = it.title.cleanTitleIfNeeded() |
| 107 | + } |
| 108 | + it |
| 109 | + }, |
| 110 | + hasNextPage, |
| 111 | + ) |
| 112 | + } |
| 113 | + |
| 114 | + override fun mangaDetailsParse(response: Response): SManga = super.mangaDetailsParse(response).apply { |
| 115 | + val cleanedTitle = title.cleanTitleIfNeeded() |
| 116 | + if (cleanedTitle != title.trim()) { |
| 117 | + description = listOfNotNull(title, description) |
| 118 | + .joinToString("\n\n") |
| 119 | + title = cleanedTitle |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + private fun String.cleanTitleIfNeeded(): String { |
| 124 | + var tempTitle = this |
| 125 | + customRemoveTitle().takeIf { it.isNotEmpty() }?.let { customRegex -> |
| 126 | + runCatching { |
| 127 | + tempTitle = tempTitle.replace(Regex(customRegex), "") |
| 128 | + } |
| 129 | + } |
| 130 | + if (isRemoveTitleVersion()) { |
| 131 | + tempTitle = tempTitle.replace(titleRegex, "") |
| 132 | + } |
| 133 | + return tempTitle.trim() |
| 134 | + } |
| 135 | + |
| 136 | + private fun isRemoveTitleVersion(): Boolean = preferences.getBoolean("${REMOVE_TITLE_VERSION_PREF}_$lang", false) |
| 137 | + private fun customRemoveTitle(): String = preferences.getString("${REMOVE_TITLE_CUSTOM_PREF}_$lang", "")!! |
| 138 | + |
| 139 | + private fun noCleanTitlesWhileBrowsing(): Boolean = preferences.getBoolean(NO_REMOVE_TITLE_BROWSING_PREF, false) |
| 140 | + |
| 141 | + companion object { |
| 142 | + private const val REMOVE_TITLE_VERSION_PREF = "REMOVE_TITLE_VERSION" |
| 143 | + private const val REMOVE_TITLE_CUSTOM_PREF = "REMOVE_TITLE_CUSTOM" |
| 144 | + private const val NO_REMOVE_TITLE_BROWSING_PREF = "NO_REMOVE_TITLE_BROWSING" |
| 145 | + |
| 146 | + private val titleRegex: Regex by lazy { |
| 147 | + Regex( |
| 148 | + """^(?:\s*(?:\([^()]*\)|\{[^{}]*\}|\[(?:(?!]).)*]|«[^»]*»|〘[^〙]*〙|「[^」]*」|『[^』]*』|≪[^≫]*≫|﹛[^﹜]*﹜|〖[^〖〗]*〗|𖤍.+?𖤍|《[^》]*》|⌜.+?⌝|⟨[^⟩]*⟩)\s*)+|(?:\s*(?:\([^()]*\)|\{[^{}]*\}|\[(?:(?!]).)*]|«[^»]*»|〘[^〙]*〙|「[^」]*」|『[^』]*』|≪[^≫]*≫|﹛[^﹜]*﹜|〖[^〖〗]*〗|𖤍.+?𖤍|《[^》]*》|⌜.+?⌝|⟨[^⟩]*⟩|/\s*Official)\s*)+$""", |
| 149 | + RegexOption.IGNORE_CASE, |
| 150 | + ) |
| 151 | + } |
| 152 | + } |
16 | 153 | } |
0 commit comments