mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 15:26:58 +00:00
feat(search): Implement and encapsulate AppSearchProvider
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package app.lawnchair.search.engine.provider
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ShortcutInfo
|
||||
import app.lawnchair.launcher
|
||||
import app.lawnchair.preferences2.PreferenceManager2
|
||||
import app.lawnchair.search.algorithms.filterHiddenApps
|
||||
import app.lawnchair.search.engine.SearchResult
|
||||
import com.android.launcher3.model.AllAppsList
|
||||
import com.android.launcher3.model.data.AppInfo
|
||||
import com.android.launcher3.popup.PopupPopulator
|
||||
import com.android.launcher3.search.StringMatcherUtility
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest
|
||||
import com.patrykmichalik.opto.core.firstBlocking
|
||||
import java.util.Locale
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
import me.xdrop.fuzzywuzzy.algorithms.WeightedRatio
|
||||
|
||||
object AppSearchProvider {
|
||||
|
||||
fun search(context: Context, query: String, allApps: AllAppsList): List<SearchResult> {
|
||||
val prefs = PreferenceManager2.getInstance(context)
|
||||
val hiddenApps = prefs.hiddenApps.firstBlocking()
|
||||
val hiddenAppsInSearch = prefs.hiddenAppsInSearch.firstBlocking()
|
||||
val maxAppResults = prefs.maxAppSearchResultCount.firstBlocking()
|
||||
val enableFuzzySearch = prefs.enableFuzzySearch.firstBlocking()
|
||||
|
||||
val appResults = if (enableFuzzySearch) {
|
||||
fuzzySearch(allApps.data, query, maxAppResults, hiddenApps, hiddenAppsInSearch)
|
||||
} else {
|
||||
normalSearch(allApps.data, query, maxAppResults, hiddenApps, hiddenAppsInSearch)
|
||||
}
|
||||
|
||||
val finalResults = mutableListOf<SearchResult>()
|
||||
appResults.mapTo(finalResults) { SearchResult.App(data = it) }
|
||||
|
||||
if (appResults.size == 1) {
|
||||
val singleApp = appResults.first()
|
||||
val shortcuts = getShortcuts(singleApp, context)
|
||||
shortcuts.mapTo(finalResults) { SearchResult.Shortcut(data = it) }
|
||||
}
|
||||
|
||||
return finalResults
|
||||
}
|
||||
|
||||
private fun normalSearch(apps: List<AppInfo>, query: String, maxResultsCount: Int, hiddenApps: Set<String>, hiddenAppsInSearch: String): List<AppInfo> {
|
||||
// Do an intersection of the words in the query and each title, and filter out all the
|
||||
// apps that don't match all of the words in the query.
|
||||
val queryTextLower = query.lowercase(Locale.getDefault())
|
||||
val matcher = StringMatcherUtility.StringMatcher.getInstance()
|
||||
return apps.asSequence()
|
||||
.filter { StringMatcherUtility.matches(queryTextLower, it.title.toString(), matcher) }
|
||||
.filterHiddenApps(queryTextLower, hiddenApps, hiddenAppsInSearch)
|
||||
.take(maxResultsCount)
|
||||
.toList()
|
||||
}
|
||||
|
||||
private fun fuzzySearch(apps: List<AppInfo>, query: String, maxResultsCount: Int, hiddenApps: Set<String>, hiddenAppsInSearch: String): List<AppInfo> {
|
||||
val queryTextLower = query.lowercase(Locale.getDefault())
|
||||
val filteredApps = apps.asSequence()
|
||||
.filterHiddenApps(queryTextLower, hiddenApps, hiddenAppsInSearch)
|
||||
.toList()
|
||||
val matches = FuzzySearch.extractSorted(
|
||||
queryTextLower,
|
||||
filteredApps,
|
||||
{ it.sectionName + it.title },
|
||||
WeightedRatio(),
|
||||
65,
|
||||
)
|
||||
|
||||
return matches.take(maxResultsCount)
|
||||
.map { it.referent }
|
||||
}
|
||||
|
||||
private fun getShortcuts(app: AppInfo, context: Context): List<ShortcutInfo> {
|
||||
val shortcuts = ShortcutRequest(context.launcher, app.user)
|
||||
.withContainer(app.targetComponent)
|
||||
.query(ShortcutRequest.PUBLISHED)
|
||||
return PopupPopulator.sortAndFilterShortcuts(shortcuts)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user