From 97524d66f2ccbdcb02144c05c14779f46cbc6592 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Fri, 13 Oct 2023 14:26:52 +0300 Subject: [PATCH] Fix pages thumbnails loading --- .../kotatsu/core/model/FavouriteCategory.kt | 4 +- .../kotatsu/core/prefs/AppSettings.kt | 11 ++- .../kotatsu/core/util/ext/Collections.kt | 2 + .../kotatsu/favourites/data/EntityMapping.kt | 5 +- .../kotatsu/favourites/data/FavouritesDao.kt | 26 ++++--- .../favourites/domain/FavouritesRepository.kt | 17 ++--- .../categories/FavouriteCategoriesActivity.kt | 7 -- .../edit/FavouritesCategoryEditActivity.kt | 22 +++--- .../edit/FavouritesCategoryEditViewModel.kt | 4 +- .../ui/list/FavouritesListFragment.kt | 17 +++-- .../ui/list/FavouritesListMenuProvider.kt | 24 ------ .../ui/list/FavouritesListViewModel.kt | 8 +- .../kotatsu/filter/ui/FilterCoordinator.kt | 3 +- .../kotatsu/history/data/HistoryDao.kt | 13 ++-- .../kotatsu/history/data/HistoryRepository.kt | 4 +- .../history/domain/model/HistoryOrder.kt | 16 ---- .../history/ui/HistoryListViewModel.kt | 20 +++-- .../kotatsu/list/domain/ListSortOrder.kt | 30 ++++++++ .../kotatsu/list/ui/MangaListMenuProvider.kt | 12 ++- .../list/ui/config/ListConfigBottomSheet.kt | 59 ++++++-------- .../list/ui/config/ListConfigSection.kt | 21 +++++ .../list/ui/config/ListConfigViewModel.kt | 76 +++++++++++++++++++ .../ui/thumbnails/PagesThumbnailsViewModel.kt | 4 +- .../suggestions/ui/SuggestionsViewModel.kt | 4 + app/src/main/res/menu/opt_favourites.xml | 15 +--- .../res/menu/opt_favourites_container.xml | 4 +- app/src/main/res/menu/opt_list.xml | 2 +- app/src/main/res/values/strings.xml | 2 + 28 files changed, 258 insertions(+), 174 deletions(-) delete mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/HistoryOrder.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListSortOrder.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigSection.kt create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigViewModel.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/FavouriteCategory.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/FavouriteCategory.kt index 19dbeb9b0..1a0ed5b23 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/FavouriteCategory.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/FavouriteCategory.kt @@ -2,9 +2,9 @@ package org.koitharu.kotatsu.core.model import android.os.Parcelable import kotlinx.parcelize.Parcelize +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.list.ui.ListModelDiffCallback import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.parsers.model.SortOrder import java.util.Date @Parcelize @@ -12,7 +12,7 @@ data class FavouriteCategory( val id: Long, val title: String, val sortKey: Int, - val order: SortOrder, + val order: ListSortOrder, val createdAt: Date, val isTrackingEnabled: Boolean, val isVisibleInLibrary: Boolean, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 9ea90e53e..92ae4dfde 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -22,7 +22,7 @@ import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.putEnumValue import org.koitharu.kotatsu.core.util.ext.takeIfReadable import org.koitharu.kotatsu.core.util.ext.toUriOrNull -import org.koitharu.kotatsu.history.domain.model.HistoryOrder +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.util.find import org.koitharu.kotatsu.parsers.util.mapNotNullToSet @@ -76,6 +76,10 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { get() = prefs.getEnumValue(KEY_LIST_MODE_HISTORY, listMode) set(value) = prefs.edit { putEnumValue(KEY_LIST_MODE_HISTORY, value) } + var suggestionsListMode: ListMode + get() = prefs.getEnumValue(KEY_LIST_MODE_SUGGESTIONS, listMode) + set(value) = prefs.edit { putEnumValue(KEY_LIST_MODE_SUGGESTIONS, value) } + var favoritesListMode: ListMode get() = prefs.getEnumValue(KEY_LIST_MODE_FAVORITES, listMode) set(value) = prefs.edit { putEnumValue(KEY_LIST_MODE_FAVORITES, value) } @@ -315,8 +319,8 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { get() = prefs.getEnumValue(KEY_LOCAL_LIST_ORDER, SortOrder.NEWEST) set(value) = prefs.edit { putEnumValue(KEY_LOCAL_LIST_ORDER, value) } - var historySortOrder: HistoryOrder - get() = prefs.getEnumValue(KEY_HISTORY_ORDER, HistoryOrder.UPDATED) + var historySortOrder: ListSortOrder + get() = prefs.getEnumValue(KEY_HISTORY_ORDER, ListSortOrder.UPDATED) set(value) = prefs.edit { putEnumValue(KEY_HISTORY_ORDER, value) } val isRelatedMangaEnabled: Boolean @@ -417,6 +421,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_LIST_MODE = "list_mode_2" const val KEY_LIST_MODE_HISTORY = "list_mode_history" const val KEY_LIST_MODE_FAVORITES = "list_mode_favorites" + const val KEY_LIST_MODE_SUGGESTIONS = "list_mode_suggestions" const val KEY_THEME = "theme" const val KEY_COLOR_THEME = "color_theme" const val KEY_THEME_AMOLED = "amoled_theme" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt index 92edc2773..aedd8eb39 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Collections.kt @@ -55,3 +55,5 @@ inline fun > Collection.toEnumSet(): EnumSet = if (isE } else { EnumSet.copyOf(this) } + +fun > Collection.sortedByOrdinal() = sortedBy { it.ordinal } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/EntityMapping.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/EntityMapping.kt index af468c3e8..df2320a87 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/EntityMapping.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/EntityMapping.kt @@ -1,17 +1,16 @@ package org.koitharu.kotatsu.favourites.data -import org.koitharu.kotatsu.core.db.entity.SortOrder import org.koitharu.kotatsu.core.db.entity.toManga import org.koitharu.kotatsu.core.db.entity.toMangaTags import org.koitharu.kotatsu.core.model.FavouriteCategory -import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.list.domain.ListSortOrder import java.util.Date fun FavouriteCategoryEntity.toFavouriteCategory(id: Long = categoryId.toLong()) = FavouriteCategory( id = id, title = title, sortKey = sortKey, - order = SortOrder(order, SortOrder.NEWEST), + order = ListSortOrder(order, ListSortOrder.NEWEST), createdAt = Date(createdAt), isTrackingEnabled = track, isVisibleInLibrary = isVisibleInLibrary, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt index 066b031ce..dc2acef7e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/data/FavouritesDao.kt @@ -1,13 +1,19 @@ package org.koitharu.kotatsu.favourites.data -import androidx.room.* +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.RawQuery +import androidx.room.Transaction +import androidx.room.Upsert import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SupportSQLiteQuery import kotlinx.coroutines.flow.Flow import org.intellij.lang.annotations.Language import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.favourites.domain.model.Cover -import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.list.domain.ListSortOrder @Dao abstract class FavouritesDao { @@ -22,7 +28,7 @@ abstract class FavouritesDao { @Query("SELECT * FROM favourites WHERE deleted_at = 0 GROUP BY manga_id ORDER BY created_at DESC LIMIT :limit") abstract suspend fun findLast(limit: Int): List - fun observeAll(order: SortOrder): Flow> { + fun observeAll(order: ListSortOrder): Flow> { val orderBy = getOrderBy(order) @Language("RoomSql") @@ -47,7 +53,7 @@ abstract class FavouritesDao { ) abstract suspend fun findAll(categoryId: Long): List - fun observeAll(categoryId: Long, order: SortOrder): Flow> { + fun observeAll(categoryId: Long, order: ListSortOrder): Flow> { val orderBy = getOrderBy(order) @Language("RoomSql") @@ -72,7 +78,7 @@ abstract class FavouritesDao { ) abstract suspend fun findAllManga(categoryId: Int): List - suspend fun findCovers(categoryId: Long, order: SortOrder): List { + suspend fun findCovers(categoryId: Long, order: ListSortOrder): List { val orderBy = getOrderBy(order) @Language("RoomSql") @@ -157,13 +163,13 @@ abstract class FavouritesDao { @Query("UPDATE favourites SET deleted_at = :deletedAt WHERE category_id = :categoryId AND deleted_at = 0") protected abstract suspend fun setDeletedAtAll(categoryId: Long, deletedAt: Long) - private fun getOrderBy(sortOrder: SortOrder) = when (sortOrder) { - SortOrder.RATING -> "rating DESC" - SortOrder.NEWEST, - SortOrder.UPDATED, + private fun getOrderBy(sortOrder: ListSortOrder) = when (sortOrder) { + ListSortOrder.RATING -> "rating DESC" + ListSortOrder.NEWEST, + ListSortOrder.UPDATED, -> "created_at DESC" - SortOrder.ALPHABETICAL -> "title ASC" + ListSortOrder.ALPHABETIC -> "title ASC" else -> throw IllegalArgumentException("Sort order $sortOrder is not supported") } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt index 04c149a16..b61713cb8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/domain/FavouritesRepository.kt @@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import org.koitharu.kotatsu.core.db.MangaDatabase -import org.koitharu.kotatsu.core.db.entity.SortOrder import org.koitharu.kotatsu.core.db.entity.toEntities import org.koitharu.kotatsu.core.db.entity.toEntity import org.koitharu.kotatsu.core.model.FavouriteCategory @@ -20,8 +19,8 @@ import org.koitharu.kotatsu.favourites.data.toFavouriteCategory import org.koitharu.kotatsu.favourites.data.toManga import org.koitharu.kotatsu.favourites.data.toMangaList import org.koitharu.kotatsu.favourites.domain.model.Cover +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels import javax.inject.Inject @@ -41,7 +40,7 @@ class FavouritesRepository @Inject constructor( return entities.toMangaList() } - fun observeAll(order: SortOrder): Flow> { + fun observeAll(order: ListSortOrder): Flow> { return db.favouritesDao.observeAll(order) .mapItems { it.toManga() } } @@ -51,7 +50,7 @@ class FavouritesRepository @Inject constructor( return entities.toMangaList() } - fun observeAll(categoryId: Long, order: SortOrder): Flow> { + fun observeAll(categoryId: Long, order: ListSortOrder): Flow> { return db.favouritesDao.observeAll(categoryId, order) .mapItems { it.toManga() } } @@ -105,7 +104,7 @@ class FavouritesRepository @Inject constructor( suspend fun createCategory( title: String, - sortOrder: SortOrder, + sortOrder: ListSortOrder, isTrackerEnabled: Boolean, isVisibleOnShelf: Boolean, ): FavouriteCategory { @@ -128,7 +127,7 @@ class FavouritesRepository @Inject constructor( suspend fun updateCategory( id: Long, title: String, - sortOrder: SortOrder, + sortOrder: ListSortOrder, isTrackerEnabled: Boolean, isVisibleOnShelf: Boolean, ) { @@ -156,7 +155,7 @@ class FavouritesRepository @Inject constructor( } } - suspend fun setCategoryOrder(id: Long, order: SortOrder) { + suspend fun setCategoryOrder(id: Long, order: ListSortOrder) { db.favouriteCategoriesDao.updateOrder(id, order.name) } @@ -205,10 +204,10 @@ class FavouritesRepository @Inject constructor( return ReversibleHandle { recoverToCategory(categoryId, ids) } } - private fun observeOrder(categoryId: Long): Flow { + private fun observeOrder(categoryId: Long): Flow { return db.favouriteCategoriesDao.observe(categoryId) .filterNotNull() - .map { x -> SortOrder(x.order, SortOrder.NEWEST) } + .map { x -> ListSortOrder(x.order, ListSortOrder.NEWEST) } .distinctUntilChanged() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt index 62fa74862..7de530222 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt @@ -27,7 +27,6 @@ import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEdit import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration import org.koitharu.kotatsu.list.ui.model.ListModel -import org.koitharu.kotatsu.parsers.model.SortOrder import javax.inject.Inject @AndroidEntryPoint @@ -176,12 +175,6 @@ class FavouriteCategoriesActivity : companion object { - val SORT_ORDERS = arrayOf( - SortOrder.ALPHABETICAL, - SortOrder.NEWEST, - SortOrder.RATING, - ) - fun newIntent(context: Context) = Intent(context, FavouriteCategoriesActivity::class.java) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt index 3b055ddff..f22bad095 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditActivity.kt @@ -18,16 +18,15 @@ import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.ui.BaseActivity -import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getSerializableCompat import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.setChecked +import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding -import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity -import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.list.domain.ListSortOrder import com.google.android.material.R as materialR @AndroidEntryPoint @@ -38,7 +37,8 @@ class FavouritesCategoryEditActivity : DefaultTextWatcher { private val viewModel by viewModels() - private var selectedSortOrder: SortOrder? = null + private var selectedSortOrder: ListSortOrder? = null + private val sortOrders = ListSortOrder.FAVORITES.sortedByOrdinal() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -68,7 +68,7 @@ class FavouritesCategoryEditActivity : override fun onRestoreInstanceState(savedInstanceState: Bundle) { super.onRestoreInstanceState(savedInstanceState) - val order = savedInstanceState.getSerializableCompat(KEY_SORT_ORDER) + val order = savedInstanceState.getSerializableCompat(KEY_SORT_ORDER) if (order != null) { selectedSortOrder = order } @@ -103,7 +103,7 @@ class FavouritesCategoryEditActivity : } override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - selectedSortOrder = FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(position) + selectedSortOrder = sortOrders.getOrNull(position) } private fun onCategoryChanged(category: FavouriteCategory?) { @@ -113,7 +113,7 @@ class FavouritesCategoryEditActivity : } viewBinding.editName.setText(category?.title) selectedSortOrder = category?.order - val sortText = getString((category?.order ?: SortOrder.NEWEST).titleRes) + val sortText = getString((category?.order ?: ListSortOrder.NEWEST).titleResId) viewBinding.editSort.setText(sortText, false) viewBinding.switchTracker.setChecked(category?.isTrackingEnabled ?: true, false) viewBinding.switchShelf.setChecked(category?.isVisibleInLibrary ?: true, false) @@ -135,17 +135,17 @@ class FavouritesCategoryEditActivity : } private fun initSortSpinner() { - val entries = FavouriteCategoriesActivity.SORT_ORDERS.map { getString(it.titleRes) } + val entries = sortOrders.map { getString(it.titleResId) } val adapter = SortAdapter(this, entries) viewBinding.editSort.setAdapter(adapter) viewBinding.editSort.onItemClickListener = this } - private fun getSelectedSortOrder(): SortOrder { + private fun getSelectedSortOrder(): ListSortOrder { selectedSortOrder?.let { return it } - val entries = FavouriteCategoriesActivity.SORT_ORDERS.map { getString(it.titleRes) } + val entries = sortOrders.map { getString(it.titleResId) } val index = entries.indexOf(viewBinding.editSort.text.toString()) - return FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(index) ?: SortOrder.NEWEST + return sortOrders.getOrNull(index) ?: ListSortOrder.NEWEST } private class SortAdapter( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt index 2b32a3d5c..6c9e8161f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/edit/FavouritesCategoryEditViewModel.kt @@ -17,7 +17,7 @@ import org.koitharu.kotatsu.core.util.ext.call import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.EXTRA_ID import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity.Companion.NO_ID -import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.list.domain.ListSortOrder import javax.inject.Inject @HiltViewModel @@ -48,7 +48,7 @@ class FavouritesCategoryEditViewModel @Inject constructor( fun save( title: String, - sortOrder: SortOrder, + sortOrder: ListSortOrder, isTrackerEnabled: Boolean, isVisibleOnShelf: Boolean, ) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt index 19d08a66b..86f0a83e6 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt @@ -10,13 +10,11 @@ import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.list.ListSelectionController -import org.koitharu.kotatsu.core.ui.model.titleRes -import org.koitharu.kotatsu.core.ui.util.MenuInvalidator import org.koitharu.kotatsu.core.util.ext.addMenuProvider -import org.koitharu.kotatsu.core.util.ext.observe +import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.databinding.FragmentListBinding -import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource @@ -27,12 +25,14 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis override val isSwipeRefreshEnabled = false + val categoryId + get() = viewModel.categoryId + override fun onViewBindingCreated(binding: FragmentListBinding, savedInstanceState: Bundle?) { super.onViewBindingCreated(binding, savedInstanceState) if (viewModel.categoryId != NO_ID) { addMenuProvider(FavouritesListMenuProvider(binding.root.context, viewModel)) } - viewModel.sortOrder.observe(viewLifecycleOwner, MenuInvalidator(requireActivity())) } override fun onScrolledToEnd() = Unit @@ -40,14 +40,15 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis override fun onFilterClick(view: View?) { val menu = PopupMenu(view?.context ?: return, view) menu.setOnMenuItemClickListener(this) - for ((i, item) in FavouriteCategoriesActivity.SORT_ORDERS.withIndex()) { - menu.menu.add(Menu.NONE, Menu.NONE, i, item.titleRes) + val orders = ListSortOrder.FAVORITES.sortedByOrdinal() + for ((i, item) in orders.withIndex()) { + menu.menu.add(Menu.NONE, Menu.NONE, i, item.titleResId) } menu.show() } override fun onMenuItemClick(item: MenuItem): Boolean { - val order = FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(item.order) ?: return false + val order = ListSortOrder.FAVORITES.sortedByOrdinal().getOrNull(item.order) ?: return false viewModel.setSortOrder(order) return true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt index f4c246b27..ca134d8e8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListMenuProvider.kt @@ -5,12 +5,8 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import androidx.core.view.MenuProvider -import androidx.core.view.forEach import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.ui.model.titleRes -import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.favourites.ui.categories.edit.FavouritesCategoryEditActivity -import org.koitharu.kotatsu.parsers.model.SortOrder class FavouritesListMenuProvider( private val context: Context, @@ -19,29 +15,9 @@ class FavouritesListMenuProvider( override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { menuInflater.inflate(R.menu.opt_favourites, menu) - val subMenu = menu.findItem(R.id.action_order)?.subMenu ?: return - for (order in FavouriteCategoriesActivity.SORT_ORDERS) { - subMenu.add(R.id.group_order, Menu.NONE, order.ordinal, order.titleRes) - } - subMenu.setGroupCheckable(R.id.group_order, true, true) - } - - override fun onPrepareMenu(menu: Menu) { - super.onPrepareMenu(menu) - val order = viewModel.sortOrder.value ?: return - menu.findItem(R.id.action_order)?.subMenu?.forEach { item -> - if (item.order == order.ordinal) { - item.isChecked = true - } - } } override fun onMenuItemSelected(menuItem: MenuItem): Boolean { - if (menuItem.groupId == R.id.group_order) { - val order = SortOrder.entries[menuItem.order] - viewModel.setSortOrder(order) - return true - } return when (menuItem.itemId) { R.id.action_edit -> { context.startActivity(FavouritesCategoryEditActivity.newIntent(context, viewModel.categoryId)) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt index 0c2b050f4..e4e305060 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListViewModel.kt @@ -22,12 +22,12 @@ import org.koitharu.kotatsu.favourites.domain.FavouritesRepository import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.ARG_CATEGORY_ID import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment.Companion.NO_ID import org.koitharu.kotatsu.list.domain.ListExtraProvider +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyState import org.koitharu.kotatsu.list.ui.model.LoadingState import org.koitharu.kotatsu.list.ui.model.toErrorState import org.koitharu.kotatsu.list.ui.model.toUi -import org.koitharu.kotatsu.parsers.model.SortOrder import javax.inject.Inject @HiltViewModel @@ -44,7 +44,7 @@ class FavouritesListViewModel @Inject constructor( override val listMode = settings.observeAsFlow(AppSettings.KEY_LIST_MODE_FAVORITES) { favoritesListMode } .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, settings.favoritesListMode) - val sortOrder: StateFlow = if (categoryId == NO_ID) { + val sortOrder: StateFlow = if (categoryId == NO_ID) { MutableStateFlow(null) } else { repository.observeCategory(categoryId) @@ -54,7 +54,7 @@ class FavouritesListViewModel @Inject constructor( override val content = combine( if (categoryId == NO_ID) { - repository.observeAll(SortOrder.NEWEST) + repository.observeAll(ListSortOrder.NEWEST) } else { repository.observeAll(categoryId) }, @@ -98,7 +98,7 @@ class FavouritesListViewModel @Inject constructor( } } - fun setSortOrder(order: SortOrder) { + fun setSortOrder(order: ListSortOrder) { if (categoryId == NO_ID) { return } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/FilterCoordinator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/FilterCoordinator.kt index 700afcd86..7c04099ab 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/FilterCoordinator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/filter/ui/FilterCoordinator.kt @@ -25,6 +25,7 @@ import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.util.ext.lifecycleScope import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.require +import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal import org.koitharu.kotatsu.filter.ui.model.FilterHeaderModel import org.koitharu.kotatsu.filter.ui.model.FilterItem import org.koitharu.kotatsu.filter.ui.model.FilterState @@ -207,7 +208,7 @@ class FilterCoordinator @Inject constructor( state: FilterState, query: String, ): List { - val sortOrders = repository.sortOrders.sortedBy { it.ordinal } + val sortOrders = repository.sortOrders.sortedByOrdinal() val tags = mergeTags(state.tags, allTags.tags).toList() val list = ArrayList(tags.size + sortOrders.size + 3) if (query.isEmpty()) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt index cc51633e6..7530fcf25 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryDao.kt @@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.Flow import org.intellij.lang.annotations.Language import org.koitharu.kotatsu.core.db.entity.MangaEntity import org.koitharu.kotatsu.core.db.entity.TagEntity -import org.koitharu.kotatsu.history.domain.model.HistoryOrder +import org.koitharu.kotatsu.list.domain.ListSortOrder @Dao abstract class HistoryDao { @@ -33,12 +33,13 @@ abstract class HistoryDao { @Query("SELECT * FROM history WHERE deleted_at = 0 ORDER BY updated_at DESC LIMIT :limit") abstract fun observeAll(limit: Int): Flow> - fun observeAll(order: HistoryOrder): Flow> { + fun observeAll(order: ListSortOrder): Flow> { val orderBy = when (order) { - HistoryOrder.UPDATED -> "history.updated_at DESC" - HistoryOrder.CREATED -> "history.created_at DESC" - HistoryOrder.PROGRESS -> "history.percent DESC" - HistoryOrder.ALPHABETIC -> "manga.title" + ListSortOrder.UPDATED -> "history.updated_at DESC" + ListSortOrder.NEWEST -> "history.created_at DESC" + ListSortOrder.PROGRESS -> "history.percent DESC" + ListSortOrder.ALPHABETIC -> "manga.title" + else -> throw IllegalArgumentException("Sort order $order is not supported") } @Language("RoomSql") diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt index fd8a4ab58..689c4c0f6 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/data/HistoryRepository.kt @@ -18,8 +18,8 @@ import org.koitharu.kotatsu.core.model.findById import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.util.ReversibleHandle import org.koitharu.kotatsu.core.util.ext.mapItems -import org.koitharu.kotatsu.history.domain.model.HistoryOrder import org.koitharu.kotatsu.history.domain.model.MangaWithHistory +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.scrobbling.common.domain.Scrobbler @@ -66,7 +66,7 @@ class HistoryRepository @Inject constructor( } } - fun observeAllWithHistory(order: HistoryOrder): Flow> { + fun observeAllWithHistory(order: ListSortOrder): Flow> { return db.historyDao.observeAll(order).mapItems { MangaWithHistory( it.manga.toManga(it.tags.toMangaTags()), diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/HistoryOrder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/HistoryOrder.kt deleted file mode 100644 index dd1fcd5b9..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/domain/model/HistoryOrder.kt +++ /dev/null @@ -1,16 +0,0 @@ -package org.koitharu.kotatsu.history.domain.model - -import androidx.annotation.StringRes -import org.koitharu.kotatsu.R - -enum class HistoryOrder( - @StringRes val titleResId: Int, -) { - - UPDATED(R.string.updated), - CREATED(R.string.order_added), - PROGRESS(R.string.progress), - ALPHABETIC(R.string.by_name); - - fun isGroupingSupported() = this == UPDATED || this == CREATED || this == PROGRESS -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt index baa05e68c..9bc462785 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListViewModel.kt @@ -26,9 +26,9 @@ import org.koitharu.kotatsu.core.util.ext.daysDiff import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.history.data.HistoryRepository -import org.koitharu.kotatsu.history.domain.model.HistoryOrder import org.koitharu.kotatsu.history.domain.model.MangaWithHistory import org.koitharu.kotatsu.list.domain.ListExtraProvider +import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.model.EmptyHint import org.koitharu.kotatsu.list.ui.model.EmptyState @@ -54,7 +54,7 @@ class HistoryListViewModel @Inject constructor( downloadScheduler: DownloadWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { - private val sortOrder: StateFlow = settings.observeAsStateFlow( + private val sortOrder: StateFlow = settings.observeAsStateFlow( scope = viewModelScope + Dispatchers.IO, key = AppSettings.KEY_HISTORY_ORDER, valueProducer = { historySortOrder }, @@ -123,10 +123,6 @@ class HistoryListViewModel @Inject constructor( } } - fun setGrouping(isGroupingEnabled: Boolean) { - settings.isHistoryGroupingEnabled = isGroupingEnabled - } - private suspend fun mapList( list: List, grouped: Boolean, @@ -168,10 +164,10 @@ class HistoryListViewModel @Inject constructor( return result } - private fun MangaHistory.header(order: HistoryOrder): ListHeader? = when (order) { - HistoryOrder.UPDATED -> ListHeader(timeAgo(updatedAt)) - HistoryOrder.CREATED -> ListHeader(timeAgo(createdAt)) - HistoryOrder.PROGRESS -> ListHeader( + private fun MangaHistory.header(order: ListSortOrder): ListHeader? = when (order) { + ListSortOrder.UPDATED -> ListHeader(timeAgo(updatedAt)) + ListSortOrder.NEWEST -> ListHeader(timeAgo(createdAt)) + ListSortOrder.PROGRESS -> ListHeader( when (percent) { 1f -> R.string.status_completed in 0f..0.01f -> R.string.status_planned @@ -180,7 +176,9 @@ class HistoryListViewModel @Inject constructor( }, ) - HistoryOrder.ALPHABETIC -> null + ListSortOrder.ALPHABETIC, + ListSortOrder.RELEVANCE, + ListSortOrder.RATING -> null } private fun timeAgo(date: Date): DateTimeAgo { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListSortOrder.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListSortOrder.kt new file mode 100644 index 000000000..9286b0aff --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/domain/ListSortOrder.kt @@ -0,0 +1,30 @@ +package org.koitharu.kotatsu.list.domain + +import androidx.annotation.StringRes +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.parsers.util.find +import java.util.EnumSet + +enum class ListSortOrder( + @StringRes val titleResId: Int, +) { + + UPDATED(R.string.updated), + NEWEST(R.string.order_added), + PROGRESS(R.string.progress), + ALPHABETIC(R.string.by_name), + RATING(R.string.by_rating), + RELEVANCE(R.string.by_relevance), + ; + + fun isGroupingSupported() = this == UPDATED || this == NEWEST || this == PROGRESS + + companion object { + + val HISTORY = EnumSet.of(UPDATED, NEWEST, PROGRESS, ALPHABETIC) + val FAVORITES = EnumSet.of(ALPHABETIC, NEWEST, RATING) + val SUGGESTIONS = EnumSet.of(RELEVANCE) + + operator fun invoke(value: String, fallback: ListSortOrder) = entries.find(value) ?: fallback + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt index 6d2518f4c..fd5e16aab 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListMenuProvider.kt @@ -6,7 +6,11 @@ import android.view.MenuItem import androidx.core.view.MenuProvider import androidx.fragment.app.Fragment import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment +import org.koitharu.kotatsu.history.ui.HistoryListFragment import org.koitharu.kotatsu.list.ui.config.ListConfigBottomSheet +import org.koitharu.kotatsu.list.ui.config.ListConfigSection +import org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment class MangaListMenuProvider( private val fragment: Fragment, @@ -18,7 +22,13 @@ class MangaListMenuProvider( override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) { R.id.action_list_mode -> { - ListConfigBottomSheet.show(fragment.childFragmentManager) + val section: ListConfigSection = when (fragment) { + is HistoryListFragment -> ListConfigSection.History + is SuggestionsFragment -> ListConfigSection.Suggestions + is FavouritesListFragment -> ListConfigSection.Favorites(fragment.categoryId) + else -> ListConfigSection.General + } + ListConfigBottomSheet.show(fragment.childFragmentManager, section) true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigBottomSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigBottomSheet.kt index 8ad3796df..ef3cac052 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigBottomSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigBottomSheet.kt @@ -9,6 +9,7 @@ import android.widget.ArrayAdapter import android.widget.CompoundButton import androidx.core.view.isVisible import androidx.fragment.app.FragmentManager +import androidx.fragment.app.viewModels import com.google.android.material.button.MaterialButtonToggleGroup import com.google.android.material.slider.Slider import dagger.hilt.android.AndroidEntryPoint @@ -18,11 +19,9 @@ import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.core.util.ext.showDistinct +import org.koitharu.kotatsu.core.util.ext.withArgs import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter import org.koitharu.kotatsu.databinding.SheetListModeBinding -import org.koitharu.kotatsu.favourites.ui.list.FavouritesListFragment -import org.koitharu.kotatsu.history.domain.model.HistoryOrder -import org.koitharu.kotatsu.history.ui.HistoryListFragment import javax.inject.Inject @AndroidEntryPoint @@ -33,8 +32,11 @@ class ListConfigBottomSheet : AdapterView.OnItemSelectedListener { @Inject + @Deprecated("") lateinit var settings: AppSettings + private val viewModel by viewModels() + override fun onCreateViewBinding( inflater: LayoutInflater, container: ViewGroup?, @@ -42,12 +44,7 @@ class ListConfigBottomSheet : override fun onViewBindingCreated(binding: SheetListModeBinding, savedInstanceState: Bundle?) { super.onViewBindingCreated(binding, savedInstanceState) - val section = getSection() - val mode = when (section) { - Section.GENERAL -> settings.listMode - Section.HISTORY -> settings.historyListMode - Section.FAVORITES -> settings.favoritesListMode - } + val mode = viewModel.listMode binding.buttonList.isChecked = mode == ListMode.LIST binding.buttonListDetailed.isChecked = mode == ListMode.DETAILED_LIST binding.buttonGrid.isChecked = mode == ListMode.GRID @@ -55,27 +52,31 @@ class ListConfigBottomSheet : binding.sliderGrid.isVisible = mode == ListMode.GRID binding.sliderGrid.setLabelFormatter(IntPercentLabelFormatter(binding.root.context)) - binding.sliderGrid.setValueRounded(settings.gridSize.toFloat()) + binding.sliderGrid.setValueRounded(viewModel.gridSize.toFloat()) binding.sliderGrid.addOnChangeListener(this) binding.checkableGroup.addOnButtonCheckedListener(this) - binding.switchGrouping.isVisible = section == Section.HISTORY - if (section == Section.HISTORY) { + binding.switchGrouping.isVisible = viewModel.isGroupingAvailable + if (viewModel.isGroupingAvailable) { binding.switchGrouping.isEnabled = settings.historySortOrder.isGroupingSupported() } binding.switchGrouping.isChecked = settings.isHistoryGroupingEnabled binding.switchGrouping.setOnCheckedChangeListener(this) - if (section == Section.HISTORY) { + val sortOrders = viewModel.getSortOrders() + if (sortOrders != null) { binding.textViewOrderTitle.isVisible = true binding.spinnerOrder.adapter = ArrayAdapter( binding.spinnerOrder.context, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1, - HistoryOrder.entries.map { getString(it.titleResId) }, + sortOrders.map { binding.spinnerOrder.context.getString(it.titleResId) }, ) - binding.spinnerOrder.setSelection(settings.historySortOrder.ordinal, false) + val selected = sortOrders.indexOf(viewModel.getSelectedSortOrder()) + if (selected >= 0) { + binding.spinnerOrder.setSelection(selected, false) + } binding.spinnerOrder.onItemSelectedListener = this binding.cardOrder.isVisible = true } @@ -93,11 +94,7 @@ class ListConfigBottomSheet : } requireViewBinding().textViewGridTitle.isVisible = mode == ListMode.GRID requireViewBinding().sliderGrid.isVisible = mode == ListMode.GRID - when (getSection()) { - Section.GENERAL -> settings.listMode = mode - Section.HISTORY -> settings.historyListMode = mode - Section.FAVORITES -> settings.favoritesListMode = mode - } + viewModel.listMode = mode } override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) { @@ -108,36 +105,28 @@ class ListConfigBottomSheet : override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) { if (fromUser) { - settings.gridSize = value.toInt() + viewModel.gridSize = value.toInt() } } override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) { when (parent.id) { R.id.spinner_order -> { - val value = HistoryOrder.entries[position] - settings.historySortOrder = value - viewBinding?.switchGrouping?.isEnabled = value.isGroupingSupported() + viewModel.setSortOrder(position) + viewBinding?.switchGrouping?.isEnabled = settings.historySortOrder.isGroupingSupported() } } } override fun onNothingSelected(parent: AdapterView<*>?) = Unit - private fun getSection(): Section = when (parentFragment) { - is HistoryListFragment -> Section.HISTORY - is FavouritesListFragment -> Section.FAVORITES - else -> Section.GENERAL - } - - enum class Section { - GENERAL, HISTORY, FAVORITES; - } - companion object { private const val TAG = "ListModeSelectDialog" + const val ARG_SECTION = "section" - fun show(fm: FragmentManager) = ListConfigBottomSheet().showDistinct(fm, TAG) + fun show(fm: FragmentManager, section: ListConfigSection) = ListConfigBottomSheet().withArgs(1) { + putParcelable(ARG_SECTION, section) + }.showDistinct(fm, TAG) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigSection.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigSection.kt new file mode 100644 index 000000000..14d8bdbe7 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigSection.kt @@ -0,0 +1,21 @@ +package org.koitharu.kotatsu.list.ui.config + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +sealed interface ListConfigSection : Parcelable { + + @Parcelize + data object History : ListConfigSection + + @Parcelize + data object General : ListConfigSection + + @Parcelize + data class Favorites( + val categoryId: Long, + ) : ListConfigSection + + @Parcelize + data object Suggestions : ListConfigSection +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigViewModel.kt new file mode 100644 index 000000000..743ce5546 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/config/ListConfigViewModel.kt @@ -0,0 +1,76 @@ +package org.koitharu.kotatsu.list.ui.config + +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.runBlocking +import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.prefs.ListMode +import org.koitharu.kotatsu.core.ui.BaseViewModel +import org.koitharu.kotatsu.core.util.ext.require +import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal +import org.koitharu.kotatsu.favourites.domain.FavouritesRepository +import org.koitharu.kotatsu.list.domain.ListSortOrder +import javax.inject.Inject + +@HiltViewModel +class ListConfigViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, + private val settings: AppSettings, + private val favouritesRepository: FavouritesRepository, +) : BaseViewModel() { + + val section = savedStateHandle.require(ListConfigBottomSheet.ARG_SECTION) + + var listMode: ListMode + get() = when (section) { + is ListConfigSection.Favorites -> settings.favoritesListMode + ListConfigSection.General -> settings.listMode + ListConfigSection.History -> settings.historyListMode + ListConfigSection.Suggestions -> settings.suggestionsListMode + } + set(value) { + when (section) { + is ListConfigSection.Favorites -> settings.favoritesListMode = value + ListConfigSection.General -> settings.listMode = value + ListConfigSection.History -> settings.historyListMode = value + ListConfigSection.Suggestions -> settings.suggestionsListMode = value + } + } + + var gridSize: Int + get() = settings.gridSize + set(value) { + settings.gridSize = value + } + + val isGroupingAvailable: Boolean + get() = section == ListConfigSection.History + + fun getSortOrders(): List? = when (section) { + is ListConfigSection.Favorites -> ListSortOrder.FAVORITES + ListConfigSection.General -> null + ListConfigSection.History -> ListSortOrder.HISTORY + ListConfigSection.Suggestions -> ListSortOrder.SUGGESTIONS + }?.sortedByOrdinal() + + fun getSelectedSortOrder(): ListSortOrder? = when (section) { + is ListConfigSection.Favorites -> runBlocking { favouritesRepository.getCategory(section.categoryId).order } + ListConfigSection.General -> null + ListConfigSection.History -> settings.historySortOrder + ListConfigSection.Suggestions -> ListSortOrder.RELEVANCE // TODO + } + + fun setSortOrder(position: Int) { + val value = getSortOrders()?.getOrNull(position) ?: return + when (section) { + is ListConfigSection.Favorites -> launchJob { + favouritesRepository.setCategoryOrder(section.categoryId, value) + } + + ListConfigSection.General -> Unit + ListConfigSection.History -> settings.historySortOrder = value + + ListConfigSection.Suggestions -> Unit + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt index cc2cdf394..27e5d2015 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/thumbnails/PagesThumbnailsViewModel.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.last +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import org.koitharu.kotatsu.core.model.findById @@ -52,7 +52,7 @@ class PagesThumbnailsViewModel @Inject constructor( init { loadingJob = launchLoadingJob(Dispatchers.Default) { - chaptersLoader.init(checkNotNull(mangaDetails.last())) + chaptersLoader.init(checkNotNull(mangaDetails.first { x -> x?.isLoaded == true })) chaptersLoader.loadSingleChapter(initialChapterId) updateList() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt index 2f9510b30..2dcde8897 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsViewModel.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.util.ext.onFirst import org.koitharu.kotatsu.download.ui.worker.DownloadWorker import org.koitharu.kotatsu.list.domain.ListExtraProvider @@ -31,6 +32,9 @@ class SuggestionsViewModel @Inject constructor( private val suggestionsScheduler: SuggestionsWorker.Scheduler, ) : MangaListViewModel(settings, downloadScheduler) { + override val listMode = settings.observeAsFlow(AppSettings.KEY_LIST_MODE_SUGGESTIONS) { suggestionsListMode } + .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, settings.suggestionsListMode) + override val content = combine( repository.observeAll(), listMode, diff --git a/app/src/main/res/menu/opt_favourites.xml b/app/src/main/res/menu/opt_favourites.xml index 1f6696c87..20b2dd771 100644 --- a/app/src/main/res/menu/opt_favourites.xml +++ b/app/src/main/res/menu/opt_favourites.xml @@ -2,22 +2,9 @@ - - - - - - - - - - diff --git a/app/src/main/res/menu/opt_favourites_container.xml b/app/src/main/res/menu/opt_favourites_container.xml index 5a15dd9c2..83433bf3e 100644 --- a/app/src/main/res/menu/opt_favourites_container.xml +++ b/app/src/main/res/menu/opt_favourites_container.xml @@ -5,7 +5,7 @@ + android:title="@string/favourites_categories" + android:titleCondensed="@string/categories" /> diff --git a/app/src/main/res/menu/opt_list.xml b/app/src/main/res/menu/opt_list.xml index d37dfe238..27c6d3844 100644 --- a/app/src/main/res/menu/opt_list.xml +++ b/app/src/main/res/menu/opt_list.xml @@ -5,7 +5,7 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 30cf3d11d..ac8e8fa69 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -497,4 +497,6 @@ Suggest new sources after app update Prompt to enable newly added sources after updating the application List options + Relevance + Categories