From d0e6a2d2d06e345361691c37c24dd6ba173445c1 Mon Sep 17 00:00:00 2001 From: Alexandre G Pereira Date: Sat, 13 Jul 2024 18:59:01 -0300 Subject: [PATCH] Fix spell search not working with special chars (#297) --- core/search/build.gradle.kts | 11 +++++++++++ .../br/alexandregpereira/hunter/search/Search.kt | 16 ++++++++++++++++ feature/search/compose/build.gradle.kts | 1 + .../search/domain/SearchMonstersByUseCase.kt | 16 +--------------- .../state-holder/build.gradle.kts | 1 + .../compendium/SpellCompendiumStateHolder.kt | 7 ++++++- settings.gradle | 1 + 7 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 core/search/build.gradle.kts create mode 100644 core/search/src/commonMain/kotlin/br/alexandregpereira/hunter/search/Search.kt diff --git a/core/search/build.gradle.kts b/core/search/build.gradle.kts new file mode 100644 index 00000000..08d90b12 --- /dev/null +++ b/core/search/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + kotlin("multiplatform") +} + +multiplatform { + commonMain { + implementation(libs.kotlin.coroutines.core) + } + jvmMain() + iosMain() +} diff --git a/core/search/src/commonMain/kotlin/br/alexandregpereira/hunter/search/Search.kt b/core/search/src/commonMain/kotlin/br/alexandregpereira/hunter/search/Search.kt new file mode 100644 index 00000000..e7617a58 --- /dev/null +++ b/core/search/src/commonMain/kotlin/br/alexandregpereira/hunter/search/Search.kt @@ -0,0 +1,16 @@ +package br.alexandregpereira.hunter.search + +fun String.removeAccents(): String { + val accentMappings = mapOf( + 'á' to 'a', 'é' to 'e', 'í' to 'i', 'ó' to 'o', 'ú' to 'u', + 'â' to 'a', 'ê' to 'e', 'î' to 'i', 'ô' to 'o', 'û' to 'u', + 'ã' to 'a', 'õ' to 'o', 'ç' to 'c', + 'à' to 'a', 'è' to 'e', 'ì' to 'i', 'ò' to 'o', 'ù' to 'u', + 'Á' to 'A', 'É' to 'E', 'Í' to 'I', 'Ó' to 'O', 'Ú' to 'U', + 'Â' to 'A', 'Ê' to 'E', 'Î' to 'I', 'Ô' to 'O', 'Û' to 'U', + 'Ã' to 'A', 'Õ' to 'O', 'Ç' to 'C', + 'À' to 'A', 'È' to 'E', 'Ì' to 'I', 'Ò' to 'O', 'Ù' to 'U' + ) + + return map { char -> accentMappings[char] ?: char }.joinToString("") +} diff --git a/feature/search/compose/build.gradle.kts b/feature/search/compose/build.gradle.kts index 20b86836..99dd2f05 100644 --- a/feature/search/compose/build.gradle.kts +++ b/feature/search/compose/build.gradle.kts @@ -10,6 +10,7 @@ multiplatform { implementation(project(":core:analytics")) implementation(project(":core:localization")) implementation(project(":core:state-holder")) + implementation(project(":core:search")) implementation(project(":domain:monster:core")) implementation(project(":domain:spell:core")) implementation(project(":feature:folder-preview:event")) diff --git a/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/domain/SearchMonstersByUseCase.kt b/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/domain/SearchMonstersByUseCase.kt index c86327ec..44855d3d 100644 --- a/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/domain/SearchMonstersByUseCase.kt +++ b/feature/search/compose/src/commonMain/kotlin/br/alexandregpereira/hunter/search/domain/SearchMonstersByUseCase.kt @@ -22,6 +22,7 @@ import br.alexandregpereira.hunter.domain.spell.GetSpellsByIdsUseCase import br.alexandregpereira.hunter.domain.spell.model.Spell import br.alexandregpereira.hunter.domain.usecase.GetMonsterPreviewsCacheUseCase import br.alexandregpereira.hunter.domain.usecase.GetMonstersUseCase +import br.alexandregpereira.hunter.search.removeAccents import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch @@ -179,21 +180,6 @@ internal class SearchMonstersByUseCase internal constructor( } ?: false } - private fun String.removeAccents(): String { - val accentMappings = mapOf( - 'á' to 'a', 'é' to 'e', 'í' to 'i', 'ó' to 'o', 'ú' to 'u', - 'â' to 'a', 'ê' to 'e', 'î' to 'i', 'ô' to 'o', 'û' to 'u', - 'ã' to 'a', 'õ' to 'o', 'ç' to 'c', - 'à' to 'a', 'è' to 'e', 'ì' to 'i', 'ò' to 'o', 'ù' to 'u', - 'Á' to 'A', 'É' to 'E', 'Í' to 'I', 'Ó' to 'O', 'Ú' to 'U', - 'Â' to 'A', 'Ê' to 'E', 'Î' to 'I', 'Ô' to 'O', 'Û' to 'U', - 'Ã' to 'A', 'Õ' to 'O', 'Ç' to 'C', - 'À' to 'A', 'È' to 'E', 'Ì' to 'I', 'Ò' to 'O', 'Ù' to 'U' - ) - - return map { char -> accentMappings[char] ?: char }.joinToString("") - } - private enum class KeySearch { NAME, TYPE, CHALLENGE_RATING, SPELL } diff --git a/feature/spell-compendium/state-holder/build.gradle.kts b/feature/spell-compendium/state-holder/build.gradle.kts index e207857c..557347e4 100644 --- a/feature/spell-compendium/state-holder/build.gradle.kts +++ b/feature/spell-compendium/state-holder/build.gradle.kts @@ -23,6 +23,7 @@ multiplatform { implementation(project(":core:state-holder")) implementation(project(":core:event")) implementation(project(":core:localization")) + implementation(project(":core:search")) implementation(project(":domain:spell:core")) implementation(project(":feature:spell-compendium:event")) implementation(libs.kotlin.coroutines.core) diff --git a/feature/spell-compendium/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/spell/compendium/SpellCompendiumStateHolder.kt b/feature/spell-compendium/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/spell/compendium/SpellCompendiumStateHolder.kt index 18419b24..f725831f 100644 --- a/feature/spell-compendium/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/spell/compendium/SpellCompendiumStateHolder.kt +++ b/feature/spell-compendium/state-holder/src/commonMain/kotlin/br/alexandregpereira/hunter/spell/compendium/SpellCompendiumStateHolder.kt @@ -4,6 +4,7 @@ import br.alexandregpereira.hunter.domain.spell.model.Spell import br.alexandregpereira.hunter.event.EventDispatcher import br.alexandregpereira.hunter.event.EventListener import br.alexandregpereira.hunter.localization.AppLocalization +import br.alexandregpereira.hunter.search.removeAccents import br.alexandregpereira.hunter.spell.compendium.domain.GetSpellsUseCase import br.alexandregpereira.hunter.spell.compendium.event.SpellCompendiumEvent import br.alexandregpereira.hunter.spell.compendium.event.SpellCompendiumResult @@ -14,6 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach @OptIn(FlowPreview::class) @@ -67,11 +69,14 @@ class SpellCompendiumStateHolder internal constructor( private fun debounceSearch() { searchQuery.debounce(500L) + .map { + it.removeAccents().trim() + } .onEach { text -> setState { val spellsGroupByLevel = if (text.isNotBlank()){ val spellsFiltered = originalSpellsGroupByLevel.values.flatten() - .filter { it.name.contains(text, ignoreCase = true) } + .filter { it.name.removeAccents().contains(text, ignoreCase = true) } mapOf(strings.searchResults(spellsFiltered.size) to spellsFiltered) } else originalSpellsGroupByLevel diff --git a/settings.gradle b/settings.gradle index dc38ec01..f9e3ff73 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,6 +16,7 @@ include ':core:localization' include ':core:state-holder' include ':core:ui:state-recovery' include ':core:uuid' +include ':core:search' include ':domain:app:core' include ':domain:monster:core'