fix: sorting extensions order
This commit is contained in:
parent
15abcd77d0
commit
c2f108bf44
12 changed files with 146 additions and 82 deletions
|
@ -49,8 +49,8 @@ import ani.dantotsu.settings.CurrentReaderSettings.Companion.applyWebtoon
|
||||||
import ani.dantotsu.settings.CurrentReaderSettings.Directions.*
|
import ani.dantotsu.settings.CurrentReaderSettings.Directions.*
|
||||||
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.*
|
import ani.dantotsu.settings.CurrentReaderSettings.DualPageModes.*
|
||||||
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.*
|
import ani.dantotsu.settings.CurrentReaderSettings.Layouts.*
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.themes.ThemeManager
|
import ani.dantotsu.themes.ThemeManager
|
||||||
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
import com.alexvasilkov.gestures.views.GestureFrameLayout
|
||||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||||
|
@ -207,27 +207,19 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||||
chapter = chapters[media.manga!!.selectedChapter] ?: return
|
chapter = chapters[media.manga!!.selectedChapter] ?: return
|
||||||
|
|
||||||
model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources
|
model.mangaReadSources = if (media.isAdult) HMangaSources else MangaSources
|
||||||
binding.mangaReaderSource.visibility = if (PrefManager.getVal(PrefName.ShowSource)) View.VISIBLE else View.GONE
|
binding.mangaReaderSource.visibility =
|
||||||
|
if (PrefManager.getVal(PrefName.ShowSource)) View.VISIBLE else View.GONE
|
||||||
if (model.mangaReadSources!!.names.isEmpty()) {
|
if (model.mangaReadSources!!.names.isEmpty()) {
|
||||||
//try to reload sources
|
//try to reload sources
|
||||||
try {
|
try {
|
||||||
if (media.isAdult) {
|
val mangaSources = MangaSources
|
||||||
val mangaSources = MangaSources
|
val scope = lifecycleScope
|
||||||
val scope = lifecycleScope
|
scope.launch(Dispatchers.IO) {
|
||||||
scope.launch(Dispatchers.IO) {
|
mangaSources.init(
|
||||||
mangaSources.init(
|
Injekt.get<MangaExtensionManager>().installedExtensionsFlow
|
||||||
Injekt.get<MangaExtensionManager>().installedExtensionsFlow
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
model.mangaReadSources = mangaSources
|
|
||||||
} else {
|
|
||||||
val mangaSources = HMangaSources
|
|
||||||
val scope = lifecycleScope
|
|
||||||
scope.launch(Dispatchers.IO) {
|
|
||||||
mangaSources.init(Injekt.get<MangaExtensionManager>().installedExtensionsFlow)
|
|
||||||
}
|
|
||||||
model.mangaReadSources = mangaSources
|
|
||||||
}
|
}
|
||||||
|
model.mangaReadSources = mangaSources
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Firebase.crashlytics.recordException(e)
|
Firebase.crashlytics.recordException(e)
|
||||||
logError(e)
|
logError(e)
|
||||||
|
@ -260,7 +252,10 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||||
//Chapter Change
|
//Chapter Change
|
||||||
fun change(index: Int) {
|
fun change(index: Int) {
|
||||||
mangaCache.clear()
|
mangaCache.clear()
|
||||||
PrefManager.setCustomVal("${media.id}_${chaptersArr[currentChapterIndex]}", currentChapterPage)
|
PrefManager.setCustomVal(
|
||||||
|
"${media.id}_${chaptersArr[currentChapterIndex]}",
|
||||||
|
currentChapterPage
|
||||||
|
)
|
||||||
ChapterLoaderDialog.newInstance(chapters[chaptersArr[index]]!!)
|
ChapterLoaderDialog.newInstance(chapters[chaptersArr[index]]!!)
|
||||||
.show(supportFragmentManager, "dialog")
|
.show(supportFragmentManager, "dialog")
|
||||||
}
|
}
|
||||||
|
@ -850,8 +845,11 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||||
private fun progress(runnable: Runnable) {
|
private fun progress(runnable: Runnable) {
|
||||||
if (maxChapterPage - currentChapterPage <= 1 && Anilist.userid != null) {
|
if (maxChapterPage - currentChapterPage <= 1 && Anilist.userid != null) {
|
||||||
showProgressDialog =
|
showProgressDialog =
|
||||||
if (PrefManager.getVal(PrefName.AskIndividualReader)) PrefManager.getCustomVal("${media.id}_progressDialog", true)
|
if (PrefManager.getVal(PrefName.AskIndividualReader)) PrefManager.getCustomVal(
|
||||||
else false
|
"${media.id}_progressDialog",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
else false
|
||||||
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
|
val incognito: Boolean = PrefManager.getVal(PrefName.Incognito)
|
||||||
if (showProgressDialog && !incognito) {
|
if (showProgressDialog && !incognito) {
|
||||||
|
|
||||||
|
@ -885,9 +883,13 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||||
.create()
|
.create()
|
||||||
.show()
|
.show()
|
||||||
} else {
|
} else {
|
||||||
if (!incognito && PrefManager.getCustomVal("${media.id}_save_progress", true) && if (media.isAdult) PrefManager.getVal<Boolean>(PrefName.UpdateForHReader) else true)
|
if (!incognito && PrefManager.getCustomVal(
|
||||||
updateProgress(
|
"${media.id}_save_progress",
|
||||||
media,
|
true
|
||||||
|
) && if (media.isAdult) PrefManager.getVal<Boolean>(PrefName.UpdateForHReader) else true
|
||||||
|
)
|
||||||
|
updateProgress(
|
||||||
|
media,
|
||||||
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
MangaNameAdapter.findChapterNumber(media.manga!!.selectedChapter!!)
|
||||||
.toString()
|
.toString()
|
||||||
)
|
)
|
||||||
|
@ -900,7 +902,11 @@ class MangaReaderActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun <T> loadReaderSettings(fileName: String, context: Context? = null, toast: Boolean = true): T? {
|
private fun <T> loadReaderSettings(
|
||||||
|
fileName: String,
|
||||||
|
context: Context? = null,
|
||||||
|
toast: Boolean = true
|
||||||
|
): T? {
|
||||||
val a = context ?: currContext()
|
val a = context ?: currContext()
|
||||||
try {
|
try {
|
||||||
if (a?.fileList() != null)
|
if (a?.fileList() != null)
|
||||||
|
|
|
@ -4,21 +4,16 @@ import android.content.Context
|
||||||
import ani.dantotsu.Lazier
|
import ani.dantotsu.Lazier
|
||||||
import ani.dantotsu.lazyList
|
import ani.dantotsu.lazyList
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefManager.asLiveString
|
|
||||||
import ani.dantotsu.settings.saving.PrefManager.asLiveStringSet
|
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
object AnimeSources : WatchSources() {
|
object AnimeSources : WatchSources() {
|
||||||
override var list: List<Lazier<BaseParser>> = emptyList()
|
override var list: List<Lazier<BaseParser>> = emptyList()
|
||||||
var pinnedAnimeSources: List<String> = emptyList()
|
var pinnedAnimeSources: List<String> = emptyList()
|
||||||
|
|
||||||
suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>, context: Context) {
|
suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>) {
|
||||||
pinnedAnimeSources = PrefManager.getNullableVal<List<String>>(PrefName.AnimeSourcesOrder, null)
|
pinnedAnimeSources = PrefManager.getNullableVal<List<String>>(PrefName.AnimeSourcesOrder, null)
|
||||||
?: emptyList()
|
?: emptyList()
|
||||||
|
|
||||||
|
@ -58,17 +53,15 @@ object AnimeSources : WatchSources() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sortPinnedAnimeSources(
|
private fun sortPinnedAnimeSources(
|
||||||
Sources: List<Lazier<BaseParser>>,
|
sources: List<Lazier<BaseParser>>,
|
||||||
pinnedAnimeSources: List<String>
|
pinnedAnimeSources: List<String>
|
||||||
): List<Lazier<BaseParser>> {
|
): List<Lazier<BaseParser>> {
|
||||||
val pinnedSourcesMap = Sources.filter { pinnedAnimeSources.contains(it.name) }
|
val pinnedSourcesMap = sources.filter { pinnedAnimeSources.contains(it.name) }
|
||||||
.associateBy { it.name }
|
.associateBy { it.name }
|
||||||
val orderedPinnedSources = pinnedAnimeSources.mapNotNull { name ->
|
val orderedPinnedSources = pinnedAnimeSources.mapNotNull { name ->
|
||||||
pinnedSourcesMap[name]
|
pinnedSourcesMap[name]
|
||||||
}
|
}
|
||||||
//find the unpinned sources
|
val unpinnedSources = sources.filterNot { pinnedAnimeSources.contains(it.name) }
|
||||||
val unpinnedSources = Sources.filter { !pinnedAnimeSources.contains(it.name) }
|
|
||||||
//put the pinned sources at the top of the list
|
|
||||||
return orderedPinnedSources + unpinnedSources
|
return orderedPinnedSources + unpinnedSources
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,26 +52,20 @@ object MangaSources : MangaReadSources() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sortPinnedMangaSources(
|
private fun sortPinnedMangaSources(
|
||||||
Sources: List<Lazier<BaseParser>>,
|
sources: List<Lazier<BaseParser>>,
|
||||||
pinnedMangaSources: List<String>
|
pinnedMangaSources: List<String>
|
||||||
): List<Lazier<BaseParser>> {
|
): List<Lazier<BaseParser>> {
|
||||||
val pinnedSourcesMap = Sources.filter { pinnedMangaSources.contains(it.name) }
|
val pinnedSourcesMap = sources.filter { pinnedMangaSources.contains(it.name) }
|
||||||
.associateBy { it.name }
|
.associateBy { it.name }
|
||||||
val orderedPinnedSources = pinnedMangaSources.mapNotNull { name ->
|
val orderedPinnedSources = pinnedMangaSources.mapNotNull { name ->
|
||||||
pinnedSourcesMap[name]
|
pinnedSourcesMap[name]
|
||||||
}
|
}
|
||||||
//find the unpinned sources
|
val unpinnedSources = sources.filterNot { pinnedMangaSources.contains(it.name) }
|
||||||
val unpinnedSources = Sources.filter { !pinnedMangaSources.contains(it.name) }
|
|
||||||
//put the pinned sources at the top of the list
|
|
||||||
return orderedPinnedSources + unpinnedSources
|
return orderedPinnedSources + unpinnedSources
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object HMangaSources : MangaReadSources() {
|
object HMangaSources : MangaReadSources() {
|
||||||
val aList: List<Lazier<BaseParser>> = lazyList()
|
private val aList: List<Lazier<BaseParser>> = lazyList()
|
||||||
suspend fun init(fromExtensions: StateFlow<List<MangaExtension.Installed>>) {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
|
|
||||||
override val list = listOf(aList, MangaSources.list).flatten()
|
override val list = listOf(aList, MangaSources.list).flatten()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,19 @@ import android.util.Log
|
||||||
import ani.dantotsu.Lazier
|
import ani.dantotsu.Lazier
|
||||||
import ani.dantotsu.parsers.novel.DynamicNovelParser
|
import ani.dantotsu.parsers.novel.DynamicNovelParser
|
||||||
import ani.dantotsu.parsers.novel.NovelExtension
|
import ani.dantotsu.parsers.novel.NovelExtension
|
||||||
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
object NovelSources : NovelReadSources() {
|
object NovelSources : NovelReadSources() {
|
||||||
override var list: List<Lazier<BaseParser>> = emptyList()
|
override var list: List<Lazier<BaseParser>> = emptyList()
|
||||||
|
var pinnedNovelSources: List<String> = emptyList()
|
||||||
|
|
||||||
suspend fun init(fromExtensions: StateFlow<List<NovelExtension.Installed>>) {
|
suspend fun init(fromExtensions: StateFlow<List<NovelExtension.Installed>>) {
|
||||||
|
pinnedNovelSources = PrefManager.getNullableVal<List<String>>(PrefName.NovelSourcesOrder, null)
|
||||||
|
?: emptyList()
|
||||||
|
|
||||||
// Initialize with the first value from StateFlow
|
// Initialize with the first value from StateFlow
|
||||||
val initialExtensions = fromExtensions.first()
|
val initialExtensions = fromExtensions.first()
|
||||||
list = createParsersFromExtensions(initialExtensions) + Lazier(
|
list = createParsersFromExtensions(initialExtensions) + Lazier(
|
||||||
|
@ -20,13 +26,25 @@ object NovelSources : NovelReadSources() {
|
||||||
|
|
||||||
// Update as StateFlow emits new values
|
// Update as StateFlow emits new values
|
||||||
fromExtensions.collect { extensions ->
|
fromExtensions.collect { extensions ->
|
||||||
list = createParsersFromExtensions(extensions) + Lazier(
|
list = sortPinnedNovelSources(
|
||||||
|
createParsersFromExtensions(extensions),
|
||||||
|
pinnedNovelSources
|
||||||
|
) + Lazier(
|
||||||
{ OfflineNovelParser() },
|
{ OfflineNovelParser() },
|
||||||
"Downloaded"
|
"Downloaded"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun performReorderNovelSources() {
|
||||||
|
//remove the downloaded source from the list to avoid duplicates
|
||||||
|
list = list.filter { it.name != "Downloaded" }
|
||||||
|
list = sortPinnedNovelSources(list, pinnedNovelSources) + Lazier(
|
||||||
|
{ OfflineNovelParser() },
|
||||||
|
"Downloaded"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createParsersFromExtensions(extensions: List<NovelExtension.Installed>): List<Lazier<BaseParser>> {
|
private fun createParsersFromExtensions(extensions: List<NovelExtension.Installed>): List<Lazier<BaseParser>> {
|
||||||
Log.d("NovelSources", "createParsersFromExtensions")
|
Log.d("NovelSources", "createParsersFromExtensions")
|
||||||
Log.d("NovelSources", extensions.toString())
|
Log.d("NovelSources", extensions.toString())
|
||||||
|
@ -35,4 +53,17 @@ object NovelSources : NovelReadSources() {
|
||||||
Lazier({ DynamicNovelParser(extension) }, name)
|
Lazier({ DynamicNovelParser(extension) }, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sortPinnedNovelSources(
|
||||||
|
parsers: List<Lazier<BaseParser>>,
|
||||||
|
pinnedSources: List<String>
|
||||||
|
): List<Lazier<BaseParser>> {
|
||||||
|
val pinnedSourcesMap = parsers.filter { pinnedSources.contains(it.name) }
|
||||||
|
.associateBy { it.name }
|
||||||
|
val orderedPinnedSources = pinnedSources.mapNotNull { name ->
|
||||||
|
pinnedSourcesMap[name]
|
||||||
|
}
|
||||||
|
val unpinnedSources = parsers.filterNot { pinnedSources.contains(it.name) }
|
||||||
|
return orderedPinnedSources + unpinnedSources
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -6,9 +6,7 @@ import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.GestureDetector
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
@ -200,7 +198,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
target: RecyclerView.ViewHolder
|
target: RecyclerView.ViewHolder
|
||||||
): Boolean {
|
): Boolean {
|
||||||
extensionsAdapter.onMove(viewHolder.adapterPosition, target.adapterPosition)
|
extensionsAdapter.onMove(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
||||||
|
@ -224,10 +222,10 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
animeExtensionManager.installedExtensionsFlow.collect { extensions ->
|
animeExtensionManager.installedExtensionsFlow.collect { extensions ->
|
||||||
|
logger("asdfg: Extensions updated")
|
||||||
extensionsAdapter.updateData(sortToAnimeSourcesList(extensions))
|
extensionsAdapter.updateData(sortToAnimeSourcesList(extensions))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val extensionsRecyclerView: RecyclerView = binding.allAnimeExtensionsRecyclerView
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +243,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateContentBasedOnQuery(query: String?) {
|
override fun updateContentBasedOnQuery(query: String?) {
|
||||||
extensionsAdapter.filter(query ?: "", animeExtensionManager.installedExtensionsFlow.value)
|
extensionsAdapter.filter(query ?: "", sortToAnimeSourcesList(animeExtensionManager.installedExtensionsFlow.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun notifyDataChanged() { // Do nothing
|
override fun notifyDataChanged() { // Do nothing
|
||||||
|
@ -258,7 +256,6 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
|
) : ListAdapter<AnimeExtension.Installed, AnimeExtensionsAdapter.ViewHolder>(
|
||||||
DIFF_CALLBACK_INSTALLED
|
DIFF_CALLBACK_INSTALLED
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val data: MutableList<AnimeExtension.Installed> = mutableListOf()
|
private val data: MutableList<AnimeExtension.Installed> = mutableListOf()
|
||||||
|
|
||||||
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
|
fun updateData(newExtensions: List<AnimeExtension.Installed>) {
|
||||||
|
@ -282,7 +279,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
return ViewHolder(view)
|
return ViewHolder(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = getItem(position) // Use getItem() from ListAdapter
|
val extension = getItem(position) // Use getItem() from ListAdapter
|
||||||
val nsfw = if (extension.isNsfw) "(18+)" else ""
|
val nsfw = if (extension.isNsfw) "(18+)" else ""
|
||||||
|
@ -326,7 +323,6 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||||
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
||||||
val card = view.findViewById<View>(R.id.extensionCardView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -8,7 +8,6 @@ import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
@ -36,7 +35,6 @@ import com.google.android.material.tabs.TabLayout
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
|
|
||||||
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
import eu.kanade.tachiyomi.extension.manga.MangaExtensionManager
|
||||||
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
import eu.kanade.tachiyomi.extension.manga.model.MangaExtension
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
|
@ -162,7 +160,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
context,
|
context,
|
||||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
)
|
)
|
||||||
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
|
.setSmallIcon(R.drawable.ic_check)
|
||||||
.setContentTitle("Update complete")
|
.setContentTitle("Update complete")
|
||||||
.setContentText("The extension has been successfully updated.")
|
.setContentText("The extension has been successfully updated.")
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
@ -196,7 +194,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
target: RecyclerView.ViewHolder
|
target: RecyclerView.ViewHolder
|
||||||
): Boolean {
|
): Boolean {
|
||||||
extensionsAdapter.onMove(viewHolder.adapterPosition, target.adapterPosition)
|
extensionsAdapter.onMove(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
||||||
|
@ -223,7 +221,6 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
extensionsAdapter.updateData(sortToMangaSourcesList(extensions))
|
extensionsAdapter.updateData(sortToMangaSourcesList(extensions))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val extensionsRecyclerView: RecyclerView = binding.allMangaExtensionsRecyclerView
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +237,7 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateContentBasedOnQuery(query: String?) {
|
override fun updateContentBasedOnQuery(query: String?) {
|
||||||
extensionsAdapter.filter(query ?: "", mangaExtensionManager.installedExtensionsFlow.value)
|
extensionsAdapter.filter(query ?: "", sortToMangaSourcesList(mangaExtensionManager.installedExtensionsFlow.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun notifyDataChanged() { // Do nothing
|
override fun notifyDataChanged() { // Do nothing
|
||||||
|
@ -317,7 +314,6 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||||
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
||||||
val card: View = view.findViewById(R.id.extensionCardView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ani.dantotsu.settings
|
package ani.dantotsu.settings
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -14,6 +15,7 @@ import androidx.core.app.NotificationCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -21,6 +23,7 @@ import ani.dantotsu.R
|
||||||
import ani.dantotsu.currContext
|
import ani.dantotsu.currContext
|
||||||
import ani.dantotsu.databinding.FragmentNovelExtensionsBinding
|
import ani.dantotsu.databinding.FragmentNovelExtensionsBinding
|
||||||
import ani.dantotsu.others.LanguageMapper
|
import ani.dantotsu.others.LanguageMapper
|
||||||
|
import ani.dantotsu.parsers.NovelSources
|
||||||
import ani.dantotsu.parsers.novel.NovelExtension
|
import ani.dantotsu.parsers.novel.NovelExtension
|
||||||
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
import ani.dantotsu.parsers.novel.NovelExtensionManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
|
@ -32,6 +35,7 @@ import kotlinx.coroutines.launch
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import java.util.Collections
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
|
@ -41,7 +45,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
|
private val skipIcons: Boolean = PrefManager.getVal(PrefName.SkipExtensionIcons)
|
||||||
private val novelExtensionManager: NovelExtensionManager = Injekt.get()
|
private val novelExtensionManager: NovelExtensionManager = Injekt.get()
|
||||||
private val extensionsAdapter = NovelExtensionsAdapter(
|
private val extensionsAdapter = NovelExtensionsAdapter(
|
||||||
{ pkg ->
|
{ _ ->
|
||||||
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
Toast.makeText(requireContext(), "Source is not configurable", Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
},
|
},
|
||||||
|
@ -85,7 +89,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
context,
|
context,
|
||||||
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
Notifications.CHANNEL_DOWNLOADER_PROGRESS
|
||||||
)
|
)
|
||||||
.setSmallIcon(androidx.media3.ui.R.drawable.exo_ic_check)
|
.setSmallIcon(R.drawable.ic_check)
|
||||||
.setContentTitle("Update complete")
|
.setContentTitle("Update complete")
|
||||||
.setContentText("The extension has been successfully updated.")
|
.setContentText("The extension has been successfully updated.")
|
||||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||||
|
@ -112,22 +116,58 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||||
extensionsRecyclerView.adapter = extensionsAdapter
|
extensionsRecyclerView.adapter = extensionsAdapter
|
||||||
|
|
||||||
|
val itemTouchHelperCallback = object : ItemTouchHelper.SimpleCallback(
|
||||||
|
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0) {
|
||||||
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
target: RecyclerView.ViewHolder
|
||||||
|
): Boolean {
|
||||||
|
extensionsAdapter.onMove(viewHolder.absoluteAdapterPosition, target.absoluteAdapterPosition)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
|
||||||
|
|
||||||
|
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
|
||||||
|
super.onSelectedChanged(viewHolder, actionState)
|
||||||
|
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
|
||||||
|
viewHolder?.itemView?.elevation = 8f
|
||||||
|
viewHolder?.itemView?.translationZ = 8f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
|
||||||
|
super.clearView(recyclerView, viewHolder)
|
||||||
|
viewHolder.itemView.elevation = 0f
|
||||||
|
viewHolder.itemView.translationZ = 0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(extensionsRecyclerView)
|
||||||
|
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
novelExtensionManager.installedExtensionsFlow.collect { extensions ->
|
novelExtensionManager.installedExtensionsFlow.collect { extensions ->
|
||||||
extensionsAdapter.updateData(extensions)
|
extensionsAdapter.updateData(sortToNovelSourcesList(extensions))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val extensionsRecyclerView: RecyclerView = binding.allNovelExtensionsRecyclerView
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun sortToNovelSourcesList(inpt: List<NovelExtension.Installed>): List<NovelExtension.Installed> {
|
||||||
|
val sourcesMap = inpt.associateBy { it.name }
|
||||||
|
val orderedSources = NovelSources.pinnedNovelSources.mapNotNull { name ->
|
||||||
|
sourcesMap[name]
|
||||||
|
}
|
||||||
|
return orderedSources + inpt.filter { !NovelSources.pinnedNovelSources.contains(it.name) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView();_binding = null
|
super.onDestroyView();_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateContentBasedOnQuery(query: String?) {
|
override fun updateContentBasedOnQuery(query: String?) {
|
||||||
extensionsAdapter.filter(query ?: "", novelExtensionManager.installedExtensionsFlow.value)
|
extensionsAdapter.filter(query ?: "", sortToNovelSourcesList(novelExtensionManager.installedExtensionsFlow.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun notifyDataChanged() { // do nothing
|
override fun notifyDataChanged() { // do nothing
|
||||||
|
@ -136,16 +176,25 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
private class NovelExtensionsAdapter(
|
private class NovelExtensionsAdapter(
|
||||||
private val onSettingsClicked: (NovelExtension.Installed) -> Unit,
|
private val onSettingsClicked: (NovelExtension.Installed) -> Unit,
|
||||||
private val onUninstallClicked: (NovelExtension.Installed, Boolean) -> Unit,
|
private val onUninstallClicked: (NovelExtension.Installed, Boolean) -> Unit,
|
||||||
skipIcons: Boolean
|
val skipIcons: Boolean
|
||||||
) : ListAdapter<NovelExtension.Installed, NovelExtensionsAdapter.ViewHolder>(
|
) : ListAdapter<NovelExtension.Installed, NovelExtensionsAdapter.ViewHolder>(
|
||||||
DIFF_CALLBACK_INSTALLED
|
DIFF_CALLBACK_INSTALLED
|
||||||
) {
|
) {
|
||||||
|
private val data: MutableList<NovelExtension.Installed> = mutableListOf()
|
||||||
val skipIcons = skipIcons
|
|
||||||
|
|
||||||
fun updateData(newExtensions: List<NovelExtension.Installed>) {
|
fun updateData(newExtensions: List<NovelExtension.Installed>) {
|
||||||
Log.d("NovelExtensionsAdapter", "updateData: $newExtensions")
|
submitList(newExtensions)
|
||||||
submitList(newExtensions) // Use submitList instead of manual list handling
|
data.clear()
|
||||||
|
data.addAll(newExtensions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMove(fromPosition: Int, toPosition: Int) {
|
||||||
|
Collections.swap(data, fromPosition, toPosition)
|
||||||
|
val map = data.map { it.name }.toList()
|
||||||
|
PrefManager.setVal(PrefName.NovelSourcesOrder, map)
|
||||||
|
NovelSources.pinnedNovelSources = map
|
||||||
|
NovelSources.performReorderNovelSources()
|
||||||
|
notifyItemMoved(fromPosition, toPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
@ -155,6 +204,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
return ViewHolder(view)
|
return ViewHolder(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
val extension = getItem(position) // Use getItem() from ListAdapter
|
val extension = getItem(position) // Use getItem() from ListAdapter
|
||||||
val nsfw = ""
|
val nsfw = ""
|
||||||
|
@ -175,7 +225,7 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
holder.settingsImageView.setOnClickListener {
|
holder.settingsImageView.setOnClickListener {
|
||||||
onSettingsClicked(extension)
|
onSettingsClicked(extension)
|
||||||
}
|
}
|
||||||
holder.card.setOnLongClickListener {
|
holder.closeTextView.setOnLongClickListener {
|
||||||
onUninstallClicked(extension, true)
|
onUninstallClicked(extension, true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -198,7 +248,6 @@ class InstalledNovelExtensionsFragment : Fragment(), SearchQueryHandler {
|
||||||
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
val settingsImageView: ImageView = view.findViewById(R.id.settingsImageView)
|
||||||
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
val extensionIconImageView: ImageView = view.findViewById(R.id.extensionIconImageView)
|
||||||
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
val closeTextView: ImageView = view.findViewById(R.id.closeTextView)
|
||||||
val card = view.findViewById<View>(R.id.extensionCardView)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -15,8 +15,6 @@ import java.io.ObjectOutputStream
|
||||||
object PrefManager {
|
object PrefManager {
|
||||||
|
|
||||||
private var generalPreferences: SharedPreferences? = null
|
private var generalPreferences: SharedPreferences? = null
|
||||||
private var animePreferences: SharedPreferences? = null
|
|
||||||
private var mangaPreferences: SharedPreferences? = null
|
|
||||||
private var playerPreferences: SharedPreferences? = null
|
private var playerPreferences: SharedPreferences? = null
|
||||||
private var readerPreferences: SharedPreferences? = null
|
private var readerPreferences: SharedPreferences? = null
|
||||||
private var irrelevantPreferences: SharedPreferences? = null
|
private var irrelevantPreferences: SharedPreferences? = null
|
||||||
|
|
|
@ -25,6 +25,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
||||||
AnimeSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
AnimeSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
||||||
MangaSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
|
MangaSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
|
||||||
MangaSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
MangaSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
||||||
|
NovelSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
|
||||||
|
|
||||||
//User Interface
|
//User Interface
|
||||||
UseOLED(Pref(Location.UI, Boolean::class, false)),
|
UseOLED(Pref(Location.UI, Boolean::class, false)),
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingStart="32dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="32dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/allAnimeExtensionsRecyclerView"
|
android:id="@+id/allAnimeExtensionsRecyclerView"
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingStart="32dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="32dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/allMangaExtensionsRecyclerView"
|
android:id="@+id/allMangaExtensionsRecyclerView"
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingStart="32dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="32dp">
|
android:paddingEnd="16dp">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/allNovelExtensionsRecyclerView"
|
android:id="@+id/allNovelExtensionsRecyclerView"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue