diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index ed027fa1b..54b7261a4 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -40,7 +40,6 @@ import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.util.applyEdge import org.oxycblt.auxio.util.logD diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt index aa958829e..5d3e8c4e0 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchViewModel.kt @@ -31,10 +31,10 @@ import org.oxycblt.auxio.music.Header import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.ui.DisplayMode +import java.text.Normalizer /** * The [ViewModel] for the search functionality - * TODO: Try to find adjacent characters [e.g accented o == o] * @author OxygenCobalt */ class SearchViewModel : ViewModel() { @@ -130,12 +130,41 @@ class SearchViewModel : ViewModel() { */ private fun List.filterByOrNull(value: String): List? { val filtered = filter { - it.name.contains(value, ignoreCase = true) + it.name.normalized().contains(value.normalized(), ignoreCase = true) } return if (filtered.isNotEmpty()) filtered else null } + private fun String.normalized(): String { + // This method normalizes strings so that songs with accented characters will show + // up in search even if the actual character was not inputted. + // https://stackoverflow.com/a/32030586/14143986 + + // Normalize with NFKD [Meaning that symbols with identical meanings will be turned into + // their letter variants]. + val norm = Normalizer.normalize(this, Normalizer.Form.NFKD) + + // Normalizer doesn't exactly finish the job though. We have to rebuild all the codepoints + // in the string and remove the hidden characters that were added by Normalizer. + var idx = 0 + val sb = StringBuilder() + + while (idx < norm.length) { + val cp = norm.codePointAt(idx) + idx += Character.charCount(cp) + + when (Character.getType(cp)) { + Character.NON_SPACING_MARK.toInt(), Character.COMBINING_SPACING_MARK.toInt() -> + continue + + else -> sb.appendCodePoint(cp) + } + } + + return sb.toString() + } + /** * Update the current navigation status to [isNavigating] */