diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index 967542d9ad..9858dcf0a6 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -89,4 +89,6 @@
Open Settings
Show Feed
Feed is not available
+ Fuzzy Search
+ Use fuzzy matching to search for apps
diff --git a/lawnchair/src/app/lawnchair/allapps/LawnchairAppSearchAlgorithm.kt b/lawnchair/src/app/lawnchair/allapps/LawnchairAppSearchAlgorithm.kt
new file mode 100644
index 0000000000..49cc85e5cb
--- /dev/null
+++ b/lawnchair/src/app/lawnchair/allapps/LawnchairAppSearchAlgorithm.kt
@@ -0,0 +1,28 @@
+package app.lawnchair.allapps
+
+import android.content.Context
+import app.lawnchair.util.preferences.PreferenceManager
+import com.android.launcher3.allapps.search.DefaultAppSearchAlgorithm
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.util.ComponentKey
+import me.xdrop.fuzzywuzzy.FuzzySearch
+import me.xdrop.fuzzywuzzy.algorithms.WeightedRatio
+import java.util.*
+
+class LawnchairAppSearchAlgorithm(context: Context, apps: MutableList) : DefaultAppSearchAlgorithm(apps) {
+
+ private val useFuzzySearch by PreferenceManager.getInstance(context).useFuzzySearch
+
+ override fun getTitleMatchResult(query: String): ArrayList {
+ if (!useFuzzySearch) return super.getTitleMatchResult(query)
+
+ // Run a fuzzy search on all available titles using the Winkler-Jaro algorithm
+ val result = ArrayList()
+ val matches = FuzzySearch.extractSorted(query.toLowerCase(Locale.getDefault()), mApps,
+ { it.title.toString() }, WeightedRatio(), 65)
+ for (match in matches) {
+ result.add(match.referent.toComponentKey())
+ }
+ return result
+ }
+}
diff --git a/lawnchair/src/app/lawnchair/nexuslauncher/AllAppsHotseatQsb.kt b/lawnchair/src/app/lawnchair/nexuslauncher/AllAppsHotseatQsb.kt
index 6b0729d82d..f27dddb477 100644
--- a/lawnchair/src/app/lawnchair/nexuslauncher/AllAppsHotseatQsb.kt
+++ b/lawnchair/src/app/lawnchair/nexuslauncher/AllAppsHotseatQsb.kt
@@ -15,6 +15,7 @@ import android.view.animation.Interpolator
import android.widget.EditText
import android.widget.FrameLayout
import androidx.recyclerview.widget.RecyclerView
+import app.lawnchair.allapps.LawnchairAppSearchAlgorithm
import app.lawnchair.util.preferences.PreferenceManager
import com.android.launcher3.*
import com.android.launcher3.allapps.AllAppsContainerView
@@ -92,7 +93,7 @@ class AllAppsHotseatQsb @JvmOverloads constructor(context: Context, attrs: Attri
mFallbackSearchView.elevation = initialElevation + elevationScale * initialElevation
}
})
- mSearchBarController.initialize(DefaultAppSearchAlgorithm(mApps.apps),
+ mSearchBarController.initialize(LawnchairAppSearchAlgorithm(context, mApps.apps),
mFallbackSearchView, Launcher.cast(mActivity), this)
}
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt
index 490d8e6be3..6ab3f3bbaf 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/AppDrawerPreferences.kt
@@ -21,10 +21,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
-import app.lawnchair.ui.preferences.components.NavigationActionPreference
-import app.lawnchair.ui.preferences.components.PreferenceGroup
-import app.lawnchair.ui.preferences.components.PreferenceLayout
-import app.lawnchair.ui.preferences.components.SliderPreference
+import app.lawnchair.ui.preferences.components.*
import app.lawnchair.util.Meta
import app.lawnchair.util.pageMeta
import app.lawnchair.util.preferences.getAdapter
@@ -55,6 +52,11 @@ fun AppDrawerPreferences() {
subtitle = resources.getQuantityString(R.plurals.apps_count, hiddenAppsCount(), hiddenAppsCount()),
destination = subRoute(name = AppDrawerRoutes.HIDDEN_APPS),
)
+ SwitchPreference(
+ adapter = prefs.useFuzzySearch.getAdapter(),
+ label = stringResource(id = R.string.fuzzy_search_title),
+ description = stringResource(id = R.string.fuzzy_search_desc)
+ )
SliderPreference(
label = stringResource(id = R.string.background_opacity),
adapter = prefs.drawerOpacity.getAdapter(),
diff --git a/lawnchair/src/app/lawnchair/util/preferences/PreferenceManager.kt b/lawnchair/src/app/lawnchair/util/preferences/PreferenceManager.kt
index 5a689c9f3e..b6461954e1 100644
--- a/lawnchair/src/app/lawnchair/util/preferences/PreferenceManager.kt
+++ b/lawnchair/src/app/lawnchair/util/preferences/PreferenceManager.kt
@@ -56,6 +56,7 @@ class PreferenceManager private constructor(context: Context) : BasePreferenceMa
val allAppsColumns = IdpIntPref("pref_allAppsColumns", { numAllAppsColumns }, reloadGrid)
val smartSpaceEnable = BoolPref("pref_smartSpaceEnable", true, scheduleRestart)
val minusOneEnable = BoolPref("pref_enableMinusOne", true)
+ val useFuzzySearch = BoolPref("pref_useFuzzySearch", false)
// TODO: Add the ability to manually delete empty pages.
val allowEmptyPages = BoolPref("pref_allowEmptyPages", false)
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 8e8693a8ec..31ddffb5b9 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -12,8 +12,6 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- *
- * Modifications copyright 2021, Lawnchair
*/
package com.android.launcher3.allapps.search;
@@ -26,16 +24,12 @@ import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
-import me.xdrop.fuzzywuzzy.FuzzySearch;
-import me.xdrop.fuzzywuzzy.algorithms.WeightedRatio;
-import me.xdrop.fuzzywuzzy.model.BoundExtractedResult;
-
/**
* The default search implementation.
*/
public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
- private final List mApps;
+ protected final List mApps;
protected final Handler mResultHandler;
public DefaultAppSearchAlgorithm(List apps) {
@@ -52,18 +46,27 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm {
@Override
public void doSearch(final String query,
- final AllAppsSearchBarController.Callbacks callback) {
+ final AllAppsSearchBarController.Callbacks callback) {
final ArrayList result = getTitleMatchResult(query);
- mResultHandler.post(() -> callback.onSearchResult(query, result));
+ mResultHandler.post(new Runnable() {
+
+ @Override
+ public void run() {
+ callback.onSearchResult(query, result);
+ }
+ });
}
- private ArrayList getTitleMatchResult(String query) {
- // Run a fuzzy search on all available titles using the Winkler-Jaro algorithm
+ protected ArrayList getTitleMatchResult(String query) {
+ // 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.
+ final String queryTextLower = query.toLowerCase();
final ArrayList result = new ArrayList<>();
- final List> matches = FuzzySearch.extractSorted(query.toLowerCase(), mApps,
- item -> item.title.toString(), new WeightedRatio(), 65);
- for (BoundExtractedResult match : matches) {
- result.add(match.getReferent().toComponentKey());
+ StringMatcher matcher = StringMatcher.getInstance();
+ for (AppInfo info : mApps) {
+ if (matches(info, queryTextLower, matcher)) {
+ result.add(info.toComponentKey());
+ }
}
return result;
}