Improve mouse interaction

This commit is contained in:
Koitharu
2025-05-11 18:46:05 +03:00
parent 8ad28fd509
commit 94ef64c4b7
15 changed files with 65 additions and 14 deletions

View File

@@ -9,9 +9,11 @@ import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.TooltipCompat
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans import androidx.core.text.inSpans
import androidx.core.text.method.LinkMovementMethodCompat import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
@@ -43,6 +45,7 @@ import org.koitharu.kotatsu.core.image.CoilMemoryCacheKey
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.model.LocalMangaSource import org.koitharu.kotatsu.core.model.LocalMangaSource
import org.koitharu.kotatsu.core.model.UnknownMangaSource import org.koitharu.kotatsu.core.model.UnknownMangaSource
import org.koitharu.kotatsu.core.model.getSummary
import org.koitharu.kotatsu.core.model.getTitle import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.core.model.titleResId import org.koitharu.kotatsu.core.model.titleResId
import org.koitharu.kotatsu.core.nav.ReaderIntent import org.koitharu.kotatsu.core.nav.ReaderIntent
@@ -426,6 +429,7 @@ class DetailsActivity :
textViewSourceLabel.isVisible = false textViewSourceLabel.isVisible = false
} else { } else {
textViewSource.textAndVisible = manga.source.getTitle(this@DetailsActivity) textViewSource.textAndVisible = manga.source.getTitle(this@DetailsActivity)
TooltipCompat.setTooltipText(textViewSource, manga.source.getSummary(this@DetailsActivity))
textViewSourceLabel.isVisible = textViewSource.isVisible == true textViewSourceLabel.isVisible = textViewSource.isVisible == true
} }
val faviconPlaceholderFactory = FaviconDrawable.Factory(R.style.FaviconDrawable_Chip) val faviconPlaceholderFactory = FaviconDrawable.Factory(R.style.FaviconDrawable_Chip)

View File

@@ -33,7 +33,7 @@ class DestinationsAdapter(context: Context, dataset: List<DirectoryModel>) :
val item = getItem(position) ?: return view val item = getItem(position) ?: return view
val binding = val binding =
view.tag as? ItemStorageConfigBinding ?: ItemStorageConfigBinding.bind(view).also { view.tag = it } view.tag as? ItemStorageConfigBinding ?: ItemStorageConfigBinding.bind(view).also { view.tag = it }
binding.imageViewRemove.isVisible = false binding.buttonRemove.isVisible = false
binding.textViewTitle.text = item.title ?: view.context.getString(item.titleRes) binding.textViewTitle.text = item.title ?: view.context.getString(item.titleRes)
binding.textViewSubtitle.textAndVisible = item.file?.path binding.textViewSubtitle.textAndVisible = item.file?.path
return view return view

View File

@@ -1,7 +1,10 @@
package org.koitharu.kotatsu.explore.ui.adapter package org.koitharu.kotatsu.explore.ui.adapter
import android.view.View import android.view.View
import androidx.appcompat.widget.TooltipCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getSummary import org.koitharu.kotatsu.core.model.getSummary
@@ -122,7 +125,18 @@ fun exploreSourceGridItemAD(
val iconPinned = ContextCompat.getDrawable(context, R.drawable.ic_pin_small) val iconPinned = ContextCompat.getDrawable(context, R.drawable.ic_pin_small)
bind { bind {
binding.textViewTitle.text = item.source.getTitle(context) val title = item.source.getTitle(context)
TooltipCompat.setTooltipText(
itemView,
buildSpannedString {
bold {
append(title)
}
appendLine()
append(item.source.getSummary(context))
},
)
binding.textViewTitle.text = title
binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null
binding.imageViewIcon.setImageAsync(item.source) binding.imageViewIcon.setImageAsync(item.source)
} }

View File

@@ -43,8 +43,8 @@ class ReadingProgressView @JvmOverloads constructor(
null, null,
NONE -> "" NONE -> ""
PERCENT_READ -> percentPattern.format((value.percent * 100f).toInt().toString()) PERCENT_READ -> percentPattern.format(ReadingProgress.percentToString(value.percent))
PERCENT_LEFT -> "-" + percentPattern.format((value.percentLeft * 100f).toInt().toString()) PERCENT_LEFT -> "-" + percentPattern.format(ReadingProgress.percentToString(value.percentLeft))
CHAPTERS_READ -> value.chapters.toString() CHAPTERS_READ -> value.chapters.toString()
CHAPTERS_LEFT -> "-" + value.chaptersLeft.toString() CHAPTERS_LEFT -> "-" + value.chaptersLeft.toString()

View File

@@ -44,5 +44,11 @@ data class ReadingProgress(
fun isValid(percent: Float) = percent in 0f..1f fun isValid(percent: Float) = percent in 0f..1f
fun isCompleted(percent: Float) = percent >= PROGRESS_COMPLETED_THRESHOLD fun isCompleted(percent: Float) = percent >= PROGRESS_COMPLETED_THRESHOLD
fun percentToString(percent: Float): String = if (isValid(percent)) {
if (isCompleted(percent)) "100" else (percent * 100f).toInt().toString()
} else {
"0"
}
} }
} }

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.list.ui.adapter package org.koitharu.kotatsu.list.ui.adapter
import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@@ -23,6 +24,7 @@ fun mangaGridItemAD(
sizeResolver.attachToView(itemView, binding.textViewTitle, binding.progressView) sizeResolver.attachToView(itemView, binding.textViewTitle, binding.progressView)
bind { payloads -> bind { payloads ->
TooltipCompat.setTooltipText(itemView, item.getSummary(context))
binding.textViewTitle.text = item.title binding.textViewTitle.text = item.title
binding.progressView.setProgress(item.progress, PAYLOAD_PROGRESS_CHANGED in payloads) binding.progressView.setProgress(item.progress, PAYLOAD_PROGRESS_CHANGED in payloads)
with(binding.iconsView) { with(binding.iconsView) {

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.list.ui.adapter package org.koitharu.kotatsu.list.ui.adapter
import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
@@ -19,6 +20,7 @@ fun mangaListItemAD(
AdapterDelegateClickListenerAdapter(this, clickListener, MangaCompactListModel::manga).attach(itemView) AdapterDelegateClickListenerAdapter(this, clickListener, MangaCompactListModel::manga).attach(itemView)
bind { bind {
TooltipCompat.setTooltipText(itemView, item.getSummary(context))
binding.textViewTitle.text = item.title binding.textViewTitle.text = item.title
binding.textViewSubtitle.textAndVisible = item.subtitle binding.textViewSubtitle.textAndVisible = item.subtitle
binding.imageViewCover.setImageAsync(item.coverUrl, item.manga) binding.imageViewCover.setImageAsync(item.coverUrl, item.manga)

View File

@@ -1,5 +1,9 @@
package org.koitharu.kotatsu.list.ui.model package org.koitharu.kotatsu.list.ui.model
import android.content.Context
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import org.koitharu.kotatsu.core.model.getTitle
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_ANYTHING_CHANGED import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_ANYTHING_CHANGED
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
@@ -15,6 +19,18 @@ sealed class MangaListModel : ListModel {
val source: MangaSource val source: MangaSource
get() = manga.source get() = manga.source
open fun getSummary(context: Context): CharSequence = buildSpannedString {
bold {
append(manga.title)
}
appendLine()
if (manga.tags.isNotEmpty()) {
manga.tags.joinTo(this) { it.title }
appendLine()
}
append(manga.source.getTitle(context))
}
override fun areItemsTheSame(other: ListModel): Boolean { override fun areItemsTheSame(other: ListModel): Boolean {
return other is MangaListModel && other.javaClass == javaClass && id == other.id return other is MangaListModel && other.javaClass == javaClass && id == other.id
} }

View File

@@ -13,6 +13,7 @@ import android.widget.FrameLayout
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@@ -253,13 +254,13 @@ class ReaderActionsView @JvmOverloads constructor(
private fun Button.initAction() { private fun Button.initAction() {
setOnClickListener(this@ReaderActionsView) setOnClickListener(this@ReaderActionsView)
setOnLongClickListener(this@ReaderActionsView) setOnLongClickListener(this@ReaderActionsView)
ViewCompat.setTooltipText(this, contentDescription) TooltipCompat.setTooltipText(this, contentDescription)
} }
private fun Button.setTitle(@StringRes titleResId: Int) { private fun Button.setTitle(@StringRes titleResId: Int) {
val text = resources.getString(titleResId) val text = resources.getString(titleResId)
contentDescription = text contentDescription = text
ViewCompat.setTooltipText(this, text) TooltipCompat.setTooltipText(this, text)
} }
private fun isAutoRotationEnabled(): Boolean = Settings.System.getInt( private fun isAutoRotationEnabled(): Boolean = Settings.System.getInt(

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.search.ui.suggestion.adapter package org.koitharu.kotatsu.search.ui.suggestion.adapter
import androidx.appcompat.widget.TooltipCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@@ -46,6 +47,7 @@ private fun searchSuggestionMangaGridAD(
} }
bind { bind {
TooltipCompat.setTooltipText(itemView, item.title)
binding.imageViewCover.setImageAsync(item.coverUrl, item.source) binding.imageViewCover.setImageAsync(item.coverUrl, item.source)
binding.textViewTitle.text = item.title binding.textViewTitle.text = item.title
} }

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.settings.storage.directories package org.koitharu.kotatsu.settings.storage.directories
import androidx.appcompat.widget.TooltipCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
@@ -16,13 +17,14 @@ fun directoryConfigAD(
{ layoutInflater, parent -> ItemStorageConfigBinding.inflate(layoutInflater, parent, false) }, { layoutInflater, parent -> ItemStorageConfigBinding.inflate(layoutInflater, parent, false) },
) { ) {
binding.imageViewRemove.setOnClickListener { v -> clickListener.onItemClick(item, v) } binding.buttonRemove.setOnClickListener { v -> clickListener.onItemClick(item, v) }
TooltipCompat.setTooltipText(binding.buttonRemove, binding.buttonRemove.contentDescription)
bind { bind {
binding.textViewTitle.text = item.title ?: getString(item.titleRes) binding.textViewTitle.text = item.title ?: getString(item.titleRes)
binding.textViewSubtitle.textAndVisible = item.file?.absolutePath binding.textViewSubtitle.textAndVisible = item.file?.absolutePath
binding.imageViewRemove.isVisible = item.isRemovable binding.buttonRemove.isVisible = item.isRemovable
binding.imageViewRemove.isEnabled = !item.isChecked binding.buttonRemove.isEnabled = !item.isChecked
binding.textViewTitle.drawableStart = if (!item.isAvailable) { binding.textViewTitle.drawableStart = if (!item.isAvailable) {
ContextCompat.getDrawable(context, R.drawable.ic_alert_outline)?.apply { ContextCompat.getDrawable(context, R.drawable.ic_alert_outline)?.apply {
setTint(ContextCompat.getColor(context, R.color.warning)) setTint(ContextCompat.getColor(context, R.color.warning))

View File

@@ -54,7 +54,7 @@
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
tools:text="@tools:sample/lorem[1]" /> tools:text="@tools:sample/lorem[1]" />
<ImageView <ImageButton
android:id="@+id/imageView_visible" android:id="@+id/imageView_visible"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@@ -78,7 +78,7 @@
app:layout_constraintTop_toTopOf="@id/textView_subtitle" app:layout_constraintTop_toTopOf="@id/textView_subtitle"
app:srcCompat="@drawable/ic_eye_off" /> app:srcCompat="@drawable/ic_eye_off" />
<ImageView <ImageButton
android:id="@+id/imageView_edit" android:id="@+id/imageView_edit"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -86,6 +86,7 @@
android:contentDescription="@string/edit" android:contentDescription="@string/edit"
android:padding="@dimen/margin_normal" android:padding="@dimen/margin_normal"
android:src="@drawable/ic_edit" android:src="@drawable/ic_edit"
android:tooltipText="@string/edit"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/imageView_handle" app:layout_constraintEnd_toStartOf="@id/imageView_handle"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@@ -97,7 +98,9 @@
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/reorder" android:contentDescription="@string/reorder"
android:padding="@dimen/margin_normal" android:padding="@dimen/margin_normal"
android:pointerIcon="grab"
android:src="@drawable/ic_reorder_handle" android:src="@drawable/ic_reorder_handle"
android:tooltipText="@string/reorder"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />

View File

@@ -40,8 +40,8 @@
</LinearLayout> </LinearLayout>
<ImageView <ImageButton
android:id="@+id/imageView_remove" android:id="@+id/button_remove"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless" android:background="?selectableItemBackgroundBorderless"

View File

@@ -58,7 +58,6 @@
<item name="bottomSheetDialogTheme">@style/ThemeOverlay.Kotatsu.BottomSheetDialog</item> <item name="bottomSheetDialogTheme">@style/ThemeOverlay.Kotatsu.BottomSheetDialog</item>
<item name="sideSheetDialogTheme">@style/ThemeOverlay.Kotatsu.SideSheetDialog</item> <item name="sideSheetDialogTheme">@style/ThemeOverlay.Kotatsu.SideSheetDialog</item>
<item name="textInputStyle">?textInputOutlinedStyle</item> <item name="textInputStyle">?textInputOutlinedStyle</item>
<!--<item name="toolbarStyle">@style/Widget.Material3.Toolbar</item>-->
<item name="materialCardViewStyle">?materialCardViewFilledStyle</item> <item name="materialCardViewStyle">?materialCardViewFilledStyle</item>
<item name="recyclerViewStyle">@style/Widget.Kotatsu.RecyclerView</item> <item name="recyclerViewStyle">@style/Widget.Kotatsu.RecyclerView</item>
<item name="android:dropDownSpinnerStyle">@style/Widget.Kotatsu.Spinner.DropDown</item> <item name="android:dropDownSpinnerStyle">@style/Widget.Kotatsu.Spinner.DropDown</item>