From e4282a8e9d4dca0dc8886bebe382b422e6cfe90c Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 20 Aug 2024 15:17:29 +0300 Subject: [PATCH] Improve favorite categories screen (fix #1047) --- .../kotatsu/core/ui/ReorderableListAdapter.kt | 6 ++++++ .../categories/FavouriteCategoriesActivity.kt | 21 +++++++++++++++++++ .../FavouritesCategoriesViewModel.kt | 16 +++++++++++--- .../adapter/AllCategoriesListModel.kt | 12 +++++------ .../ui/categories/adapter/CategoryAD.kt | 3 +++ .../categories/adapter/CategoryListModel.kt | 10 +++++++++ .../layout-w600dp-land/activity_details.xml | 1 + .../main/res/layout/activity_categories.xml | 7 +++---- 8 files changed, 63 insertions(+), 13 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/ReorderableListAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/ReorderableListAdapter.kt index ccfc5d0b9..c34cb8382 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/ReorderableListAdapter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/ReorderableListAdapter.kt @@ -71,5 +71,11 @@ open class ReorderableListAdapter : ListDelegationAdapter val newItem = newList[newItemPosition] return newItem == oldItem } + + override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? { + val oldItem = oldList[oldItemPosition] + val newItem = newList[newItemPosition] + return newItem.getChangePayload(oldItem) + } } } 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 951014329..3b029b45a 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 @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.View import android.view.ViewGroup import androidx.activity.viewModels +import androidx.appcompat.view.ActionMode import androidx.core.graphics.Insets import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding @@ -100,6 +101,18 @@ class FavouriteCategoriesActivity : return item != null && selectionController.onItemLongClick(item.id) } + override fun onSupportActionModeStarted(mode: ActionMode) { + super.onSupportActionModeStarted(mode) + viewBinding.fabAdd.hide() + viewModel.setActionsEnabled(false) + } + + override fun onSupportActionModeFinished(mode: ActionMode) { + super.onSupportActionModeFinished(mode) + viewBinding.fabAdd.show() + viewModel.setActionsEnabled(true) + } + override fun onShowAllClick(isChecked: Boolean) { viewModel.setAllCategoriesVisible(isChecked) } @@ -138,6 +151,14 @@ class FavouriteCategoriesActivity : 0, ) { + override fun getDragDirs(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int { + return if (actionModeDelegate.isActionModeStarted) { + 0 + } else { + super.getDragDirs(recyclerView, viewHolder) + } + } + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit override fun onMove( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt index b4c653264..dcec89d4f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouritesCategoriesViewModel.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.mapLatest @@ -34,13 +35,15 @@ class FavouritesCategoriesViewModel @Inject constructor( ) : BaseViewModel() { private var commitJob: Job? = null + private val isActionsEnabled = MutableStateFlow(true) val content = combine( repository.observeCategoriesWithCovers(), observeAllCategories(), settings.observeAsFlow(AppSettings.KEY_ALL_FAVOURITES_VISIBLE) { isAllFavouritesVisible }, - ) { cats, all, showAll -> - cats.toUiList(all, showAll) + isActionsEnabled, + ) { cats, all, showAll, hasActions -> + cats.toUiList(all, showAll, hasActions) }.withErrorHandling() .stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState)) @@ -77,6 +80,10 @@ class FavouritesCategoriesViewModel @Inject constructor( } } + fun setActionsEnabled(value: Boolean) { + isActionsEnabled.value = value + } + fun getCategories(ids: LongSet): ArrayList { val items = content.requireValue() return items.mapNotNullTo(ArrayList(ids.size)) { item -> @@ -86,7 +93,8 @@ class FavouritesCategoriesViewModel @Inject constructor( private fun Map>.toUiList( allFavorites: Pair>, - showAll: Boolean + showAll: Boolean, + hasActions: Boolean, ): List { if (isEmpty()) { return listOf( @@ -104,6 +112,7 @@ class FavouritesCategoriesViewModel @Inject constructor( mangaCount = allFavorites.first, covers = allFavorites.second, isVisible = showAll, + isActionsEnabled = hasActions, ), ) mapTo(result) { (category, covers) -> @@ -111,6 +120,7 @@ class FavouritesCategoriesViewModel @Inject constructor( mangaCount = covers.size, covers = covers.take(3), category = category, + isActionsEnabled = hasActions, isTrackerEnabled = settings.isTrackerEnabled && AppSettings.TRACK_FAVOURITES in settings.trackSources, ) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/AllCategoriesListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/AllCategoriesListModel.kt index d1dffc421..fb794403c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/AllCategoriesListModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/AllCategoriesListModel.kt @@ -8,17 +8,17 @@ data class AllCategoriesListModel( val mangaCount: Int, val covers: List, val isVisible: Boolean, + val isActionsEnabled: Boolean, ) : ListModel { override fun areItemsTheSame(other: ListModel): Boolean { return other is AllCategoriesListModel } - override fun getChangePayload(previousState: ListModel): Any? { - return if (previousState is AllCategoriesListModel && previousState.isVisible != isVisible) { - ListModelDiffCallback.PAYLOAD_CHECKED_CHANGED - } else { - super.getChangePayload(previousState) - } + override fun getChangePayload(previousState: ListModel): Any? = when { + previousState !is AllCategoriesListModel -> super.getChangePayload(previousState) + previousState.isVisible != isVisible -> ListModelDiffCallback.PAYLOAD_CHECKED_CHANGED + previousState.isActionsEnabled != isActionsEnabled -> ListModelDiffCallback.PAYLOAD_ANYTHING_CHANGED + else -> super.getChangePayload(previousState) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt index 121bc77b3..643aec708 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryAD.kt @@ -68,6 +68,8 @@ fun categoryAD( binding.imageViewHandle.setOnTouchListener(eventListener) bind { + binding.imageViewHandle.isVisible = item.isActionsEnabled + binding.imageViewEdit.isVisible = item.isActionsEnabled binding.textViewTitle.text = item.category.title binding.textViewSubtitle.text = if (item.mangaCount == 0) { getString(R.string.empty) @@ -138,6 +140,7 @@ fun allCategoriesAD( item.mangaCount, ) } + binding.imageViewVisible.isVisible = item.isActionsEnabled binding.imageViewVisible.setImageResource( if (item.isVisible) { R.drawable.ic_eye diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt index c60243594..edcef486d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/adapter/CategoryListModel.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.favourites.ui.categories.adapter import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.favourites.domain.model.Cover +import org.koitharu.kotatsu.list.ui.ListModelDiffCallback import org.koitharu.kotatsu.list.ui.model.ListModel class CategoryListModel( @@ -9,12 +10,19 @@ class CategoryListModel( val covers: List, val category: FavouriteCategory, val isTrackerEnabled: Boolean, + val isActionsEnabled: Boolean, ) : ListModel { override fun areItemsTheSame(other: ListModel): Boolean { return other is CategoryListModel && other.category.id == category.id } + override fun getChangePayload(previousState: ListModel): Any? = when { + previousState !is CategoryListModel -> super.getChangePayload(previousState) + previousState.isActionsEnabled != isActionsEnabled -> ListModelDiffCallback.PAYLOAD_ANYTHING_CHANGED + else -> super.getChangePayload(previousState) + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false @@ -23,6 +31,7 @@ class CategoryListModel( if (mangaCount != other.mangaCount) return false if (isTrackerEnabled != other.isTrackerEnabled) return false + if (isActionsEnabled != other.isActionsEnabled) return false if (covers != other.covers) return false if (category.id != other.category.id) return false if (category.title != other.category.title) return false @@ -36,6 +45,7 @@ class CategoryListModel( override fun hashCode(): Int { var result = mangaCount result = 31 * result + isTrackerEnabled.hashCode() + result = 31 * result + isActionsEnabled.hashCode() result = 31 * result + covers.hashCode() result = 31 * result + category.id.hashCode() result = 31 * result + category.title.hashCode() diff --git a/app/src/main/res/layout-w600dp-land/activity_details.xml b/app/src/main/res/layout-w600dp-land/activity_details.xml index 2b2addde4..e3e6fab06 100644 --- a/app/src/main/res/layout-w600dp-land/activity_details.xml +++ b/app/src/main/res/layout-w600dp-land/activity_details.xml @@ -179,6 +179,7 @@ layout="@layout/layout_details_chips" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/screen_padding" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/barrier_header" /> diff --git a/app/src/main/res/layout/activity_categories.xml b/app/src/main/res/layout/activity_categories.xml index 015099611..d157625e4 100644 --- a/app/src/main/res/layout/activity_categories.xml +++ b/app/src/main/res/layout/activity_categories.xml @@ -54,18 +54,17 @@ app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" tools:listitem="@layout/item_category" /> -