diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/AllBookmarksFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/AllBookmarksFragment.kt index 7f2f5f762..3a0182c70 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/AllBookmarksFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/AllBookmarksFragment.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.bookmarks.ui import android.os.Bundle import android.view.LayoutInflater import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -129,7 +130,11 @@ class AllBookmarksFragment : } 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 @@ -148,23 +153,23 @@ class AllBookmarksFragment : override fun onCreateActionMode( controller: ListSelectionController, - mode: ActionMode, + menuInflater: MenuInflater, menu: Menu, ): Boolean { - mode.menuInflater.inflate(R.menu.mode_bookmarks, menu) + menuInflater.inflate(R.menu.mode_bookmarks, menu) return true } override fun onActionItemClicked( controller: ListSelectionController, - mode: ActionMode, + mode: ActionMode?, item: MenuItem, ): Boolean { return when (item.itemId) { R.id.action_remove -> { val ids = selectionController?.snapshot() ?: return false viewModel.removeBookmarks(ids) - mode.finish() + mode?.finish() true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkLargeAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkLargeAD.kt index bdbd35ef0..00c0f6a2e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkLargeAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkLargeAD.kt @@ -22,10 +22,7 @@ fun bookmarkLargeAD( ) = adapterDelegateViewBinding( { inflater, parent -> ItemBookmarkLargeBinding.inflate(inflater, parent, false) }, ) { - val listener = AdapterDelegateClickListenerAdapter(this, clickListener) - - binding.root.setOnClickListener(listener) - binding.root.setOnLongClickListener(listener) + AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView) bind { binding.imageViewThumb.newImageRequest(lifecycleOwner, item.imageLoadData)?.run { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt index e86073cb1..065bf84dc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/bookmarks/ui/adapter/BookmarkListAD.kt @@ -21,10 +21,7 @@ fun bookmarkListAD( ) = adapterDelegateViewBinding( { inflater, parent -> ItemBookmarkBinding.inflate(inflater, parent, false) }, ) { - val listener = AdapterDelegateClickListenerAdapter(this, clickListener) - - binding.root.setOnClickListener(listener) - binding.root.setOnLongClickListener(listener) + AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView) bind { binding.imageViewThumb.newImageRequest(lifecycleOwner, item.imageLoadData)?.run { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/OnContextClickListenerCompat.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/OnContextClickListenerCompat.kt new file mode 100644 index 000000000..c53d0f71a --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/OnContextClickListenerCompat.kt @@ -0,0 +1,8 @@ +package org.koitharu.kotatsu.core.ui + +import android.view.View + +fun interface OnContextClickListenerCompat { + + fun onContextClick(v: View): Boolean +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt index a9e6e13ea..fd8d865f8 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/AdapterDelegateClickListenerAdapter.kt @@ -3,18 +3,46 @@ package org.koitharu.kotatsu.core.ui.list import android.view.View import android.view.View.OnClickListener import android.view.View.OnLongClickListener +import androidx.core.util.Function import com.hannesdorfmann.adapterdelegates4.dsl.AdapterDelegateViewBindingViewHolder +import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat +import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat -class AdapterDelegateClickListenerAdapter( +class AdapterDelegateClickListenerAdapter( private val adapterDelegate: AdapterDelegateViewBindingViewHolder, - private val clickListener: OnListItemClickListener, -) : OnClickListener, OnLongClickListener { + private val clickListener: OnListItemClickListener, + private val itemMapper: Function, +) : OnClickListener, OnLongClickListener, OnContextClickListenerCompat { override fun onClick(v: View) { - clickListener.onItemClick(adapterDelegate.item, v) + clickListener.onItemClick(mappedItem(), v) } 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 invoke( + adapterDelegate: AdapterDelegateViewBindingViewHolder, + clickListener: OnListItemClickListener + ): AdapterDelegateClickListenerAdapter = AdapterDelegateClickListenerAdapter( + adapterDelegate = adapterDelegate, + clickListener = clickListener, + itemMapper = { x -> x }, + ) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt index 94ce689dc..9d834ef84 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/ListSelectionController.kt @@ -2,10 +2,14 @@ package org.koitharu.kotatsu.core.ui.list import android.os.Bundle import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem +import android.view.View import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.view.ActionMode +import androidx.appcompat.widget.PopupMenu import androidx.collection.LongSet +import androidx.collection.longSetOf import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleOwner @@ -29,18 +33,21 @@ class ListSelectionController( ) : ActionMode.Callback, SavedStateRegistry.SavedStateProvider { private var actionMode: ActionMode? = null + private var focusedItemId: LongSet? = null + + var useActionMode: Boolean = true val count: Int - get() = decoration.checkedItemsCount + get() = if (focusedItemId != null) 1 else decoration.checkedItemsCount init { registryOwner.lifecycle.addObserver(StateEventObserver()) } - fun snapshot(): Set = peekCheckedIds().toSet() + fun snapshot(): Set = (focusedItemId ?: peekCheckedIds()).toSet() fun peekCheckedIds(): LongSet { - return decoration.checkedItemsIds + return focusedItemId ?: decoration.checkedItemsIds } fun clear() { @@ -52,6 +59,7 @@ class ListSelectionController( if (ids.isEmpty()) { return } + startActionMode() decoration.checkAll(ids) notifySelectionChanged() } @@ -80,15 +88,42 @@ class ListSelectionController( return false } - fun onItemLongClick(id: Long): Boolean { - return startActionMode()?.also { - decoration.setItemIsChecked(id, true) - notifySelectionChanged() - } != null + fun onItemLongClick(view: View, id: Long): Boolean { + return if (useActionMode) { + startSelection(id) + } else { + 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 { - return callback.onCreateActionMode(this, mode, menu) + return callback.onCreateActionMode(this, mode.menuInflater, menu) } override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { @@ -106,6 +141,7 @@ class ListSelectionController( } private fun startActionMode(): ActionMode? { + focusedItemId = null return actionMode ?: appCompatDelegate.startSupportActionMode(this).also { actionMode = it } @@ -134,14 +170,14 @@ class ListSelectionController( 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 { - mode.title = controller.count.toString() + fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode?, menu: Menu): Boolean { + mode?.title = controller.count.toString() 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 } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt index e394740b9..26df0cb21 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/list/OnListItemClickListener.kt @@ -6,5 +6,7 @@ fun interface OnListItemClickListener { 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) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/PopupMenuMediator.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/PopupMenuMediator.kt index 558931d3a..22bbdac14 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/PopupMenuMediator.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/util/PopupMenuMediator.kt @@ -4,11 +4,15 @@ import android.view.MenuItem import android.view.View import androidx.appcompat.widget.PopupMenu import androidx.core.view.MenuProvider +import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat class PopupMenuMediator( 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 { val menu = PopupMenu(v.context, v) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/View.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/View.kt index 82091bee9..1b0afb72a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/View.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/View.kt @@ -21,6 +21,7 @@ import com.google.android.material.progressindicator.BaseProgressIndicator import com.google.android.material.slider.RangeSlider import com.google.android.material.slider.Slider import com.google.android.material.tabs.TabLayout +import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat import kotlin.math.roundToInt 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) { - setOnContextClickListener(listener::onLongClick) + setOnContextClickListener(listener::onContextClick) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt index 6a3dfab94..951c479db 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/DetailsActivity.kt @@ -54,6 +54,7 @@ import org.koitharu.kotatsu.core.parser.MangaIntent import org.koitharu.kotatsu.core.parser.favicon.faviconUri import org.koitharu.kotatsu.core.ui.BaseActivity 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.CoverSizeResolver import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener @@ -114,7 +115,8 @@ class DetailsActivity : BaseActivity(), View.OnClickListener, View.OnLongClickListener, PopupMenu.OnMenuItemClickListener, View.OnLayoutChangeListener, - ViewTreeObserver.OnDrawListener, ChipsView.OnChipClickListener, OnListItemClickListener { + ViewTreeObserver.OnDrawListener, ChipsView.OnChipClickListener, OnListItemClickListener, + OnContextClickListenerCompat { @Inject lateinit var shortcutManager: AppShortcutManager @@ -291,6 +293,8 @@ class DetailsActivity : 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) { R.id.button_read -> { val menu = PopupMenu(v.context, v) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt index 7ee67d92d..5cb2d5794 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt @@ -18,9 +18,7 @@ fun chapterGridItemAD( on = { item, _, _ -> item is ChapterListItem && item.isGrid }, ) { - val eventListener = AdapterDelegateClickListenerAdapter(this, clickListener) - itemView.setOnClickListener(eventListener) - itemView.setOnLongClickListener(eventListener) + AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView) bind { payloads -> if (payloads.isEmpty()) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt index 5be9aff8c..8d6275875 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterListItemAD.kt @@ -22,9 +22,7 @@ fun chapterListItemAD( on = { item, _, _ -> item is ChapterListItem && !item.isGrid }, ) { - val eventListener = AdapterDelegateClickListenerAdapter(this, clickListener) - itemView.setOnClickListener(eventListener) - itemView.setOnLongClickListener(eventListener) + AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView) bind { binding.textViewTitle.text = item.chapter.name diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/bookmarks/BookmarksFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/bookmarks/BookmarksFragment.kt index 8da855d10..faa8c4069 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/bookmarks/BookmarksFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/bookmarks/BookmarksFragment.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.details.ui.pager.bookmarks import android.os.Bundle import android.view.LayoutInflater import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -133,7 +134,11 @@ class BookmarksFragment : BaseFragment(), } 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) { @@ -142,23 +147,23 @@ class BookmarksFragment : BaseFragment(), override fun onCreateActionMode( controller: ListSelectionController, - mode: ActionMode, + menuInflater: MenuInflater, menu: Menu, ): Boolean { - mode.menuInflater.inflate(R.menu.mode_bookmarks, menu) + menuInflater.inflate(R.menu.mode_bookmarks, menu) return true } override fun onActionItemClicked( controller: ListSelectionController, - mode: ActionMode, + mode: ActionMode?, item: MenuItem, ): Boolean { return when (item.itemId) { R.id.action_remove -> { val ids = selectionController?.snapshot() ?: return false viewModel.removeBookmarks(ids) - mode.finish() + mode?.finish() true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt index 4aa3b5295..de808b1b4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt @@ -116,7 +116,11 @@ class ChaptersFragment : } 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 @@ -149,7 +153,7 @@ class ChaptersFragment : items?.indexOfFirst(predicate) ?: -1 } if (position >= 0) { - selectionController?.onItemLongClick(chapterId) + selectionController?.startSelection(chapterId) val lm = (viewBinding?.recyclerViewChapters?.layoutManager as? LinearLayoutManager) if (lm != null) { val offset = resources.getDimensionPixelOffset(R.dimen.chapter_list_item_height) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersSelectionCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersSelectionCallback.kt index 46b9fdf78..a5cb76c3c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersSelectionCallback.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersSelectionCallback.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.details.ui.pager.chapters import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import androidx.appcompat.view.ActionMode import androidx.recyclerview.widget.RecyclerView @@ -19,12 +20,16 @@ class ChaptersSelectionCallback( recyclerView: RecyclerView, ) : BaseListSelectionCallback(recyclerView) { - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_chapters, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_chapters, menu) 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 allItems = viewModel.chapters.value 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_select_all).isVisible = items.size < allItems.size menu.findItem(R.id.action_mark_current).isVisible = items.size == 1 - mode.title = items.size.toString() + mode?.title = items.size.toString() var hasGap = false for (i in 0 until items.size - 1) { if (items[i].index + 1 != items[i + 1].index) { @@ -50,11 +55,11 @@ class ChaptersSelectionCallback( 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) { R.id.action_save -> { viewModel.download(controller.snapshot()) - mode.finish() + mode?.finish() true } @@ -73,7 +78,7 @@ class ChaptersSelectionCallback( ).show() } } - mode.finish() + mode?.finish() true } @@ -112,7 +117,7 @@ class ChaptersSelectionCallback( } else { return false } - mode.finish() + mode?.finish() true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/PageThumbnailAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/PageThumbnailAD.kt index d315fe027..832a6df67 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/PageThumbnailAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/pages/PageThumbnailAD.kt @@ -32,9 +32,7 @@ fun pageThumbnailAD( height = (gridWidth / 13f * 18f).toInt(), ) - val clickListenerAdapter = AdapterDelegateClickListenerAdapter(this, clickListener) - binding.root.setOnClickListener(clickListenerAdapter) - binding.root.setOnLongClickListener(clickListenerAdapter) + AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView) bind { val data: Any = item.page.preview?.takeUnless { it.isEmpty() } ?: item.page.toMangaPage() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/related/RelatedListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/related/RelatedListFragment.kt index 8ec35ac90..45cb044d4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/related/RelatedListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/related/RelatedListFragment.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.details.ui.related import android.view.Menu -import androidx.appcompat.view.ActionMode +import android.view.MenuInflater import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import org.koitharu.kotatsu.R @@ -16,9 +16,13 @@ class RelatedListFragment : MangaListFragment() { override fun onScrolledToEnd() = Unit - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_remote, menu) - return super.onCreateActionMode(controller, mode, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_remote, menu) + return super.onCreateActionMode(controller, menuInflater, menu) } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt index 42d7eb43a..65cd369b9 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/download/ui/list/DownloadsActivity.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.download.ui.list import android.os.Bundle import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import androidx.activity.viewModels @@ -87,7 +88,11 @@ class DownloadsActivity : BaseActivity(), } 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) { @@ -120,34 +125,38 @@ class DownloadsActivity : BaseActivity(), viewBinding.recyclerView.invalidateItemDecorations() } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_downloads, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_downloads, menu) 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) { R.id.action_resume -> { viewModel.resume(controller.snapshot()) - mode.finish() + mode?.finish() true } R.id.action_pause -> { viewModel.pause(controller.snapshot()) - mode.finish() + mode?.finish() true } R.id.action_cancel -> { viewModel.cancel(controller.snapshot()) - mode.finish() + mode?.finish() true } R.id.action_remove -> { viewModel.remove(controller.snapshot()) - mode.finish() + mode?.finish() true } @@ -160,7 +169,7 @@ class DownloadsActivity : BaseActivity(), } } - 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()) var canPause = true var canResume = true diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt index 8c71cb5d5..8313db521 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/ExploreFragment.kt @@ -7,6 +7,7 @@ import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -147,7 +148,11 @@ class ExploreFragment : } 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 @@ -160,12 +165,16 @@ class ExploreFragment : viewBinding?.recyclerView?.invalidateItemDecorations() } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_source, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_source, menu) 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 isSingleSelection = selectedSources.size == 1 menu.findItem(R.id.action_settings).isVisible = isSingleSelection @@ -177,7 +186,7 @@ class ExploreFragment : 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()) if (selectedSources.isEmpty()) { return false @@ -186,35 +195,35 @@ class ExploreFragment : R.id.action_settings -> { val source = selectedSources.singleOrNull() ?: return false startActivity(SettingsActivity.newSourceSettingsIntent(requireContext(), source)) - mode.finish() + mode?.finish() } R.id.action_disable -> { viewModel.disableSources(selectedSources) - mode.finish() + mode?.finish() } R.id.action_delete -> { selectedSources.forEach { (it.mangaSource as? ExternalMangaSource)?.let { uninstallExternalSource(it) } } - mode.finish() + mode?.finish() } R.id.action_shortcut -> { val source = selectedSources.singleOrNull() ?: return false viewModel.requestPinShortcut(source) - mode.finish() + mode?.finish() } R.id.action_pin -> { viewModel.setSourcesPinned(selectedSources, isPinned = true) - mode.finish() + mode?.finish() } R.id.action_unpin -> { viewModel.setSourcesPinned(selectedSources, isPinned = false) - mode.finish() + mode?.finish() } else -> return false diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt index 28b93d6e5..72cb24a6e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/ui/adapter/ExploreAdapterDelegates.kt @@ -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.newImageRequest 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.source import org.koitharu.kotatsu.core.util.ext.textAndVisible @@ -117,13 +116,9 @@ fun exploreSourceListItemAD( 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) - binding.root.setOnClickListener(eventListener) - binding.root.setOnLongClickListener(eventListener) - binding.root.setOnContextClickListenerCompat(eventListener) - bind { binding.textViewTitle.text = item.source.getTitle(context) binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null @@ -154,13 +149,9 @@ fun exploreSourceGridItemAD( 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) - binding.root.setOnClickListener(eventListener) - binding.root.setOnLongClickListener(eventListener) - binding.root.setOnContextClickListenerCompat(eventListener) - bind { binding.textViewTitle.text = item.source.getTitle(context) binding.textViewTitle.drawableStart = if (item.source.isPinned) iconPinned else null diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt index 0a269669e..e8366ad69 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/CategoriesSelectionCallback.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.favourites.ui.categories import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import androidx.appcompat.view.ActionMode import androidx.recyclerview.widget.RecyclerView @@ -17,12 +18,16 @@ class CategoriesSelectionCallback( recyclerView.invalidateItemDecorations() } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_category, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_category, menu) 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()) var canShow = categories.isNotEmpty() var canHide = canShow @@ -35,11 +40,11 @@ class CategoriesSelectionCallback( } menu.findItem(R.id.action_show)?.isVisible = canShow menu.findItem(R.id.action_hide)?.isVisible = canHide - mode.title = controller.count.toString() + mode?.title = controller.count.toString() 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) { /*R.id.action_view -> { val id = controller.peekCheckedIds().singleOrNull() ?: return false @@ -53,13 +58,13 @@ class CategoriesSelectionCallback( R.id.action_show -> { viewModel.setIsVisible(controller.snapshot(), true) - mode.finish() + mode?.finish() true } R.id.action_hide -> { viewModel.setIsVisible(controller.snapshot(), false) - mode.finish() + mode?.finish() true } @@ -72,7 +77,7 @@ class CategoriesSelectionCallback( } } - private fun confirmDeleteCategories(ids: Set, mode: ActionMode) { + private fun confirmDeleteCategories(ids: Set, mode: ActionMode?) { buildAlertDialog(recyclerView.context, isCentered = true) { setMessage(R.string.categories_delete_confirm) setTitle(R.string.remove_category) @@ -80,7 +85,7 @@ class CategoriesSelectionCallback( setNegativeButton(android.R.string.cancel, null) setPositiveButton(R.string.remove) { _, _ -> viewModel.deleteCategories(ids) - mode.finish() + mode?.finish() } }.show() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt index 3b029b45a..f5129ba9a 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/categories/FavouriteCategoriesActivity.kt @@ -98,7 +98,11 @@ class FavouriteCategoriesActivity : } 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) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt index 0f632f025..474bd4159 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.favourites.ui.list import android.os.Bundle import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import androidx.appcompat.view.ActionMode @@ -52,27 +53,32 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis return true } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_favourites, menu) - return super.onCreateActionMode(controller, mode, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + 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) { R.id.action_remove -> { viewModel.removeFromFavourites(selectedItemsIds) - mode.finish() + mode?.finish() true } R.id.action_mark_current -> { + val itemsSnapshot = selectedItems MaterialAlertDialogBuilder(context ?: return false) .setTitle(item.title) .setMessage(R.string.mark_as_completed_prompt) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(android.R.string.ok) { _, _ -> - viewModel.markAsRead(selectedItems) - mode.finish() + viewModel.markAsRead(itemsSnapshot) + mode?.finish() }.show() true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt index da7a1d1c6..c283b4fba 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.history.ui import android.os.Bundle import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import androidx.appcompat.view.ActionMode import androidx.fragment.app.viewModels @@ -34,28 +35,33 @@ class HistoryListFragment : MangaListFragment() { override fun onEmptyActionClick() = viewModel.clearFilter() - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_history, menu) - return super.onCreateActionMode(controller, mode, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + 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) { R.id.action_remove -> { viewModel.removeFromHistory(selectedItemsIds) - mode.finish() + mode?.finish() true } R.id.action_mark_current -> { + val itemsSnapshot = selectedItems buildAlertDialog(context ?: return false, isCentered = true) { setTitle(item.title) setIcon(item.icon) setMessage(R.string.mark_as_completed_prompt) setNegativeButton(android.R.string.cancel, null) setPositiveButton(android.R.string.ok) { _, _ -> - viewModel.markAsRead(selectedItems) - mode.finish() + viewModel.markAsRead(itemsSnapshot) + mode?.finish() } }.show() true diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index e7d48b33b..4efd19b52 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.list.ui import android.os.Bundle import android.view.LayoutInflater import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup @@ -11,7 +12,6 @@ import androidx.annotation.CallSuper import androidx.appcompat.view.ActionMode import androidx.collection.ArraySet import androidx.core.graphics.Insets -import androidx.core.view.isNotEmpty import androidx.core.view.updateLayoutParams import androidx.core.view.updatePadding import androidx.recyclerview.widget.GridLayoutManager @@ -153,7 +153,11 @@ abstract class MangaListFragment : } 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) { @@ -280,18 +284,22 @@ abstract class MangaListFragment : } @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 } menu.findItem(R.id.action_save)?.isVisible = hasNoLocal menu.findItem(R.id.action_fix)?.isVisible = hasNoLocal return super.onPrepareActionMode(controller, mode, menu) } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - return menu.isNotEmpty() + override fun onCreateActionMode( + 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) { R.id.action_select_all -> { val ids = listAdapter?.items?.mapNotNull { @@ -303,31 +311,32 @@ abstract class MangaListFragment : R.id.action_share -> { ShareHelper(requireContext()).shareMangaLinks(selectedItems) - mode.finish() + mode?.finish() true } R.id.action_favourite -> { FavoriteSheet.show(getChildFragmentManager(), selectedItems) - mode.finish() + mode?.finish() true } R.id.action_save -> { viewModel.download(selectedItems) - mode.finish() + mode?.finish() true } R.id.action_fix -> { + val itemsSnapshot = selectedItemsIds buildAlertDialog(context ?: return false, isCentered = true) { setTitle(item.title) setIcon(item.icon) setMessage(R.string.manga_fix_prompt) setNegativeButton(android.R.string.cancel, null) setPositiveButton(R.string.fix) { _, _ -> - AutoFixService.start(context, selectedItemsIds) - mode.finish() + AutoFixService.start(context, itemsSnapshot) + mode?.finish() } }.show() true diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt index ade54bbdd..97fa7b00e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaGridItemAD.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.list.ui.adapter -import android.view.View import androidx.core.view.isVisible import androidx.lifecycle.LifecycleOwner import coil.ImageLoader @@ -8,11 +7,11 @@ import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver 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.util.ext.defaultPlaceholders import org.koitharu.kotatsu.core.util.ext.enqueueWith 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.databinding.ItemMangaGridBinding import org.koitharu.kotatsu.list.ui.ListModelDiffCallback.Companion.PAYLOAD_PROGRESS_CHANGED @@ -31,13 +30,7 @@ fun mangaGridItemAD( ) { var badge: BadgeDrawable? = null - val eventListener = object : View.OnClickListener, View.OnLongClickListener { - 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) + AdapterDelegateClickListenerAdapter(this, clickListener, MangaGridModel::manga).attach(itemView) sizeResolver.attachToView(lifecycleOwner, itemView, binding.textViewTitle, binding.progressView) bind { payloads -> diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt index 05dac38a8..272235c05 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListDetailedItemAD.kt @@ -1,16 +1,15 @@ package org.koitharu.kotatsu.list.ui.adapter -import android.view.View import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver 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.enqueueWith 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.textAndVisible import org.koitharu.kotatsu.databinding.ItemMangaListDetailsBinding @@ -27,14 +26,7 @@ fun mangaListDetailedItemAD( ) { var badge: BadgeDrawable? = null - val listenerAdapter = object : View.OnClickListener, View.OnLongClickListener { - 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) + AdapterDelegateClickListenerAdapter(this, clickListener, MangaDetailedListModel::manga).attach(itemView) bind { payloads -> binding.textViewTitle.text = item.title diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt index 8115b990b..14bf7f70b 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/MangaListItemAD.kt @@ -1,16 +1,15 @@ package org.koitharu.kotatsu.list.ui.adapter -import android.view.View import androidx.lifecycle.LifecycleOwner import coil.ImageLoader import com.google.android.material.badge.BadgeDrawable import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding 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.util.ext.defaultPlaceholders import org.koitharu.kotatsu.core.util.ext.enqueueWith 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.textAndVisible import org.koitharu.kotatsu.databinding.ItemMangaListBinding @@ -27,13 +26,7 @@ fun mangaListItemAD( ) { var badge: BadgeDrawable? = null - val eventListener = object : View.OnClickListener, View.OnLongClickListener { - 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) + AdapterDelegateClickListenerAdapter(this, clickListener, MangaCompactListModel::manga).attach(itemView) bind { binding.textViewTitle.text = item.title diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt index 41b7307b0..d374e3360 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/local/ui/LocalListFragment.kt @@ -4,6 +4,7 @@ import android.Manifest import android.os.Build import android.os.Bundle import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import androidx.activity.result.contract.ActivityResultContracts @@ -88,16 +89,16 @@ class LocalListFragment : MangaListFragment(), FilterCoordinator.Owner { override fun onCreateActionMode( controller: ListSelectionController, - mode: ActionMode, + menuInflater: MenuInflater, menu: Menu, ): Boolean { - mode.menuInflater.inflate(R.menu.mode_local, menu) - return super.onCreateActionMode(controller, mode, menu) + menuInflater.inflate(R.menu.mode_local, menu) + return super.onCreateActionMode(controller, menuInflater, menu) } override fun onActionItemClicked( controller: ListSelectionController, - mode: ActionMode, + mode: ActionMode?, item: MenuItem, ): Boolean { return when (item.itemId) { @@ -109,7 +110,7 @@ class LocalListFragment : MangaListFragment(), FilterCoordinator.Owner { R.id.action_share -> { val files = selectedItems.map { it.url.toUri().toFile() } ShareHelper(requireContext()).shareCbz(files) - mode.finish() + mode?.finish() true } @@ -117,13 +118,13 @@ class LocalListFragment : MangaListFragment(), FilterCoordinator.Owner { } } - private fun showDeletionConfirm(ids: Set, mode: ActionMode) { + private fun showDeletionConfirm(ids: Set, mode: ActionMode?) { MaterialAlertDialogBuilder(context ?: return) .setTitle(R.string.delete_manga) .setMessage(getString(R.string.text_delete_local_manga_batch)) .setPositiveButton(R.string.delete) { _, _ -> viewModel.delete(ids) - mode.finish() + mode?.finish() } .setNegativeButton(android.R.string.cancel, null) .show() diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt index 19f3aed74..41257db6f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt @@ -5,7 +5,6 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View -import androidx.appcompat.view.ActionMode import androidx.core.view.MenuProvider import androidx.fragment.app.viewModels import com.google.android.material.snackbar.Snackbar @@ -56,9 +55,13 @@ class RemoteListFragment : MangaListFragment(), FilterCoordinator.Owner { viewModel.loadNextPage() } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_remote, menu) - return super.onCreateActionMode(controller, mode, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_remote, menu) + return super.onCreateActionMode(controller, menuInflater, menu) } override fun onFilterClick(view: View?) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt index dd6c1a1b4..68050b01f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/scrobbling/common/ui/config/adapter/ScrobblingMangaAD.kt @@ -20,8 +20,7 @@ fun scrobblingMangaAD( { layoutInflater, parent -> ItemScrobblingMangaBinding.inflate(layoutInflater, parent, false) }, ) { - val clickListenerAdapter = AdapterDelegateClickListenerAdapter(this, clickListener) - itemView.setOnClickListener(clickListenerAdapter) + AdapterDelegateClickListenerAdapter(this, clickListener).attach(itemView) bind { binding.imageViewCover.newImageRequest(lifecycleOwner, item.coverUrl)?.run { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/SearchActivity.kt b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/SearchActivity.kt index dc72807e8..975dad0d4 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/SearchActivity.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/search/ui/multi/SearchActivity.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import android.view.View import androidx.activity.viewModels @@ -118,7 +119,11 @@ class SearchActivity : } 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) { @@ -155,28 +160,32 @@ class SearchActivity : viewBinding.recyclerView.invalidateNestedItemDecorations() } - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_remote, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + menuInflater: MenuInflater, + menu: Menu + ): Boolean { + menuInflater.inflate(R.menu.mode_remote, menu) 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) { R.id.action_share -> { ShareHelper(this).shareMangaLinks(collectSelectedItems()) - mode.finish() + mode?.finish() true } R.id.action_favourite -> { FavoriteSheet.show(supportFragmentManager, collectSelectedItems()) - mode.finish() + mode?.finish() true } R.id.action_save -> { viewModel.download(collectSelectedItems()) - mode.finish() + mode?.finish() true } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt index 4c5bedbfe..92e192e1d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.Menu import android.view.MenuInflater import android.view.MenuItem -import androidx.appcompat.view.ActionMode import androidx.core.view.MenuProvider import androidx.fragment.app.viewModels import com.google.android.material.snackbar.Snackbar @@ -29,11 +28,11 @@ class SuggestionsFragment : MangaListFragment() { override fun onCreateActionMode( controller: ListSelectionController, - mode: ActionMode, + menuInflater: MenuInflater, menu: Menu, ): Boolean { - mode.menuInflater.inflate(R.menu.mode_remote, menu) - return super.onCreateActionMode(controller, mode, menu) + menuInflater.inflate(R.menu.mode_remote, menu) + return super.onCreateActionMode(controller, menuInflater, menu) } private inner class SuggestionMenuProvider : MenuProvider { @@ -71,10 +70,11 @@ class SuggestionsFragment : MangaListFragment() { companion object { @Deprecated( - "", ReplaceWith( + "", + ReplaceWith( "SuggestionsFragment()", - "org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment" - ) + "org.koitharu.kotatsu.suggestions.ui.SuggestionsFragment", + ), ) fun newInstance() = SuggestionsFragment() } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt index 9c03bbd0f..9ac349c60 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/feed/FeedFragment.kt @@ -62,6 +62,8 @@ class FeedFragment : onItemClick(item.manga, v) } with(binding.recyclerView) { + val paddingVertical = resources.getDimensionPixelSize(R.dimen.list_spacing_normal) + setPadding(0, paddingVertical, 0, paddingVertical) layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false) adapter = feedAdapter setHasFixedSize(true) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt index 8fe56b9a3..01b4afb3c 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/ui/updates/UpdatesFragment.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.tracker.ui.updates import android.view.Menu +import android.view.MenuInflater import android.view.MenuItem import androidx.appcompat.view.ActionMode import androidx.fragment.app.viewModels @@ -17,16 +18,20 @@ class UpdatesFragment : MangaListFragment() { override fun onScrolledToEnd() = Unit - override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { - mode.menuInflater.inflate(R.menu.mode_updates, menu) - return super.onCreateActionMode(controller, mode, menu) + override fun onCreateActionMode( + controller: ListSelectionController, + 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) { R.id.action_remove -> { viewModel.remove(controller.snapshot()) - mode.finish() + mode?.finish() true }