Popup menu on sources in Explore fragment
This commit is contained in:
@@ -2,8 +2,10 @@ package org.koitharu.kotatsu.explore.ui
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
@@ -11,11 +13,12 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.base.domain.reverseAsync
|
||||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
||||||
|
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
||||||
import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity
|
import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity
|
||||||
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
|
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
|
||||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
@@ -31,6 +34,7 @@ import org.koitharu.kotatsu.search.ui.MangaListActivity
|
|||||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||||
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ExploreFragment :
|
class ExploreFragment :
|
||||||
@@ -67,6 +71,7 @@ class ExploreFragment :
|
|||||||
}
|
}
|
||||||
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
||||||
viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga)
|
viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga)
|
||||||
|
viewModel.onActionDone.observe(viewLifecycleOwner, ::onActionDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@@ -95,6 +100,7 @@ class ExploreFragment :
|
|||||||
viewModel.openRandom()
|
viewModel.openRandom()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
@@ -105,6 +111,14 @@ class ExploreFragment :
|
|||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onItemLongClick(item: ExploreItem.Source, view: View): Boolean {
|
||||||
|
val menu = PopupMenu(view.context, view)
|
||||||
|
menu.inflate(R.menu.popup_source)
|
||||||
|
menu.setOnMenuItemClickListener(SourceMenuListener(item))
|
||||||
|
menu.show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRetryClick(error: Throwable) = Unit
|
override fun onRetryClick(error: Throwable) = Unit
|
||||||
|
|
||||||
override fun onEmptyActionClick() = onManageClick(requireView())
|
override fun onEmptyActionClick() = onManageClick(requireView())
|
||||||
@@ -124,6 +138,37 @@ class ExploreFragment :
|
|||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onActionDone(action: ReversibleAction) {
|
||||||
|
val handle = action.handle
|
||||||
|
val length = if (handle == null) Snackbar.LENGTH_SHORT else Snackbar.LENGTH_LONG
|
||||||
|
val snackbar = Snackbar.make(binding.recyclerView, action.stringResId, length)
|
||||||
|
if (handle != null) {
|
||||||
|
snackbar.setAction(R.string.undo) { handle.reverseAsync() }
|
||||||
|
}
|
||||||
|
snackbar.anchorView = (activity as? BottomNavOwner)?.bottomNav
|
||||||
|
snackbar.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class SourceMenuListener(
|
||||||
|
private val sourceItem: ExploreItem.Source,
|
||||||
|
) : PopupMenu.OnMenuItemClickListener {
|
||||||
|
|
||||||
|
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.action_settings -> {
|
||||||
|
startActivity(SettingsActivity.newSourceSettingsIntent(requireContext(), sourceItem.source))
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_hide -> {
|
||||||
|
viewModel.hideSource(sourceItem.source)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun newInstance() = ExploreFragment()
|
fun newInstance() = ExploreFragment()
|
||||||
|
|||||||
@@ -4,11 +4,17 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.asFlow
|
import androidx.lifecycle.asFlow
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onStart
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.base.domain.ReversibleHandle
|
||||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
|
import org.koitharu.kotatsu.base.ui.util.ReversibleAction
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||||
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
||||||
@@ -16,6 +22,7 @@ import org.koitharu.kotatsu.parsers.model.Manga
|
|||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ExploreViewModel @Inject constructor(
|
class ExploreViewModel @Inject constructor(
|
||||||
@@ -24,6 +31,7 @@ class ExploreViewModel @Inject constructor(
|
|||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
val onOpenManga = SingleLiveEvent<Manga>()
|
val onOpenManga = SingleLiveEvent<Manga>()
|
||||||
|
val onActionDone = SingleLiveEvent<ReversibleAction>()
|
||||||
|
|
||||||
val content: LiveData<List<ExploreItem>> = isLoading.asFlow().flatMapLatest { loading ->
|
val content: LiveData<List<ExploreItem>> = isLoading.asFlow().flatMapLatest { loading ->
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -40,6 +48,16 @@ class ExploreViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun hideSource(source: MangaSource) {
|
||||||
|
launchJob(Dispatchers.Default) {
|
||||||
|
settings.hiddenSources += source.name
|
||||||
|
val rollback = ReversibleHandle {
|
||||||
|
settings.hiddenSources -= source.name
|
||||||
|
}
|
||||||
|
onActionDone.postCall(ReversibleAction(R.string.source_disabled, rollback))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createContentFlow() = settings.observe()
|
private fun createContentFlow() = settings.observe()
|
||||||
.filter {
|
.filter {
|
||||||
it == AppSettings.KEY_SOURCES_HIDDEN ||
|
it == AppSettings.KEY_SOURCES_HIDDEN ||
|
||||||
|
|||||||
13
app/src/main/res/menu/popup_source.xml
Normal file
13
app/src/main/res/menu/popup_source.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_settings"
|
||||||
|
android:title="@string/settings" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_hide"
|
||||||
|
android:title="@string/hide" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -398,4 +398,5 @@
|
|||||||
<string name="server_error">Server side error (%1$d). Please try again later</string>
|
<string name="server_error">Server side error (%1$d). Please try again later</string>
|
||||||
<string name="clear_new_chapters_counters">Also clear information about new chapters</string>
|
<string name="clear_new_chapters_counters">Also clear information about new chapters</string>
|
||||||
<string name="compact">Compact</string>
|
<string name="compact">Compact</string>
|
||||||
|
<string name="source_disabled">Source disabled</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user