extension settings
This commit is contained in:
parent
9c0ef7a788
commit
3368a1bc8d
76 changed files with 2320 additions and 131 deletions
|
@ -85,14 +85,20 @@ class MainActivity : AppCompatActivity() {
|
|||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
|
||||
val _bottomBar = findViewById<AnimatedBottomBar>(R.id.navbar)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val bottomBar = findViewById<AnimatedBottomBar>(R.id.navbar)
|
||||
val backgroundDrawable = bottomBar.background as GradientDrawable
|
||||
|
||||
val backgroundDrawable = _bottomBar.background as GradientDrawable
|
||||
val currentColor = backgroundDrawable.color?.defaultColor ?: 0
|
||||
val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xE8000000.toInt()
|
||||
backgroundDrawable.setColor(semiTransparentColor)
|
||||
bottomBar.background = backgroundDrawable
|
||||
_bottomBar.background = backgroundDrawable
|
||||
}
|
||||
val colorOverflow = this.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
.getBoolean("colorOverflow", false)
|
||||
if (!colorOverflow) {
|
||||
_bottomBar.background = ContextCompat.getDrawable(this, R.drawable.bottom_nav_gray)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package ani.dantotsu.aniyomi.anime.custom
|
|||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
|
@ -12,7 +13,11 @@ import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
|
|||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||
import eu.kanade.tachiyomi.source.anime.AndroidAnimeSourceManager
|
||||
import eu.kanade.tachiyomi.source.manga.AndroidMangaSourceManager
|
||||
import kotlinx.serialization.json.Json
|
||||
import tachiyomi.domain.source.anime.service.AnimeSourceManager
|
||||
import tachiyomi.domain.source.manga.service.MangaSourceManager
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addSingleton
|
||||
|
@ -26,9 +31,11 @@ class AppModule(val app: Application) : InjektModule {
|
|||
addSingletonFactory { NetworkHelper(app, get()) }
|
||||
|
||||
addSingletonFactory { AnimeExtensionManager(app) }
|
||||
|
||||
addSingletonFactory { MangaExtensionManager(app) }
|
||||
|
||||
addSingletonFactory<AnimeSourceManager> { AndroidAnimeSourceManager(app, get()) }
|
||||
addSingletonFactory<MangaSourceManager> { AndroidMangaSourceManager(app, get()) }
|
||||
|
||||
val sharedPreferences = app.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)
|
||||
addSingleton(sharedPreferences)
|
||||
|
||||
|
@ -40,6 +47,11 @@ class AppModule(val app: Application) : InjektModule {
|
|||
}
|
||||
|
||||
addSingletonFactory { MangaCache() }
|
||||
|
||||
ContextCompat.getMainExecutor(app).execute {
|
||||
get<AnimeSourceManager>()
|
||||
get<MangaSourceManager>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package ani.dantotsu.home
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -19,6 +22,7 @@ import ani.dantotsu.media.GenreActivity
|
|||
import ani.dantotsu.MediaPageTransformer
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ItemAnimePageBinding
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.loadImage
|
||||
|
@ -58,6 +62,16 @@ class AnimePageAdapter : RecyclerView.Adapter<AnimePageAdapter.AnimePageViewHold
|
|||
textInputLayout.boxBackgroundColor = semiTransparentColor
|
||||
val materialCardView = holder.itemView.findViewById<MaterialCardView>(R.id.animeUserAvatarContainer)
|
||||
materialCardView.setCardBackgroundColor(semiTransparentColor)
|
||||
val typedValue = TypedValue()
|
||||
currContext()?.theme?.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
|
||||
val color = typedValue.data
|
||||
|
||||
|
||||
val colorOverflow = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)?.getBoolean("colorOverflow", false) ?: false
|
||||
if (!colorOverflow) {
|
||||
textInputLayout.boxBackgroundColor = (color and 0x00FFFFFF) or 0x28000000.toInt()
|
||||
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000.toInt())
|
||||
}
|
||||
|
||||
binding.animeTitleContainer.updatePadding(top = statusBarHeight)
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package ani.dantotsu.home
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -19,6 +21,7 @@ import ani.dantotsu.media.GenreActivity
|
|||
import ani.dantotsu.MediaPageTransformer
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.currContext
|
||||
import ani.dantotsu.databinding.ItemMangaPageBinding
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.loadImage
|
||||
|
@ -53,10 +56,20 @@ class MangaPageAdapter : RecyclerView.Adapter<MangaPageAdapter.MangaPageViewHold
|
|||
|
||||
val textInputLayout = holder.itemView.findViewById<TextInputLayout>(R.id.mangaSearchBar)
|
||||
val currentColor = textInputLayout.boxBackgroundColor
|
||||
val semiTransparentColor= (currentColor and 0x00FFFFFF) or 0xA8000000.toInt()
|
||||
val semiTransparentColor = (currentColor and 0x00FFFFFF) or 0xA8000000.toInt()
|
||||
textInputLayout.boxBackgroundColor = semiTransparentColor
|
||||
val materialCardView = holder.itemView.findViewById<MaterialCardView>(R.id.mangaUserAvatarContainer)
|
||||
materialCardView.setCardBackgroundColor(semiTransparentColor)
|
||||
val typedValue = TypedValue()
|
||||
currContext()?.theme?.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
|
||||
val color = typedValue.data
|
||||
|
||||
|
||||
val colorOverflow = currContext()?.getSharedPreferences("Dantotsu", Context.MODE_PRIVATE)?.getBoolean("colorOverflow", false) ?: false
|
||||
if (!colorOverflow) {
|
||||
textInputLayout.boxBackgroundColor = (color and 0x00FFFFFF) or 0x28000000.toInt()
|
||||
materialCardView.setCardBackgroundColor((color and 0x00FFFFFF) or 0x28000000.toInt())
|
||||
}
|
||||
|
||||
binding.mangaTitleContainer.updatePadding(top = statusBarHeight)
|
||||
|
||||
|
|
|
@ -120,8 +120,8 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
private val episodes = MutableLiveData<MutableMap<Int, MutableMap<String, Episode>>>(null)
|
||||
private val epsLoaded = mutableMapOf<Int, MutableMap<String, Episode>>()
|
||||
fun getEpisodes(): LiveData<MutableMap<Int, MutableMap<String, Episode>>> = episodes
|
||||
suspend fun loadEpisodes(media: Media, i: Int) {
|
||||
if (!epsLoaded.containsKey(i)) {
|
||||
suspend fun loadEpisodes(media: Media, i: Int, invalidate: Boolean = false) {
|
||||
if (!epsLoaded.containsKey(i) || invalidate) {
|
||||
epsLoaded[i] = watchSources?.loadEpisodesFromMedia(i, media) ?: return
|
||||
}
|
||||
episodes.postValue(epsLoaded)
|
||||
|
@ -240,9 +240,9 @@ class MediaDetailsViewModel : ViewModel() {
|
|||
private val mangaChapters = MutableLiveData<MutableMap<Int, MutableMap<String, MangaChapter>>>(null)
|
||||
private val mangaLoaded = mutableMapOf<Int, MutableMap<String, MangaChapter>>()
|
||||
fun getMangaChapters(): LiveData<MutableMap<Int, MutableMap<String, MangaChapter>>> = mangaChapters
|
||||
suspend fun loadMangaChapters(media: Media, i: Int) {
|
||||
suspend fun loadMangaChapters(media: Media, i: Int, invalidate: Boolean = false) {
|
||||
logger("Loading Manga Chapters : $mangaLoaded")
|
||||
if (!mangaLoaded.containsKey(i)) tryWithSuspend {
|
||||
if (!mangaLoaded.containsKey(i) || invalidate) tryWithSuspend {
|
||||
mangaLoaded[i] = mangaReadSources?.loadChaptersFromMedia(i, media) ?: return@tryWithSuspend
|
||||
}
|
||||
mangaChapters.postValue(mangaLoaded)
|
||||
|
|
|
@ -9,6 +9,7 @@ data class Selected(
|
|||
var chip: Int = 0,
|
||||
//var source: String = "",
|
||||
var sourceIndex: Int = 0,
|
||||
var langIndex: Int = 0,
|
||||
var preferDub: Boolean = false,
|
||||
var server: String? = null,
|
||||
var video: Int = 0,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package ani.dantotsu.media.anime
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.util.TypedValue
|
||||
|
@ -8,23 +10,38 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.databinding.ItemAnimeWatchBinding
|
||||
import ani.dantotsu.databinding.ItemChipBinding
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.parsers.WatchSources
|
||||
import ani.dantotsu.settings.ExtensionsActivity
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
|
||||
class AnimeWatchAdapter(
|
||||
private val media: Media,
|
||||
|
@ -70,7 +87,8 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
|
||||
//Source Selection
|
||||
val source = media.selected!!.sourceIndex.let { if (it >= watchSources.names.size) 0 else it }
|
||||
var source = media.selected!!.sourceIndex.let { if (it >= watchSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex,source)
|
||||
if (watchSources.names.isNotEmpty() && source in 0 until watchSources.names.size) {
|
||||
binding.animeSource.setText(watchSources.names[source])
|
||||
watchSources[source].apply {
|
||||
|
@ -92,11 +110,41 @@ class AnimeWatchAdapter(
|
|||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
binding.animeSourceDubbedCont.visibility = if (isDubAvailableSeparately) View.VISIBLE else View.GONE
|
||||
source = i
|
||||
setLanguageList(0,i)
|
||||
}
|
||||
subscribeButton(false)
|
||||
fragment.loadEpisodes(i)
|
||||
fragment.loadEpisodes(i, false)
|
||||
}
|
||||
|
||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
// Check if 'extension' and 'selected' properties exist and are accessible
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
ext.sourceLanguage = i
|
||||
fragment.onLangChange(i)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
changing = true
|
||||
binding.animeSourceDubbed.isChecked = selectDub
|
||||
changing = false
|
||||
binding.animeSourceDubbedCont.visibility = if (isDubAvailableSeparately) View.VISIBLE else View.GONE
|
||||
setLanguageList(i, source)
|
||||
}
|
||||
subscribeButton(false)
|
||||
fragment.loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
} ?: run {
|
||||
}
|
||||
}
|
||||
|
||||
//settings
|
||||
binding.animeSourceSettings.setOnClickListener {
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
fragment.openSettings(ext.extension)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Subscription
|
||||
subscribe = MediaDetailsActivity.PopImageButton(
|
||||
fragment.lifecycleScope,
|
||||
|
@ -263,6 +311,25 @@ class AnimeWatchAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
fun setLanguageList(lang: Int, source: Int) {
|
||||
val binding = _binding
|
||||
if (watchSources is AnimeSources) {
|
||||
val parser = watchSources[source] as? DynamicAnimeParser
|
||||
if (parser != null) {
|
||||
(watchSources[source] as? DynamicAnimeParser)?.let { ext ->
|
||||
ext.sourceLanguage = lang
|
||||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
}catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources.firstOrNull()?.lang ?: "Unknown")
|
||||
}
|
||||
binding?.animeSourceLanguage?.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, parser.extension.sources.map { it.lang }))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
package ani.dantotsu.media.anime
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.math.MathUtils
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -13,24 +19,38 @@ import androidx.fragment.app.activityViewModels
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.parsers.AnimeParser
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.HAnimeSources
|
||||
import ani.dantotsu.settings.ExtensionsActivity
|
||||
import ani.dantotsu.settings.InstalledAnimeExtensionsFragment
|
||||
import ani.dantotsu.settings.PlayerSettings
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.subcriptions.Notifications
|
||||
import ani.dantotsu.subcriptions.Notifications.Group.ANIME_GROUP
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
@ -214,6 +234,13 @@ class AnimeWatchFragment : Fragment() {
|
|||
return model.watchSources?.get(i)!!
|
||||
}
|
||||
|
||||
fun onLangChange(i: Int) {
|
||||
val selected = model.loadSelected(media)
|
||||
selected.langIndex = i
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
media.selected = selected
|
||||
}
|
||||
|
||||
fun onDubClicked(checked: Boolean) {
|
||||
val selected = model.loadSelected(media)
|
||||
model.watchSources?.get(selected.sourceIndex)?.selectDub = checked
|
||||
|
@ -223,8 +250,8 @@ class AnimeWatchFragment : Fragment() {
|
|||
lifecycleScope.launch(Dispatchers.IO) { model.forceLoadEpisode(media, selected.sourceIndex) }
|
||||
}
|
||||
|
||||
fun loadEpisodes(i: Int) {
|
||||
lifecycleScope.launch(Dispatchers.IO) { model.loadEpisodes(media, i) }
|
||||
fun loadEpisodes(i: Int, invalidate: Boolean) {
|
||||
lifecycleScope.launch(Dispatchers.IO) { model.loadEpisodes(media, i, invalidate) }
|
||||
}
|
||||
|
||||
fun onIconPressed(viewType: Int, rev: Boolean) {
|
||||
|
@ -262,45 +289,115 @@ class AnimeWatchFragment : Fragment() {
|
|||
else getString(R.string.unsubscribed_notification)
|
||||
)
|
||||
}
|
||||
|
||||
fun onEpisodeClick(i: String) {
|
||||
model.continueMedia = false
|
||||
model.saveSelected(media.id, media.selected!!, requireActivity())
|
||||
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest episode for subscription
|
||||
selected.latest = media.anime?.episodes?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest = media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
headerAdapter.handleEpisodes()
|
||||
episodeAdapter.notifyItemRangeRemoved(0, episodeAdapter.arr.size)
|
||||
var arr: ArrayList<Episode> = arrayListOf()
|
||||
if (media.anime!!.episodes != null) {
|
||||
val end = if (end != null && end!! < media.anime!!.episodes!!.size) end else null
|
||||
arr.addAll(
|
||||
media.anime!!.episodes!!.values.toList()
|
||||
.slice(start..(end ?: (media.anime!!.episodes!!.size - 1)))
|
||||
)
|
||||
if (reverse)
|
||||
arr = (arr.reversed() as? ArrayList<Episode>) ?: arr
|
||||
fun openSettings(pkg: AnimeExtension.Installed){
|
||||
val changeUIVisibility: (Boolean) -> Unit = { show ->
|
||||
val activity = requireActivity() as MediaDetailsActivity
|
||||
val visibility = if (show) View.VISIBLE else View.GONE
|
||||
activity.findViewById<AppBarLayout>(R.id.mediaAppBar).visibility = visibility
|
||||
activity.findViewById<ViewPager2>(R.id.mediaViewPager).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaCover).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaClose).visibility = visibility
|
||||
try{
|
||||
activity.findViewById<CustomBottomNavBar>(R.id.mediaTab).visibility = visibility
|
||||
}catch (e: ClassCastException){
|
||||
activity.findViewById<NavigationRailView>(R.id.mediaTab).visibility = visibility
|
||||
}
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
val allSettings = pkg.sources.filterIsInstance<ConfigurableAnimeSource>()
|
||||
if (allSettings.isNotEmpty()) {
|
||||
var selectedSetting = allSettings[0]
|
||||
if (allSettings.size > 1) {
|
||||
val names = allSettings.map { it.lang }.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { _, which ->
|
||||
selectedIndex = which
|
||||
}
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.cancel()
|
||||
changeUIVisibility(true)
|
||||
return@setNegativeButton
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
changeUIVisibility(true)
|
||||
loadEpisodes(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
changeUIVisibility(false)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
episodeAdapter.arr = arr
|
||||
episodeAdapter.updateType(style ?: uiSettings.animeDefaultView)
|
||||
episodeAdapter.notifyItemRangeInserted(0, arr.size)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
model.watchSources?.flushText()
|
||||
super.onDestroy()
|
||||
}
|
||||
fun onEpisodeClick(i: String) {
|
||||
model.continueMedia = false
|
||||
model.saveSelected(media.id, media.selected!!, requireActivity())
|
||||
model.onEpisodeClick(media, i, requireActivity().supportFragmentManager)
|
||||
}
|
||||
|
||||
var state: Parcelable? = null
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun reload() {
|
||||
val selected = model.loadSelected(media)
|
||||
|
||||
//Find latest episode for subscription
|
||||
selected.latest =
|
||||
media.anime?.episodes?.values?.maxOfOrNull { it.number.toFloatOrNull() ?: 0f } ?: 0f
|
||||
selected.latest =
|
||||
media.userProgress?.toFloat()?.takeIf { selected.latest < it } ?: selected.latest
|
||||
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
headerAdapter.handleEpisodes()
|
||||
episodeAdapter.notifyItemRangeRemoved(0, episodeAdapter.arr.size)
|
||||
var arr: ArrayList<Episode> = arrayListOf()
|
||||
if (media.anime!!.episodes != null) {
|
||||
val end = if (end != null && end!! < media.anime!!.episodes!!.size) end else null
|
||||
arr.addAll(
|
||||
media.anime!!.episodes!!.values.toList()
|
||||
.slice(start..(end ?: (media.anime!!.episodes!!.size - 1)))
|
||||
)
|
||||
if (reverse)
|
||||
arr = (arr.reversed() as? ArrayList<Episode>) ?: arr
|
||||
}
|
||||
episodeAdapter.arr = arr
|
||||
episodeAdapter.updateType(style ?: uiSettings.animeDefaultView)
|
||||
episodeAdapter.notifyItemRangeInserted(0, arr.size)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
model.watchSources?.flushText()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
var state: Parcelable? = null
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.mediaInfoProgressBar.visibility = progress
|
||||
|
|
|
@ -17,12 +17,17 @@ import ani.dantotsu.databinding.ItemChipBinding
|
|||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.SourceSearchDialogFragment
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.DynamicAnimeParser
|
||||
import ani.dantotsu.parsers.DynamicMangaParser
|
||||
import ani.dantotsu.parsers.MangaReadSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.subcriptions.Notifications.Companion.openSettings
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import com.google.android.material.chip.Chip
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
|
||||
class MangaReadAdapter(
|
||||
private val media: Media,
|
||||
|
@ -50,10 +55,10 @@ class MangaReadAdapter(
|
|||
}
|
||||
|
||||
//Source Selection
|
||||
val source = media.selected!!.sourceIndex.let { if (it >= mangaReadSources.names.size) 0 else it }
|
||||
var source = media.selected!!.sourceIndex.let { if (it >= mangaReadSources.names.size) 0 else it }
|
||||
setLanguageList(media.selected!!.langIndex,source)
|
||||
if (mangaReadSources.names.isNotEmpty() && source in 0 until mangaReadSources.names.size) {
|
||||
binding.animeSource.setText(mangaReadSources.names[source])
|
||||
|
||||
mangaReadSources[source].apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
|
@ -65,9 +70,34 @@ class MangaReadAdapter(
|
|||
fragment.onSourceChange(i).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
source = i
|
||||
setLanguageList(0,i)
|
||||
}
|
||||
subscribeButton(false)
|
||||
fragment.loadChapters(i)
|
||||
fragment.loadChapters(i, false)
|
||||
}
|
||||
|
||||
binding.animeSourceLanguage.setOnItemClickListener { _, _, i, _ ->
|
||||
// Check if 'extension' and 'selected' properties exist and are accessible
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
ext.sourceLanguage = i
|
||||
fragment.onLangChange(i)
|
||||
fragment.onSourceChange(media.selected!!.sourceIndex).apply {
|
||||
binding.animeSourceTitle.text = showUserText
|
||||
showUserTextListener = { MainScope().launch { binding.animeSourceTitle.text = it } }
|
||||
setLanguageList(i, source)
|
||||
}
|
||||
subscribeButton(false)
|
||||
fragment.loadChapters(media.selected!!.sourceIndex, true)
|
||||
} ?: run {
|
||||
}
|
||||
}
|
||||
|
||||
//settings
|
||||
binding.animeSourceSettings.setOnClickListener {
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
fragment.openSettings(ext.extension)
|
||||
}
|
||||
}
|
||||
|
||||
//Subscription
|
||||
|
@ -224,6 +254,25 @@ class MangaReadAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
fun setLanguageList(lang: Int, source: Int) {
|
||||
val binding = _binding
|
||||
if (mangaReadSources is MangaSources) {
|
||||
val parser = mangaReadSources[source] as? DynamicMangaParser
|
||||
if (parser != null) {
|
||||
(mangaReadSources[source] as? DynamicMangaParser)?.let { ext ->
|
||||
ext.sourceLanguage = lang
|
||||
}
|
||||
try {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources[lang].lang)
|
||||
}catch (e: IndexOutOfBoundsException) {
|
||||
binding?.animeSourceLanguage?.setText(parser.extension.sources.firstOrNull()?.lang ?: "Unknown")
|
||||
}
|
||||
binding?.animeSourceLanguage?.setAdapter(ArrayAdapter(fragment.requireContext(), R.layout.item_dropdown, parser.extension.sources.map { it.lang }))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = 1
|
||||
|
||||
inner class ViewHolder(val binding: ItemAnimeWatchBinding) : RecyclerView.ViewHolder(binding.root)
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package ani.dantotsu.media.manga
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.Toast
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.core.math.MathUtils.clamp
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -13,20 +17,30 @@ import androidx.fragment.app.activityViewModels
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.*
|
||||
import ani.dantotsu.databinding.FragmentAnimeWatchBinding
|
||||
import ani.dantotsu.media.manga.mangareader.ChapterLoaderDialog
|
||||
import ani.dantotsu.media.Media
|
||||
import ani.dantotsu.media.MediaDetailsActivity
|
||||
import ani.dantotsu.media.MediaDetailsViewModel
|
||||
import ani.dantotsu.parsers.HMangaSources
|
||||
import ani.dantotsu.parsers.MangaParser
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
|
||||
import ani.dantotsu.subcriptions.Notifications
|
||||
import ani.dantotsu.subcriptions.Notifications.Group.MANGA_GROUP
|
||||
import ani.dantotsu.subcriptions.Subscription.Companion.getChannelId
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper
|
||||
import ani.dantotsu.subcriptions.SubscriptionHelper.Companion.saveSubscription
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import com.google.android.material.navigationrail.NavigationRailView
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.ceil
|
||||
|
@ -185,8 +199,16 @@ open class MangaReadFragment : Fragment() {
|
|||
return model.mangaReadSources?.get(i)!!
|
||||
}
|
||||
|
||||
fun loadChapters(i: Int) {
|
||||
lifecycleScope.launch(Dispatchers.IO) { model.loadMangaChapters(media, i) }
|
||||
fun onLangChange(i: Int) {
|
||||
val selected = model.loadSelected(media)
|
||||
selected.langIndex = i
|
||||
model.saveSelected(media.id, selected, requireActivity())
|
||||
media.selected = selected
|
||||
}
|
||||
|
||||
|
||||
fun loadChapters(i: Int, invalidate: Boolean) {
|
||||
lifecycleScope.launch(Dispatchers.IO) { model.loadMangaChapters(media, i, invalidate) }
|
||||
}
|
||||
|
||||
fun onIconPressed(viewType: Int, rev: Boolean) {
|
||||
|
@ -225,6 +247,75 @@ open class MangaReadFragment : Fragment() {
|
|||
)
|
||||
}
|
||||
|
||||
fun openSettings(pkg: MangaExtension.Installed){
|
||||
val changeUIVisibility: (Boolean) -> Unit = { show ->
|
||||
val activity = requireActivity() as MediaDetailsActivity
|
||||
val visibility = if (show) View.VISIBLE else View.GONE
|
||||
activity.findViewById<AppBarLayout>(R.id.mediaAppBar).visibility = visibility
|
||||
activity.findViewById<ViewPager2>(R.id.mediaViewPager).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaCover).visibility = visibility
|
||||
activity.findViewById<CardView>(R.id.mediaClose).visibility = visibility
|
||||
try{
|
||||
activity.findViewById<CustomBottomNavBar>(R.id.mediaTab).visibility = visibility
|
||||
}catch (e: ClassCastException){
|
||||
activity.findViewById<NavigationRailView>(R.id.mediaTab).visibility = visibility
|
||||
}
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
val allSettings = pkg.sources.filterIsInstance<ConfigurableSource>()
|
||||
if (allSettings.isNotEmpty()) {
|
||||
var selectedSetting = allSettings[0]
|
||||
if (allSettings.size > 1) {
|
||||
val names = allSettings.map { it.lang }.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { _, which ->
|
||||
selectedIndex = which
|
||||
}
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment =
|
||||
MangaSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.cancel()
|
||||
changeUIVisibility(true)
|
||||
return@setNegativeButton
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
changeUIVisibility(true)
|
||||
loadChapters(media.selected!!.sourceIndex, true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
changeUIVisibility(false)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun onMangaChapterClick(i: String) {
|
||||
model.continueMedia = false
|
||||
media.manga?.chapters?.get(i)?.let {
|
||||
|
|
|
@ -18,6 +18,8 @@ import ani.dantotsu.currContext
|
|||
import ani.dantotsu.logger
|
||||
import ani.dantotsu.media.manga.ImageData
|
||||
import ani.dantotsu.media.manga.MangaCache
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
|
@ -62,6 +64,7 @@ class AniyomiAdapter {
|
|||
|
||||
class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
||||
val extension: AnimeExtension.Installed
|
||||
var sourceLanguage = 0
|
||||
init {
|
||||
this.extension = extension
|
||||
}
|
||||
|
@ -71,7 +74,12 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
override val isDubAvailableSeparately = false
|
||||
override val isNSFW = extension.isNsfw
|
||||
override suspend fun loadEpisodes(animeLink: String, extra: Map<String, String>?, sAnime: SAnime): List<Episode> {
|
||||
val source = extension.sources.first()
|
||||
val source = try{
|
||||
extension.sources[sourceLanguage]
|
||||
}catch (e: Exception){
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
}
|
||||
if (source is AnimeCatalogueSource) {
|
||||
try {
|
||||
val res = source.getEpisodeList(sAnime)
|
||||
|
@ -91,7 +99,12 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
}
|
||||
|
||||
override suspend fun loadVideoServers(episodeLink: String, extra: Map<String, String>?, sEpisode: SEpisode): List<VideoServer> {
|
||||
val source = extension.sources.first() as? AnimeCatalogueSource ?: return emptyList()
|
||||
val source = try{
|
||||
extension.sources[sourceLanguage]
|
||||
}catch (e: Exception){
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? AnimeCatalogueSource ?: return emptyList()
|
||||
|
||||
return try {
|
||||
val videos = source.getVideoList(sEpisode)
|
||||
|
@ -108,8 +121,12 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
}
|
||||
|
||||
override suspend fun search(query: String): List<ShowResponse> {
|
||||
val source = extension.sources.first() as? AnimeCatalogueSource ?: return emptyList()
|
||||
|
||||
val source = try{
|
||||
extension.sources[sourceLanguage]
|
||||
}catch (e: Exception){
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? AnimeCatalogueSource ?: return emptyList()
|
||||
return try {
|
||||
val res = source.fetchSearchAnime(1, query, AnimeFilterList()).toBlocking().first()
|
||||
convertAnimesPageToShowResponse(res)
|
||||
|
@ -174,6 +191,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
|
|||
class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
||||
val mangaCache = Injekt.get<MangaCache>()
|
||||
val extension: MangaExtension.Installed
|
||||
var sourceLanguage = 0
|
||||
init {
|
||||
this.extension = extension
|
||||
}
|
||||
|
@ -183,7 +201,12 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
|||
override val isNSFW = extension.isNsfw
|
||||
|
||||
override suspend fun loadChapters(mangaLink: String, extra: Map<String, String>?, sManga: SManga): List<MangaChapter> {
|
||||
val source = extension.sources.first() as? CatalogueSource ?: return emptyList()
|
||||
val source = try{
|
||||
extension.sources[sourceLanguage]
|
||||
}catch (e: Exception){
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? HttpSource ?: return emptyList()
|
||||
|
||||
return try {
|
||||
val res = source.getChapterList(sManga)
|
||||
|
@ -201,7 +224,12 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
|||
|
||||
|
||||
override suspend fun loadImages(chapterLink: String, sChapter: SChapter): List<MangaImage> {
|
||||
val source = extension.sources.first() as? HttpSource ?: return emptyList()
|
||||
val source = try{
|
||||
extension.sources[sourceLanguage]
|
||||
}catch (e: Exception){
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? HttpSource ?: return emptyList()
|
||||
|
||||
return coroutineScope {
|
||||
try {
|
||||
|
@ -321,7 +349,12 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
|
|||
|
||||
|
||||
override suspend fun search(query: String): List<ShowResponse> {
|
||||
val source = extension.sources.first() as? HttpSource ?: return emptyList()
|
||||
val source = try{
|
||||
extension.sources[sourceLanguage]
|
||||
}catch (e: Exception){
|
||||
sourceLanguage = 0
|
||||
extension.sources[sourceLanguage]
|
||||
} as? HttpSource ?: return emptyList()
|
||||
|
||||
return try {
|
||||
val res = source.fetchSearchManga(1, query, FilterList()).toBlocking().first()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ani.dantotsu.settings
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
|
@ -7,8 +8,10 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -17,10 +20,15 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.FragmentAnimeExtensionsBinding
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.extension.anime.AnimeExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||
|
@ -30,62 +38,129 @@ import uy.kohesive.injekt.Injekt
|
|||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class InstalledAnimeExtensionsFragment : Fragment() {
|
||||
|
||||
|
||||
private var _binding: FragmentAnimeExtensionsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
private lateinit var extensionsRecyclerView: RecyclerView
|
||||
val skipIcons = loadData("skip_extension_icons") ?: false
|
||||
private val animeExtensionManager: AnimeExtensionManager = Injekt.get()
|
||||
private val extensionsAdapter = AnimeExtensionsAdapter({ pkg ->
|
||||
if (isAdded) { // Check if the fragment is currently added to its activity
|
||||
val context = requireContext() // Store context in a variable
|
||||
val notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
|
||||
val allSettings = pkg.sources.filterIsInstance<ConfigurableAnimeSource>()
|
||||
if (allSettings.isNotEmpty()) {
|
||||
var selectedSetting = allSettings[0]
|
||||
if (allSettings.size > 1) {
|
||||
val names = allSettings.map { it.lang }.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { _, which ->
|
||||
selectedIndex = which
|
||||
}
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
if (pkg.hasUpdate) {
|
||||
animeExtensionManager.updateExtension(pkg)
|
||||
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
|
||||
.subscribe(
|
||||
{ installStep ->
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_sync_24)
|
||||
.setContentTitle("Updating extension")
|
||||
.setContentText("Step: $installStep")
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
},
|
||||
{ error ->
|
||||
FirebaseCrashlytics.getInstance().recordException(error)
|
||||
Log.e("AnimeExtensionsAdapter", "Error: ", error) // Log the error
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_info_24)
|
||||
.setContentTitle("Update failed: ${error.message}")
|
||||
.setContentText("Error: ${error.message}")
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
notificationManager.notify(1, builder.build())
|
||||
},
|
||||
{
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
|
||||
.setContentTitle("Update complete")
|
||||
.setContentText("The extension has been successfully updated.")
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
// Move the fragment transaction here
|
||||
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
val activity = requireActivity() as ExtensionsActivity
|
||||
activity.findViewById<ViewPager2>(R.id.viewPager).visibility = View.VISIBLE
|
||||
activity.findViewById<TabLayout>(R.id.tabLayout).visibility = View.VISIBLE
|
||||
activity.findViewById<TextInputLayout>(R.id.searchView).visibility = View.VISIBLE
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
View.GONE
|
||||
}
|
||||
)
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.cancel()
|
||||
return@setNegativeButton
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
animeExtensionManager.uninstallExtension(pkg.pkgName)
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = AnimeSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
val activity = requireActivity() as ExtensionsActivity
|
||||
activity.findViewById<ViewPager2>(R.id.viewPager).visibility = View.VISIBLE
|
||||
activity.findViewById<TabLayout>(R.id.tabLayout).visibility = View.VISIBLE
|
||||
activity.findViewById<TextInputLayout>(R.id.searchView).visibility = View.VISIBLE
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
View.GONE
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
// Hide ViewPager2 and TabLayout
|
||||
val activity = requireActivity() as ExtensionsActivity
|
||||
activity.findViewById<ViewPager2>(R.id.viewPager).visibility = View.GONE
|
||||
activity.findViewById<TabLayout>(R.id.tabLayout).visibility = View.GONE
|
||||
activity.findViewById<TextInputLayout>(R.id.searchView).visibility = View.GONE
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility = View.VISIBLE
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}, skipIcons)
|
||||
},
|
||||
{ pkg ->
|
||||
if (isAdded) { // Check if the fragment is currently added to its activity
|
||||
val context = requireContext() // Store context in a variable
|
||||
val notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Initialize NotificationManager once
|
||||
|
||||
if (pkg.hasUpdate) {
|
||||
animeExtensionManager.updateExtension(pkg)
|
||||
.observeOn(AndroidSchedulers.mainThread()) // Observe on main thread
|
||||
.subscribe(
|
||||
{ installStep ->
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_sync_24)
|
||||
.setContentTitle("Updating extension")
|
||||
.setContentText("Step: $installStep")
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
},
|
||||
{ error ->
|
||||
FirebaseCrashlytics.getInstance().recordException(error)
|
||||
Log.e("AnimeExtensionsAdapter", "Error: ", error) // Log the error
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
Notifications.CHANNEL_DOWNLOADER_ERROR
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_round_info_24)
|
||||
.setContentTitle("Update failed: ${error.message}")
|
||||
.setContentText("Error: ${error.message}")
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
notificationManager.notify(1, builder.build())
|
||||
},
|
||||
{
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||
)
|
||||
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
|
||||
.setContentTitle("Update complete")
|
||||
.setContentText("The extension has been successfully updated.")
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
notificationManager.notify(1, builder.build())
|
||||
}
|
||||
)
|
||||
} else {
|
||||
animeExtensionManager.uninstallExtension(pkg.pkgName)
|
||||
}
|
||||
}
|
||||
}, skipIcons
|
||||
)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
@ -114,6 +189,7 @@ class InstalledAnimeExtensionsFragment : Fragment() {
|
|||
|
||||
|
||||
private class AnimeExtensionsAdapter(
|
||||
private val onSettingsClicked: (AnimeExtension.Installed) -> Unit,
|
||||
private val onUninstallClicked: (AnimeExtension.Installed) -> Unit,
|
||||
skipIcons: Boolean
|
||||
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
|
||||
|
@ -152,10 +228,14 @@ class InstalledAnimeExtensionsFragment : Fragment() {
|
|||
holder.closeTextView.setOnClickListener {
|
||||
onUninstallClicked(extension)
|
||||
}
|
||||
holder.settingsImageView.setOnClickListener {
|
||||
onSettingsClicked(extension)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
|
||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
|
||||
}
|
||||
|
@ -180,5 +260,4 @@ class InstalledAnimeExtensionsFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package ani.dantotsu.settings
|
||||
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
|
@ -8,8 +9,10 @@ import android.util.Log
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
|
@ -18,13 +21,18 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.FragmentMangaExtensionsBinding
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import kotlinx.coroutines.launch
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
@ -37,6 +45,66 @@ class InstalledMangaExtensionsFragment : Fragment() {
|
|||
val skipIcons = loadData("skip_extension_icons") ?: false
|
||||
private val mangaExtensionManager: MangaExtensionManager = Injekt.get()
|
||||
private val extensionsAdapter = MangaExtensionsAdapter({ pkg ->
|
||||
val changeUIVisibility: (Boolean) -> Unit = { show ->
|
||||
val activity = requireActivity() as ExtensionsActivity
|
||||
val visibility = if (show) View.VISIBLE else View.GONE
|
||||
activity.findViewById<ViewPager2>(R.id.viewPager).visibility = visibility
|
||||
activity.findViewById<TabLayout>(R.id.tabLayout).visibility = visibility
|
||||
activity.findViewById<TextInputLayout>(R.id.searchView).visibility = visibility
|
||||
activity.findViewById<FrameLayout>(R.id.fragmentExtensionsContainer).visibility =
|
||||
if (show) View.GONE else View.VISIBLE
|
||||
}
|
||||
val allSettings = pkg.sources.filterIsInstance<ConfigurableSource>()
|
||||
if (allSettings.isNotEmpty()) {
|
||||
var selectedSetting = allSettings[0]
|
||||
if (allSettings.size > 1) {
|
||||
val names = allSettings.map { it.lang }.toTypedArray()
|
||||
var selectedIndex = 0
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle("Select a Source")
|
||||
.setSingleChoiceItems(names, selectedIndex) { _, which ->
|
||||
selectedIndex = which
|
||||
}
|
||||
.setPositiveButton("OK") { dialog, _ ->
|
||||
selectedSetting = allSettings[selectedIndex]
|
||||
dialog.dismiss()
|
||||
|
||||
// Move the fragment transaction here
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
.setNegativeButton("Cancel") { dialog, _ ->
|
||||
dialog.cancel()
|
||||
changeUIVisibility(true)
|
||||
return@setNegativeButton
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
// If there's only one setting, proceed with the fragment transaction
|
||||
val fragment = MangaSourcePreferencesFragment().getInstance(selectedSetting.id){
|
||||
changeUIVisibility(true)
|
||||
}
|
||||
parentFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.slide_up, R.anim.slide_down)
|
||||
.replace(R.id.fragmentExtensionsContainer, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
|
||||
// Hide ViewPager2 and TabLayout
|
||||
changeUIVisibility(false)
|
||||
} else {
|
||||
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
},
|
||||
{ pkg ->
|
||||
if (isAdded) { // Check if the fragment is currently added to its activity
|
||||
val context = requireContext() // Store context in a variable
|
||||
val notificationManager =
|
||||
|
@ -115,6 +183,7 @@ class InstalledMangaExtensionsFragment : Fragment() {
|
|||
|
||||
|
||||
private class MangaExtensionsAdapter(
|
||||
private val onSettingsClicked: (MangaExtension.Installed) -> Unit,
|
||||
private val onUninstallClicked: (MangaExtension.Installed) -> Unit,
|
||||
skipIcons: Boolean
|
||||
) : ListAdapter<MangaExtension.Installed, MangaExtensionsAdapter.ViewHolder>(
|
||||
|
@ -153,10 +222,14 @@ class InstalledMangaExtensionsFragment : Fragment() {
|
|||
holder.closeTextView.setOnClickListener {
|
||||
onUninstallClicked(extension)
|
||||
}
|
||||
holder.settingsImageView.setOnClickListener {
|
||||
onSettingsClicked(extension)
|
||||
}
|
||||
}
|
||||
|
||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||
val extensionNameTextView: TextView = view.findViewById(R.id.extensionNameTextView)
|
||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||
val closeTextView: TextView = view.findViewById(R.id.closeTextView)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package ani.dantotsu.settings.extensionprefs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.util.TypedValue
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.DialogPreference
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.forEach
|
||||
import androidx.preference.getOnBindEditTextListener
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.settings.ExtensionsActivity
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
||||
import eu.kanade.tachiyomi.source.anime.getPreferenceKey
|
||||
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
|
||||
import tachiyomi.domain.source.anime.service.AnimeSourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class AnimeSourcePreferencesFragment : PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceScreen = populateAnimePreferenceScreen()
|
||||
//set background color
|
||||
val color = TypedValue()
|
||||
requireContext().theme.resolveAttribute(com.google.android.material.R.attr.backgroundColor, color, true)
|
||||
view?.setBackgroundColor(color.data)
|
||||
}
|
||||
private var onCloseAction: (() -> Unit)? = null
|
||||
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
onCloseAction?.invoke()
|
||||
}
|
||||
|
||||
fun populateAnimePreferenceScreen(): PreferenceScreen {
|
||||
val sourceId = requireArguments().getLong(SOURCE_ID)
|
||||
val source = Injekt.get<AnimeSourceManager>().get(sourceId)!!
|
||||
check(source is ConfigurableAnimeSource)
|
||||
val sharedPreferences = requireContext().getSharedPreferences(source.getPreferenceKey(), Context.MODE_PRIVATE)
|
||||
val dataStore = SharedPreferencesDataStore(sharedPreferences)
|
||||
preferenceManager.preferenceDataStore = dataStore
|
||||
val sourceScreen = preferenceManager.createPreferenceScreen(requireContext())
|
||||
source.setupPreferenceScreen(sourceScreen)
|
||||
sourceScreen.forEach { pref ->
|
||||
pref.isIconSpaceReserved = false
|
||||
if (pref is DialogPreference) {
|
||||
pref.dialogTitle = pref.title
|
||||
println("pref.dialogTitle: ${pref.dialogTitle}")
|
||||
}
|
||||
for (entry in sharedPreferences.all.entries) {
|
||||
Log.d("Preferences", "Key: ${entry.key}, Value: ${entry.value}")
|
||||
}
|
||||
|
||||
// Apply incognito IME for EditTextPreference
|
||||
if (pref is EditTextPreference) {
|
||||
val setListener = pref.getOnBindEditTextListener()
|
||||
pref.setOnBindEditTextListener {
|
||||
setListener?.onBindEditText(it)
|
||||
it.setIncognito(lifecycleScope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sourceScreen
|
||||
}
|
||||
fun getInstance(sourceId: Long, onCloseAction: (() -> Unit)? = null): AnimeSourcePreferencesFragment {
|
||||
val fragment = AnimeSourcePreferencesFragment()
|
||||
fragment.arguments = bundleOf(SOURCE_ID to sourceId)
|
||||
fragment.onCloseAction = onCloseAction
|
||||
return fragment
|
||||
}
|
||||
|
||||
companion object { //idk why it needs both
|
||||
private const val SOURCE_ID = "source_id"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package ani.dantotsu.settings.extensionprefs
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.DialogPreference
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.forEach
|
||||
import androidx.preference.getOnBindEditTextListener
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.settings.ExtensionsActivity
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import eu.kanade.tachiyomi.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.manga.getPreferenceKey
|
||||
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
|
||||
import tachiyomi.domain.source.manga.service.MangaSourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class MangaSourcePreferencesFragment : PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceScreen = populateMangaPreferenceScreen()
|
||||
}
|
||||
private var onCloseAction: (() -> Unit)? = null
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
onCloseAction?.invoke()
|
||||
|
||||
}
|
||||
|
||||
fun populateMangaPreferenceScreen(): PreferenceScreen {
|
||||
val sourceId = requireArguments().getLong(SOURCE_ID)
|
||||
val source = Injekt.get<MangaSourceManager>().get(sourceId)!!
|
||||
check(source is ConfigurableSource)
|
||||
val sharedPreferences = requireContext().getSharedPreferences(source.getPreferenceKey(), Context.MODE_PRIVATE)
|
||||
val dataStore = SharedPreferencesDataStore(sharedPreferences)
|
||||
preferenceManager.preferenceDataStore = dataStore
|
||||
val sourceScreen = preferenceManager.createPreferenceScreen(requireContext())
|
||||
source.setupPreferenceScreen(sourceScreen)
|
||||
sourceScreen.forEach { pref ->
|
||||
pref.isIconSpaceReserved = false
|
||||
if (pref is DialogPreference) {
|
||||
pref.dialogTitle = pref.title
|
||||
println("pref.dialogTitle: ${pref.dialogTitle}")
|
||||
}
|
||||
|
||||
// Apply incognito IME for EditTextPreference
|
||||
if (pref is EditTextPreference) {
|
||||
val setListener = pref.getOnBindEditTextListener()
|
||||
pref.setOnBindEditTextListener {
|
||||
setListener?.onBindEditText(it)
|
||||
it.setIncognito(lifecycleScope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sourceScreen
|
||||
}
|
||||
fun getInstance(sourceId: Long, onCloseAction: (() -> Unit)? = null): MangaSourcePreferencesFragment {
|
||||
val fragment = MangaSourcePreferencesFragment()
|
||||
fragment.arguments = bundleOf(SOURCE_ID to sourceId)
|
||||
fragment.onCloseAction = onCloseAction
|
||||
return fragment
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SOURCE_ID = "source_id"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue