mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
More floating action modes in details
Tags now use action mode, shows the option to search the manga's source, even in library Description text now also adds the option for global/local searching All of these no longer show a snackbar that the text is copied (since you'd be tapping the option to select the text anyway
This commit is contained in:
parent
955277c4ae
commit
ef5a05050d
5 changed files with 134 additions and 23 deletions
|
@ -1,6 +1,8 @@
|
|||
package eu.kanade.tachiyomi.ui.manga
|
||||
|
||||
import android.view.ActionMode
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
@ -133,11 +135,12 @@ class MangaDetailsAdapter(
|
|||
fun topCoverHeight(): Int
|
||||
fun localSearch(text: String)
|
||||
fun globalSearch(text: String)
|
||||
fun showFloatingActionMode(view: View, content: String, label: Int)
|
||||
fun showFloatingActionMode(view: TextView, content: String? = null, searchSource: Boolean = false)
|
||||
fun showChapterFilter()
|
||||
fun favoriteManga(longPress: Boolean)
|
||||
fun copyToClipboard(content: String, label: Int, useToast: Boolean = false)
|
||||
fun copyToClipboard(content: String, label: String, useToast: Boolean = false)
|
||||
fun customActionMode(view: TextView): ActionMode.Callback
|
||||
fun copyToClipboard(content: String, label: String?, useToast: Boolean = false)
|
||||
fun zoomImageFromThumb(thumbView: View)
|
||||
fun showTrackingSheet()
|
||||
fun updateScroll()
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.view.MotionEvent
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
@ -39,6 +40,7 @@ import coil.imageLoader
|
|||
import coil.request.ImageRequest
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.ControllerChangeType
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
|
@ -54,8 +56,10 @@ import eu.kanade.tachiyomi.data.image.coil.getBestColor
|
|||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import eu.kanade.tachiyomi.databinding.MangaDetailsControllerBinding
|
||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.icon
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
|
||||
import eu.kanade.tachiyomi.ui.base.SmallToolbarInterface
|
||||
|
@ -1379,12 +1383,27 @@ class MangaDetailsController :
|
|||
router.getControllerWithTag(R.id.nav_library.toString()) as LibraryController
|
||||
controller.search(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun sourceSearch(text: String) {
|
||||
when (
|
||||
val previousController =
|
||||
router.backstack.getOrNull(router.backstackSize - 2)?.controller
|
||||
) {
|
||||
is BrowseSourceController -> {
|
||||
if (presenter.source is HttpSource) {
|
||||
router.handleBack()
|
||||
previousController.searchWithGenre(text)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
if (presenter.source is CatalogueSource) {
|
||||
val controller = BrowseSourceController(presenter.source)
|
||||
router.pushController(controller.withFadeTransaction())
|
||||
controller.searchWithGenre(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1393,13 +1412,22 @@ class MangaDetailsController :
|
|||
router.pushController(GlobalSearchController(text).withFadeTransaction())
|
||||
}
|
||||
|
||||
override fun showFloatingActionMode(view: View, content: String, label: Int) {
|
||||
if (content.isBlank()) return
|
||||
override fun showFloatingActionMode(view: TextView, content: String?, searchSource: Boolean) {
|
||||
finishFloatingActionMode()
|
||||
floatingActionMode = view.startActionMode(
|
||||
FloatingMangaDetailsActionModeCallback(content, label),
|
||||
android.view.ActionMode.TYPE_FLOATING,
|
||||
val actionModeCallback = if (content != null) FloatingMangaDetailsActionModeCallback(
|
||||
content,
|
||||
searchSource = searchSource,
|
||||
)
|
||||
else FloatingMangaDetailsActionModeCallback(view, searchSource = searchSource)
|
||||
if (view is Chip) {
|
||||
view.isActivated = true
|
||||
}
|
||||
floatingActionMode =
|
||||
view.startActionMode(actionModeCallback, android.view.ActionMode.TYPE_FLOATING)
|
||||
}
|
||||
|
||||
override fun customActionMode(view: TextView): android.view.ActionMode.Callback {
|
||||
return FloatingMangaDetailsActionModeCallback(view, false)
|
||||
}
|
||||
|
||||
override fun showChapterFilter() {
|
||||
|
@ -1500,7 +1528,7 @@ class MangaDetailsController :
|
|||
*/
|
||||
override fun copyToClipboard(content: String, label: Int, useToast: Boolean) {
|
||||
val view = view ?: return
|
||||
val contentType = view.context.getString(label)
|
||||
val contentType = if (label != 0) view.context.getString(label) else null
|
||||
copyToClipboard(content, contentType, useToast)
|
||||
}
|
||||
|
||||
|
@ -1510,7 +1538,7 @@ class MangaDetailsController :
|
|||
* @param content the actual text to copy to the board
|
||||
* @param label Label to show to the user describing the content
|
||||
*/
|
||||
override fun copyToClipboard(content: String, label: String, useToast: Boolean) {
|
||||
override fun copyToClipboard(content: String, label: String?, useToast: Boolean) {
|
||||
if (content.isBlank()) return
|
||||
|
||||
val activity = activity ?: return
|
||||
|
@ -1519,6 +1547,7 @@ class MangaDetailsController :
|
|||
val clipboard = activity.getSystemService(ClipboardManager::class.java)
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(label, content))
|
||||
|
||||
label ?: return
|
||||
if (useToast) {
|
||||
activity.toast(view.context.getString(R.string._copied_to_clipboard, label))
|
||||
} else {
|
||||
|
@ -1681,20 +1710,49 @@ class MangaDetailsController :
|
|||
}
|
||||
|
||||
inner class FloatingMangaDetailsActionModeCallback(
|
||||
val text: String,
|
||||
val label: Int,
|
||||
private val textView: TextView?,
|
||||
private val showCopy: Boolean = true,
|
||||
private val searchSource: Boolean = false,
|
||||
) : android.view.ActionMode.Callback {
|
||||
constructor(
|
||||
text: String,
|
||||
showCopy: Boolean = true,
|
||||
searchSource: Boolean = false,
|
||||
) : this(null, showCopy, searchSource) {
|
||||
customText = text
|
||||
}
|
||||
|
||||
var customText: String? = null
|
||||
val text: String
|
||||
get() {
|
||||
return customText ?: if (textView?.isTextSelectable == true) {
|
||||
textView.text.subSequence(textView.selectionStart, textView.selectionEnd)
|
||||
.toString()
|
||||
} else {
|
||||
textView?.text?.toString() ?: ""
|
||||
}
|
||||
}
|
||||
override fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
|
||||
mode?.menuInflater?.inflate(R.menu.manga_details_title, menu)
|
||||
mode?.menuInflater?.inflate(
|
||||
if (searchSource) R.menu.manga_details_tag else R.menu.manga_details_title,
|
||||
menu,
|
||||
)
|
||||
menu?.findItem(R.id.action_copy)?.isVisible = showCopy
|
||||
val sourceMenuItem = menu?.findItem(R.id.action_source_search)
|
||||
sourceMenuItem?.isVisible = searchSource && presenter.source is CatalogueSource
|
||||
val context = view?.context ?: return false
|
||||
val prevController = router.backstack.getOrNull(router.backstackSize - 2)?.controller
|
||||
val localItem = menu?.findItem(R.id.action_local_search) ?: return true
|
||||
localItem.isVisible = when (prevController) {
|
||||
is LibraryController, is BrowseController, is RecentsController -> true
|
||||
is LibraryController, is RecentsController -> true
|
||||
else -> false
|
||||
}
|
||||
val library = context.getString(R.string.library).lowercase(Locale.getDefault())
|
||||
localItem.title = context.getString(R.string.search_, library)
|
||||
sourceMenuItem?.title = context.getString(R.string.search_, presenter.source.name)
|
||||
if (searchSource) {
|
||||
sourceMenuItem?.icon = presenter.source.icon()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -1706,18 +1764,25 @@ class MangaDetailsController :
|
|||
mode: android.view.ActionMode?,
|
||||
item: MenuItem?,
|
||||
): Boolean {
|
||||
mode?.finish()
|
||||
val context = view?.context ?: return true
|
||||
when (item?.itemId) {
|
||||
R.id.action_copy -> copyToClipboard(text, context.getString(label))
|
||||
R.id.action_copy -> copyToClipboard(text, null)
|
||||
R.id.action_global_search -> globalSearch(text)
|
||||
R.id.action_source_search -> sourceSearch(text)
|
||||
R.id.action_local_search -> localSearch(text)
|
||||
}
|
||||
if (showCopy) {
|
||||
mode?.finish()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(mode: android.view.ActionMode?) {
|
||||
if (showCopy) {
|
||||
floatingActionMode = null
|
||||
}
|
||||
if (textView is Chip) {
|
||||
textView.isActivated = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.os.Build
|
|||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
|
@ -129,14 +130,15 @@ class MangaHeaderHolder(
|
|||
}
|
||||
title.setOnClickListener { view ->
|
||||
title.text?.toString()?.toNormalized()?.let {
|
||||
adapter.delegate.showFloatingActionMode(view, it, R.string.title)
|
||||
adapter.delegate.showFloatingActionMode(view as TextView, it)
|
||||
}
|
||||
}
|
||||
mangaAuthor.setOnClickListener { view ->
|
||||
mangaAuthor.text?.toString()?.let {
|
||||
adapter.delegate.showFloatingActionMode(view, it, R.string.title)
|
||||
adapter.delegate.showFloatingActionMode(view as TextView, it)
|
||||
}
|
||||
}
|
||||
mangaSummary.customSelectionActionModeCallback = adapter.delegate.customActionMode(mangaSummary)
|
||||
applyBlur()
|
||||
mangaCover.setOnClickListener { adapter.delegate.zoomImageFromThumb(coverCard) }
|
||||
trackButton.setOnClickListener { adapter.delegate.showTrackingSheet() }
|
||||
|
@ -469,6 +471,19 @@ class MangaHeaderHolder(
|
|||
if (dark) 0.945f else 0.175f,
|
||||
),
|
||||
)
|
||||
val states = arrayOf(
|
||||
intArrayOf(-android.R.attr.state_activated),
|
||||
intArrayOf(),
|
||||
)
|
||||
val colors = intArrayOf(
|
||||
downloadedColor,
|
||||
ColorUtils.blendARGB(
|
||||
downloadedColor,
|
||||
context.getResourceColor(R.attr.colorControlNormal),
|
||||
0.25f,
|
||||
),
|
||||
)
|
||||
val colorStateList = ColorStateList(states, colors)
|
||||
if (manga.genre.isNullOrBlank().not()) {
|
||||
(manga.getGenres() ?: emptyList()).map { genreText ->
|
||||
val chip = LayoutInflater.from(binding.root.context).inflate(
|
||||
|
@ -478,14 +493,14 @@ class MangaHeaderHolder(
|
|||
) as Chip
|
||||
val id = View.generateViewId()
|
||||
chip.id = id
|
||||
chip.chipBackgroundColor = ColorStateList.valueOf(downloadedColor)
|
||||
chip.chipBackgroundColor = colorStateList
|
||||
chip.setTextColor(textColor)
|
||||
chip.text = genreText
|
||||
chip.setOnClickListener {
|
||||
adapter.delegate.localSearch(genreText)
|
||||
adapter.delegate.showFloatingActionMode(chip, searchSource = true)
|
||||
}
|
||||
chip.setOnLongClickListener {
|
||||
adapter.delegate.copyToClipboard(genreText, genreText)
|
||||
adapter.delegate.showFloatingActionMode(chip, searchSource = true)
|
||||
true
|
||||
}
|
||||
this.addView(chip)
|
||||
|
|
28
app/src/main/res/menu/manga_details_tag.xml
Normal file
28
app/src/main/res/menu/manga_details_tag.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_copy"
|
||||
android:icon="@drawable/ic_done_all_24dp"
|
||||
android:title="@string/copy_value"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_local_search"
|
||||
android:icon="@drawable/ic_search_24dp"
|
||||
android:title="@string/search"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_source_search"
|
||||
android:icon="@drawable/ic_extension_update_24dp"
|
||||
android:title="@string/search"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_global_search"
|
||||
android:icon="@drawable/ic_open_in_webview_24dp"
|
||||
android:title="@string/label_global_search"
|
||||
app:showAsAction="ifRoom" />
|
||||
</menu>
|
|
@ -8,7 +8,7 @@
|
|||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/action_global_search"
|
||||
android:icon="@drawable/ic_search_24dp"
|
||||
android:icon="@drawable/ic_open_in_webview_24dp"
|
||||
android:title="@string/label_global_search"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue