subdub toggle | regex fix (yomiroll) | idk I forgot

This commit is contained in:
rebelonion 2024-01-26 00:17:33 -06:00
parent 4a5eab13c9
commit 49b3c33fbc
8 changed files with 134 additions and 17 deletions

View file

@ -10,8 +10,8 @@ class AnimeNameAdapter {
"(episode|ep|e)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*" "(episode|ep|e)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*"
const val failedEpisodeNumberRegex = const val failedEpisodeNumberRegex =
"(?<!part\\s)\\b(\\d+)\\b" "(?<!part\\s)\\b(\\d+)\\b"
const val seasonRegex = "\\s+(season|s)[\\s:.\\-]*(\\d+)[\\s:.\\-]*" const val seasonRegex = "(season|s)[\\s:.\\-]*(\\d+)[\\s:.\\-]*"
const val subdubRegex = "^(soft)?[\\s-]*(sub|dub|mixed)(bed)?\\s*$" const val subdubRegex = "^(soft)?[\\s-]*(sub|dub|mixed)(bed|s)?\\s*$"
fun setSubDub(text: String, typeToSetTo: SubDubType): String? { fun setSubDub(text: String, typeToSetTo: SubDubType): String? {
val subdubPattern: Pattern = Pattern.compile(subdubRegex, Pattern.CASE_INSENSITIVE) val subdubPattern: Pattern = Pattern.compile(subdubRegex, Pattern.CASE_INSENSITIVE)
@ -25,6 +25,7 @@ class AnimeNameAdapter {
val toggled = when (typeToSetTo) { val toggled = when (typeToSetTo) {
SubDubType.SUB -> "sub" SubDubType.SUB -> "sub"
SubDubType.DUB -> "dub" SubDubType.DUB -> "dub"
SubDubType.NULL -> ""
} }
val toggledCasePreserved = val toggledCasePreserved =
if (subdub?.get(0)?.isUpperCase() == true || soft?.get(0) if (subdub?.get(0)?.isUpperCase() == true || soft?.get(0)
@ -41,8 +42,24 @@ class AnimeNameAdapter {
} }
} }
fun getSubDub(text: String): SubDubType {
val subdubPattern: Pattern = Pattern.compile(subdubRegex, Pattern.CASE_INSENSITIVE)
val subdubMatcher: Matcher = subdubPattern.matcher(text)
return if (subdubMatcher.find()) {
val subdub = subdubMatcher.group(2)?.lowercase(Locale.ROOT)
when (subdub) {
"sub" -> SubDubType.SUB
"dub" -> SubDubType.DUB
else -> SubDubType.NULL
}
} else {
SubDubType.NULL
}
}
enum class SubDubType { enum class SubDubType {
SUB, DUB SUB, DUB, NULL
} }
fun findSeasonNumber(text: String): Int? { fun findSeasonNumber(text: String): Int? {

View file

@ -113,7 +113,7 @@ class AnimeWatchAdapter(
binding.animeSourceTitle.text = showUserText binding.animeSourceTitle.text = showUserText
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } } showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
binding.animeSourceDubbedCont.visibility = binding.animeSourceDubbedCont.visibility =
if (isDubAvailableSeparately) View.VISIBLE else View.GONE if (isDubAvailableSeparately()) View.VISIBLE else View.GONE
} }
} }
@ -133,7 +133,7 @@ class AnimeWatchAdapter(
binding.animeSourceDubbed.isChecked = selectDub binding.animeSourceDubbed.isChecked = selectDub
changing = false changing = false
binding.animeSourceDubbedCont.visibility = binding.animeSourceDubbedCont.visibility =
if (isDubAvailableSeparately) View.VISIBLE else View.GONE if (isDubAvailableSeparately()) View.VISIBLE else View.GONE
source = i source = i
setLanguageList(0, i) setLanguageList(0, i)
} }
@ -154,7 +154,7 @@ class AnimeWatchAdapter(
binding.animeSourceDubbed.isChecked = selectDub binding.animeSourceDubbed.isChecked = selectDub
changing = false changing = false
binding.animeSourceDubbedCont.visibility = binding.animeSourceDubbedCont.visibility =
if (isDubAvailableSeparately) View.VISIBLE else View.GONE if (isDubAvailableSeparately()) View.VISIBLE else View.GONE
setLanguageList(i, source) setLanguageList(i, source)
} }
subscribeButton(false) subscribeButton(false)

View file

@ -840,7 +840,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
isFastForwarding = true isFastForwarding = true
exoPlayer.setPlaybackSpeed(exoPlayer.playbackParameters.speed * 2) exoPlayer.setPlaybackSpeed(exoPlayer.playbackParameters.speed * 2)
fastForward.visibility = View.VISIBLE fastForward.visibility = View.VISIBLE
fastForward.text = ("${exoPlayer.playbackParameters.speed}x") fastForward.text = "${exoPlayer.playbackParameters.speed}x"
} }
fun stopFastForward() { fun stopFastForward() {
@ -1286,7 +1286,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL
} }
println("sub: $sub") println("sub: $sub")
} else { } else {
val subUri = Uri.parse((subtitle!!.file.url)) val subUri = Uri.parse(subtitle!!.file.url)
sub = MediaItem.SubtitleConfiguration sub = MediaItem.SubtitleConfiguration
.Builder(subUri) .Builder(subUri)
.setSelectionFlags(C.SELECTION_FLAG_FORCED) .setSelectionFlags(C.SELECTION_FLAG_FORCED)

View file

@ -716,7 +716,7 @@ class MangaReaderActivity : AppCompatActivity() {
val y = event.rawY.toInt() val y = event.rawY.toInt()
val screenWidth = Resources.getSystem().displayMetrics.widthPixels val screenWidth = Resources.getSystem().displayMetrics.widthPixels
//if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left //if in the 1st 1/5th of the screen width, left and lower than 1/5th of the screen height, left
if (screenWidth / 5 in (x + 1)..<y) { if (screenWidth / 5 in x + 1..<y) {
pressLocation = if (settings.default.direction == RIGHT_TO_LEFT) { pressLocation = if (settings.default.direction == RIGHT_TO_LEFT) {
pressPos.RIGHT pressPos.RIGHT
} else { } else {

View file

@ -163,7 +163,7 @@ abstract class AnimeParser : BaseParser() {
* *
* **NOTE : do not forget to override `search` if the site does not support only dub search** * **NOTE : do not forget to override `search` if the site does not support only dub search**
* **/ * **/
open val isDubAvailableSeparately by Delegates.notNull<Boolean>() open fun isDubAvailableSeparately(sourceLang: Int? = null): Boolean = false
/** /**
* The app changes this, depending on user's choice. * The app changes this, depending on user's choice.
@ -182,7 +182,7 @@ abstract class AnimeParser : BaseParser() {
* **/ * **/
override suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? { override suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? {
checkIfVariablesAreEmpty() checkIfVariablesAreEmpty()
val dub = if (isDubAvailableSeparately) "_${if (selectDub) "dub" else "sub"}" else "" val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else ""
var loaded = loadData<ShowResponse>("${saveName}${dub}_$mediaId") var loaded = loadData<ShowResponse>("${saveName}${dub}_$mediaId")
if (loaded == null && malSyncBackupName.isNotEmpty()) if (loaded == null && malSyncBackupName.isNotEmpty())
loaded = MalSyncBackup.get(mediaId, malSyncBackupName, selectDub) loaded = MalSyncBackup.get(mediaId, malSyncBackupName, selectDub)
@ -200,7 +200,7 @@ abstract class AnimeParser : BaseParser() {
) )
} : ${response.name}" } : ${response.name}"
) )
val dub = if (isDubAvailableSeparately) "_${if (selectDub) "dub" else "sub"}" else "" val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else ""
saveData("${saveName}${dub}_$mediaId", response) saveData("${saveName}${dub}_$mediaId", response)
} }
} }
@ -209,8 +209,6 @@ abstract class AnimeParser : BaseParser() {
class EmptyAnimeParser : AnimeParser() { class EmptyAnimeParser : AnimeParser() {
override val name: String = "None" override val name: String = "None"
override val saveName: String = "None" override val saveName: String = "None"
override val isDubAvailableSeparately: Boolean = false
override suspend fun loadEpisodes( override suspend fun loadEpisodes(
animeLink: String, animeLink: String,
extra: Map<String, String>?, extra: Map<String, String>?,

View file

@ -10,12 +10,14 @@ import android.os.Build
import android.os.Environment import android.os.Environment
import android.provider.MediaStore import android.provider.MediaStore
import ani.dantotsu.FileUrl import ani.dantotsu.FileUrl
import ani.dantotsu.currContext
import ani.dantotsu.logger import ani.dantotsu.logger
import ani.dantotsu.media.anime.AnimeNameAdapter import ani.dantotsu.media.anime.AnimeNameAdapter
import ani.dantotsu.media.manga.ImageData import ani.dantotsu.media.manga.ImageData
import ani.dantotsu.media.manga.MangaCache import ani.dantotsu.media.manga.MangaCache
import ani.dantotsu.snackString import ani.dantotsu.snackString
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimesPage import eu.kanade.tachiyomi.animesource.model.AnimesPage
import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.SEpisode
@ -26,6 +28,7 @@ import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.interceptor.CloudflareBypassException import eu.kanade.tachiyomi.network.interceptor.CloudflareBypassException
import eu.kanade.tachiyomi.source.anime.getPreferenceKey
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
@ -71,8 +74,63 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
override val name = extension.name override val name = extension.name
override val saveName = extension.name override val saveName = extension.name
override val hostUrl = extension.sources.first().name override val hostUrl = extension.sources.first().name
override val isDubAvailableSeparately = false
override val isNSFW = extension.isNsfw override val isNSFW = extension.isNsfw
override var selectDub: Boolean
get() = getDub()
set(value) {
setDub(value)
}
private fun getDub(): Boolean {
val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource
?: return false
currContext()?.let { context ->
val sharedPreferences =
context.getSharedPreferences(configurableSource.getPreferenceKey(), Context.MODE_PRIVATE)
sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL }
.forEach { value ->
return when (AnimeNameAdapter.getSubDub(value.value.toString())) {
AnimeNameAdapter.Companion.SubDubType.SUB -> false
AnimeNameAdapter.Companion.SubDubType.DUB -> true
AnimeNameAdapter.Companion.SubDubType.NULL -> false
}
}
}
return false
}
fun setDub(setDub: Boolean) {
val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource
?: return
val type = when (setDub) {
true -> AnimeNameAdapter.Companion.SubDubType.DUB
false -> AnimeNameAdapter.Companion.SubDubType.SUB
}
currContext()?.let { context ->
val sharedPreferences =
context.getSharedPreferences(configurableSource.getPreferenceKey(), Context.MODE_PRIVATE)
sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL }
.forEach { value ->
val setValue = AnimeNameAdapter.setSubDub(value.value.toString(), type)
if (setValue != null) {
sharedPreferences.edit().putString(value.key, setValue).apply()
}
}
}
}
override fun isDubAvailableSeparately(sourceLang: Int?): Boolean {
val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource
?: return false
currContext()?.let { context ->
logger("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}")
val sharedPreferences =
context.getSharedPreferences(configurableSource.getPreferenceKey(), Context.MODE_PRIVATE)
sharedPreferences.all.filterValues { AnimeNameAdapter.setSubDub(it.toString(), AnimeNameAdapter.Companion.SubDubType.NULL) != null }
.forEach { _ -> return true }
}
return false
}
override suspend fun loadEpisodes( override suspend fun loadEpisodes(
animeLink: String, animeLink: String,
extra: Map<String, String>?, extra: Map<String, String>?,
@ -106,6 +164,8 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
} }
it it
} }
} else if (episodesAreIncrementing(res)) {
res.sortedBy { it.episode_number }
} else { } else {
var episodeCounter = 1f var episodeCounter = 1f
// Group by season, sort within each season, and then renumber while keeping episode number 0 as is // Group by season, sort within each season, and then renumber while keeping episode number 0 as is
@ -135,6 +195,19 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
return emptyList() return emptyList()
} }
private fun episodesAreIncrementing(episodes: List<SEpisode>): Boolean {
val sortedEpisodes = episodes.sortedBy { it.episode_number }
val takenNumbers = mutableListOf<Float>()
sortedEpisodes.forEach {
if (it.episode_number !in takenNumbers) {
takenNumbers.add(it.episode_number)
} else {
return false
}
}
return true
}
override suspend fun loadVideoServers( override suspend fun loadVideoServers(
episodeLink: String, episodeLink: String,
extra: Map<String, String>?, extra: Map<String, String>?,

View file

@ -21,7 +21,6 @@ class OfflineAnimeParser : AnimeParser() {
override val name = "Offline" override val name = "Offline"
override val saveName = "Offline" override val saveName = "Offline"
override val hostUrl = "Offline" override val hostUrl = "Offline"
override val isDubAvailableSeparately = false
override val isNSFW = false override val isNSFW = false
override suspend fun loadEpisodes( override suspend fun loadEpisodes(

View file

@ -1,6 +1,7 @@
package ani.dantotsu.settings.extensionprefs package ani.dantotsu.settings.extensionprefs
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue import android.util.TypedValue
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
@ -8,6 +9,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.preference.DialogPreference import androidx.preference.DialogPreference
import androidx.preference.EditTextPreference import androidx.preference.EditTextPreference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.preference.forEach import androidx.preference.forEach
import androidx.preference.getOnBindEditTextListener import androidx.preference.getOnBindEditTextListener
import ani.dantotsu.snackString import ani.dantotsu.snackString
@ -46,7 +48,7 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
onCloseAction?.invoke() onCloseAction?.invoke()
} }
private fun populateAnimePreferenceScreen(): PreferenceScreen { fun populateAnimePreferenceScreen(): PreferenceScreen {
val sourceId = requireArguments().getLong(SOURCE_ID) val sourceId = requireArguments().getLong(SOURCE_ID)
val source = Injekt.get<AnimeSourceManager>().get(sourceId) as? ConfigurableAnimeSource val source = Injekt.get<AnimeSourceManager>().get(sourceId) as? ConfigurableAnimeSource
?: error("Source with id: $sourceId not found!") ?: error("Source with id: $sourceId not found!")
@ -93,3 +95,31 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
private const val SOURCE_ID = "source_id" private const val SOURCE_ID = "source_id"
} }
} }
class InitialAnimeSourcePreferencesFragment(val sharedPreferences: SharedPreferences, val source: ConfigurableAnimeSource, val currContext: Context) : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceScreen = try {
populateAnimePreferenceScreen()
} catch (e: Exception) {
snackString(e.message ?: "Unknown error")
preferenceManager.createPreferenceScreen(requireContext())
}
//set background color
val color = TypedValue()
requireContext().theme.resolveAttribute(
com.google.android.material.R.attr.backgroundColor,
color,
true
)
view?.setBackgroundColor(color.data)
}
fun populateAnimePreferenceScreen(): PreferenceScreen {
val dataStore = SharedPreferencesDataStore(sharedPreferences)
preferenceManager.preferenceDataStore = dataStore
val sourceScreen = preferenceManager.createPreferenceScreen(requireContext())
source.setupPreferenceScreen(sourceScreen)
return sourceScreen
}
}