UI improvements
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
package org.koitharu.kotatsu.details.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import android.transition.AutoTransition
|
||||
import android.transition.Slide
|
||||
import android.transition.TransitionManager
|
||||
import android.view.Gravity
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -17,6 +20,8 @@ import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.core.graphics.Insets
|
||||
import androidx.core.text.buildSpannedString
|
||||
import androidx.core.text.inSpans
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
@@ -33,12 +38,11 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.parser.MangaIntent
|
||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||
import org.koitharu.kotatsu.core.ui.dialog.RecyclerViewAlertDialog
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
||||
import org.koitharu.kotatsu.core.util.ViewBadge
|
||||
import org.koitharu.kotatsu.core.util.ext.doOnExpansionsChanged
|
||||
import org.koitharu.kotatsu.core.util.ext.getAnimationDuration
|
||||
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
||||
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
|
||||
import org.koitharu.kotatsu.core.util.ext.measureHeight
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
@@ -48,10 +52,8 @@ import org.koitharu.kotatsu.core.util.ext.setNavigationIconSafe
|
||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||
import org.koitharu.kotatsu.databinding.ActivityDetailsBinding
|
||||
import org.koitharu.kotatsu.details.service.MangaPrefetchService
|
||||
import org.koitharu.kotatsu.details.ui.adapter.branchAD
|
||||
import org.koitharu.kotatsu.details.ui.model.ChapterListItem
|
||||
import org.koitharu.kotatsu.details.ui.model.HistoryInfo
|
||||
import org.koitharu.kotatsu.details.ui.model.MangaBranch
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver
|
||||
import org.koitharu.kotatsu.main.ui.owners.NoModalBottomSheetOwner
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
@@ -157,7 +159,7 @@ class DetailsActivity :
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.button_read -> openReader(isIncognitoMode = false)
|
||||
R.id.button_dropdown -> showBranchPopupMenu()
|
||||
R.id.button_dropdown -> showBranchPopupMenu(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,20 +277,28 @@ class DetailsActivity :
|
||||
viewBadge.counter = newChapters
|
||||
}
|
||||
|
||||
private fun showBranchPopupMenu() {
|
||||
var dialog: DialogInterface? = null
|
||||
val listener = OnListItemClickListener<MangaBranch> { item, _ ->
|
||||
viewModel.setSelectedBranch(item.name)
|
||||
dialog?.dismiss()
|
||||
private fun showBranchPopupMenu(v: View) {
|
||||
val menu = PopupMenu(v.context, v)
|
||||
val branches = viewModel.branches.value
|
||||
for ((i, branch) in branches.withIndex()) {
|
||||
val title = buildSpannedString {
|
||||
append(branch.name ?: getString(R.string.system_default))
|
||||
append(' ')
|
||||
append(' ')
|
||||
inSpans(
|
||||
ForegroundColorSpan(v.context.getThemeColor(android.R.attr.textColorSecondary, Color.LTGRAY)),
|
||||
RelativeSizeSpan(0.74f),
|
||||
) {
|
||||
append(branch.count.toString())
|
||||
}
|
||||
}
|
||||
menu.menu.add(Menu.NONE, Menu.NONE, i, title)
|
||||
}
|
||||
dialog = RecyclerViewAlertDialog.Builder<MangaBranch>(this)
|
||||
.addAdapterDelegate(branchAD(listener))
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setTitle(R.string.translations)
|
||||
.setItems(viewModel.branches.value)
|
||||
.create()
|
||||
.also { it.show() }
|
||||
menu.setOnMenuItemClickListener {
|
||||
viewModel.setSelectedBranch(branches.getOrNull(it.order)?.name)
|
||||
true
|
||||
}
|
||||
menu.show()
|
||||
}
|
||||
|
||||
private fun openReader(isIncognitoMode: Boolean) {
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.koitharu.kotatsu.core.os.AppShortcutManager
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.util.ShareHelper
|
||||
import org.koitharu.kotatsu.download.ui.dialog.DownloadOption
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesSheet
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteSheet
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.scrobbling.common.ui.selector.ScrobblingSelectorSheet
|
||||
import org.koitharu.kotatsu.search.ui.multi.MultiSearchActivity
|
||||
@@ -62,7 +62,7 @@ class DetailsMenuProvider(
|
||||
|
||||
R.id.action_favourite -> {
|
||||
viewModel.manga.value?.let {
|
||||
FavouriteCategoriesSheet.show(activity.supportFragmentManager, it)
|
||||
FavouriteSheet.show(activity.supportFragmentManager, it)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.koitharu.kotatsu.explore.ui.model
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
class RecommendationsItem(
|
||||
data class RecommendationsItem(
|
||||
val manga: Manga
|
||||
) : ListModel {
|
||||
|
||||
@@ -12,18 +12,4 @@ class RecommendationsItem(
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
return other is RecommendationsItem
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as RecommendationsItem
|
||||
|
||||
return manga == other.manga
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return 31 * manga.hashCode()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
|
||||
@AndroidEntryPoint
|
||||
class FavouriteCategoriesSheet :
|
||||
class FavouriteSheet :
|
||||
BaseAdaptiveSheet<SheetFavoriteCategoriesBinding>(),
|
||||
OnListItemClickListener<MangaCategoryItem> {
|
||||
|
||||
@@ -53,7 +53,7 @@ class FavouriteCategoriesSheet :
|
||||
}
|
||||
|
||||
override fun onItemClick(item: MangaCategoryItem, view: View) {
|
||||
viewModel.setChecked(item.id, !item.isChecked)
|
||||
viewModel.setChecked(item.category.id, !item.isChecked)
|
||||
}
|
||||
|
||||
private fun onContentChanged(categories: List<ListModel>) {
|
||||
@@ -72,7 +72,7 @@ class FavouriteCategoriesSheet :
|
||||
fun show(fm: FragmentManager, manga: Manga) = Companion.show(fm, listOf(manga))
|
||||
|
||||
fun show(fm: FragmentManager, manga: Collection<Manga>) =
|
||||
FavouriteCategoriesSheet().withArgs(1) {
|
||||
FavouriteSheet().withArgs(1) {
|
||||
putParcelableArrayList(
|
||||
KEY_MANGA_LIST,
|
||||
manga.mapTo(ArrayList(manga.size)) {
|
||||
@@ -14,7 +14,7 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
|
||||
import org.koitharu.kotatsu.core.ui.BaseViewModel
|
||||
import org.koitharu.kotatsu.core.util.ext.require
|
||||
import org.koitharu.kotatsu.favourites.domain.FavouritesRepository
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesSheet.Companion.KEY_MANGA_LIST
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteSheet.Companion.KEY_MANGA_LIST
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.model.CategoriesHeaderItem
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
@@ -37,8 +37,7 @@ class MangaCategoriesViewModel @Inject constructor(
|
||||
add(header)
|
||||
all.mapTo(this) {
|
||||
MangaCategoryItem(
|
||||
id = it.id,
|
||||
name = it.title,
|
||||
category = it,
|
||||
isChecked = it.id in checked,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package org.koitharu.kotatsu.favourites.ui.categories.select.adapter
|
||||
|
||||
import androidx.core.view.isVisible
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.core.util.ext.setChecked
|
||||
import org.koitharu.kotatsu.databinding.ItemCheckableNewBinding
|
||||
import org.koitharu.kotatsu.databinding.ItemCategoryCheckableBinding
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.model.MangaCategoryItem
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
|
||||
fun mangaCategoryAD(
|
||||
clickListener: OnListItemClickListener<MangaCategoryItem>,
|
||||
) = adapterDelegateViewBinding<MangaCategoryItem, ListModel, ItemCheckableNewBinding>(
|
||||
{ inflater, parent -> ItemCheckableNewBinding.inflate(inflater, parent, false) },
|
||||
) = adapterDelegateViewBinding<MangaCategoryItem, ListModel, ItemCategoryCheckableBinding>(
|
||||
{ inflater, parent -> ItemCategoryCheckableBinding.inflate(inflater, parent, false) },
|
||||
) {
|
||||
|
||||
itemView.setOnClickListener {
|
||||
@@ -19,9 +20,9 @@ fun mangaCategoryAD(
|
||||
}
|
||||
|
||||
bind { payloads ->
|
||||
with(binding.root) {
|
||||
text = item.name
|
||||
setChecked(item.isChecked, ListModelDiffCallback.PAYLOAD_CHECKED_CHANGED in payloads)
|
||||
}
|
||||
binding.checkableImageView.setChecked(item.isChecked, ListModelDiffCallback.PAYLOAD_CHECKED_CHANGED !in payloads)
|
||||
binding.textViewTitle.text = item.category.title
|
||||
binding.imageViewTracker.isVisible = item.category.isTrackingEnabled
|
||||
binding.imageViewVisible.isVisible = item.category.isVisibleInLibrary
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
package org.koitharu.kotatsu.favourites.ui.categories.select.model
|
||||
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback
|
||||
import org.koitharu.kotatsu.list.ui.model.ListModel
|
||||
|
||||
class MangaCategoryItem(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
data class MangaCategoryItem(
|
||||
val category: FavouriteCategory,
|
||||
val isChecked: Boolean,
|
||||
) : ListModel {
|
||||
|
||||
override fun areItemsTheSame(other: ListModel): Boolean {
|
||||
return other is MangaCategoryItem && other.id == id
|
||||
return other is MangaCategoryItem && other.category.id == category.id
|
||||
}
|
||||
|
||||
override fun getChangePayload(previousState: ListModel): Any? {
|
||||
@@ -20,22 +20,4 @@ class MangaCategoryItem(
|
||||
super.getChangePayload(previousState)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as MangaCategoryItem
|
||||
|
||||
if (id != other.id) return false
|
||||
if (name != other.name) return false
|
||||
return isChecked == other.isChecked
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = id.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + isChecked.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
|
||||
import org.koitharu.kotatsu.databinding.FragmentListBinding
|
||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesSheet
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteSheet
|
||||
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
|
||||
import org.koitharu.kotatsu.list.ui.adapter.MangaListAdapter
|
||||
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
||||
@@ -283,7 +283,7 @@ abstract class MangaListFragment :
|
||||
}
|
||||
|
||||
R.id.action_favourite -> {
|
||||
FavouriteCategoriesSheet.show(childFragmentManager, selectedItems)
|
||||
FavouriteSheet.show(childFragmentManager, selectedItems)
|
||||
mode.finish()
|
||||
true
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
|
||||
import org.koitharu.kotatsu.databinding.ActivitySearchMultiBinding
|
||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||
import org.koitharu.kotatsu.download.ui.worker.DownloadStartedObserver
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteCategoriesSheet
|
||||
import org.koitharu.kotatsu.favourites.ui.categories.select.FavouriteSheet
|
||||
import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
|
||||
import org.koitharu.kotatsu.list.ui.adapter.MangaListListener
|
||||
import org.koitharu.kotatsu.list.ui.model.ListHeader
|
||||
@@ -159,7 +159,7 @@ class MultiSearchActivity :
|
||||
}
|
||||
|
||||
R.id.action_favourite -> {
|
||||
FavouriteCategoriesSheet.show(supportFragmentManager, collectSelectedItems())
|
||||
FavouriteSheet.show(supportFragmentManager, collectSelectedItems())
|
||||
mode.finish()
|
||||
true
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#000000"
|
||||
android:tint="?colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
|
||||
66
app/src/main/res/layout/item_category_checkable.xml
Normal file
66
app/src/main/res/layout/item_category_checkable.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?listPreferredItemHeightSmall"
|
||||
android:paddingStart="?android:listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:listPreferredItemPaddingEnd"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<org.koitharu.kotatsu.core.ui.widgets.CheckableImageView
|
||||
android:id="@+id/checkableImageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="?android:listChoiceIndicatorMultiple" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="?listPreferredItemPaddingStart"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?attr/textAppearanceBodyMedium"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/imageView_tracker"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/checkableImageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/lorem[1]" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView_tracker"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:contentDescription="@string/check_for_new_chapters"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/imageView_visible"
|
||||
app:layout_constraintStart_toEndOf="@id/textView_title"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_notification" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView_visible"
|
||||
android:layout_width="14dp"
|
||||
android:layout_height="14dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:contentDescription="@string/show_on_shelf"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/imageView_tracker"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_eye" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -18,9 +18,9 @@
|
||||
android:textAppearance="@style/TextAppearance.Kotatsu.SectionHeader"
|
||||
tools:text="@tools:sample/lorem[2]" />
|
||||
|
||||
<Button
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_more"
|
||||
style="@style/Widget.Kotatsu.Button.More"
|
||||
style="@style/Widget.Kotatsu.Button.More.Small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
|
||||
@@ -119,6 +119,12 @@
|
||||
<item name="android:minWidth">48dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Kotatsu.Button.More.Small">
|
||||
<item name="android:insetTop">0dp</item>
|
||||
<item name="android:insetBottom">0dp</item>
|
||||
<item name="android:minHeight">42dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Kotatsu.ToggleButton" parent="Widget.Material3.Button.OutlinedButton">
|
||||
<item name="android:checkable">true</item>
|
||||
<item name="android:textAlignment">textStart</item>
|
||||
|
||||
Reference in New Issue
Block a user