#8 Configure sort order for each favourites category
This commit is contained in:
@@ -118,6 +118,7 @@ class BackupRepository(private val db: MangaDatabase) {
|
||||
jo.put("created_at", createdAt)
|
||||
jo.put("sort_key", sortKey)
|
||||
jo.put("title", title)
|
||||
jo.put("order", order)
|
||||
return jo
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
|
||||
import org.koitharu.kotatsu.history.data.HistoryEntity
|
||||
@@ -101,7 +102,8 @@ class RestoreRepository(private val db: MangaDatabase) {
|
||||
categoryId = json.getInt("category_id"),
|
||||
createdAt = json.getLong("created_at"),
|
||||
sortKey = json.getInt("sort_key"),
|
||||
title = json.getString("title")
|
||||
title = json.getString("title"),
|
||||
order = json.getStringOrNull("order") ?: SortOrder.NEWEST.name,
|
||||
)
|
||||
|
||||
private fun parseFavourite(json: JSONObject) = FavouriteEntity(
|
||||
|
||||
@@ -20,6 +20,7 @@ val databaseModule
|
||||
Migration5To6(),
|
||||
Migration6To7(),
|
||||
Migration7To8(),
|
||||
Migration8To9(),
|
||||
).addCallback(
|
||||
DatabasePrePopulateCallback(androidContext().resources)
|
||||
).build()
|
||||
|
||||
@@ -16,7 +16,7 @@ import org.koitharu.kotatsu.history.data.HistoryEntity
|
||||
MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class,
|
||||
FavouriteCategoryEntity::class, FavouriteEntity::class, MangaPrefsEntity::class,
|
||||
TrackEntity::class, TrackLogEntity::class, SuggestionEntity::class
|
||||
], version = 8
|
||||
], version = 9
|
||||
)
|
||||
abstract class MangaDatabase : RoomDatabase() {
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.core.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
|
||||
class Migration8To9 : Migration(8, 9) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE favourite_categories ADD COLUMN `order` TEXT NOT NULL DEFAULT ${SortOrder.NEWEST.name}")
|
||||
}
|
||||
}
|
||||
@@ -9,5 +9,6 @@ data class FavouriteCategory(
|
||||
val id: Long,
|
||||
val title: String,
|
||||
val sortKey: Int,
|
||||
val createdAt: Date
|
||||
val order: SortOrder,
|
||||
val createdAt: Date,
|
||||
) : Parcelable
|
||||
@@ -2,7 +2,6 @@ package org.koitharu.kotatsu.favourites.data
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
|
||||
@Dao
|
||||
abstract class FavouriteCategoriesDao {
|
||||
@@ -13,6 +12,9 @@ abstract class FavouriteCategoriesDao {
|
||||
@Query("SELECT * FROM favourite_categories ORDER BY sort_key")
|
||||
abstract fun observeAll(): Flow<List<FavouriteCategoryEntity>>
|
||||
|
||||
@Query("SELECT * FROM favourite_categories WHERE category_id = :id")
|
||||
abstract fun observe(id: Long): Flow<FavouriteCategoryEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.ABORT)
|
||||
abstract suspend fun insert(category: FavouriteCategoryEntity): Long
|
||||
|
||||
@@ -23,10 +25,13 @@ abstract class FavouriteCategoriesDao {
|
||||
abstract suspend fun delete(id: Long)
|
||||
|
||||
@Query("UPDATE favourite_categories SET title = :title WHERE category_id = :id")
|
||||
abstract suspend fun update(id: Long, title: String)
|
||||
abstract suspend fun updateTitle(id: Long, title: String)
|
||||
|
||||
@Query("UPDATE favourite_categories SET `order` = :order WHERE category_id = :id")
|
||||
abstract suspend fun updateOrder(id: Long, order: String)
|
||||
|
||||
@Query("UPDATE favourite_categories SET sort_key = :sortKey WHERE category_id = :id")
|
||||
abstract suspend fun update(id: Long, sortKey: Int)
|
||||
abstract suspend fun updateSortKey(id: Long, sortKey: Int)
|
||||
|
||||
@Query("SELECT MAX(sort_key) FROM favourite_categories")
|
||||
protected abstract suspend fun getMaxSortKey(): Int?
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "favourite_categories")
|
||||
@@ -12,13 +13,15 @@ data class FavouriteCategoryEntity(
|
||||
@ColumnInfo(name = "category_id") val categoryId: Int,
|
||||
@ColumnInfo(name = "created_at") val createdAt: Long,
|
||||
@ColumnInfo(name = "sort_key") val sortKey: Int,
|
||||
@ColumnInfo(name = "title") val title: String
|
||||
@ColumnInfo(name = "title") val title: String,
|
||||
@ColumnInfo(name = "order") val order: String,
|
||||
) {
|
||||
|
||||
fun toFavouriteCategory(id: Long? = null) = FavouriteCategory(
|
||||
id = id ?: categoryId.toLong(),
|
||||
title = title,
|
||||
sortKey = sortKey,
|
||||
createdAt = Date(createdAt)
|
||||
order = SortOrder.values().find { x -> x.name == order } ?: SortOrder.NEWEST,
|
||||
createdAt = Date(createdAt),
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.koitharu.kotatsu.favourites.data
|
||||
|
||||
import androidx.room.*
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import androidx.sqlite.db.SupportSQLiteQuery
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
|
||||
@Dao
|
||||
abstract class FavouritesDao {
|
||||
@@ -11,9 +14,13 @@ abstract class FavouritesDao {
|
||||
@Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at DESC")
|
||||
abstract suspend fun findAll(): List<FavouriteManga>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at DESC")
|
||||
abstract fun observeAll(): Flow<List<FavouriteManga>>
|
||||
fun observeAll(order: SortOrder): Flow<List<FavouriteManga>> {
|
||||
val orderBy = getOrderBy(order)
|
||||
val query = SimpleSQLiteQuery(
|
||||
"SELECT * FROM favourites LEFT JOIN manga ON favourites.manga_id = manga.manga_id GROUP BY favourites.manga_id ORDER BY $orderBy",
|
||||
)
|
||||
return observeAllRaw(query)
|
||||
}
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM favourites GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit OFFSET :offset")
|
||||
@@ -23,9 +30,14 @@ abstract class FavouritesDao {
|
||||
@Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at DESC")
|
||||
abstract suspend fun findAll(categoryId: Long): List<FavouriteManga>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at DESC")
|
||||
abstract fun observeAll(categoryId: Long): Flow<List<FavouriteManga>>
|
||||
fun observeAll(categoryId: Long, order: SortOrder): Flow<List<FavouriteManga>> {
|
||||
val orderBy = getOrderBy(order)
|
||||
val query = SimpleSQLiteQuery(
|
||||
"SELECT * FROM favourites LEFT JOIN manga ON favourites.manga_id = manga.manga_id WHERE category_id = ? GROUP BY favourites.manga_id ORDER BY $orderBy",
|
||||
arrayOf<Any>(categoryId),
|
||||
)
|
||||
return observeAllRaw(query)
|
||||
}
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM favourites WHERE category_id = :categoryId GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit OFFSET :offset")
|
||||
@@ -63,4 +75,16 @@ abstract class FavouritesDao {
|
||||
insert(entity)
|
||||
}
|
||||
}
|
||||
|
||||
@Transaction
|
||||
@RawQuery(observedEntities = [FavouriteEntity::class])
|
||||
protected abstract fun observeAllRaw(query: SupportSQLiteQuery): Flow<List<FavouriteManga>>
|
||||
|
||||
private fun getOrderBy(sortOrder: SortOrder) = when(sortOrder) {
|
||||
SortOrder.RATING -> "rating DESC"
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.UPDATED -> "created_at DESC"
|
||||
SortOrder.ALPHABETICAL -> "title ASC"
|
||||
else -> throw IllegalArgumentException("Sort order $sortOrder is not supported")
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,14 @@ package org.koitharu.kotatsu.favourites.domain
|
||||
import androidx.room.withTransaction
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
|
||||
import org.koitharu.kotatsu.utils.ext.mapItems
|
||||
@@ -21,26 +23,26 @@ class FavouritesRepository(private val db: MangaDatabase) {
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
fun observeAll(): Flow<List<Manga>> {
|
||||
return db.favouritesDao.observeAll()
|
||||
fun observeAll(order: SortOrder): Flow<List<Manga>> {
|
||||
return db.favouritesDao.observeAll(order)
|
||||
.mapItems { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun getAllManga(offset: Int): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll(offset, 20)
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
suspend fun getManga(categoryId: Long): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll(categoryId)
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
fun observeAll(categoryId: Long): Flow<List<Manga>> {
|
||||
return db.favouritesDao.observeAll(categoryId)
|
||||
fun observeAll(categoryId: Long, order: SortOrder): Flow<List<Manga>> {
|
||||
return db.favouritesDao.observeAll(categoryId, order)
|
||||
.mapItems { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
}
|
||||
|
||||
fun observeAll(categoryId: Long): Flow<List<Manga>> {
|
||||
return observeOrder(categoryId)
|
||||
.flatMapLatest { order -> observeAll(categoryId, order) }
|
||||
}
|
||||
|
||||
suspend fun getManga(categoryId: Long, offset: Int): List<Manga> {
|
||||
val entities = db.favouritesDao.findAll(categoryId, offset, 20)
|
||||
return entities.map { it.manga.toManga(it.tags.mapToSet(TagEntity::toMangaTag)) }
|
||||
@@ -77,25 +79,30 @@ class FavouritesRepository(private val db: MangaDatabase) {
|
||||
title = title,
|
||||
createdAt = System.currentTimeMillis(),
|
||||
sortKey = db.favouriteCategoriesDao.getNextSortKey(),
|
||||
categoryId = 0
|
||||
categoryId = 0,
|
||||
order = SortOrder.UPDATED.name,
|
||||
)
|
||||
val id = db.favouriteCategoriesDao.insert(entity)
|
||||
return entity.toFavouriteCategory(id)
|
||||
}
|
||||
|
||||
suspend fun renameCategory(id: Long, title: String) {
|
||||
db.favouriteCategoriesDao.update(id, title)
|
||||
db.favouriteCategoriesDao.updateTitle(id, title)
|
||||
}
|
||||
|
||||
suspend fun removeCategory(id: Long) {
|
||||
db.favouriteCategoriesDao.delete(id)
|
||||
}
|
||||
|
||||
suspend fun setCategoryOrder(id: Long, order: SortOrder) {
|
||||
db.favouriteCategoriesDao.updateOrder(id, order.name)
|
||||
}
|
||||
|
||||
suspend fun reorderCategories(orderedIds: List<Long>) {
|
||||
val dao = db.favouriteCategoriesDao
|
||||
db.withTransaction {
|
||||
for ((i, id) in orderedIds.withIndex()) {
|
||||
dao.update(id, i)
|
||||
dao.updateSortKey(id, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,4 +124,10 @@ class FavouritesRepository(private val db: MangaDatabase) {
|
||||
suspend fun removeFromFavourites(manga: Manga) {
|
||||
db.favouritesDao.delete(manga.id)
|
||||
}
|
||||
|
||||
private fun observeOrder(categoryId: Long): Flow<SortOrder> {
|
||||
return db.favouriteCategoriesDao.observe(categoryId)
|
||||
.map { x -> SortOrder.values().find { it.name == x.order } ?: SortOrder.NEWEST }
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.databinding.FragmentFavouritesBinding
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesEditDelegate
|
||||
@@ -19,7 +20,6 @@ import org.koitharu.kotatsu.utils.RecycledViewPoolHolder
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.utils.ext.showPopupMenu
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
|
||||
FavouritesTabLongClickListener, CategoriesEditDelegate.CategoriesEditCallback,
|
||||
@@ -100,11 +100,19 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
|
||||
|
||||
override fun onTabLongClick(tabView: View, category: FavouriteCategory): Boolean {
|
||||
val menuRes = if (category.id == 0L) R.menu.popup_category_empty else R.menu.popup_category
|
||||
tabView.showPopupMenu(menuRes) {
|
||||
tabView.showPopupMenu(menuRes, { menu ->
|
||||
createOrderSubmenu(menu, category)
|
||||
}) {
|
||||
when (it.itemId) {
|
||||
R.id.action_remove -> editDelegate.deleteCategory(category)
|
||||
R.id.action_rename -> editDelegate.renameCategory(category)
|
||||
R.id.action_create -> editDelegate.createCategory()
|
||||
R.id.action_order -> return@showPopupMenu false
|
||||
else -> {
|
||||
val order = CategoriesActivity.SORT_ORDERS.getOrNull(it.order)
|
||||
?: return@showPopupMenu false
|
||||
viewModel.setCategoryOrder(category.id, order)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -125,11 +133,26 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesBinding>(),
|
||||
|
||||
private fun wrapCategories(categories: List<FavouriteCategory>): List<FavouriteCategory> {
|
||||
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, SortOrder.NEWEST, Date())
|
||||
data += categories
|
||||
return data
|
||||
}
|
||||
|
||||
private fun createOrderSubmenu(menu: Menu, category: FavouriteCategory) {
|
||||
val submenu = menu.findItem(R.id.action_order)?.subMenu ?: return
|
||||
for ((i, item) in CategoriesActivity.SORT_ORDERS.withIndex()) {
|
||||
val menuItem = submenu.add(
|
||||
R.id.group_order,
|
||||
Menu.NONE,
|
||||
i,
|
||||
item.titleRes
|
||||
)
|
||||
menuItem.isCheckable = true
|
||||
menuItem.isChecked = item == category.order
|
||||
}
|
||||
submenu.setGroupCheckable(R.id.group_order, true, true)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance() = FavouritesContainerFragment()
|
||||
|
||||
@@ -36,7 +36,7 @@ class FavouritesPagerAdapter(
|
||||
override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
|
||||
val item = differ.currentList[position]
|
||||
tab.text = item.title
|
||||
tab.view.tag = item
|
||||
tab.view.tag = item.id
|
||||
tab.view.setOnLongClickListener(this)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ class FavouritesPagerAdapter(
|
||||
}
|
||||
|
||||
override fun onLongClick(v: View): Boolean {
|
||||
val item = v.tag as? FavouriteCategory ?: return false
|
||||
val itemId = v.tag as? Long ?: return false
|
||||
val item = differ.currentList.find { x -> x.id == itemId } ?: return false
|
||||
return longClickListener.onTabLongClick(v, item)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.graphics.Insets
|
||||
@@ -20,6 +21,7 @@ import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
|
||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||
import org.koitharu.kotatsu.utils.ext.showPopupMenu
|
||||
@@ -61,10 +63,17 @@ class CategoriesActivity : BaseActivity<ActivityCategoriesBinding>(),
|
||||
}
|
||||
|
||||
override fun onItemClick(item: FavouriteCategory, view: View) {
|
||||
view.showPopupMenu(R.menu.popup_category) {
|
||||
view.showPopupMenu(R.menu.popup_category, { menu ->
|
||||
createOrderSubmenu(menu, item)
|
||||
}) {
|
||||
when (it.itemId) {
|
||||
R.id.action_remove -> editDelegate.deleteCategory(item)
|
||||
R.id.action_rename -> editDelegate.renameCategory(item)
|
||||
R.id.action_order -> return@showPopupMenu false
|
||||
else -> {
|
||||
val order = SORT_ORDERS.getOrNull(it.order) ?: return@showPopupMenu false
|
||||
viewModel.setCategoryOrder(item.id, order)
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -117,6 +126,21 @@ class CategoriesActivity : BaseActivity<ActivityCategoriesBinding>(),
|
||||
viewModel.createCategory(name)
|
||||
}
|
||||
|
||||
private fun createOrderSubmenu(menu: Menu, category: FavouriteCategory) {
|
||||
val submenu = menu.findItem(R.id.action_order)?.subMenu ?: return
|
||||
for ((i, item) in SORT_ORDERS.withIndex()) {
|
||||
val menuItem = submenu.add(
|
||||
R.id.group_order,
|
||||
Menu.NONE,
|
||||
i,
|
||||
item.titleRes
|
||||
)
|
||||
menuItem.isCheckable = true
|
||||
menuItem.isChecked = item == category.order
|
||||
}
|
||||
submenu.setGroupCheckable(R.id.group_order, true, true)
|
||||
}
|
||||
|
||||
private inner class ReorderHelperCallback : ItemTouchHelper.SimpleCallback(
|
||||
ItemTouchHelper.DOWN or ItemTouchHelper.UP, 0
|
||||
) {
|
||||
@@ -145,6 +169,12 @@ class CategoriesActivity : BaseActivity<ActivityCategoriesBinding>(),
|
||||
|
||||
companion object {
|
||||
|
||||
val SORT_ORDERS = arrayOf(
|
||||
SortOrder.ALPHABETICAL,
|
||||
SortOrder.NEWEST,
|
||||
SortOrder.RATING,
|
||||
)
|
||||
|
||||
fun newIntent(context: Context) = Intent(context, CategoriesActivity::class.java)
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
|
||||
class CategoriesAdapter(
|
||||
onItemClickListener: OnListItemClickListener<FavouriteCategory>
|
||||
onItemClickListener: OnListItemClickListener<FavouriteCategory>,
|
||||
) : AsyncListDifferDelegationAdapter<FavouriteCategory>(DiffCallback()) {
|
||||
|
||||
init {
|
||||
@@ -20,12 +20,27 @@ class CategoriesAdapter(
|
||||
|
||||
private class DiffCallback : DiffUtil.ItemCallback<FavouriteCategory>() {
|
||||
|
||||
override fun areItemsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: FavouriteCategory,
|
||||
newItem: FavouriteCategory,
|
||||
): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: FavouriteCategory, newItem: FavouriteCategory): Boolean {
|
||||
override fun areContentsTheSame(
|
||||
oldItem: FavouriteCategory,
|
||||
newItem: FavouriteCategory,
|
||||
): Boolean {
|
||||
return oldItem.id == newItem.id && oldItem.title == newItem.title
|
||||
&& oldItem.order == newItem.order
|
||||
}
|
||||
|
||||
override fun getChangePayload(
|
||||
oldItem: FavouriteCategory,
|
||||
newItem: FavouriteCategory,
|
||||
): Any? = when {
|
||||
oldItem.title == newItem.title && oldItem.order != newItem.order -> newItem.order
|
||||
else -> super.getChangePayload(oldItem, newItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class FavouritesCategoriesViewModel(
|
||||
private val repository: FavouritesRepository
|
||||
@@ -19,23 +19,29 @@ class FavouritesCategoriesViewModel(
|
||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
|
||||
|
||||
fun createCategory(name: String) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
launchJob {
|
||||
repository.addCategory(name)
|
||||
}
|
||||
}
|
||||
|
||||
fun renameCategory(id: Long, name: String) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
launchJob {
|
||||
repository.renameCategory(id, name)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteCategory(id: Long) {
|
||||
launchJob(Dispatchers.Default) {
|
||||
launchJob {
|
||||
repository.removeCategory(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCategoryOrder(id: Long, order: SortOrder) {
|
||||
launchJob {
|
||||
repository.setCategoryOrder(id, order)
|
||||
}
|
||||
}
|
||||
|
||||
fun reorderCategories(oldPos: Int, newPos: Int) {
|
||||
val prevJob = reorderJob
|
||||
reorderJob = launchJob(Dispatchers.Default) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.list.ui.MangaListViewModel
|
||||
@@ -22,7 +23,11 @@ class FavouritesListViewModel(
|
||||
) : MangaListViewModel(settings) {
|
||||
|
||||
override val content = combine(
|
||||
if (categoryId == 0L) repository.observeAll() else repository.observeAll(categoryId),
|
||||
if (categoryId == 0L) {
|
||||
repository.observeAll(SortOrder.NEWEST)
|
||||
} else {
|
||||
repository.observeAll(categoryId)
|
||||
},
|
||||
createListModeFlow()
|
||||
) { list, mode ->
|
||||
when {
|
||||
|
||||
@@ -8,6 +8,7 @@ import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.retry
|
||||
import org.koitharu.kotatsu.core.model.SortOrder
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.history.domain.HistoryRepository
|
||||
import org.koitharu.kotatsu.utils.ext.processLifecycleScope
|
||||
@@ -17,7 +18,7 @@ import org.koitharu.kotatsu.widget.shelf.ShelfWidgetProvider
|
||||
class WidgetUpdater(private val context: Context) {
|
||||
|
||||
fun subscribeToFavourites(repository: FavouritesRepository) {
|
||||
repository.observeAll()
|
||||
repository.observeAll(SortOrder.NEWEST)
|
||||
.onEach { updateWidget(ShelfWidgetProvider::class.java) }
|
||||
.retry { error -> error !is CancellationException }
|
||||
.launchIn(processLifecycleScope)
|
||||
|
||||
@@ -10,4 +10,17 @@
|
||||
android:id="@+id/action_rename"
|
||||
android:title="@string/rename" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_order"
|
||||
android:title="@string/sort_order">
|
||||
|
||||
<menu>
|
||||
|
||||
<group
|
||||
android:id="@+id/group_order"
|
||||
android:checkableBehavior="single" />
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
||||
</menu>
|
||||
Reference in New Issue
Block a user