Skip to content

Commit

Permalink
sortable sources
Browse files Browse the repository at this point in the history
  • Loading branch information
rebelonion committed Feb 3, 2024
1 parent 402e057 commit d3f097f
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 155 deletions.
23 changes: 16 additions & 7 deletions app/src/main/java/ani/dantotsu/parsers/AnimeSources.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@ package ani.dantotsu.parsers
import android.content.Context
import ani.dantotsu.Lazier
import ani.dantotsu.lazyList
import ani.dantotsu.settings.saving.PrefName
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 eu.kanade.tachiyomi.extension.anime.model.AnimeExtension
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

object AnimeSources : WatchSources() {
override var list: List<Lazier<BaseParser>> = emptyList()
var pinnedAnimeSources: Set<String> = emptySet()
var pinnedAnimeSources: List<String> = emptyList()

suspend fun init(fromExtensions: StateFlow<List<AnimeExtension.Installed>>, context: Context) {
pinnedAnimeSources = PrefManager.getVal(PrefName.PinnedAnimeSources)
pinnedAnimeSources = PrefManager.getNullableVal<List<String>>(PrefName.AnimeSourcesOrder, null)
?: emptyList()

// Initialize with the first value from StateFlow
val initialExtensions = fromExtensions.first()
Expand Down Expand Up @@ -53,14 +59,17 @@ object AnimeSources : WatchSources() {

private fun sortPinnedAnimeSources(
Sources: List<Lazier<BaseParser>>,
pinnedAnimeSources: Set<String>
pinnedAnimeSources: List<String>
): List<Lazier<BaseParser>> {
//find the pinned sources
val pinnedSources = Sources.filter { pinnedAnimeSources.contains(it.name) }
val pinnedSourcesMap = Sources.filter { pinnedAnimeSources.contains(it.name) }
.associateBy { it.name }
val orderedPinnedSources = pinnedAnimeSources.mapNotNull { name ->
pinnedSourcesMap[name]
}
//find the unpinned sources
val unpinnedSources = Sources.filter { !pinnedAnimeSources.contains(it.name) }
//put the pinned sources at the top of the list
return pinnedSources + unpinnedSources
return orderedPinnedSources + unpinnedSources
}
}

Expand Down
16 changes: 10 additions & 6 deletions app/src/main/java/ani/dantotsu/parsers/MangaSources.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import kotlinx.coroutines.flow.first

object MangaSources : MangaReadSources() {
override var list: List<Lazier<BaseParser>> = emptyList()
var pinnedMangaSources: Set<String> = emptySet()
var pinnedMangaSources: List<String> = emptyList()

suspend fun init(fromExtensions: StateFlow<List<MangaExtension.Installed>>) {
pinnedMangaSources = PrefManager.getVal(PrefName.PinnedMangaSources)
pinnedMangaSources = PrefManager.getNullableVal<List<String>>(PrefName.MangaSourcesOrder, null)
?: emptyList()

// Initialize with the first value from StateFlow
val initialExtensions = fromExtensions.first()
Expand Down Expand Up @@ -52,14 +53,17 @@ object MangaSources : MangaReadSources() {

private fun sortPinnedMangaSources(
Sources: List<Lazier<BaseParser>>,
pinnedMangaSources: Set<String>
pinnedMangaSources: List<String>
): List<Lazier<BaseParser>> {
//find the pinned sources
val pinnedSources = Sources.filter { pinnedMangaSources.contains(it.name) }
val pinnedSourcesMap = Sources.filter { pinnedMangaSources.contains(it.name) }
.associateBy { it.name }
val orderedPinnedSources = pinnedMangaSources.mapNotNull { name ->
pinnedSourcesMap[name]
}
//find the unpinned sources
val unpinnedSources = Sources.filter { !pinnedMangaSources.contains(it.name) }
//put the pinned sources at the top of the list
return pinnedSources + unpinnedSources
return orderedPinnedSources + unpinnedSources
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import android.app.NotificationManager
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.GestureDetector
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
Expand All @@ -17,16 +19,19 @@ import androidx.core.app.NotificationCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
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.logger
import ani.dantotsu.others.LanguageMapper
import ani.dantotsu.parsers.AnimeSources
import ani.dantotsu.settings.extensionprefs.AnimeSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.snackString
import com.google.android.material.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout
Expand All @@ -39,8 +44,10 @@ import kotlinx.coroutines.launch
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Collections
import java.util.Locale


class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {


Expand Down Expand Up @@ -174,6 +181,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
}, skipIcons
)


override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand All @@ -185,16 +193,53 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
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.adapterPosition, target.adapterPosition)
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 {
animeExtensionManager.installedExtensionsFlow.collect { extensions ->
extensionsAdapter.updateData(extensions)
extensionsAdapter.updateData(sortToAnimeSourcesList(extensions))
}
}
val extensionsRecyclerView: RecyclerView = binding.allAnimeExtensionsRecyclerView
return binding.root
}


private fun sortToAnimeSourcesList(inpt: List<AnimeExtension.Installed>): List<AnimeExtension.Installed> {
val sourcesMap = inpt.associateBy { it.name }
val orderedSources = AnimeSources.pinnedAnimeSources.mapNotNull { name ->
sourcesMap[name]
}
return orderedSources + inpt.filter { !AnimeSources.pinnedAnimeSources.contains(it.name) }
}

override fun onDestroyView() {
super.onDestroyView();_binding = null
}
Expand All @@ -211,8 +256,21 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
DIFF_CALLBACK_INSTALLED
) {

private val data: MutableList<AnimeExtension.Installed> = mutableListOf()

fun updateData(newExtensions: List<AnimeExtension.Installed>) {
submitList(newExtensions) // Use submitList instead of manual list handling
submitList(newExtensions)
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.AnimeSourcesOrder, map)
AnimeSources.pinnedAnimeSources = map
AnimeSources.performReorderAnimeSources()
notifyItemMoved(fromPosition, toPosition)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
Expand All @@ -221,7 +279,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
return ViewHolder(view)
}

@SuppressLint("SetTextI18n")
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
val nsfw = if (extension.isNsfw) "(18+)" else ""
Expand All @@ -242,7 +300,7 @@ class InstalledAnimeExtensionsFragment : Fragment(), SearchQueryHandler {
holder.settingsImageView.setOnClickListener {
onSettingsClicked(extension)
}
holder.card.setOnLongClickListener {
holder.closeTextView.setOnLongClickListener {
onUninstallClicked(extension, true)
true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
Expand All @@ -18,13 +19,15 @@ import androidx.core.app.NotificationCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ItemTouchHelper
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.others.LanguageMapper
import ani.dantotsu.parsers.MangaSources
import ani.dantotsu.settings.extensionprefs.MangaSourcePreferencesFragment
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.settings.saving.PrefManager
Expand All @@ -33,13 +36,15 @@ 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.anime.model.AnimeExtension
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
import uy.kohesive.injekt.api.get
import java.util.Collections
import java.util.Locale

class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
Expand Down Expand Up @@ -184,16 +189,52 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
extensionsRecyclerView.layoutManager = LinearLayoutManager(requireContext())
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.adapterPosition, target.adapterPosition)
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 {
mangaExtensionManager.installedExtensionsFlow.collect { extensions ->
extensionsAdapter.updateData(extensions)
extensionsAdapter.updateData(sortToMangaSourcesList(extensions))
}
}
val extensionsRecyclerView: RecyclerView = binding.allMangaExtensionsRecyclerView
return binding.root
}

private fun sortToMangaSourcesList(inpt: List<MangaExtension.Installed>): List<MangaExtension.Installed> {
val sourcesMap = inpt.associateBy { it.name }
val orderedSources = MangaSources.pinnedMangaSources.mapNotNull { name ->
sourcesMap[name]
}
return orderedSources + inpt.filter { !MangaSources.pinnedMangaSources.contains(it.name) }
}

override fun onDestroyView() {
super.onDestroyView();_binding = null
}
Expand All @@ -205,15 +246,17 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
private class MangaExtensionsAdapter(
private val onSettingsClicked: (MangaExtension.Installed) -> Unit,
private val onUninstallClicked: (MangaExtension.Installed, Boolean) -> Unit,
skipIcons: Boolean
val skipIcons: Boolean
) : ListAdapter<MangaExtension.Installed, MangaExtensionsAdapter.ViewHolder>(
DIFF_CALLBACK_INSTALLED
) {

val skipIcons = skipIcons
private val data: MutableList<MangaExtension.Installed> = mutableListOf()

fun updateData(newExtensions: List<MangaExtension.Installed>) {
submitList(newExtensions) // Use submitList instead of manual list handling
submitList(newExtensions)
data.clear()
data.addAll(newExtensions)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
Expand All @@ -222,7 +265,16 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
return ViewHolder(view)
}

@SuppressLint("SetTextI18n")
fun onMove(fromPosition: Int, toPosition: Int) {
Collections.swap(data, fromPosition, toPosition)
val map = data.map { it.name }.toList()
PrefManager.setVal(PrefName.MangaSourcesOrder, map)
MangaSources.pinnedMangaSources = map
MangaSources.performReorderMangaSources()
notifyItemMoved(fromPosition, toPosition)
}

@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val extension = getItem(position) // Use getItem() from ListAdapter
val nsfw = if (extension.isNsfw) "(18+)" else ""
Expand All @@ -243,11 +295,6 @@ class InstalledMangaExtensionsFragment : Fragment(), SearchQueryHandler {
holder.settingsImageView.setOnClickListener {
onSettingsClicked(extension)
}

holder.card.setOnLongClickListener {
onUninstallClicked(extension, true)
true
}
}

fun filter(query: String, currentList: List<MangaExtension.Installed>) {
Expand Down
Loading

0 comments on commit d3f097f

Please sign in to comment.