From 49b3c33fbc0d1795a8b98fc80d64fde3c6e88c3a Mon Sep 17 00:00:00 2001 From: rebelonion <87634197+rebelonion@users.noreply.github.com> Date: Fri, 26 Jan 2024 00:17:33 -0600 Subject: [PATCH] subdub toggle | regex fix (yomiroll) | idk I forgot --- .../dantotsu/media/anime/AnimeNameAdapter.kt | 23 +++++- .../dantotsu/media/anime/AnimeWatchAdapter.kt | 6 +- .../ani/dantotsu/media/anime/ExoplayerView.kt | 4 +- .../manga/mangareader/MangaReaderActivity.kt | 2 +- .../java/ani/dantotsu/parsers/AnimeParser.kt | 8 +- .../ani/dantotsu/parsers/AniyomiAdapter.kt | 75 ++++++++++++++++++- .../dantotsu/parsers/OfflineAnimeParser.kt | 1 - .../AnimePreferenceFragmentCompat.kt | 32 +++++++- 8 files changed, 134 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt index ccc44eec..a30da85f 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeNameAdapter.kt @@ -10,8 +10,8 @@ class AnimeNameAdapter { "(episode|ep|e)[\\s:.\\-]*([\\d]+\\.?[\\d]*)[\\s:.\\-]*\\(?\\s*(sub|subbed|dub|dubbed)*\\s*\\)?\\s*" const val failedEpisodeNumberRegex = "(? "sub" SubDubType.DUB -> "dub" + SubDubType.NULL -> "" } val toggledCasePreserved = 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 { - SUB, DUB + SUB, DUB, NULL } fun findSeasonNumber(text: String): Int? { diff --git a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt index 2f70a2a9..1c06c806 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/AnimeWatchAdapter.kt @@ -113,7 +113,7 @@ class AnimeWatchAdapter( binding.animeSourceTitle.text = showUserText showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } } 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 changing = false binding.animeSourceDubbedCont.visibility = - if (isDubAvailableSeparately) View.VISIBLE else View.GONE + if (isDubAvailableSeparately()) View.VISIBLE else View.GONE source = i setLanguageList(0, i) } @@ -154,7 +154,7 @@ class AnimeWatchAdapter( binding.animeSourceDubbed.isChecked = selectDub changing = false binding.animeSourceDubbedCont.visibility = - if (isDubAvailableSeparately) View.VISIBLE else View.GONE + if (isDubAvailableSeparately()) View.VISIBLE else View.GONE setLanguageList(i, source) } subscribeButton(false) diff --git a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt index f3844246..a907eee8 100644 --- a/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt +++ b/app/src/main/java/ani/dantotsu/media/anime/ExoplayerView.kt @@ -840,7 +840,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL isFastForwarding = true exoPlayer.setPlaybackSpeed(exoPlayer.playbackParameters.speed * 2) fastForward.visibility = View.VISIBLE - fastForward.text = ("${exoPlayer.playbackParameters.speed}x") + fastForward.text = "${exoPlayer.playbackParameters.speed}x" } fun stopFastForward() { @@ -1286,7 +1286,7 @@ class ExoplayerView : AppCompatActivity(), Player.Listener, SessionAvailabilityL } println("sub: $sub") } else { - val subUri = Uri.parse((subtitle!!.file.url)) + val subUri = Uri.parse(subtitle!!.file.url) sub = MediaItem.SubtitleConfiguration .Builder(subUri) .setSelectionFlags(C.SELECTION_FLAG_FORCED) diff --git a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt index 600d9305..23f8260e 100644 --- a/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt +++ b/app/src/main/java/ani/dantotsu/media/manga/mangareader/MangaReaderActivity.kt @@ -716,7 +716,7 @@ class MangaReaderActivity : AppCompatActivity() { val y = event.rawY.toInt() 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 (screenWidth / 5 in (x + 1)..() + open fun isDubAvailableSeparately(sourceLang: Int? = null): Boolean = false /** * The app changes this, depending on user's choice. @@ -182,7 +182,7 @@ abstract class AnimeParser : BaseParser() { * **/ override suspend fun loadSavedShowResponse(mediaId: Int): ShowResponse? { checkIfVariablesAreEmpty() - val dub = if (isDubAvailableSeparately) "_${if (selectDub) "dub" else "sub"}" else "" + val dub = if (isDubAvailableSeparately()) "_${if (selectDub) "dub" else "sub"}" else "" var loaded = loadData("${saveName}${dub}_$mediaId") if (loaded == null && malSyncBackupName.isNotEmpty()) loaded = MalSyncBackup.get(mediaId, malSyncBackupName, selectDub) @@ -200,7 +200,7 @@ abstract class AnimeParser : BaseParser() { ) } : ${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) } } @@ -209,8 +209,6 @@ abstract class AnimeParser : BaseParser() { class EmptyAnimeParser : AnimeParser() { override val name: String = "None" override val saveName: String = "None" - - override val isDubAvailableSeparately: Boolean = false override suspend fun loadEpisodes( animeLink: String, extra: Map?, diff --git a/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt b/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt index 4ef6aee2..5c39bae5 100644 --- a/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt +++ b/app/src/main/java/ani/dantotsu/parsers/AniyomiAdapter.kt @@ -10,12 +10,14 @@ import android.os.Build import android.os.Environment import android.provider.MediaStore import ani.dantotsu.FileUrl +import ani.dantotsu.currContext import ani.dantotsu.logger import ani.dantotsu.media.anime.AnimeNameAdapter import ani.dantotsu.media.manga.ImageData import ani.dantotsu.media.manga.MangaCache import ani.dantotsu.snackString 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.SAnime 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.network.NetworkHelper 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.Page import eu.kanade.tachiyomi.source.model.SChapter @@ -71,8 +74,63 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { override val name = extension.name override val saveName = extension.name override val hostUrl = extension.sources.first().name - override val isDubAvailableSeparately = false 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( animeLink: String, extra: Map?, @@ -106,6 +164,8 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() { } it } + } else if (episodesAreIncrementing(res)) { + res.sortedBy { it.episode_number } } else { var episodeCounter = 1f // 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() } + private fun episodesAreIncrementing(episodes: List): Boolean { + val sortedEpisodes = episodes.sortedBy { it.episode_number } + val takenNumbers = mutableListOf() + sortedEpisodes.forEach { + if (it.episode_number !in takenNumbers) { + takenNumbers.add(it.episode_number) + } else { + return false + } + } + return true + } + override suspend fun loadVideoServers( episodeLink: String, extra: Map?, diff --git a/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt b/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt index 0f8c7924..f66de95e 100644 --- a/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt +++ b/app/src/main/java/ani/dantotsu/parsers/OfflineAnimeParser.kt @@ -21,7 +21,6 @@ class OfflineAnimeParser : AnimeParser() { override val name = "Offline" override val saveName = "Offline" override val hostUrl = "Offline" - override val isDubAvailableSeparately = false override val isNSFW = false override suspend fun loadEpisodes( diff --git a/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt b/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt index 4caf9e21..40eed893 100644 --- a/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt +++ b/app/src/main/java/ani/dantotsu/settings/extensionprefs/AnimePreferenceFragmentCompat.kt @@ -1,6 +1,7 @@ package ani.dantotsu.settings.extensionprefs import android.content.Context +import android.content.SharedPreferences import android.os.Bundle import android.util.TypedValue import androidx.core.os.bundleOf @@ -8,6 +9,7 @@ import androidx.lifecycle.lifecycleScope import androidx.preference.DialogPreference import androidx.preference.EditTextPreference import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceManager import androidx.preference.forEach import androidx.preference.getOnBindEditTextListener import ani.dantotsu.snackString @@ -46,7 +48,7 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() { onCloseAction?.invoke() } - private fun populateAnimePreferenceScreen(): PreferenceScreen { + fun populateAnimePreferenceScreen(): PreferenceScreen { val sourceId = requireArguments().getLong(SOURCE_ID) val source = Injekt.get().get(sourceId) as? ConfigurableAnimeSource ?: error("Source with id: $sourceId not found!") @@ -93,3 +95,31 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() { 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 + } +} \ No newline at end of file