This commit is contained in:
rebelonion 2024-01-26 00:29:19 -06:00
parent 49b3c33fbc
commit 0ebd067bc2
22 changed files with 121 additions and 68 deletions

View file

@ -77,7 +77,8 @@ class App : MultiDexApplication() {
Firebase.crashlytics.setUserId("$dUsername - $aUsername") Firebase.crashlytics.setUserId("$dUsername - $aUsername")
} }
} }
FirebaseCrashlytics.getInstance().setCustomKey("device Info", SettingsActivity.getDeviceInfo()) FirebaseCrashlytics.getInstance()
.setCustomKey("device Info", SettingsActivity.getDeviceInfo())
Injekt.importModule(AppModule(this)) Injekt.importModule(AppModule(this))
Injekt.importModule(PreferenceModule(this)) Injekt.importModule(PreferenceModule(this))

View file

@ -15,7 +15,6 @@ import android.content.res.Configuration
import android.content.res.Resources.getSystem import android.content.res.Resources.getSystem
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.media.MediaScannerConnection import android.media.MediaScannerConnection
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.NetworkCapabilities.* import android.net.NetworkCapabilities.*
@ -50,7 +49,6 @@ import ani.dantotsu.media.Media
import ani.dantotsu.parsers.ShowResponse import ani.dantotsu.parsers.ShowResponse
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.subcriptions.NotificationClickReceiver import ani.dantotsu.subcriptions.NotificationClickReceiver
import ani.dantotsu.themes.ThemeManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade
@ -216,7 +214,11 @@ open class BottomSheetDialogFragment : BottomSheetDialogFragment() {
} }
val typedValue = TypedValue() val typedValue = TypedValue()
val theme = requireContext().theme val theme = requireContext().theme
theme.resolveAttribute(com.google.android.material.R.attr.colorOnSurfaceInverse, typedValue, true) theme.resolveAttribute(
com.google.android.material.R.attr.colorOnSurfaceInverse,
typedValue,
true
)
window.navigationBarColor = typedValue.data window.navigationBarColor = typedValue.data
} }

View file

@ -36,7 +36,10 @@ class AnilistQueries {
val user = response?.data?.user ?: return false val user = response?.data?.user ?: return false
currContext()?.let { currContext()?.let {
it.getSharedPreferences(it.getString(R.string.preference_file_key), Context.MODE_PRIVATE) it.getSharedPreferences(
it.getString(R.string.preference_file_key),
Context.MODE_PRIVATE
)
.edit() .edit()
.putString("anilist_username", user.name) .putString("anilist_username", user.name)
.apply() .apply()

View file

@ -1,11 +1,9 @@
package ani.dantotsu.download.anime package ani.dantotsu.download.anime
import android.animation.ObjectAnimator
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.text.Editable import android.text.Editable
@ -16,7 +14,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.AlphaAnimation import android.view.animation.AlphaAnimation
import android.view.animation.LayoutAnimationController import android.view.animation.LayoutAnimationController
import android.view.animation.OvershootInterpolator
import android.widget.AbsListView import android.widget.AbsListView
import android.widget.AutoCompleteTextView import android.widget.AutoCompleteTextView
import android.widget.GridView import android.widget.GridView
@ -48,7 +45,6 @@ import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsDialogFragment import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.settings.UserInterfaceSettings import ani.dantotsu.settings.UserInterfaceSettings
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.imageview.ShapeableImageView import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
@ -64,8 +60,6 @@ import eu.kanade.tachiyomi.source.model.SChapterImpl
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import java.io.File
import kotlin.math.max
import kotlin.math.min
class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener { class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
@ -73,7 +67,7 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
private var downloads: List<OfflineAnimeModel> = listOf() private var downloads: List<OfflineAnimeModel> = listOf()
private lateinit var gridView: GridView private lateinit var gridView: GridView
private lateinit var adapter: OfflineAnimeAdapter private lateinit var adapter: OfflineAnimeAdapter
private lateinit var total : TextView private lateinit var total: TextView
private var uiSettings: UserInterfaceSettings = private var uiSettings: UserInterfaceSettings =
loadData("ui_settings") ?: UserInterfaceSettings() loadData("ui_settings") ?: UserInterfaceSettings()
@ -162,7 +156,8 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
grid() grid()
} }
gridView = if (style == 0) view.findViewById(R.id.gridView) else view.findViewById(R.id.gridView1) gridView =
if (style == 0) view.findViewById(R.id.gridView) else view.findViewById(R.id.gridView1)
total = view.findViewById(R.id.total) total = view.findViewById(R.id.total)
grid() grid()
return view return view
@ -198,7 +193,8 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
ActivityOptionsCompat.makeSceneTransitionAnimation( ActivityOptionsCompat.makeSceneTransitionAnimation(
requireActivity(), requireActivity(),
Pair.create( Pair.create(
gridView.getChildAt(position).findViewById<ImageView>(R.id.itemCompactImage), gridView.getChildAt(position)
.findViewById<ImageView>(R.id.itemCompactImage),
ViewCompat.getTransitionName(requireActivity().findViewById(R.id.itemCompactImage)) ViewCompat.getTransitionName(requireActivity().findViewById(R.id.itemCompactImage))
), ),
).toBundle() ).toBundle()

View file

@ -17,7 +17,6 @@ import androidx.core.content.ContextCompat.getString
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes import androidx.media3.common.MimeTypes
import androidx.media3.common.TrackSelectionParameters
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.database.StandaloneDatabaseProvider import androidx.media3.database.StandaloneDatabaseProvider
import androidx.media3.datasource.DataSource import androidx.media3.datasource.DataSource
@ -31,7 +30,6 @@ import androidx.media3.exoplayer.offline.DownloadHelper
import androidx.media3.exoplayer.offline.DownloadManager import androidx.media3.exoplayer.offline.DownloadManager
import androidx.media3.exoplayer.offline.DownloadService import androidx.media3.exoplayer.offline.DownloadService
import androidx.media3.exoplayer.scheduler.Requirements import androidx.media3.exoplayer.scheduler.Requirements
import androidx.media3.ui.TrackSelectionDialogBuilder
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.defaultHeaders import ani.dantotsu.defaultHeaders
import ani.dantotsu.download.DownloadedType import ani.dantotsu.download.DownloadedType

View file

@ -271,8 +271,15 @@ class AnimeFragment : Fragment() {
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
if (isAdded) { // Check if the fragment is still attached if (isAdded) { // Check if the fragment is still attached
model.loadPopular("ANIME", sort = Anilist.sortBy[1], onList = requireContext().getSharedPreferences("Dantotsu", Context.MODE_PRIVATE) model.loadPopular(
.getBoolean("popular_list", false)) "ANIME",
sort = Anilist.sortBy[1],
onList = requireContext().getSharedPreferences(
"Dantotsu",
Context.MODE_PRIVATE
)
.getBoolean("popular_list", false)
)
} }
live.postValue(false) live.postValue(false)
_binding?.animeRefresh?.isRefreshing = false _binding?.animeRefresh?.isRefreshing = false

View file

@ -245,9 +245,16 @@ class MangaFragment : Fragment() {
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
if (isAdded) { if (isAdded) {
val sharedPrefs = requireContext().getSharedPreferences("Dantotsu", Context.MODE_PRIVATE) val sharedPrefs = requireContext().getSharedPreferences(
"Dantotsu",
Context.MODE_PRIVATE
)
val isPopularList = sharedPrefs.getBoolean("popular_list", false) val isPopularList = sharedPrefs.getBoolean("popular_list", false)
model.loadPopular("MANGA", sort = Anilist.sortBy[1], onList = isPopularList) model.loadPopular(
"MANGA",
sort = Anilist.sortBy[1],
onList = isPopularList
)
} }
live.postValue(false) live.postValue(false)
_binding?.mangaRefresh?.isRefreshing = false _binding?.mangaRefresh?.isRefreshing = false

View file

@ -126,8 +126,9 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
binding.mangaIncludeList.visibility = binding.mangaIncludeList.visibility =
if (Anilist.userid != null) View.VISIBLE else View.GONE if (Anilist.userid != null) View.VISIBLE else View.GONE
binding.mangaIncludeList.isChecked = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE) binding.mangaIncludeList.isChecked =
?.getBoolean("popular_list", true) ?: true currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
?.getBoolean("popular_list", true) ?: true
binding.mangaIncludeList.setOnCheckedChangeListener { _, isChecked -> binding.mangaIncludeList.setOnCheckedChangeListener { _, isChecked ->
onIncludeListClick.invoke(isChecked) onIncludeListClick.invoke(isChecked)

View file

@ -160,10 +160,11 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
}) })
banner.setOnTouchListener { _, motionEvent -> gestureDetector.onTouchEvent(motionEvent);true } banner.setOnTouchListener { _, motionEvent -> gestureDetector.onTouchEvent(motionEvent);true }
if (this.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE) if (this.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
.getBoolean("incognito", false)) { .getBoolean("incognito", false)
) {
binding.mediaTitle.text = " ${media.userPreferredName}" binding.mediaTitle.text = " ${media.userPreferredName}"
binding.incognito.visibility = View.VISIBLE binding.incognito.visibility = View.VISIBLE
}else { } else {
binding.mediaTitle.text = media.userPreferredName binding.mediaTitle.text = media.userPreferredName
} }
binding.mediaTitle.setOnLongClickListener { binding.mediaTitle.setOnLongClickListener {

View file

@ -60,7 +60,8 @@ class MediaInfoFragment : Fragment() {
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val model: MediaDetailsViewModel by activityViewModels() val model: MediaDetailsViewModel by activityViewModels()
val offline = requireContext().getSharedPreferences("Dantotsu", Context.MODE_PRIVATE).getBoolean("offlineMode", false) || !isOnline(requireContext()) val offline = requireContext().getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
.getBoolean("offlineMode", false) || !isOnline(requireContext())
binding.mediaInfoProgressBar.visibility = if (!loaded) View.VISIBLE else View.GONE binding.mediaInfoProgressBar.visibility = if (!loaded) View.VISIBLE else View.GONE
binding.mediaInfoContainer.visibility = if (loaded) View.VISIBLE else View.GONE binding.mediaInfoContainer.visibility = if (loaded) View.VISIBLE else View.GONE
binding.mediaInfoContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += 128f.px + navBarHeight } binding.mediaInfoContainer.updateLayoutParams<ViewGroup.MarginLayoutParams> { bottomMargin += 128f.px + navBarHeight }
@ -464,7 +465,7 @@ class MediaInfoFragment : Fragment() {
parent.addView(bindi.root) parent.addView(bindi.root)
} }
if (!media.recommendations.isNullOrEmpty() && !offline ) { if (!media.recommendations.isNullOrEmpty() && !offline) {
val bind = ItemTitleRecyclerBinding.inflate( val bind = ItemTitleRecyclerBinding.inflate(
LayoutInflater.from(context), LayoutInflater.from(context),
parent, parent,

View file

@ -17,7 +17,7 @@ import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.databinding.BottomSheetSearchFilterBinding import ani.dantotsu.databinding.BottomSheetSearchFilterBinding
import ani.dantotsu.databinding.ItemChipBinding import ani.dantotsu.databinding.ItemChipBinding
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import java.util.* import java.util.Calendar
class SearchFilterBottomDialog : BottomSheetDialogFragment() { class SearchFilterBottomDialog : BottomSheetDialogFragment() {
private var _binding: BottomSheetSearchFilterBinding? = null private var _binding: BottomSheetSearchFilterBinding? = null
@ -104,7 +104,8 @@ class SearchFilterBottomDialog : BottomSheetDialogFragment() {
ArrayAdapter( ArrayAdapter(
binding.root.context, binding.root.context,
R.layout.item_dropdown, R.layout.item_dropdown,
(1970 until Calendar.getInstance().get(Calendar.YEAR) + 2).map { it.toString() }.reversed().toTypedArray() (1970 until Calendar.getInstance().get(Calendar.YEAR) + 2).map { it.toString() }
.reversed().toTypedArray()
) )
) )
} }

View file

@ -45,9 +45,18 @@ class SubtitleDownloader {
} }
//actually downloads lol //actually downloads lol
suspend fun downloadSubtitle(context: Context, url: String, downloadedType: DownloadedType) { suspend fun downloadSubtitle(
context: Context,
url: String,
downloadedType: DownloadedType
) {
try { try {
val directory = DownloadsManager.getDirectory(context, downloadedType.type, downloadedType.title, downloadedType.chapter) val directory = DownloadsManager.getDirectory(
context,
downloadedType.type,
downloadedType.title,
downloadedType.chapter
)
if (!directory.exists()) { //just in case if (!directory.exists()) { //just in case
directory.mkdirs() directory.mkdirs()
} }

View file

@ -129,7 +129,7 @@ class EpisodeAdapter(
binding.itemEpisodeDesc.visibility = binding.itemEpisodeDesc.visibility =
if (ep.desc != null && ep.desc?.trim(' ') != "") View.VISIBLE else View.GONE if (ep.desc != null && ep.desc?.trim(' ') != "") View.VISIBLE else View.GONE
binding.itemEpisodeDesc.text = ep.desc ?: "" binding.itemEpisodeDesc.text = ep.desc ?: ""
holder.bind(ep.number, ep.downloadProgress , ep.desc) holder.bind(ep.number, ep.downloadProgress, ep.desc)
if (media.userProgress != null) { if (media.userProgress != null) {
if ((ep.number.toFloatOrNull() ?: 9999f) <= media.userProgress!!.toFloat()) { if ((ep.number.toFloatOrNull() ?: 9999f) <= media.userProgress!!.toFloat()) {
@ -391,7 +391,8 @@ class EpisodeAdapter(
}, 1000) }, 1000)
} else { } else {
binding.itemDownloadStatus.visibility = View.GONE binding.itemDownloadStatus.visibility = View.GONE
binding.itemEpisodeDesc.visibility = if (desc != null && desc.trim(' ') != "") View.VISIBLE else View.GONE binding.itemEpisodeDesc.visibility =
if (desc != null && desc.trim(' ') != "") View.VISIBLE else View.GONE
// Show download icon // Show download icon
binding.itemDownload.setImageResource(R.drawable.ic_circle_add) binding.itemDownload.setImageResource(R.drawable.ic_circle_add)
binding.itemDownload.rotation = 0f binding.itemDownload.rotation = 0f

View file

@ -8,7 +8,6 @@ import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue import android.util.TypedValue
import android.view.HapticFeedbackConstants
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup

View file

@ -2,12 +2,10 @@ package ani.dantotsu.others
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import ani.dantotsu.BottomSheetDialogFragment import ani.dantotsu.BottomSheetDialogFragment
import ani.dantotsu.R
import ani.dantotsu.databinding.BottomSheetCustomBinding import ani.dantotsu.databinding.BottomSheetCustomBinding
open class CustomBottomDialog : BottomSheetDialogFragment() { open class CustomBottomDialog : BottomSheetDialogFragment() {

View file

@ -1,11 +1,7 @@
package ani.dantotsu.others package ani.dantotsu.others
import ani.dantotsu.R
import ani.dantotsu.client import ani.dantotsu.client
import ani.dantotsu.currContext
import ani.dantotsu.media.Media import ani.dantotsu.media.Media
import ani.dantotsu.snackString
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeout
object MalScraper { object MalScraper {
@ -50,7 +46,7 @@ object MalScraper {
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
// if (e is TimeoutCancellationException) snackString(currContext()?.getString(R.string.error_loading_mal_data)) // if (e is TimeoutCancellationException) snackString(currContext()?.getString(R.string.error_loading_mal_data))
} }
} }
} }

View file

@ -11,7 +11,6 @@ import ani.dantotsu.saveData
import ani.dantotsu.tryWithSuspend import ani.dantotsu.tryWithSuspend
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
import kotlin.properties.Delegates
/** /**
* An abstract class for creating a new Source * An abstract class for creating a new Source

View file

@ -13,7 +13,8 @@ object AnimeSources : WatchSources() {
suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>, context: Context) { suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>, context: Context) {
val sharedPrefs = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE) val sharedPrefs = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
pinnedAnimeSources = sharedPrefs.getStringSet("pinned_anime_sources", emptySet()) ?: emptySet() pinnedAnimeSources =
sharedPrefs.getStringSet("pinned_anime_sources", emptySet()) ?: emptySet()
// Initialize with the first value from StateFlow // Initialize with the first value from StateFlow
val initialExtensions = fromExtensions.first() val initialExtensions = fromExtensions.first()
@ -24,7 +25,10 @@ object AnimeSources : WatchSources() {
// Update as StateFlow emits new values // Update as StateFlow emits new values
fromExtensions.collect { extensions -> fromExtensions.collect { extensions ->
list = sortPinnedAnimeSources(createParsersFromExtensions(extensions), pinnedAnimeSources) + Lazier( list = sortPinnedAnimeSources(
createParsersFromExtensions(extensions),
pinnedAnimeSources
) + Lazier(
{ OfflineAnimeParser() }, { OfflineAnimeParser() },
"Downloaded" "Downloaded"
) )
@ -34,7 +38,7 @@ object AnimeSources : WatchSources() {
fun performReorderAnimeSources() { fun performReorderAnimeSources() {
//remove the downloaded source from the list to avoid duplicates //remove the downloaded source from the list to avoid duplicates
list = list.filter { it.name != "Downloaded" } list = list.filter { it.name != "Downloaded" }
list = sortPinnedAnimeSources(list, pinnedAnimeSources) + Lazier( list = sortPinnedAnimeSources(list, pinnedAnimeSources) + Lazier(
{ OfflineAnimeParser() }, { OfflineAnimeParser() },
"Downloaded" "Downloaded"
) )
@ -47,7 +51,10 @@ object AnimeSources : WatchSources() {
} }
} }
private fun sortPinnedAnimeSources(Sources: List<Lazier<BaseParser>>, pinnedAnimeSources: Set<String>): List<Lazier<BaseParser>> { private fun sortPinnedAnimeSources(
Sources: List<Lazier<BaseParser>>,
pinnedAnimeSources: Set<String>
): List<Lazier<BaseParser>> {
//find the pinned sources //find the pinned sources
val pinnedSources = Sources.filter { pinnedAnimeSources.contains(it.name) } val pinnedSources = Sources.filter { pinnedAnimeSources.contains(it.name) }
//find the unpinned sources //find the unpinned sources

View file

@ -86,7 +86,10 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
?: return false ?: return false
currContext()?.let { context -> currContext()?.let { context ->
val sharedPreferences = val sharedPreferences =
context.getSharedPreferences(configurableSource.getPreferenceKey(), Context.MODE_PRIVATE) context.getSharedPreferences(
configurableSource.getPreferenceKey(),
Context.MODE_PRIVATE
)
sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL } sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL }
.forEach { value -> .forEach { value ->
return when (AnimeNameAdapter.getSubDub(value.value.toString())) { return when (AnimeNameAdapter.getSubDub(value.value.toString())) {
@ -108,7 +111,10 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
} }
currContext()?.let { context -> currContext()?.let { context ->
val sharedPreferences = val sharedPreferences =
context.getSharedPreferences(configurableSource.getPreferenceKey(), Context.MODE_PRIVATE) context.getSharedPreferences(
configurableSource.getPreferenceKey(),
Context.MODE_PRIVATE
)
sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL } sharedPreferences.all.filterValues { AnimeNameAdapter.getSubDub(it.toString()) != AnimeNameAdapter.Companion.SubDubType.NULL }
.forEach { value -> .forEach { value ->
val setValue = AnimeNameAdapter.setSubDub(value.value.toString(), type) val setValue = AnimeNameAdapter.setSubDub(value.value.toString(), type)
@ -118,14 +124,23 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
} }
} }
} }
override fun isDubAvailableSeparately(sourceLang: Int?): Boolean { override fun isDubAvailableSeparately(sourceLang: Int?): Boolean {
val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource
?: return false ?: return false
currContext()?.let { context -> currContext()?.let { context ->
logger("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}") logger("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}")
val sharedPreferences = val sharedPreferences =
context.getSharedPreferences(configurableSource.getPreferenceKey(), Context.MODE_PRIVATE) context.getSharedPreferences(
sharedPreferences.all.filterValues { AnimeNameAdapter.setSubDub(it.toString(), AnimeNameAdapter.Companion.SubDubType.NULL) != null } configurableSource.getPreferenceKey(),
Context.MODE_PRIVATE
)
sharedPreferences.all.filterValues {
AnimeNameAdapter.setSubDub(
it.toString(),
AnimeNameAdapter.Companion.SubDubType.NULL
) != null
}
.forEach { _ -> return true } .forEach { _ -> return true }
} }
return false return false
@ -173,20 +188,20 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
res.groupBy { AnimeNameAdapter.findSeasonNumber(it.name) ?: 0 } res.groupBy { AnimeNameAdapter.findSeasonNumber(it.name) ?: 0 }
seasonGroups.keys.sortedBy { it.toInt() } seasonGroups.keys.sortedBy { it.toInt() }
.flatMap { season -> .flatMap { season ->
seasonGroups[season]?.sortedBy { it.episode_number }?.map { episode -> seasonGroups[season]?.sortedBy { it.episode_number }?.map { episode ->
if (episode.episode_number != 0f) { // Skip renumbering for episode number 0 if (episode.episode_number != 0f) { // Skip renumbering for episode number 0
val potentialNumber = val potentialNumber =
AnimeNameAdapter.findEpisodeNumber(episode.name) AnimeNameAdapter.findEpisodeNumber(episode.name)
if (potentialNumber != null) { if (potentialNumber != null) {
episode.episode_number = potentialNumber episode.episode_number = potentialNumber
} else { } else {
episode.episode_number = episodeCounter episode.episode_number = episodeCounter
}
episodeCounter++
} }
episodeCounter++ episode
} } ?: emptyList()
episode }
} ?: emptyList()
}
} }
return sortedEpisodes.map { SEpisodeToEpisode(it) } return sortedEpisodes.map { SEpisodeToEpisode(it) }
} catch (e: Exception) { } catch (e: Exception) {
@ -250,7 +265,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
} catch (e: CloudflareBypassException) { } catch (e: CloudflareBypassException) {
logger("Exception in search: $e") logger("Exception in search: $e")
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
snackString( "Failed to bypass Cloudflare") snackString("Failed to bypass Cloudflare")
} }
emptyList() emptyList()
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -13,7 +13,8 @@ object MangaSources : MangaReadSources() {
suspend fun init(fromExtensions: StateFlow<List<MangaExtension.Installed>>, context: Context) { suspend fun init(fromExtensions: StateFlow<List<MangaExtension.Installed>>, context: Context) {
val sharedPrefs = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE) val sharedPrefs = context.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
pinnedMangaSources = sharedPrefs.getStringSet("pinned_manga_sources", emptySet()) ?: emptySet() pinnedMangaSources =
sharedPrefs.getStringSet("pinned_manga_sources", emptySet()) ?: emptySet()
// Initialize with the first value from StateFlow // Initialize with the first value from StateFlow
val initialExtensions = fromExtensions.first() val initialExtensions = fromExtensions.first()
@ -24,7 +25,10 @@ object MangaSources : MangaReadSources() {
// Update as StateFlow emits new values // Update as StateFlow emits new values
fromExtensions.collect { extensions -> fromExtensions.collect { extensions ->
list = sortPinnedMangaSources(createParsersFromExtensions(extensions), pinnedMangaSources) + Lazier( list = sortPinnedMangaSources(
createParsersFromExtensions(extensions),
pinnedMangaSources
) + Lazier(
{ OfflineMangaParser() }, { OfflineMangaParser() },
"Downloaded" "Downloaded"
) )
@ -47,7 +51,10 @@ object MangaSources : MangaReadSources() {
} }
} }
private fun sortPinnedMangaSources(Sources: List<Lazier<BaseParser>>, pinnedMangaSources: Set<String>): List<Lazier<BaseParser>> { private fun sortPinnedMangaSources(
Sources: List<Lazier<BaseParser>>,
pinnedMangaSources: Set<String>
): List<Lazier<BaseParser>> {
//find the pinned sources //find the pinned sources
val pinnedSources = Sources.filter { pinnedMangaSources.contains(it.name) } val pinnedSources = Sources.filter { pinnedMangaSources.contains(it.name) }
//find the unpinned sources //find the unpinned sources

View file

@ -62,6 +62,7 @@ data class VideoServer(
) : Serializable { ) : Serializable {
constructor(name: String, embedUrl: String, extraData: Map<String, String>? = null) constructor(name: String, embedUrl: String, extraData: Map<String, String>? = null)
: this(name, FileUrl(embedUrl), extraData) : this(name, FileUrl(embedUrl), extraData)
constructor(name: String, offline: Boolean, extraData: Map<String, String>?) constructor(name: String, offline: Boolean, extraData: Map<String, String>?)
: this(name, FileUrl(""), extraData, null, offline) : this(name, FileUrl(""), extraData, null, offline)

View file

@ -9,7 +9,6 @@ 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
@ -96,7 +95,11 @@ class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
} }
} }
class InitialAnimeSourcePreferencesFragment(val sharedPreferences: SharedPreferences, val source: ConfigurableAnimeSource, val currContext: Context) : PreferenceFragmentCompat() { class InitialAnimeSourcePreferencesFragment(
val sharedPreferences: SharedPreferences,
val source: ConfigurableAnimeSource,
val currContext: Context
) : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceScreen = try { preferenceScreen = try {
populateAnimePreferenceScreen() populateAnimePreferenceScreen()