diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt index c4047e01be4c..540a249e4627 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt @@ -382,6 +382,7 @@ open class CardBrowser : ) val launchOptions = intent?.toCardBrowserLaunchOptions() // must be called after super.onCreate() + // must be called once we have an accessible collection viewModel = createViewModel(launchOptions) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index a4d16bc5ac40..6836b8badc9b 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -27,7 +27,6 @@ import androidx.lifecycle.viewmodel.viewModelFactory import anki.collection.OpChanges import anki.collection.OpChangesWithCount import anki.config.ConfigKey -import anki.generic.Bool import anki.search.BrowserColumns import anki.search.BrowserRow import com.ichi2.anki.AnkiDroidApp @@ -86,7 +85,9 @@ import java.io.DataOutputStream import java.io.File import java.io.FileInputStream import java.io.FileOutputStream +import java.text.Normalizer import java.util.Collections +import java.util.regex.Pattern import kotlin.math.max import kotlin.math.min @@ -222,6 +223,8 @@ class CardBrowserViewModel( viewModelScope.launch { val defaultText = withCol { config.getString(ConfigKey.String.DEFAULT_SEARCH_TEXT) } defaultBrowserSearch = defaultText + searchTerms = defaultText + setSearchTerms(defaultText) } suspend fun setDeckId(deckId: DeckId) { @@ -303,6 +306,10 @@ class CardBrowserViewModel( emit(Unit) } + fun setSearchTerms(text: String) { + searchTerms = text + } + init { Timber.d("CardBrowserViewModel::init") @@ -321,7 +328,21 @@ class CardBrowserViewModel( is CardBrowserLaunchOptions.DeepLink -> { searchTerms = options.search } - null -> { + null -> {} + } + + viewModelScope.launch { + // Ensure intent-based search takes priority + if (searchTerms.isEmpty()) { + val searchText: String = + withCol { + config.getString(ConfigKey.String.DEFAULT_SEARCH_TEXT) + } + + Timber.d("Default search term text: $searchText") + if (searchText.isNotEmpty()) { + setSearchTerms(searchText) + } } } @@ -935,8 +956,22 @@ class CardBrowserViewModel( Timber.d("skipping duplicate search: forceRefresh is false") return } - searchTerms = searchQuery - launchSearchForCards() + viewModelScope.launch { + searchTerms = + if (shouldIgnoreAccents()) { + searchQuery.normalizeForSearch() + } else { + searchQuery + } + launchSearchForCards() + } + } + + private suspend fun shouldIgnoreAccents() = withCol { config.getBool(ConfigKey.Bool.IGNORE_ACCENTS_IN_SEARCH) } + + private fun String.normalizeForSearch(): String { + val normalized = Normalizer.normalize(this, Normalizer.Form.NFD) + return Pattern.compile("\\p{InCombiningDiacriticalMarks}+").matcher(normalized).replaceAll("") } /**