Move favourites order from menu to header

This commit is contained in:
Koitharu
2022-07-12 14:34:08 +03:00
parent 2654de96ba
commit b293fee742
12 changed files with 58 additions and 115 deletions

View File

@@ -1,19 +1,20 @@
package org.koitharu.kotatsu.favourites.ui.list
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.PopupMenu
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.titleRes
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
import org.koitharu.kotatsu.list.ui.MangaListFragment
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.utils.ext.addMenuProvider
import org.koitharu.kotatsu.utils.ext.withArgs
class FavouritesListFragment : MangaListFragment() {
class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickListener {
override val viewModel by viewModel<FavouritesListViewModel> {
parametersOf(categoryId)
@@ -24,16 +25,22 @@ class FavouritesListFragment : MangaListFragment() {
override val isSwipeRefreshEnabled = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.sortOrder.observe(viewLifecycleOwner) { activity?.invalidateOptionsMenu() }
override fun onScrolledToEnd() = Unit
if (categoryId != NO_ID) {
addMenuProvider(FavouritesListMenuProvider(viewModel))
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)
}
menu.show()
}
override fun onScrolledToEnd() = Unit
override fun onMenuItemClick(item: MenuItem): Boolean {
val order = FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(item.order) ?: return false
viewModel.setSortOrder(order)
return true
}
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.mode_favourites, menu)

View File

@@ -1,48 +0,0 @@
package org.koitharu.kotatsu.favourites.ui.list
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.core.view.MenuProvider
import androidx.core.view.iterator
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.titleRes
import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity
class FavouritesListMenuProvider(
private val viewModel: FavouritesListViewModel,
) : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.opt_favourites_list, menu)
menu.findItem(R.id.action_order)?.subMenu?.let { submenu ->
for ((i, item) in FavouriteCategoriesActivity.SORT_ORDERS.withIndex()) {
val menuItem = submenu.add(R.id.group_order, Menu.NONE, i, item.titleRes)
menuItem.isCheckable = true
}
submenu.setGroupCheckable(R.id.group_order, true, true)
}
}
override fun onPrepareMenu(menu: Menu) {
menu.findItem(R.id.action_order)?.subMenu?.let { submenu ->
val selectedOrder = viewModel.sortOrder.value
for (item in submenu) {
val order = FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(item.order)
item.isChecked = order == selectedOrder
}
}
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when {
menuItem.itemId == R.id.action_order -> false
menuItem.groupId == R.id.group_order -> {
val order = FavouriteCategoriesActivity.SORT_ORDERS.getOrNull(menuItem.order) ?: return false
viewModel.setSortOrder(order)
true
}
else -> false
}
}
}

View File

@@ -1,12 +1,9 @@
package org.koitharu.kotatsu.favourites.ui.list
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.plus
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
@@ -15,10 +12,7 @@ import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.history.domain.PROGRESS_NONE
import org.koitharu.kotatsu.list.domain.ListExtraProvider
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.list.ui.model.*
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
@@ -31,12 +25,12 @@ class FavouritesListViewModel(
private val settings: AppSettings,
) : MangaListViewModel(settings), ListExtraProvider {
var sortOrder: LiveData<SortOrder?> = if (categoryId == NO_ID) {
MutableLiveData(null)
private val sortOrder: StateFlow<SortOrder?> = if (categoryId == NO_ID) {
MutableStateFlow(null)
} else {
repository.observeCategory(categoryId)
.map { it?.order }
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default)
.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, null)
}
override val content = combine(
@@ -45,8 +39,9 @@ class FavouritesListViewModel(
} else {
repository.observeAll(categoryId)
},
sortOrder,
createListModeFlow()
) { list, mode ->
) { list, order, mode ->
when {
list.isEmpty() -> listOf(
EmptyState(
@@ -60,7 +55,12 @@ class FavouritesListViewModel(
actionStringRes = 0,
)
)
else -> list.toUi(mode, this)
else -> buildList<ListModel>(list.size + 1) {
if (order != null) {
add(ListHeader2(emptyList(), order, false))
}
list.toUi(this, mode, this@FavouritesListViewModel)
}
}
}.catch {
emit(listOf(it.toErrorState(canRetry = false)))

View File

@@ -197,7 +197,7 @@ abstract class MangaListFragment :
}
}
override fun onFilterClick() = Unit
override fun onFilterClick(view: View?) = Unit
override fun onEmptyActionClick() = Unit

View File

@@ -16,7 +16,7 @@ fun listHeader2AD(
var ignoreChecking = false
binding.textViewFilter.setOnClickListener {
listener.onFilterClick()
listener.onFilterClick(it)
}
binding.chipsTags.setOnCheckedStateChangeListener { _, _ ->
if (!ignoreChecking) {

View File

@@ -32,7 +32,7 @@ fun listHeaderWithFilterAD(
) {
binding.textViewFilter.setOnClickListener {
listener.onFilterClick()
listener.onFilterClick(it)
}
bind {

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.list.ui.adapter
import android.view.View
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaTag
@@ -8,5 +9,5 @@ interface MangaListListener : OnListItemClickListener<Manga>, ListStateHolderLis
fun onUpdateFilter(tags: Set<MangaTag>)
fun onFilterClick()
fun onFilterClick(view: View?)
}

View File

@@ -44,27 +44,13 @@ fun Manga.toGridModel(counter: Int, progress: Float) = MangaGridModel(
suspend fun List<Manga>.toUi(
mode: ListMode,
extraProvider: ListExtraProvider,
): List<MangaItemModel> = when (mode) {
ListMode.LIST -> map {
it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
}
ListMode.DETAILED_LIST -> map {
it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
}
ListMode.GRID -> map {
it.toGridModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
}
}
): List<MangaItemModel> = toUi(ArrayList(size), mode, extraProvider)
fun List<Manga>.toUi(
mode: ListMode,
): List<MangaItemModel> = when (mode) {
ListMode.LIST -> map { it.toListModel(0, PROGRESS_NONE) }
ListMode.DETAILED_LIST -> map { it.toListDetailedModel(0, PROGRESS_NONE) }
ListMode.GRID -> map { it.toGridModel(0, PROGRESS_NONE) }
}
): List<MangaItemModel> = toUi(ArrayList(size), mode)
fun <C : MutableCollection<ListModel>> List<Manga>.toUi(
fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi(
destination: C,
mode: ListMode,
): C = when (mode) {
@@ -73,6 +59,22 @@ fun <C : MutableCollection<ListModel>> List<Manga>.toUi(
ListMode.GRID -> mapTo(destination) { it.toGridModel(0, PROGRESS_NONE) }
}
suspend fun <C : MutableCollection<in MangaItemModel>> List<Manga>.toUi(
destination: C,
mode: ListMode,
extraProvider: ListExtraProvider,
): C = when (mode) {
ListMode.LIST -> mapTo(destination) {
it.toListModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
}
ListMode.DETAILED_LIST -> mapTo(destination) {
it.toListDetailedModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
}
ListMode.GRID -> mapTo(destination) {
it.toGridModel(extraProvider.getCounter(it.id), extraProvider.getProgress(it.id))
}
}
fun Throwable.toErrorState(canRetry: Boolean = true) = ErrorState(
exception = this,
icon = getErrorIcon(this),

View File

@@ -42,7 +42,7 @@ class RemoteListFragment : MangaListFragment() {
return super.onCreateActionMode(mode, menu)
}
override fun onFilterClick() {
override fun onFilterClick(view: View?) {
FilterBottomSheet.show(childFragmentManager)
}
@@ -69,7 +69,7 @@ class RemoteListFragment : MangaListFragment() {
true
}
R.id.action_filter -> {
onFilterClick()
onFilterClick(null)
true
}
else -> false

View File

@@ -105,7 +105,7 @@ class MultiSearchActivity : BaseActivity<ActivitySearchMultiBinding>(), MangaLis
override fun onUpdateFilter(tags: Set<MangaTag>) = Unit
override fun onFilterClick() = Unit
override fun onFilterClick(view: View?) = Unit
override fun onEmptyActionClick() = Unit

View File

@@ -89,7 +89,7 @@ class FeedFragment :
override fun onUpdateFilter(tags: Set<MangaTag>) = Unit
override fun onFilterClick() = Unit
override fun onFilterClick(view: View?) = Unit
override fun onEmptyActionClick() = Unit

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_order"
android:orderInCategory="30"
android:title="@string/sort_order">
<menu>
<group
android:id="@+id/group_order"
android:checkableBehavior="single" />
</menu>
</item>
</menu>