Context menus
This commit is contained in:
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.bookmarks.ui
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -129,7 +130,11 @@ class AllBookmarksFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: Bookmark, view: View): Boolean {
|
override fun onItemLongClick(item: Bookmark, view: View): Boolean {
|
||||||
return selectionController?.onItemLongClick(item.pageId) ?: false
|
return selectionController?.onItemLongClick(view, item.pageId) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: Bookmark, view: View): Boolean {
|
||||||
|
return selectionController?.onItemContextClick(view, item.pageId) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRetryClick(error: Throwable) = Unit
|
override fun onRetryClick(error: Throwable) = Unit
|
||||||
@@ -148,23 +153,23 @@ class AllBookmarksFragment :
|
|||||||
|
|
||||||
override fun onCreateActionMode(
|
override fun onCreateActionMode(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
menuInflater: MenuInflater,
|
||||||
menu: Menu,
|
menu: Menu,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
mode.menuInflater.inflate(R.menu.mode_bookmarks, menu)
|
menuInflater.inflate(R.menu.mode_bookmarks, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(
|
override fun onActionItemClicked(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
mode: ActionMode?,
|
||||||
item: MenuItem,
|
item: MenuItem,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_remove -> {
|
R.id.action_remove -> {
|
||||||
val ids = selectionController?.snapshot() ?: return false
|
val ids = selectionController?.snapshot() ?: return false
|
||||||
viewModel.removeBookmarks(ids)
|
viewModel.removeBookmarks(ids)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ fun bookmarkLargeAD(
|
|||||||
) = adapterDelegateViewBinding<Bookmark, ListModel, ItemBookmarkLargeBinding>(
|
) = adapterDelegateViewBinding<Bookmark, ListModel, ItemBookmarkLargeBinding>(
|
||||||
{ inflater, parent -> ItemBookmarkLargeBinding.inflate(inflater, parent, false) },
|
{ inflater, parent -> ItemBookmarkLargeBinding.inflate(inflater, parent, false) },
|
||||||
) {
|
) {
|
||||||
val listener = AdapterDelegateClickListenerAdapter(this, clickListener)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
|
|
||||||
binding.root.setOnClickListener(listener)
|
|
||||||
binding.root.setOnLongClickListener(listener)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.imageViewThumb.newImageRequest(lifecycleOwner, item.imageLoadData)?.run {
|
binding.imageViewThumb.newImageRequest(lifecycleOwner, item.imageLoadData)?.run {
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ fun bookmarkListAD(
|
|||||||
) = adapterDelegateViewBinding<Bookmark, Bookmark, ItemBookmarkBinding>(
|
) = adapterDelegateViewBinding<Bookmark, Bookmark, ItemBookmarkBinding>(
|
||||||
{ inflater, parent -> ItemBookmarkBinding.inflate(inflater, parent, false) },
|
{ inflater, parent -> ItemBookmarkBinding.inflate(inflater, parent, false) },
|
||||||
) {
|
) {
|
||||||
val listener = AdapterDelegateClickListenerAdapter(this, clickListener)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
|
|
||||||
binding.root.setOnClickListener(listener)
|
|
||||||
binding.root.setOnLongClickListener(listener)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.imageViewThumb.newImageRequest(lifecycleOwner, item.imageLoadData)?.run {
|
binding.imageViewThumb.newImageRequest(lifecycleOwner, item.imageLoadData)?.run {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package org.koitharu.kotatsu.core.ui
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
fun interface OnContextClickListenerCompat {
|
||||||
|
|
||||||
|
fun onContextClick(v: View): Boolean
|
||||||
|
}
|
||||||
@@ -3,18 +3,46 @@ package org.koitharu.kotatsu.core.ui.list
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.OnClickListener
|
import android.view.View.OnClickListener
|
||||||
import android.view.View.OnLongClickListener
|
import android.view.View.OnLongClickListener
|
||||||
|
import androidx.core.util.Function
|
||||||
import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewBindingViewHolder
|
import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewBindingViewHolder
|
||||||
|
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
||||||
|
|
||||||
class AdapterDelegateClickListenerAdapter<I>(
|
class AdapterDelegateClickListenerAdapter<I, O>(
|
||||||
private val adapterDelegate: AdapterDelegateViewBindingViewHolder<out I, *>,
|
private val adapterDelegate: AdapterDelegateViewBindingViewHolder<out I, *>,
|
||||||
private val clickListener: OnListItemClickListener<I>,
|
private val clickListener: OnListItemClickListener<O>,
|
||||||
) : OnClickListener, OnLongClickListener {
|
private val itemMapper: Function<I, O>,
|
||||||
|
) : OnClickListener, OnLongClickListener, OnContextClickListenerCompat {
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
clickListener.onItemClick(adapterDelegate.item, v)
|
clickListener.onItemClick(mappedItem(), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(v: View): Boolean {
|
override fun onLongClick(v: View): Boolean {
|
||||||
return clickListener.onItemLongClick(adapterDelegate.item, v)
|
return clickListener.onItemLongClick(mappedItem(), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContextClick(v: View): Boolean {
|
||||||
|
return clickListener.onItemContextClick(mappedItem(), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mappedItem(): O = itemMapper.apply(adapterDelegate.item)
|
||||||
|
|
||||||
|
fun attach(itemView: View) {
|
||||||
|
itemView.setOnClickListener(this)
|
||||||
|
itemView.setOnLongClickListener(this)
|
||||||
|
itemView.setOnContextClickListenerCompat(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
operator fun <T> invoke(
|
||||||
|
adapterDelegate: AdapterDelegateViewBindingViewHolder<out T, *>,
|
||||||
|
clickListener: OnListItemClickListener<T>
|
||||||
|
): AdapterDelegateClickListenerAdapter<T, T> = AdapterDelegateClickListenerAdapter(
|
||||||
|
adapterDelegate = adapterDelegate,
|
||||||
|
clickListener = clickListener,
|
||||||
|
itemMapper = { x -> x },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,14 @@ package org.koitharu.kotatsu.core.ui.list
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.collection.LongSet
|
import androidx.collection.LongSet
|
||||||
|
import androidx.collection.longSetOf
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
@@ -29,18 +33,21 @@ class ListSelectionController(
|
|||||||
) : ActionMode.Callback, SavedStateRegistry.SavedStateProvider {
|
) : ActionMode.Callback, SavedStateRegistry.SavedStateProvider {
|
||||||
|
|
||||||
private var actionMode: ActionMode? = null
|
private var actionMode: ActionMode? = null
|
||||||
|
private var focusedItemId: LongSet? = null
|
||||||
|
|
||||||
|
var useActionMode: Boolean = true
|
||||||
|
|
||||||
val count: Int
|
val count: Int
|
||||||
get() = decoration.checkedItemsCount
|
get() = if (focusedItemId != null) 1 else decoration.checkedItemsCount
|
||||||
|
|
||||||
init {
|
init {
|
||||||
registryOwner.lifecycle.addObserver(StateEventObserver())
|
registryOwner.lifecycle.addObserver(StateEventObserver())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun snapshot(): Set<Long> = peekCheckedIds().toSet()
|
fun snapshot(): Set<Long> = (focusedItemId ?: peekCheckedIds()).toSet()
|
||||||
|
|
||||||
fun peekCheckedIds(): LongSet {
|
fun peekCheckedIds(): LongSet {
|
||||||
return decoration.checkedItemsIds
|
return focusedItemId ?: decoration.checkedItemsIds
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clear() {
|
fun clear() {
|
||||||
@@ -52,6 +59,7 @@ class ListSelectionController(
|
|||||||
if (ids.isEmpty()) {
|
if (ids.isEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
startActionMode()
|
||||||
decoration.checkAll(ids)
|
decoration.checkAll(ids)
|
||||||
notifySelectionChanged()
|
notifySelectionChanged()
|
||||||
}
|
}
|
||||||
@@ -80,15 +88,42 @@ class ListSelectionController(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onItemLongClick(id: Long): Boolean {
|
fun onItemLongClick(view: View, id: Long): Boolean {
|
||||||
return startActionMode()?.also {
|
return if (useActionMode) {
|
||||||
decoration.setItemIsChecked(id, true)
|
startSelection(id)
|
||||||
notifySelectionChanged()
|
} else {
|
||||||
} != null
|
onItemContextClick(view, id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onItemContextClick(view: View, id: Long): Boolean {
|
||||||
|
focusedItemId = longSetOf(id)
|
||||||
|
val menu = PopupMenu(view.context, view)
|
||||||
|
callback.onCreateActionMode(this, menu.menuInflater, menu.menu)
|
||||||
|
callback.onPrepareActionMode(this, null, menu.menu)
|
||||||
|
menu.setForceShowIcon(true)
|
||||||
|
if (menu.menu.hasVisibleItems()) {
|
||||||
|
menu.setOnMenuItemClickListener { menuItem ->
|
||||||
|
callback.onActionItemClicked(this, null, menuItem)
|
||||||
|
}
|
||||||
|
menu.setOnDismissListener {
|
||||||
|
focusedItemId = null
|
||||||
|
}
|
||||||
|
menu.show()
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
focusedItemId = null
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startSelection(id: Long): Boolean = startActionMode()?.also {
|
||||||
|
decoration.setItemIsChecked(id, true)
|
||||||
|
notifySelectionChanged()
|
||||||
|
} != null
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
return callback.onCreateActionMode(this, mode, menu)
|
return callback.onCreateActionMode(this, mode.menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||||
@@ -106,6 +141,7 @@ class ListSelectionController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startActionMode(): ActionMode? {
|
private fun startActionMode(): ActionMode? {
|
||||||
|
focusedItemId = null
|
||||||
return actionMode ?: appCompatDelegate.startSupportActionMode(this).also {
|
return actionMode ?: appCompatDelegate.startSupportActionMode(this).also {
|
||||||
actionMode = it
|
actionMode = it
|
||||||
}
|
}
|
||||||
@@ -134,14 +170,14 @@ class ListSelectionController(
|
|||||||
|
|
||||||
fun onSelectionChanged(controller: ListSelectionController, count: Int)
|
fun onSelectionChanged(controller: ListSelectionController, count: Int)
|
||||||
|
|
||||||
fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean
|
fun onCreateActionMode(controller: ListSelectionController, menuInflater: MenuInflater, menu: Menu): Boolean
|
||||||
|
|
||||||
fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean {
|
||||||
mode.title = controller.count.toString()
|
mode?.title = controller.count.toString()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean
|
fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean
|
||||||
|
|
||||||
fun onDestroyActionMode(controller: ListSelectionController, mode: ActionMode) = Unit
|
fun onDestroyActionMode(controller: ListSelectionController, mode: ActionMode) = Unit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,7 @@ fun interface OnListItemClickListener<I> {
|
|||||||
|
|
||||||
fun onItemClick(item: I, view: View)
|
fun onItemClick(item: I, view: View)
|
||||||
|
|
||||||
fun onItemLongClick(item: I, view: View) = false
|
fun onItemLongClick(item: I, view: View): Boolean = false
|
||||||
|
|
||||||
|
fun onItemContextClick(item: I, view: View): Boolean = onItemLongClick(item, view)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
|
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
|
||||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
||||||
|
|
||||||
class PopupMenuMediator(
|
class PopupMenuMediator(
|
||||||
private val provider: MenuProvider,
|
private val provider: MenuProvider,
|
||||||
) : View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
|
) : View.OnLongClickListener, OnContextClickListenerCompat, PopupMenu.OnMenuItemClickListener,
|
||||||
|
PopupMenu.OnDismissListener {
|
||||||
|
|
||||||
|
override fun onContextClick(v: View): Boolean = onLongClick(v)
|
||||||
|
|
||||||
override fun onLongClick(v: View): Boolean {
|
override fun onLongClick(v: View): Boolean {
|
||||||
val menu = PopupMenu(v.context, v)
|
val menu = PopupMenu(v.context, v)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.google.android.material.progressindicator.BaseProgressIndicator
|
|||||||
import com.google.android.material.slider.RangeSlider
|
import com.google.android.material.slider.RangeSlider
|
||||||
import com.google.android.material.slider.Slider
|
import com.google.android.material.slider.Slider
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
|
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
|
||||||
@@ -153,9 +154,9 @@ fun BaseProgressIndicator<*>.showOrHide(value: Boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun View.setOnContextClickListenerCompat(listener: View.OnLongClickListener) {
|
fun View.setOnContextClickListenerCompat(listener: OnContextClickListenerCompat) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
setOnContextClickListener(listener::onLongClick)
|
setOnContextClickListener(listener::onContextClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import org.koitharu.kotatsu.core.parser.MangaIntent
|
|||||||
import org.koitharu.kotatsu.core.parser.favicon.faviconUri
|
import org.koitharu.kotatsu.core.parser.favicon.faviconUri
|
||||||
import org.koitharu.kotatsu.core.ui.BaseActivity
|
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
||||||
|
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
|
||||||
import org.koitharu.kotatsu.core.ui.image.ChipIconTarget
|
import org.koitharu.kotatsu.core.ui.image.ChipIconTarget
|
||||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||||
@@ -114,7 +115,8 @@ class DetailsActivity :
|
|||||||
BaseActivity<ActivityDetailsBinding>(),
|
BaseActivity<ActivityDetailsBinding>(),
|
||||||
View.OnClickListener,
|
View.OnClickListener,
|
||||||
View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, View.OnLayoutChangeListener,
|
View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, View.OnLayoutChangeListener,
|
||||||
ViewTreeObserver.OnDrawListener, ChipsView.OnChipClickListener, OnListItemClickListener<Bookmark> {
|
ViewTreeObserver.OnDrawListener, ChipsView.OnChipClickListener, OnListItemClickListener<Bookmark>,
|
||||||
|
OnContextClickListenerCompat {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var shortcutManager: AppShortcutManager
|
lateinit var shortcutManager: AppShortcutManager
|
||||||
@@ -291,6 +293,8 @@ class DetailsActivity :
|
|||||||
startActivity(MangaListActivity.newIntent(this, tag.source, MangaListFilter(tags = setOf(tag))))
|
startActivity(MangaListActivity.newIntent(this, tag.source, MangaListFilter(tags = setOf(tag))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onContextClick(v: View): Boolean = onLongClick(v)
|
||||||
|
|
||||||
override fun onLongClick(v: View): Boolean = when (v.id) {
|
override fun onLongClick(v: View): Boolean = when (v.id) {
|
||||||
R.id.button_read -> {
|
R.id.button_read -> {
|
||||||
val menu = PopupMenu(v.context, v)
|
val menu = PopupMenu(v.context, v)
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ fun chapterGridItemAD(
|
|||||||
on = { item, _, _ -> item is ChapterListItem && item.isGrid },
|
on = { item, _, _ -> item is ChapterListItem && item.isGrid },
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val eventListener = AdapterDelegateClickListenerAdapter(this, clickListener)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
itemView.setOnClickListener(eventListener)
|
|
||||||
itemView.setOnLongClickListener(eventListener)
|
|
||||||
|
|
||||||
bind { payloads ->
|
bind { payloads ->
|
||||||
if (payloads.isEmpty()) {
|
if (payloads.isEmpty()) {
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ fun chapterListItemAD(
|
|||||||
on = { item, _, _ -> item is ChapterListItem && !item.isGrid },
|
on = { item, _, _ -> item is ChapterListItem && !item.isGrid },
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val eventListener = AdapterDelegateClickListenerAdapter(this, clickListener)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
itemView.setOnClickListener(eventListener)
|
|
||||||
itemView.setOnLongClickListener(eventListener)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.textViewTitle.text = item.chapter.name
|
binding.textViewTitle.text = item.chapter.name
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.details.ui.pager.bookmarks
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -133,7 +134,11 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: Bookmark, view: View): Boolean {
|
override fun onItemLongClick(item: Bookmark, view: View): Boolean {
|
||||||
return selectionController?.onItemLongClick(item.pageId) ?: false
|
return selectionController?.onItemLongClick(view, item.pageId) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: Bookmark, view: View): Boolean {
|
||||||
|
return selectionController?.onItemContextClick(view, item.pageId) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSelectionChanged(controller: ListSelectionController, count: Int) {
|
override fun onSelectionChanged(controller: ListSelectionController, count: Int) {
|
||||||
@@ -142,23 +147,23 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
|
|||||||
|
|
||||||
override fun onCreateActionMode(
|
override fun onCreateActionMode(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
menuInflater: MenuInflater,
|
||||||
menu: Menu,
|
menu: Menu,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
mode.menuInflater.inflate(R.menu.mode_bookmarks, menu)
|
menuInflater.inflate(R.menu.mode_bookmarks, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(
|
override fun onActionItemClicked(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
mode: ActionMode?,
|
||||||
item: MenuItem,
|
item: MenuItem,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_remove -> {
|
R.id.action_remove -> {
|
||||||
val ids = selectionController?.snapshot() ?: return false
|
val ids = selectionController?.snapshot() ?: return false
|
||||||
viewModel.removeBookmarks(ids)
|
viewModel.removeBookmarks(ids)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,11 @@ class ChaptersFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: ChapterListItem, view: View): Boolean {
|
override fun onItemLongClick(item: ChapterListItem, view: View): Boolean {
|
||||||
return selectionController?.onItemLongClick(item.chapter.id) ?: false
|
return selectionController?.onItemLongClick(view, item.chapter.id) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: ChapterListItem, view: View): Boolean {
|
||||||
|
return selectionController?.onItemContextClick(view, item.chapter.id) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onWindowInsetsChanged(insets: Insets) = Unit
|
override fun onWindowInsetsChanged(insets: Insets) = Unit
|
||||||
@@ -149,7 +153,7 @@ class ChaptersFragment :
|
|||||||
items?.indexOfFirst(predicate) ?: -1
|
items?.indexOfFirst(predicate) ?: -1
|
||||||
}
|
}
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
selectionController?.onItemLongClick(chapterId)
|
selectionController?.startSelection(chapterId)
|
||||||
val lm = (viewBinding?.recyclerViewChapters?.layoutManager as? LinearLayoutManager)
|
val lm = (viewBinding?.recyclerViewChapters?.layoutManager as? LinearLayoutManager)
|
||||||
if (lm != null) {
|
if (lm != null) {
|
||||||
val offset = resources.getDimensionPixelOffset(R.dimen.chapter_list_item_height)
|
val offset = resources.getDimensionPixelOffset(R.dimen.chapter_list_item_height)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.details.ui.pager.chapters
|
package org.koitharu.kotatsu.details.ui.pager.chapters
|
||||||
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@@ -19,12 +20,16 @@ class ChaptersSelectionCallback(
|
|||||||
recyclerView: RecyclerView,
|
recyclerView: RecyclerView,
|
||||||
) : BaseListSelectionCallback(recyclerView) {
|
) : BaseListSelectionCallback(recyclerView) {
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_chapters, menu)
|
controller: ListSelectionController,
|
||||||
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_chapters, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean {
|
||||||
val selectedIds = controller.peekCheckedIds()
|
val selectedIds = controller.peekCheckedIds()
|
||||||
val allItems = viewModel.chapters.value
|
val allItems = viewModel.chapters.value
|
||||||
val items = allItems.withIndex().filter { it.value.chapter.id in selectedIds }
|
val items = allItems.withIndex().filter { it.value.chapter.id in selectedIds }
|
||||||
@@ -38,7 +43,7 @@ class ChaptersSelectionCallback(
|
|||||||
menu.findItem(R.id.action_delete).isVisible = canDelete
|
menu.findItem(R.id.action_delete).isVisible = canDelete
|
||||||
menu.findItem(R.id.action_select_all).isVisible = items.size < allItems.size
|
menu.findItem(R.id.action_select_all).isVisible = items.size < allItems.size
|
||||||
menu.findItem(R.id.action_mark_current).isVisible = items.size == 1
|
menu.findItem(R.id.action_mark_current).isVisible = items.size == 1
|
||||||
mode.title = items.size.toString()
|
mode?.title = items.size.toString()
|
||||||
var hasGap = false
|
var hasGap = false
|
||||||
for (i in 0 until items.size - 1) {
|
for (i in 0 until items.size - 1) {
|
||||||
if (items[i].index + 1 != items[i + 1].index) {
|
if (items[i].index + 1 != items[i + 1].index) {
|
||||||
@@ -50,11 +55,11 @@ class ChaptersSelectionCallback(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_save -> {
|
R.id.action_save -> {
|
||||||
viewModel.download(controller.snapshot())
|
viewModel.download(controller.snapshot())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +78,7 @@ class ChaptersSelectionCallback(
|
|||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +117,7 @@ class ChaptersSelectionCallback(
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ fun pageThumbnailAD(
|
|||||||
height = (gridWidth / 13f * 18f).toInt(),
|
height = (gridWidth / 13f * 18f).toInt(),
|
||||||
)
|
)
|
||||||
|
|
||||||
val clickListenerAdapter = AdapterDelegateClickListenerAdapter(this, clickListener)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
binding.root.setOnClickListener(clickListenerAdapter)
|
|
||||||
binding.root.setOnLongClickListener(clickListenerAdapter)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
val data: Any = item.page.preview?.takeUnless { it.isEmpty() } ?: item.page.toMangaPage()
|
val data: Any = item.page.preview?.takeUnless { it.isEmpty() } ?: item.page.toMangaPage()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.details.ui.related
|
package org.koitharu.kotatsu.details.ui.related
|
||||||
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import androidx.appcompat.view.ActionMode
|
import android.view.MenuInflater
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
@@ -16,9 +16,13 @@ class RelatedListFragment : MangaListFragment() {
|
|||||||
|
|
||||||
override fun onScrolledToEnd() = Unit
|
override fun onScrolledToEnd() = Unit
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_remote, menu)
|
controller: ListSelectionController,
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_remote, menu)
|
||||||
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.download.ui.list
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
@@ -87,7 +88,11 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: DownloadItemModel, view: View): Boolean {
|
override fun onItemLongClick(item: DownloadItemModel, view: View): Boolean {
|
||||||
return selectionController.onItemLongClick(item.id.mostSignificantBits)
|
return selectionController.onItemLongClick(view, item.id.mostSignificantBits)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: DownloadItemModel, view: View): Boolean {
|
||||||
|
return selectionController.onItemContextClick(view, item.id.mostSignificantBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onExpandClick(item: DownloadItemModel) {
|
override fun onExpandClick(item: DownloadItemModel) {
|
||||||
@@ -120,34 +125,38 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
|
|||||||
viewBinding.recyclerView.invalidateItemDecorations()
|
viewBinding.recyclerView.invalidateItemDecorations()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_downloads, menu)
|
controller: ListSelectionController,
|
||||||
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_downloads, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_resume -> {
|
R.id.action_resume -> {
|
||||||
viewModel.resume(controller.snapshot())
|
viewModel.resume(controller.snapshot())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_pause -> {
|
R.id.action_pause -> {
|
||||||
viewModel.pause(controller.snapshot())
|
viewModel.pause(controller.snapshot())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_cancel -> {
|
R.id.action_cancel -> {
|
||||||
viewModel.cancel(controller.snapshot())
|
viewModel.cancel(controller.snapshot())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_remove -> {
|
R.id.action_remove -> {
|
||||||
viewModel.remove(controller.snapshot())
|
viewModel.remove(controller.snapshot())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +169,7 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean {
|
||||||
val snapshot = viewModel.snapshot(controller.peekCheckedIds())
|
val snapshot = viewModel.snapshot(controller.peekCheckedIds())
|
||||||
var canPause = true
|
var canPause = true
|
||||||
var canResume = true
|
var canResume = true
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -147,7 +148,11 @@ class ExploreFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: MangaSourceItem, view: View): Boolean {
|
override fun onItemLongClick(item: MangaSourceItem, view: View): Boolean {
|
||||||
return sourceSelectionController?.onItemLongClick(item.id) ?: false
|
return sourceSelectionController?.onItemLongClick(view, item.id) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: MangaSourceItem, view: View): Boolean {
|
||||||
|
return sourceSelectionController?.onItemContextClick(view, item.id) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRetryClick(error: Throwable) = Unit
|
override fun onRetryClick(error: Throwable) = Unit
|
||||||
@@ -160,12 +165,16 @@ class ExploreFragment :
|
|||||||
viewBinding?.recyclerView?.invalidateItemDecorations()
|
viewBinding?.recyclerView?.invalidateItemDecorations()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_source, menu)
|
controller: ListSelectionController,
|
||||||
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_source, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean {
|
||||||
val selectedSources = viewModel.sourcesSnapshot(controller.peekCheckedIds())
|
val selectedSources = viewModel.sourcesSnapshot(controller.peekCheckedIds())
|
||||||
val isSingleSelection = selectedSources.size == 1
|
val isSingleSelection = selectedSources.size == 1
|
||||||
menu.findItem(R.id.action_settings).isVisible = isSingleSelection
|
menu.findItem(R.id.action_settings).isVisible = isSingleSelection
|
||||||
@@ -177,7 +186,7 @@ class ExploreFragment :
|
|||||||
return super.onPrepareActionMode(controller, mode, menu)
|
return super.onPrepareActionMode(controller, mode, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
val selectedSources = viewModel.sourcesSnapshot(controller.peekCheckedIds())
|
val selectedSources = viewModel.sourcesSnapshot(controller.peekCheckedIds())
|
||||||
if (selectedSources.isEmpty()) {
|
if (selectedSources.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
@@ -186,35 +195,35 @@ class ExploreFragment :
|
|||||||
R.id.action_settings -> {
|
R.id.action_settings -> {
|
||||||
val source = selectedSources.singleOrNull() ?: return false
|
val source = selectedSources.singleOrNull() ?: return false
|
||||||
startActivity(SettingsActivity.newSourceSettingsIntent(requireContext(), source))
|
startActivity(SettingsActivity.newSourceSettingsIntent(requireContext(), source))
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_disable -> {
|
R.id.action_disable -> {
|
||||||
viewModel.disableSources(selectedSources)
|
viewModel.disableSources(selectedSources)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_delete -> {
|
R.id.action_delete -> {
|
||||||
selectedSources.forEach {
|
selectedSources.forEach {
|
||||||
(it.mangaSource as? ExternalMangaSource)?.let { uninstallExternalSource(it) }
|
(it.mangaSource as? ExternalMangaSource)?.let { uninstallExternalSource(it) }
|
||||||
}
|
}
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_shortcut -> {
|
R.id.action_shortcut -> {
|
||||||
val source = selectedSources.singleOrNull() ?: return false
|
val source = selectedSources.singleOrNull() ?: return false
|
||||||
viewModel.requestPinShortcut(source)
|
viewModel.requestPinShortcut(source)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_pin -> {
|
R.id.action_pin -> {
|
||||||
viewModel.setSourcesPinned(selectedSources, isPinned = true)
|
viewModel.setSourcesPinned(selectedSources, isPinned = true)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_unpin -> {
|
R.id.action_unpin -> {
|
||||||
viewModel.setSourcesPinned(selectedSources, isPinned = false)
|
viewModel.setSourcesPinned(selectedSources, isPinned = false)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return false
|
else -> return false
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.koitharu.kotatsu.core.util.ext.drawableStart
|
|||||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||||
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
||||||
import org.koitharu.kotatsu.core.util.ext.recyclerView
|
import org.koitharu.kotatsu.core.util.ext.recyclerView
|
||||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.setProgressIcon
|
import org.koitharu.kotatsu.core.util.ext.setProgressIcon
|
||||||
import org.koitharu.kotatsu.core.util.ext.source
|
import org.koitharu.kotatsu.core.util.ext.source
|
||||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||||
@@ -117,13 +116,9 @@ fun exploreSourceListItemAD(
|
|||||||
on = { item, _, _ -> item is MangaSourceItem && !item.isGrid },
|
on = { item, _, _ -> item is MangaSourceItem && !item.isGrid },
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val eventListener = AdapterDelegateClickListenerAdapter(this, listener)
|
AdapterDelegateClickListenerAdapter(this, listener).attach(itemView)
|
||||||
val iconPinned = ContextCompat.getDrawable(context, R.drawable.ic_pin_small)
|
val iconPinned = ContextCompat.getDrawable(context, R.drawable.ic_pin_small)
|
||||||
|
|
||||||
binding.root.setOnClickListener(eventListener)
|
|
||||||
binding.root.setOnLongClickListener(eventListener)
|
|
||||||
binding.root.setOnContextClickListenerCompat(eventListener)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.textViewTitle.text = item.source.getTitle(context)
|
binding.textViewTitle.text = item.source.getTitle(context)
|
||||||
binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null
|
binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null
|
||||||
@@ -154,13 +149,9 @@ fun exploreSourceGridItemAD(
|
|||||||
on = { item, _, _ -> item is MangaSourceItem && item.isGrid },
|
on = { item, _, _ -> item is MangaSourceItem && item.isGrid },
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val eventListener = AdapterDelegateClickListenerAdapter(this, listener)
|
AdapterDelegateClickListenerAdapter(this, listener).attach(itemView)
|
||||||
val iconPinned = ContextCompat.getDrawable(context, R.drawable.ic_pin_small)
|
val iconPinned = ContextCompat.getDrawable(context, R.drawable.ic_pin_small)
|
||||||
|
|
||||||
binding.root.setOnClickListener(eventListener)
|
|
||||||
binding.root.setOnLongClickListener(eventListener)
|
|
||||||
binding.root.setOnContextClickListenerCompat(eventListener)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.textViewTitle.text = item.source.getTitle(context)
|
binding.textViewTitle.text = item.source.getTitle(context)
|
||||||
binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null
|
binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.favourites.ui.categories
|
package org.koitharu.kotatsu.favourites.ui.categories
|
||||||
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@@ -17,12 +18,16 @@ class CategoriesSelectionCallback(
|
|||||||
recyclerView.invalidateItemDecorations()
|
recyclerView.invalidateItemDecorations()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_category, menu)
|
controller: ListSelectionController,
|
||||||
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_category, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean {
|
||||||
val categories = viewModel.getCategories(controller.peekCheckedIds())
|
val categories = viewModel.getCategories(controller.peekCheckedIds())
|
||||||
var canShow = categories.isNotEmpty()
|
var canShow = categories.isNotEmpty()
|
||||||
var canHide = canShow
|
var canHide = canShow
|
||||||
@@ -35,11 +40,11 @@ class CategoriesSelectionCallback(
|
|||||||
}
|
}
|
||||||
menu.findItem(R.id.action_show)?.isVisible = canShow
|
menu.findItem(R.id.action_show)?.isVisible = canShow
|
||||||
menu.findItem(R.id.action_hide)?.isVisible = canHide
|
menu.findItem(R.id.action_hide)?.isVisible = canHide
|
||||||
mode.title = controller.count.toString()
|
mode?.title = controller.count.toString()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
/*R.id.action_view -> {
|
/*R.id.action_view -> {
|
||||||
val id = controller.peekCheckedIds().singleOrNull() ?: return false
|
val id = controller.peekCheckedIds().singleOrNull() ?: return false
|
||||||
@@ -53,13 +58,13 @@ class CategoriesSelectionCallback(
|
|||||||
|
|
||||||
R.id.action_show -> {
|
R.id.action_show -> {
|
||||||
viewModel.setIsVisible(controller.snapshot(), true)
|
viewModel.setIsVisible(controller.snapshot(), true)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_hide -> {
|
R.id.action_hide -> {
|
||||||
viewModel.setIsVisible(controller.snapshot(), false)
|
viewModel.setIsVisible(controller.snapshot(), false)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +77,7 @@ class CategoriesSelectionCallback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode) {
|
private fun confirmDeleteCategories(ids: Set<Long>, mode: ActionMode?) {
|
||||||
buildAlertDialog(recyclerView.context, isCentered = true) {
|
buildAlertDialog(recyclerView.context, isCentered = true) {
|
||||||
setMessage(R.string.categories_delete_confirm)
|
setMessage(R.string.categories_delete_confirm)
|
||||||
setTitle(R.string.remove_category)
|
setTitle(R.string.remove_category)
|
||||||
@@ -80,7 +85,7 @@ class CategoriesSelectionCallback(
|
|||||||
setNegativeButton(android.R.string.cancel, null)
|
setNegativeButton(android.R.string.cancel, null)
|
||||||
setPositiveButton(R.string.remove) { _, _ ->
|
setPositiveButton(R.string.remove) { _, _ ->
|
||||||
viewModel.deleteCategories(ids)
|
viewModel.deleteCategories(ids)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,11 @@ class FavouriteCategoriesActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: FavouriteCategory?, view: View): Boolean {
|
override fun onItemLongClick(item: FavouriteCategory?, view: View): Boolean {
|
||||||
return item != null && selectionController.onItemLongClick(item.id)
|
return item != null && selectionController.onItemLongClick(view, item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: FavouriteCategory?, view: View): Boolean {
|
||||||
|
return item != null && selectionController.onItemContextClick(view, item.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSupportActionModeStarted(mode: ActionMode) {
|
override fun onSupportActionModeStarted(mode: ActionMode) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.favourites.ui.list
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
@@ -52,27 +53,32 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_favourites, menu)
|
controller: ListSelectionController,
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_favourites, menu)
|
||||||
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_remove -> {
|
R.id.action_remove -> {
|
||||||
viewModel.removeFromFavourites(selectedItemsIds)
|
viewModel.removeFromFavourites(selectedItemsIds)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_mark_current -> {
|
R.id.action_mark_current -> {
|
||||||
|
val itemsSnapshot = selectedItems
|
||||||
MaterialAlertDialogBuilder(context ?: return false)
|
MaterialAlertDialogBuilder(context ?: return false)
|
||||||
.setTitle(item.title)
|
.setTitle(item.title)
|
||||||
.setMessage(R.string.mark_as_completed_prompt)
|
.setMessage(R.string.mark_as_completed_prompt)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
viewModel.markAsRead(selectedItems)
|
viewModel.markAsRead(itemsSnapshot)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}.show()
|
}.show()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.history.ui
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
@@ -34,28 +35,33 @@ class HistoryListFragment : MangaListFragment() {
|
|||||||
|
|
||||||
override fun onEmptyActionClick() = viewModel.clearFilter()
|
override fun onEmptyActionClick() = viewModel.clearFilter()
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_history, menu)
|
controller: ListSelectionController,
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_history, menu)
|
||||||
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_remove -> {
|
R.id.action_remove -> {
|
||||||
viewModel.removeFromHistory(selectedItemsIds)
|
viewModel.removeFromHistory(selectedItemsIds)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_mark_current -> {
|
R.id.action_mark_current -> {
|
||||||
|
val itemsSnapshot = selectedItems
|
||||||
buildAlertDialog(context ?: return false, isCentered = true) {
|
buildAlertDialog(context ?: return false, isCentered = true) {
|
||||||
setTitle(item.title)
|
setTitle(item.title)
|
||||||
setIcon(item.icon)
|
setIcon(item.icon)
|
||||||
setMessage(R.string.mark_as_completed_prompt)
|
setMessage(R.string.mark_as_completed_prompt)
|
||||||
setNegativeButton(android.R.string.cancel, null)
|
setNegativeButton(android.R.string.cancel, null)
|
||||||
setPositiveButton(android.R.string.ok) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
viewModel.markAsRead(selectedItems)
|
viewModel.markAsRead(itemsSnapshot)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.list.ui
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -11,7 +12,6 @@ import androidx.annotation.CallSuper
|
|||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.collection.ArraySet
|
import androidx.collection.ArraySet
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.isNotEmpty
|
|
||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
@@ -153,7 +153,11 @@ abstract class MangaListFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: Manga, view: View): Boolean {
|
override fun onItemLongClick(item: Manga, view: View): Boolean {
|
||||||
return selectionController?.onItemLongClick(item.id) ?: false
|
return selectionController?.onItemLongClick(view, item.id) ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: Manga, view: View): Boolean {
|
||||||
|
return selectionController?.onItemContextClick(view, item.id) ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReadClick(manga: Manga, view: View) {
|
override fun onReadClick(manga: Manga, view: View) {
|
||||||
@@ -280,18 +284,22 @@ abstract class MangaListFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean {
|
||||||
val hasNoLocal = selectedItems.none { it.isLocal }
|
val hasNoLocal = selectedItems.none { it.isLocal }
|
||||||
menu.findItem(R.id.action_save)?.isVisible = hasNoLocal
|
menu.findItem(R.id.action_save)?.isVisible = hasNoLocal
|
||||||
menu.findItem(R.id.action_fix)?.isVisible = hasNoLocal
|
menu.findItem(R.id.action_fix)?.isVisible = hasNoLocal
|
||||||
return super.onPrepareActionMode(controller, mode, menu)
|
return super.onPrepareActionMode(controller, mode, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
return menu.isNotEmpty()
|
controller: ListSelectionController,
|
||||||
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
return menu.hasVisibleItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_select_all -> {
|
R.id.action_select_all -> {
|
||||||
val ids = listAdapter?.items?.mapNotNull {
|
val ids = listAdapter?.items?.mapNotNull {
|
||||||
@@ -303,31 +311,32 @@ abstract class MangaListFragment :
|
|||||||
|
|
||||||
R.id.action_share -> {
|
R.id.action_share -> {
|
||||||
ShareHelper(requireContext()).shareMangaLinks(selectedItems)
|
ShareHelper(requireContext()).shareMangaLinks(selectedItems)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_favourite -> {
|
R.id.action_favourite -> {
|
||||||
FavoriteSheet.show(getChildFragmentManager(), selectedItems)
|
FavoriteSheet.show(getChildFragmentManager(), selectedItems)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_save -> {
|
R.id.action_save -> {
|
||||||
viewModel.download(selectedItems)
|
viewModel.download(selectedItems)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_fix -> {
|
R.id.action_fix -> {
|
||||||
|
val itemsSnapshot = selectedItemsIds
|
||||||
buildAlertDialog(context ?: return false, isCentered = true) {
|
buildAlertDialog(context ?: return false, isCentered = true) {
|
||||||
setTitle(item.title)
|
setTitle(item.title)
|
||||||
setIcon(item.icon)
|
setIcon(item.icon)
|
||||||
setMessage(R.string.manga_fix_prompt)
|
setMessage(R.string.manga_fix_prompt)
|
||||||
setNegativeButton(android.R.string.cancel, null)
|
setNegativeButton(android.R.string.cancel, null)
|
||||||
setPositiveButton(R.string.fix) { _, _ ->
|
setPositiveButton(R.string.fix) { _, _ ->
|
||||||
AutoFixService.start(context, selectedItemsIds)
|
AutoFixService.start(context, itemsSnapshot)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
}.show()
|
}.show()
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.koitharu.kotatsu.list.ui.adapter
|
package org.koitharu.kotatsu.list.ui.adapter
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
@@ -8,11 +7,11 @@ import com.google.android.material.badge.BadgeDrawable
|
|||||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||||
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
||||||
|
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
|
||||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
|
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
|
||||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||||
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
||||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.source
|
import org.koitharu.kotatsu.core.util.ext.source
|
||||||
import org.koitharu.kotatsu.databinding.ItemMangaGridBinding
|
import org.koitharu.kotatsu.databinding.ItemMangaGridBinding
|
||||||
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_PROGRESS_CHANGED
|
import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_PROGRESS_CHANGED
|
||||||
@@ -31,13 +30,7 @@ fun mangaGridItemAD(
|
|||||||
) {
|
) {
|
||||||
var badge: BadgeDrawable? = null
|
var badge: BadgeDrawable? = null
|
||||||
|
|
||||||
val eventListener = object : View.OnClickListener, View.OnLongClickListener {
|
AdapterDelegateClickListenerAdapter(this, clickListener, MangaGridModel::manga).attach(itemView)
|
||||||
override fun onClick(v: View) = clickListener.onItemClick(item.manga, v)
|
|
||||||
override fun onLongClick(v: View): Boolean = clickListener.onItemLongClick(item.manga, v)
|
|
||||||
}
|
|
||||||
itemView.setOnClickListener(eventListener)
|
|
||||||
itemView.setOnLongClickListener(eventListener)
|
|
||||||
itemView.setOnContextClickListenerCompat(eventListener)
|
|
||||||
sizeResolver.attachToView(lifecycleOwner, itemView, binding.textViewTitle, binding.progressView)
|
sizeResolver.attachToView(lifecycleOwner, itemView, binding.textViewTitle, binding.progressView)
|
||||||
|
|
||||||
bind { payloads ->
|
bind { payloads ->
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package org.koitharu.kotatsu.list.ui.adapter
|
package org.koitharu.kotatsu.list.ui.adapter
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.badge.BadgeDrawable
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||||
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
||||||
|
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
|
||||||
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
|
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
|
||||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||||
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
||||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.source
|
import org.koitharu.kotatsu.core.util.ext.source
|
||||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||||
import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding
|
import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding
|
||||||
@@ -27,14 +26,7 @@ fun mangaListDetailedItemAD(
|
|||||||
) {
|
) {
|
||||||
var badge: BadgeDrawable? = null
|
var badge: BadgeDrawable? = null
|
||||||
|
|
||||||
val listenerAdapter = object : View.OnClickListener, View.OnLongClickListener {
|
AdapterDelegateClickListenerAdapter(this, clickListener, MangaDetailedListModel::manga).attach(itemView)
|
||||||
override fun onClick(v: View) = clickListener.onItemClick(item.manga, v)
|
|
||||||
|
|
||||||
override fun onLongClick(v: View): Boolean = clickListener.onItemLongClick(item.manga, v)
|
|
||||||
}
|
|
||||||
itemView.setOnClickListener(listenerAdapter)
|
|
||||||
itemView.setOnLongClickListener(listenerAdapter)
|
|
||||||
itemView.setOnContextClickListenerCompat(listenerAdapter)
|
|
||||||
|
|
||||||
bind { payloads ->
|
bind { payloads ->
|
||||||
binding.textViewTitle.text = item.title
|
binding.textViewTitle.text = item.title
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
package org.koitharu.kotatsu.list.ui.adapter
|
package org.koitharu.kotatsu.list.ui.adapter
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.badge.BadgeDrawable
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
import org.koitharu.kotatsu.core.ui.image.TrimTransformation
|
||||||
|
import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter
|
||||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
|
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
|
||||||
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
import org.koitharu.kotatsu.core.util.ext.enqueueWith
|
||||||
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
import org.koitharu.kotatsu.core.util.ext.newImageRequest
|
||||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.source
|
import org.koitharu.kotatsu.core.util.ext.source
|
||||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||||
import org.koitharu.kotatsu.databinding.ItemMangaListBinding
|
import org.koitharu.kotatsu.databinding.ItemMangaListBinding
|
||||||
@@ -27,13 +26,7 @@ fun mangaListItemAD(
|
|||||||
) {
|
) {
|
||||||
var badge: BadgeDrawable? = null
|
var badge: BadgeDrawable? = null
|
||||||
|
|
||||||
val eventListener = object : View.OnClickListener, View.OnLongClickListener {
|
AdapterDelegateClickListenerAdapter(this, clickListener, MangaCompactListModel::manga).attach(itemView)
|
||||||
override fun onClick(v: View) = clickListener.onItemClick(item.manga, v)
|
|
||||||
override fun onLongClick(v: View): Boolean = clickListener.onItemLongClick(item.manga, v)
|
|
||||||
}
|
|
||||||
itemView.setOnClickListener(eventListener)
|
|
||||||
itemView.setOnLongClickListener(eventListener)
|
|
||||||
itemView.setOnContextClickListenerCompat(eventListener)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.textViewTitle.text = item.title
|
binding.textViewTitle.text = item.title
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.Manifest
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
@@ -88,16 +89,16 @@ class LocalListFragment : MangaListFragment(), FilterCoordinator.Owner {
|
|||||||
|
|
||||||
override fun onCreateActionMode(
|
override fun onCreateActionMode(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
menuInflater: MenuInflater,
|
||||||
menu: Menu,
|
menu: Menu,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
mode.menuInflater.inflate(R.menu.mode_local, menu)
|
menuInflater.inflate(R.menu.mode_local, menu)
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(
|
override fun onActionItemClicked(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
mode: ActionMode?,
|
||||||
item: MenuItem,
|
item: MenuItem,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
@@ -109,7 +110,7 @@ class LocalListFragment : MangaListFragment(), FilterCoordinator.Owner {
|
|||||||
R.id.action_share -> {
|
R.id.action_share -> {
|
||||||
val files = selectedItems.map { it.url.toUri().toFile() }
|
val files = selectedItems.map { it.url.toUri().toFile() }
|
||||||
ShareHelper(requireContext()).shareCbz(files)
|
ShareHelper(requireContext()).shareCbz(files)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,13 +118,13 @@ class LocalListFragment : MangaListFragment(), FilterCoordinator.Owner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showDeletionConfirm(ids: Set<Long>, mode: ActionMode) {
|
private fun showDeletionConfirm(ids: Set<Long>, mode: ActionMode?) {
|
||||||
MaterialAlertDialogBuilder(context ?: return)
|
MaterialAlertDialogBuilder(context ?: return)
|
||||||
.setTitle(R.string.delete_manga)
|
.setTitle(R.string.delete_manga)
|
||||||
.setMessage(getString(R.string.text_delete_local_manga_batch))
|
.setMessage(getString(R.string.text_delete_local_manga_batch))
|
||||||
.setPositiveButton(R.string.delete) { _, _ ->
|
.setPositiveButton(R.string.delete) { _, _ ->
|
||||||
viewModel.delete(ids)
|
viewModel.delete(ids)
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
}
|
}
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.show()
|
.show()
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.view.Menu
|
|||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.view.ActionMode
|
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
@@ -56,9 +55,13 @@ class RemoteListFragment : MangaListFragment(), FilterCoordinator.Owner {
|
|||||||
viewModel.loadNextPage()
|
viewModel.loadNextPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_remote, menu)
|
controller: ListSelectionController,
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_remote, menu)
|
||||||
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFilterClick(view: View?) {
|
override fun onFilterClick(view: View?) {
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ fun scrobblingMangaAD(
|
|||||||
{ layoutInflater, parent -> ItemScrobblingMangaBinding.inflate(layoutInflater, parent, false) },
|
{ layoutInflater, parent -> ItemScrobblingMangaBinding.inflate(layoutInflater, parent, false) },
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val clickListenerAdapter = AdapterDelegateClickListenerAdapter(this, clickListener)
|
AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView)
|
||||||
itemView.setOnClickListener(clickListenerAdapter)
|
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.imageViewCover.newImageRequest(lifecycleOwner, item.coverUrl)?.run {
|
binding.imageViewCover.newImageRequest(lifecycleOwner, item.coverUrl)?.run {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
@@ -118,7 +119,11 @@ class SearchActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemLongClick(item: Manga, view: View): Boolean {
|
override fun onItemLongClick(item: Manga, view: View): Boolean {
|
||||||
return selectionController.onItemLongClick(item.id)
|
return selectionController.onItemLongClick(view, item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemContextClick(item: Manga, view: View): Boolean {
|
||||||
|
return selectionController.onItemContextClick(view, item.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReadClick(manga: Manga, view: View) {
|
override fun onReadClick(manga: Manga, view: View) {
|
||||||
@@ -155,28 +160,32 @@ class SearchActivity :
|
|||||||
viewBinding.recyclerView.invalidateNestedItemDecorations()
|
viewBinding.recyclerView.invalidateNestedItemDecorations()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_remote, menu)
|
controller: ListSelectionController,
|
||||||
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_remote, menu)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_share -> {
|
R.id.action_share -> {
|
||||||
ShareHelper(this).shareMangaLinks(collectSelectedItems())
|
ShareHelper(this).shareMangaLinks(collectSelectedItems())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_favourite -> {
|
R.id.action_favourite -> {
|
||||||
FavoriteSheet.show(supportFragmentManager, collectSelectedItems())
|
FavoriteSheet.show(supportFragmentManager, collectSelectedItems())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.action_save -> {
|
R.id.action_save -> {
|
||||||
viewModel.download(collectSelectedItems())
|
viewModel.download(collectSelectedItems())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.os.Bundle
|
|||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.view.ActionMode
|
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
@@ -29,11 +28,11 @@ class SuggestionsFragment : MangaListFragment() {
|
|||||||
|
|
||||||
override fun onCreateActionMode(
|
override fun onCreateActionMode(
|
||||||
controller: ListSelectionController,
|
controller: ListSelectionController,
|
||||||
mode: ActionMode,
|
menuInflater: MenuInflater,
|
||||||
menu: Menu,
|
menu: Menu,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
mode.menuInflater.inflate(R.menu.mode_remote, menu)
|
menuInflater.inflate(R.menu.mode_remote, menu)
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class SuggestionMenuProvider : MenuProvider {
|
private inner class SuggestionMenuProvider : MenuProvider {
|
||||||
@@ -71,10 +70,11 @@ class SuggestionsFragment : MangaListFragment() {
|
|||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"", ReplaceWith(
|
"",
|
||||||
|
ReplaceWith(
|
||||||
"SuggestionsFragment()",
|
"SuggestionsFragment()",
|
||||||
"org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment"
|
"org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
fun newInstance() = SuggestionsFragment()
|
fun newInstance() = SuggestionsFragment()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ class FeedFragment :
|
|||||||
onItemClick(item.manga, v)
|
onItemClick(item.manga, v)
|
||||||
}
|
}
|
||||||
with(binding.recyclerView) {
|
with(binding.recyclerView) {
|
||||||
|
val paddingVertical = resources.getDimensionPixelSize(R.dimen.list_spacing_normal)
|
||||||
|
setPadding(0, paddingVertical, 0, paddingVertical)
|
||||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
||||||
adapter = feedAdapter
|
adapter = feedAdapter
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.tracker.ui.updates
|
package org.koitharu.kotatsu.tracker.ui.updates
|
||||||
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
@@ -17,16 +18,20 @@ class UpdatesFragment : MangaListFragment() {
|
|||||||
|
|
||||||
override fun onScrolledToEnd() = Unit
|
override fun onScrolledToEnd() = Unit
|
||||||
|
|
||||||
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
|
override fun onCreateActionMode(
|
||||||
mode.menuInflater.inflate(R.menu.mode_updates, menu)
|
controller: ListSelectionController,
|
||||||
return super.onCreateActionMode(controller, mode, menu)
|
menuInflater: MenuInflater,
|
||||||
|
menu: Menu
|
||||||
|
): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.mode_updates, menu)
|
||||||
|
return super.onCreateActionMode(controller, menuInflater, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean {
|
override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode?, item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.action_remove -> {
|
R.id.action_remove -> {
|
||||||
viewModel.remove(controller.snapshot())
|
viewModel.remove(controller.snapshot())
|
||||||
mode.finish()
|
mode?.finish()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user