Migrate favourite categories to AdapterDelegates
This commit is contained in:
@@ -21,7 +21,7 @@ class ChaptersSelectionDecoration(context: Context) : RecyclerView.ItemDecoratio
|
|||||||
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
paint.color = context.getThemeColor(android.R.attr.colorControlActivated)
|
paint.color = context.getThemeColor(com.google.android.material.R.attr.colorSurface)
|
||||||
paint.style = Paint.Style.FILL
|
paint.style = Paint.Style.FILL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.koitharu.kotatsu.favourites.data
|
package org.koitharu.kotatsu.favourites.data
|
||||||
|
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class FavouriteCategoriesDao {
|
abstract class FavouriteCategoriesDao {
|
||||||
@@ -8,6 +10,9 @@ abstract class FavouriteCategoriesDao {
|
|||||||
@Query("SELECT * FROM favourite_categories ORDER BY sort_key")
|
@Query("SELECT * FROM favourite_categories ORDER BY sort_key")
|
||||||
abstract suspend fun findAll(): List<FavouriteCategoryEntity>
|
abstract suspend fun findAll(): List<FavouriteCategoryEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM favourite_categories ORDER BY sort_key")
|
||||||
|
abstract fun observeAll(): Flow<List<FavouriteCategoryEntity>>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.ABORT)
|
@Insert(onConflict = OnConflictStrategy.ABORT)
|
||||||
abstract suspend fun insert(category: FavouriteCategoryEntity): Long
|
abstract suspend fun insert(category: FavouriteCategoryEntity): Long
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ class FavouritesRepository(private val db: MangaDatabase) {
|
|||||||
return entities?.map { it.toFavouriteCategory() }.orEmpty()
|
return entities?.map { it.toFavouriteCategory() }.orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun observeCategories(): Flow<List<FavouriteCategory>> {
|
||||||
|
return db.favouriteCategoriesDao.observeAll().mapItems {
|
||||||
|
it.toFavouriteCategory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun observeCategories(mangaId: Long): Flow<List<FavouriteCategory>> {
|
fun observeCategories(mangaId: Long): Flow<List<FavouriteCategory>> {
|
||||||
return db.favouritesDao.observe(mangaId).map { entity ->
|
return db.favouritesDao.observe(mangaId).map { entity ->
|
||||||
entity?.categories?.map { it.toFavouriteCategory() }.orEmpty()
|
entity?.categories?.map { it.toFavouriteCategory() }.orEmpty()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.koitharu.kotatsu.favourites.domain
|
package org.koitharu.kotatsu.favourites.domain
|
||||||
|
|
||||||
|
@Deprecated("Use flow")
|
||||||
fun interface OnFavouritesChangeListener {
|
fun interface OnFavouritesChangeListener {
|
||||||
|
|
||||||
fun onFavouritesChanged(mangaId: Long)
|
fun onFavouritesChanged(mangaId: Long)
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import org.koin.android.viewmodel.ext.android.viewModel
|
|||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
|
||||||
import org.koitharu.kotatsu.favourites.domain.OnFavouritesChangeListener
|
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
|
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesEditDelegate
|
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesEditDelegate
|
||||||
import org.koitharu.kotatsu.favourites.ui.categories.FavouritesCategoriesViewModel
|
import org.koitharu.kotatsu.favourites.ui.categories.FavouritesCategoriesViewModel
|
||||||
@@ -22,8 +20,7 @@ import java.util.*
|
|||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class FavouritesContainerFragment : BaseFragment(R.layout.fragment_favourites),
|
class FavouritesContainerFragment : BaseFragment(R.layout.fragment_favourites),
|
||||||
OnFavouritesChangeListener, FavouritesTabLongClickListener,
|
FavouritesTabLongClickListener, CategoriesEditDelegate.CategoriesEditCallback {
|
||||||
CategoriesEditDelegate.CategoriesEditCallback {
|
|
||||||
|
|
||||||
private val viewModel by viewModel<FavouritesCategoriesViewModel>()
|
private val viewModel by viewModel<FavouritesCategoriesViewModel>()
|
||||||
|
|
||||||
@@ -41,18 +38,12 @@ class FavouritesContainerFragment : BaseFragment(R.layout.fragment_favourites),
|
|||||||
val adapter = FavouritesPagerAdapter(this, this)
|
val adapter = FavouritesPagerAdapter(this, this)
|
||||||
pager.adapter = adapter
|
pager.adapter = adapter
|
||||||
TabLayoutMediator(tabs, pager, adapter).attach()
|
TabLayoutMediator(tabs, pager, adapter).attach()
|
||||||
FavouritesRepository.subscribe(this)
|
|
||||||
|
|
||||||
viewModel.categories.observe(viewLifecycleOwner, ::onCategoriesChanged)
|
viewModel.categories.observe(viewLifecycleOwner, ::onCategoriesChanged)
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
private fun onCategoriesChanged(categories: List<FavouriteCategory>) {
|
||||||
FavouritesRepository.unsubscribe(this)
|
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onCategoriesChanged(categories: List<FavouriteCategory>) {
|
|
||||||
val data = ArrayList<FavouriteCategory>(categories.size + 1)
|
val data = ArrayList<FavouriteCategory>(categories.size + 1)
|
||||||
data += FavouriteCategory(0L, getString(R.string.all_favourites), -1, Date())
|
data += FavouriteCategory(0L, getString(R.string.all_favourites), -1, Date())
|
||||||
data += categories
|
data += categories
|
||||||
@@ -75,19 +66,13 @@ class FavouritesContainerFragment : BaseFragment(R.layout.fragment_favourites),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getTitle(): CharSequence? {
|
override fun getTitle(): CharSequence? {
|
||||||
return getString(R.string.favourites)
|
return context?.getString(R.string.favourites)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onError(e: Throwable) {
|
private fun onError(e: Throwable) {
|
||||||
Snackbar.make(pager, e.message ?: return, Snackbar.LENGTH_LONG).show()
|
Snackbar.make(pager, e.message ?: return, Snackbar.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFavouritesChanged(mangaId: Long) = Unit
|
|
||||||
|
|
||||||
override fun onCategoriesChanged() {
|
|
||||||
viewModel.loadAllCategories()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTabLongClick(tabView: View, category: FavouriteCategory): Boolean {
|
override fun onTabLongClick(tabView: View, category: FavouriteCategory): Boolean {
|
||||||
val menuRes = if (category.id == 0L) R.menu.popup_category_empty else R.menu.popup_category
|
val menuRes = if (category.id == 0L) R.menu.popup_category_empty else R.menu.popup_category
|
||||||
tabView.showPopupMenu(menuRes) {
|
tabView.showPopupMenu(menuRes) {
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import kotlinx.android.synthetic.main.activity_categories.*
|
|||||||
import org.koin.android.viewmodel.ext.android.viewModel
|
import org.koin.android.viewmodel.ext.android.viewModel
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.base.ui.list.OnRecyclerItemClickListener
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
import org.koitharu.kotatsu.utils.ext.showPopupMenu
|
import org.koitharu.kotatsu.utils.ext.showPopupMenu
|
||||||
|
|
||||||
class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener<FavouriteCategory>,
|
class CategoriesActivity : BaseActivity(), OnListItemClickListener<FavouriteCategory>,
|
||||||
View.OnClickListener, CategoriesEditDelegate.CategoriesEditCallback {
|
View.OnClickListener, CategoriesEditDelegate.CategoriesEditCallback {
|
||||||
|
|
||||||
private val viewModel by viewModel<FavouritesCategoriesViewModel>()
|
private val viewModel by viewModel<FavouritesCategoriesViewModel>()
|
||||||
@@ -52,7 +52,7 @@ class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener<Favourite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(item: FavouriteCategory, position: Int, view: View) {
|
override fun onItemClick(item: FavouriteCategory, view: View) {
|
||||||
view.showPopupMenu(R.menu.popup_category) {
|
view.showPopupMenu(R.menu.popup_category) {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.action_remove -> editDelegate.deleteCategory(item)
|
R.id.action_remove -> editDelegate.deleteCategory(item)
|
||||||
@@ -62,15 +62,15 @@ class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener<Favourite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: FavouriteCategory, position: Int, view: View): Boolean {
|
override fun onItemLongClick(item: FavouriteCategory, view: View): Boolean {
|
||||||
reorderHelper.startDrag(
|
reorderHelper.startDrag(
|
||||||
recyclerView.findViewHolderForAdapterPosition(position) ?: return false
|
recyclerView.findContainingViewHolder(view) ?: return false
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCategoriesChanged(categories: List<FavouriteCategory>) {
|
private fun onCategoriesChanged(categories: List<FavouriteCategory>) {
|
||||||
adapter.replaceData(categories)
|
adapter.items = categories
|
||||||
textView_holder.isVisible = categories.isEmpty()
|
textView_holder.isVisible = categories.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,8 +102,7 @@ class CategoriesActivity : BaseActivity(), OnRecyclerItemClickListener<Favourite
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
val oldPos = viewHolder.bindingAdapterPosition
|
val oldPos = viewHolder.bindingAdapterPosition
|
||||||
val newPos = target.bindingAdapterPosition
|
val newPos = target.bindingAdapterPosition
|
||||||
adapter.moveItem(oldPos, newPos)
|
viewModel.reorderCategories(oldPos, newPos)
|
||||||
viewModel.storeCategoriesOrder(adapter.items.map { it.id })
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +1,27 @@
|
|||||||
package org.koitharu.kotatsu.favourites.ui.categories
|
package org.koitharu.kotatsu.favourites.ui.categories
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import android.view.MotionEvent
|
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
|
||||||
import android.view.ViewGroup
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
import kotlinx.android.synthetic.main.item_category.*
|
|
||||||
import org.koitharu.kotatsu.base.ui.list.BaseRecyclerAdapter
|
|
||||||
import org.koitharu.kotatsu.base.ui.list.BaseViewHolder
|
|
||||||
import org.koitharu.kotatsu.base.ui.list.OnRecyclerItemClickListener
|
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
import kotlin.jvm.internal.Intrinsics
|
||||||
|
|
||||||
class CategoriesAdapter(private val onItemClickListener: OnRecyclerItemClickListener<FavouriteCategory>) :
|
class CategoriesAdapter(
|
||||||
BaseRecyclerAdapter<FavouriteCategory, Unit>() {
|
onItemClickListener: OnListItemClickListener<FavouriteCategory>
|
||||||
|
) : AsyncListDifferDelegationAdapter<FavouriteCategory>(DiffCallback()) {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup) = CategoryHolder(parent)
|
init {
|
||||||
|
delegatesManager.addDelegate(categoryAD(onItemClickListener))
|
||||||
override fun onGetItemId(item: FavouriteCategory) = item.id
|
|
||||||
|
|
||||||
override fun getExtra(item: FavouriteCategory, position: Int) = Unit
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
override fun onViewAttachedToWindow(holder: BaseViewHolder<FavouriteCategory, Unit>) {
|
|
||||||
holder.imageView_more.setOnClickListener { v ->
|
|
||||||
onItemClickListener.onItemClick(holder.requireData(), holder.bindingAdapterPosition, v)
|
|
||||||
}
|
|
||||||
holder.imageView_handle.setOnTouchListener { v, event ->
|
|
||||||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
|
||||||
onItemClickListener.onItemLongClick(
|
|
||||||
holder.requireData(),
|
|
||||||
holder.bindingAdapterPosition,
|
|
||||||
v
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewDetachedFromWindow(holder: BaseViewHolder<FavouriteCategory, Unit>) {
|
private class DiffCallback : DiffUtil.ItemCallback<FavouriteCategory>() {
|
||||||
holder.imageView_more.setOnClickListener(null)
|
|
||||||
holder.imageView_handle.setOnTouchListener(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun moveItem(oldPos: Int, newPos: Int) {
|
override fun areItemsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||||
val item = dataSet.removeAt(oldPos)
|
return oldItem.id == newItem.id
|
||||||
dataSet.add(newPos, item)
|
}
|
||||||
notifyItemMoved(oldPos, newPos)
|
|
||||||
|
override fun areContentsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||||
|
return Intrinsics.areEqual(oldItem, newItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.koitharu.kotatsu.favourites.ui.categories
|
||||||
|
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateLayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.item_category.*
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
|
|
||||||
|
fun categoryAD(
|
||||||
|
clickListener: OnListItemClickListener<FavouriteCategory>
|
||||||
|
) = adapterDelegateLayoutContainer<FavouriteCategory, FavouriteCategory>(R.layout.item_category) {
|
||||||
|
|
||||||
|
imageView_more.setOnClickListener {
|
||||||
|
clickListener.onItemClick(item, it)
|
||||||
|
}
|
||||||
|
@Suppress("ClickableViewAccessibility")
|
||||||
|
imageView_handle.setOnTouchListener { v, event ->
|
||||||
|
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||||
|
clickListener.onItemLongClick(item, v)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bind {
|
||||||
|
textView_title.text = item.title
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.favourites.ui.categories
|
|
||||||
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import kotlinx.android.synthetic.main.item_category.*
|
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.base.ui.list.BaseViewHolder
|
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
|
||||||
|
|
||||||
class CategoryHolder(parent: ViewGroup) :
|
|
||||||
BaseViewHolder<FavouriteCategory, Unit>(parent, R.layout.item_category) {
|
|
||||||
|
|
||||||
override fun onBind(data: FavouriteCategory, extra: Unit) {
|
|
||||||
textView_title.text = data.title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
package org.koitharu.kotatsu.favourites.ui.categories
|
package org.koitharu.kotatsu.favourites.ui.categories
|
||||||
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.asLiveData
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.plus
|
||||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
|
||||||
import org.koitharu.kotatsu.core.model.Manga
|
import org.koitharu.kotatsu.core.model.Manga
|
||||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||||
import org.koitharu.kotatsu.utils.ext.mapToSet
|
import org.koitharu.kotatsu.utils.ext.mapToSet
|
||||||
@@ -13,53 +19,47 @@ class FavouritesCategoriesViewModel(
|
|||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private var reorderJob: Job? = null
|
private var reorderJob: Job? = null
|
||||||
|
private var mangaSubscription: Job? = null
|
||||||
|
|
||||||
val categories = MutableLiveData<List<FavouriteCategory>>()
|
val categories = repository.observeCategories()
|
||||||
val mangaCategories = MutableLiveData<Set<Int>>()
|
.asLiveData(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||||
|
val mangaCategories = MutableLiveData<Set<Long>>(emptySet())
|
||||||
|
|
||||||
init {
|
fun observeMangaCategories(mangaId: Long) {
|
||||||
loadAllCategories()
|
mangaSubscription?.cancel()
|
||||||
}
|
mangaSubscription = repository.observeCategories(mangaId)
|
||||||
|
.map { list -> list.mapToSet { it.id } }
|
||||||
fun loadAllCategories() {
|
.onEach { mangaCategories.postValue(it) }
|
||||||
launchJob {
|
.launchIn(viewModelScope + Dispatchers.Default)
|
||||||
categories.value = repository.getAllCategories()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadMangaCategories(manga: Manga) {
|
|
||||||
launchJob {
|
|
||||||
val categories = repository.getCategories(manga.id)
|
|
||||||
mangaCategories.value = categories.mapToSet { it.id.toInt() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCategory(name: String) {
|
fun createCategory(name: String) {
|
||||||
launchJob {
|
launchJob {
|
||||||
repository.addCategory(name)
|
repository.addCategory(name)
|
||||||
categories.value = repository.getAllCategories()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun renameCategory(id: Long, name: String) {
|
fun renameCategory(id: Long, name: String) {
|
||||||
launchJob {
|
launchJob {
|
||||||
repository.renameCategory(id, name)
|
repository.renameCategory(id, name)
|
||||||
categories.value = repository.getAllCategories()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteCategory(id: Long) {
|
fun deleteCategory(id: Long) {
|
||||||
launchJob {
|
launchJob {
|
||||||
repository.removeCategory(id)
|
repository.removeCategory(id)
|
||||||
categories.value = repository.getAllCategories()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun storeCategoriesOrder(orderedIds: List<Long>) {
|
fun reorderCategories(oldPos: Int, newPos: Int) {
|
||||||
val prevJob = reorderJob
|
val prevJob = reorderJob
|
||||||
reorderJob = launchJob {
|
reorderJob = launchJob {
|
||||||
prevJob?.join()
|
prevJob?.join()
|
||||||
repository.reorderCategories(orderedIds)
|
val items = categories.value ?: error("This should not happen")
|
||||||
|
val ids = items.mapTo(ArrayList(items.size)) { it.id }
|
||||||
|
val item = ids.removeAt(oldPos)
|
||||||
|
ids.add(newPos, item)
|
||||||
|
repository.reorderCategories(ids)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package org.koitharu.kotatsu.favourites.ui.categories.select
|
package org.koitharu.kotatsu.favourites.ui.categories.select
|
||||||
|
|
||||||
import android.util.SparseBooleanArray
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.Checkable
|
import android.widget.Checkable
|
||||||
import androidx.core.util.set
|
import androidx.collection.ArraySet
|
||||||
import org.koitharu.kotatsu.base.ui.list.BaseRecyclerAdapter
|
import org.koitharu.kotatsu.base.ui.list.BaseRecyclerAdapter
|
||||||
import org.koitharu.kotatsu.base.ui.list.BaseViewHolder
|
import org.koitharu.kotatsu.base.ui.list.BaseViewHolder
|
||||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||||
@@ -11,18 +10,15 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
|
|||||||
class CategoriesSelectAdapter(private val listener: OnCategoryCheckListener) :
|
class CategoriesSelectAdapter(private val listener: OnCategoryCheckListener) :
|
||||||
BaseRecyclerAdapter<FavouriteCategory, Boolean>() {
|
BaseRecyclerAdapter<FavouriteCategory, Boolean>() {
|
||||||
|
|
||||||
private val checkedIds = SparseBooleanArray()
|
private val checkedIds = ArraySet<Long>()
|
||||||
|
|
||||||
fun setCheckedIds(ids: Iterable<Int>) {
|
fun setCheckedIds(ids: Iterable<Long>) {
|
||||||
checkedIds.clear()
|
checkedIds.clear()
|
||||||
ids.forEach {
|
checkedIds.addAll(ids)
|
||||||
checkedIds[it] = true
|
|
||||||
}
|
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExtra(item: FavouriteCategory, position: Int) =
|
override fun getExtra(item: FavouriteCategory, position: Int) = item.id in checkedIds
|
||||||
checkedIds.get(item.id.toInt(), false)
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup) =
|
override fun onCreateViewHolder(parent: ViewGroup) =
|
||||||
CategoryCheckableHolder(
|
CategoryCheckableHolder(
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class FavouriteCategoriesDialog : BaseBottomSheet(R.layout.dialog_favorite_categ
|
|||||||
createCategory()
|
createCategory()
|
||||||
}
|
}
|
||||||
manga?.let {
|
manga?.let {
|
||||||
viewModel.loadMangaCategories(it)
|
viewModel.observeMangaCategories(it.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.categories.observe(viewLifecycleOwner, ::onCategoriesChanged)
|
viewModel.categories.observe(viewLifecycleOwner, ::onCategoriesChanged)
|
||||||
@@ -53,7 +53,7 @@ class FavouriteCategoriesDialog : BaseBottomSheet(R.layout.dialog_favorite_categ
|
|||||||
adapter?.replaceData(categories)
|
adapter?.replaceData(categories)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCheckedCategoriesChanged(checkedIds: Set<Int>) {
|
private fun onCheckedCategoriesChanged(checkedIds: Set<Long>) {
|
||||||
adapter?.setCheckedIds(checkedIds)
|
adapter?.setCheckedIds(checkedIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,9 +44,6 @@ class FeedFragment : BaseFragment(R.layout.fragment_tracklogs), PaginationScroll
|
|||||||
)
|
)
|
||||||
recyclerView.setHasFixedSize(true)
|
recyclerView.setHasFixedSize(true)
|
||||||
recyclerView.addOnScrollListener(PaginationScrollListener(4, this))
|
recyclerView.addOnScrollListener(PaginationScrollListener(4, this))
|
||||||
if (savedInstanceState == null) {
|
|
||||||
onScrolledToEnd()
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
|
viewModel.content.observe(viewLifecycleOwner, this::onListChanged)
|
||||||
viewModel.isLoading.observe(viewLifecycleOwner, this::onLoadingStateChanged)
|
viewModel.isLoading.observe(viewLifecycleOwner, this::onLoadingStateChanged)
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.drop
|
import kotlinx.coroutines.flow.drop
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
import org.koitharu.kotatsu.core.model.TrackingLogItem
|
||||||
import org.koitharu.kotatsu.list.ui.model.IndeterminateProgress
|
import org.koitharu.kotatsu.list.ui.model.IndeterminateProgress
|
||||||
@@ -28,9 +27,7 @@ class FeedViewModel(
|
|||||||
|
|
||||||
val isEmptyState = MutableLiveData(false)
|
val isEmptyState = MutableLiveData(false)
|
||||||
val content = combine(
|
val content = combine(
|
||||||
logList.drop(1).onEach {
|
logList.drop(1).mapItems {
|
||||||
isEmptyState.postValue(it.isEmpty())
|
|
||||||
}.mapItems {
|
|
||||||
it.toFeedItem(context.resources)
|
it.toFeedItem(context.resources)
|
||||||
},
|
},
|
||||||
hasNextPage
|
hasNextPage
|
||||||
@@ -53,6 +50,8 @@ class FeedViewModel(
|
|||||||
logList.value = list
|
logList.value = list
|
||||||
} else if (list.isNotEmpty()) {
|
} else if (list.isNotEmpty()) {
|
||||||
logList.value += list
|
logList.value += list
|
||||||
|
} else {
|
||||||
|
isEmptyState.value = true
|
||||||
}
|
}
|
||||||
hasNextPage.value = list.isNotEmpty()
|
hasNextPage.value = list.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user