From a0d3706497f83e8d2572824f71b21cb401ce92ed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <99822064+revonateB0T@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:27:32 +0800 Subject: [PATCH] Refine TagDatabase Suggestions (#1973) * Refine rawSuggestSequence * Lift * Refine * Refine * Refine * Refine * Refine * Refine naming * Refine naming * Update app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt Co-authored-by: FooIbar <118464521+FooIbar@users.noreply.github.com> --------- Co-authored-by: Dude so hot Co-authored-by: FooIbar <118464521+FooIbar@users.noreply.github.com> --- .../hippo/ehviewer/client/EhTagDatabase.kt | 72 ++++++++----------- .../ehviewer/ui/screen/SearchBarScreen.kt | 2 +- .../com/hippo/ehviewer/ui/tools/Dialog.kt | 4 +- 3 files changed, 32 insertions(+), 46 deletions(-) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt b/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt index d81fa9e1a..0c47a7f32 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/client/EhTagDatabase.kt @@ -62,53 +62,39 @@ object EhTagDatabase : CoroutineScope { fun getTranslation(prefix: String? = NAMESPACE_PREFIX, tag: String?): String? = tagGroups[prefix]?.get(tag)?.trim()?.ifEmpty { null } - private fun rawSuggestSequence(tags: Map, keyword: String, translate: Boolean, exactly: Boolean) = sequence { - if (exactly) { - tags[keyword]?.let { - yield(keyword to it.takeIf { translate }) - } - } else { - if (translate) { - tags.forEach { (tag, hint) -> - if (tag != keyword && (tag.containsIgnoreSpace(keyword) || hint.containsIgnoreSpace(keyword))) { - yield(tag to hint) - } - } - } else { - tags.keys.forEach { tag -> - if (tag != keyword && tag.containsIgnoreSpace(keyword)) { - yield(tag to null) - } - } - } - } - } - context(Context) - fun suggestions(keyword: String, translate: Boolean) = sequence { - val doTranslate = translate && isTranslatable(implicit()) - if (initialized) { - yieldAll(suggestSequence(keyword, doTranslate, true)) - yieldAll(suggestSequence(keyword, doTranslate, false)) - } - } - - private fun suggestSequence(keyword: String, translate: Boolean, exactly: Boolean) = sequence { - val kwd = PREFIXES.fold(keyword) { kwd, pfx -> kwd.removePrefix(pfx) } - val prefix = keyword.dropLast(kwd.length) - val ns = kwd.substringBefore(':') - val tag = kwd.drop(ns.length + 1) - val namespacePrefix = TagNamespace.from(ns)?.prefix ?: ns - val tags = tagGroups[namespacePrefix.takeIf { tag.isNotEmpty() && it != NAMESPACE_PREFIX }] - tags?.let { - yieldAll(rawSuggestSequence(it, tag, translate, exactly).map { (tag, hint) -> "$prefix$namespacePrefix:$tag" to hint }) - } ?: tagGroups.forEach { (namespacePrefix, tags) -> - if (namespacePrefix != NAMESPACE_PREFIX) { - yieldAll(rawSuggestSequence(tags, kwd, translate, exactly).map { (tag, hint) -> "$prefix$namespacePrefix:$tag" to hint }) + fun suggestion(rawKeyword: String, expectTranslate: Boolean): Sequence> { + if (!initialized) return emptySequence() + val translate = expectTranslate && isTranslatable(implicit()) + val keyword = PREFIXES.fold(rawKeyword) { kwd, pfx -> kwd.removePrefix(pfx) } + val prefix = rawKeyword.dropLast(keyword.length) + val ns = keyword.substringBefore(':') + val tag = keyword.drop(ns.length + 1) + val nsPrefix = TagNamespace.from(ns)?.prefix ?: ns + val tags = tagGroups[nsPrefix.takeIf { tag.isNotEmpty() && it != NAMESPACE_PREFIX }] + fun suggestOnce(exactly: Boolean) = let { + fun lookup(tags: Map, keyword: String) = when { + exactly -> tags[keyword]?.let { t -> sequenceOf(keyword to t.takeIf { translate }) } ?: emptySequence() + translate -> tags.asSequence().filter { (tag, hint) -> + tag != keyword && (tag.containsIgnoreSpace(keyword) || hint.containsIgnoreSpace(keyword)) + }.map { (tag, hint) -> tag to hint } + else -> tags.keys.asSequence().filter { tag -> + tag != keyword && tag.containsIgnoreSpace(keyword) + }.map { tag -> tag to null } + } + if (tags != null) { + lookup(tags, tag).map { (tag, hint) -> "$prefix$nsPrefix:$tag" to hint } } else { - yieldAll(rawSuggestSequence(tags, kwd, translate, exactly).map { (ns, hint) -> "$prefix$ns:" to hint }) + tagGroups.asSequence().flatMap { (nsPrefix, tags) -> + if (nsPrefix != NAMESPACE_PREFIX) { + lookup(tags, keyword).map { (tag, hint) -> "$prefix$nsPrefix:$tag" to hint } + } else { + lookup(tags, keyword).map { (ns, hint) -> "$prefix$ns:" to hint } + } + } } } + return suggestOnce(true) + suggestOnce(false) } private fun String.removeSpace(): String = replace(" ", "") diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt index 1b4cdf81a..bad4f5d79 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/screen/SearchBarScreen.kt @@ -149,7 +149,7 @@ fun SearchBarScreen( suggestionProvider?.run { providerSuggestions(query)?.let { emit(it) } } mSearchDatabase.suggestions(query, 128).forEach { emit(KeywordSuggestion(it)) } if (query.isNotEmpty() && !query.endsWith(' ')) { - EhTagDatabase.suggestions( + EhTagDatabase.suggestion( query.substringAfterLast(' '), Settings.showTagTranslations, ).forEach { (tag, hint) -> diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt index 50937a995..91cb76f12 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/Dialog.kt @@ -94,7 +94,7 @@ import arrow.core.raise.either import arrow.core.right import com.hippo.ehviewer.R import com.hippo.ehviewer.client.EhTagDatabase -import com.hippo.ehviewer.client.EhTagDatabase.suggestions +import com.hippo.ehviewer.client.EhTagDatabase.suggestion import com.jamal.composeprefs3.ui.ifNotNullThen import com.jamal.composeprefs3.ui.ifTrueThen import kotlin.coroutines.Continuation @@ -255,7 +255,7 @@ value class DialogState(val field: MutableComposable = mutableStateOf(null)) : M val query = state.text.toString().trim().takeIf { s -> s.isNotEmpty() } val items = remember { mutableStateOf>?>(null) } LaunchedEffect(suggestionTranslate, query) { - items.value = query?.let { suggestions(query, suggestionTranslate).take(15).toList() } + items.value = query?.let { suggestion(query, suggestionTranslate).take(15).toList() } } val itemsNow = items.value ExposedDropdownMenu(