Suggestions enable tip
This commit is contained in:
@@ -245,8 +245,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
val isDownloadsWiFiOnly: Boolean
|
||||
get() = prefs.getBoolean(KEY_DOWNLOADS_WIFI, false)
|
||||
|
||||
val isSuggestionsEnabled: Boolean
|
||||
var isSuggestionsEnabled: Boolean
|
||||
get() = prefs.getBoolean(KEY_SUGGESTIONS, false)
|
||||
set(value) = prefs.edit { putBoolean(KEY_SUGGESTIONS, value) }
|
||||
|
||||
val isSuggestionsExcludeNsfw: Boolean
|
||||
get() = prefs.getBoolean(KEY_SUGGESTIONS_EXCLUDE_NSFW, false)
|
||||
@@ -292,19 +293,6 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
||||
return policy.isNetworkAllowed(connectivityManager)
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
fun getSuggestionsTagsBlacklistRegex(): Regex? {
|
||||
val string = prefs.getString(KEY_SUGGESTIONS_EXCLUDE_TAGS, null)?.trimEnd(' ', ',')
|
||||
if (string.isNullOrEmpty()) {
|
||||
return null
|
||||
}
|
||||
val tags = string.split(',')
|
||||
val regex = tags.joinToString(prefix = "(", separator = "|", postfix = ")") { tag ->
|
||||
Regex.escape(tag.trim())
|
||||
}
|
||||
return Regex(regex, RegexOption.IGNORE_CASE)
|
||||
}
|
||||
|
||||
fun getMangaSources(includeHidden: Boolean): List<MangaSource> {
|
||||
val list = remoteSources.toMutableList()
|
||||
val order = sourcesOrder
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.koitharu.kotatsu.explore.domain
|
||||
|
||||
import javax.inject.Inject
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.history.domain.HistoryRepository
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.suggestions.domain.TagsBlacklist
|
||||
import javax.inject.Inject
|
||||
|
||||
class ExploreRepository @Inject constructor(
|
||||
private val settings: AppSettings,
|
||||
@@ -14,9 +15,9 @@ class ExploreRepository @Inject constructor(
|
||||
) {
|
||||
|
||||
suspend fun findRandomManga(tagsLimit: Int): Manga {
|
||||
val blacklistTagRegex = settings.getSuggestionsTagsBlacklistRegex()
|
||||
val blacklistTagRegex = TagsBlacklist(settings.suggestionsTagsBlacklist, 0.4f)
|
||||
val allTags = historyRepository.getPopularTags(tagsLimit).filterNot {
|
||||
blacklistTagRegex?.containsMatchIn(it.title) ?: false
|
||||
it in blacklistTagRegex
|
||||
}
|
||||
val tag = allTags.randomOrNull()
|
||||
val source = checkNotNull(tag?.source ?: settings.getMangaSources(includeHidden = false).randomOrNull()) {
|
||||
@@ -32,7 +33,7 @@ class ExploreRepository @Inject constructor(
|
||||
if (settings.isSuggestionsExcludeNsfw && item.isNsfw) {
|
||||
continue
|
||||
}
|
||||
if (blacklistTagRegex != null && item.tags.any { x -> blacklistTagRegex.containsMatchIn(x.title) }) {
|
||||
if (item in blacklistTagRegex) {
|
||||
continue
|
||||
}
|
||||
return item
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.explore.ui
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
@@ -16,6 +17,7 @@ import coil.ImageLoader
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.BaseFragment
|
||||
import org.koitharu.kotatsu.base.ui.dialog.TwoButtonsAlertDialog
|
||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
||||
import org.koitharu.kotatsu.base.ui.util.ReversibleActionObserver
|
||||
@@ -76,6 +78,9 @@ class ExploreFragment :
|
||||
viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga)
|
||||
viewModel.onActionDone.observe(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
|
||||
viewModel.isGrid.observe(viewLifecycleOwner, ::onGridModeChanged)
|
||||
viewModel.onShowSuggestionsTip.observe(viewLifecycleOwner) {
|
||||
showSuggestionsTip()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
@@ -143,6 +148,19 @@ class ExploreFragment :
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private fun showSuggestionsTip() {
|
||||
val listener = DialogInterface.OnClickListener { _, which ->
|
||||
viewModel.respondSuggestionTip(which == DialogInterface.BUTTON_POSITIVE)
|
||||
}
|
||||
TwoButtonsAlertDialog.Builder(requireContext())
|
||||
.setIcon(R.drawable.ic_suggestion)
|
||||
.setTitle(R.string.suggestions_enable_prompt)
|
||||
.setPositiveButton(R.string.enable, listener)
|
||||
.setNegativeButton(R.string.no_thanks, listener)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
|
||||
private inner class SourceMenuListener(
|
||||
private val sourceItem: ExploreItem.Source,
|
||||
) : PopupMenu.OnMenuItemClickListener {
|
||||
|
||||
@@ -27,6 +27,8 @@ import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||
import org.koitharu.kotatsu.utils.asFlowLiveData
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val TIP_SUGGESTIONS = "suggestions"
|
||||
|
||||
@HiltViewModel
|
||||
class ExploreViewModel @Inject constructor(
|
||||
private val settings: AppSettings,
|
||||
@@ -41,6 +43,7 @@ class ExploreViewModel @Inject constructor(
|
||||
|
||||
val onOpenManga = SingleLiveEvent<Manga>()
|
||||
val onActionDone = SingleLiveEvent<ReversibleAction>()
|
||||
val onShowSuggestionsTip = SingleLiveEvent<Unit>()
|
||||
val isGrid = gridMode.asFlowLiveData(viewModelScope.coroutineContext)
|
||||
|
||||
val content: LiveData<List<ExploreItem>> = isLoading.asFlow().flatMapLatest { loading ->
|
||||
@@ -51,6 +54,14 @@ class ExploreViewModel @Inject constructor(
|
||||
}
|
||||
}.asFlowLiveData(viewModelScope.coroutineContext + Dispatchers.Default, listOf(ExploreItem.Loading))
|
||||
|
||||
init {
|
||||
launchJob(Dispatchers.Default) {
|
||||
if (!settings.isSuggestionsEnabled && settings.isTipEnabled(TIP_SUGGESTIONS)) {
|
||||
onShowSuggestionsTip.emitCall(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun openRandom() {
|
||||
launchLoadingJob(Dispatchers.Default) {
|
||||
val manga = exploreRepository.findRandomManga(tagsLimit = 8)
|
||||
@@ -72,6 +83,11 @@ class ExploreViewModel @Inject constructor(
|
||||
settings.isSourcesGridMode = value
|
||||
}
|
||||
|
||||
fun respondSuggestionTip(isAccepted: Boolean) {
|
||||
settings.isSuggestionsEnabled = isAccepted
|
||||
settings.closeTip(TIP_SUGGESTIONS)
|
||||
}
|
||||
|
||||
private fun createContentFlow() = settings.observe()
|
||||
.filter {
|
||||
it == AppSettings.KEY_SOURCES_HIDDEN ||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.koitharu.kotatsu.suggestions.domain
|
||||
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.utils.ext.almostEquals
|
||||
|
||||
class TagsBlacklist(
|
||||
@@ -11,6 +12,9 @@ class TagsBlacklist(
|
||||
fun isNotEmpty() = tags.isNotEmpty()
|
||||
|
||||
operator fun contains(manga: Manga): Boolean {
|
||||
if (tags.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
for (mangaTag in manga.tags) {
|
||||
for (tagTitle in tags) {
|
||||
if (mangaTag.title.almostEquals(tagTitle, threshold)) {
|
||||
@@ -20,4 +24,8 @@ class TagsBlacklist(
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
operator fun contains(tag: MangaTag): Boolean = tags.any {
|
||||
it.almostEquals(tag.title, threshold)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -453,4 +453,5 @@
|
||||
<string name="more">More</string>
|
||||
<string name="enable">Enable</string>
|
||||
<string name="no_thanks">No thanks</string>
|
||||
<string name="suggestions_enable_prompt">Do you want to receive personalized manga suggestions?</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user