Make fuzzy search optional

This commit is contained in:
Suphon Thanakornpakapong
2021-06-06 01:05:57 +07:00
parent b31b245b6e
commit 5d2c72afcd
6 changed files with 57 additions and 20 deletions

View File

@@ -89,4 +89,6 @@
<string name="dt2s_warning_open_settings">Open Settings</string>
<string name="minus_one_enable">Show Feed</string>
<string name="minus_one_unavailable">Feed is not available</string>
<string name="fuzzy_search_title">Fuzzy Search</string>
<string name="fuzzy_search_desc">Use fuzzy matching to search for apps</string>
</resources>

View File

@@ -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<AppInfo>) : DefaultAppSearchAlgorithm(apps) {
private val useFuzzySearch by PreferenceManager.getInstance(context).useFuzzySearch
override fun getTitleMatchResult(query: String): ArrayList<ComponentKey> {
if (!useFuzzySearch) return super.getTitleMatchResult(query)
// Run a fuzzy search on all available titles using the Winkler-Jaro algorithm
val result = ArrayList<ComponentKey>()
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
}
}

View File

@@ -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)
}

View File

@@ -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(),

View File

@@ -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)

View File

@@ -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<AppInfo> mApps;
protected final List<AppInfo> mApps;
protected final Handler mResultHandler;
public DefaultAppSearchAlgorithm(List<AppInfo> 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<ComponentKey> result = getTitleMatchResult(query);
mResultHandler.post(() -> callback.onSearchResult(query, result));
mResultHandler.post(new Runnable() {
@Override
public void run() {
callback.onSearchResult(query, result);
}
});
}
private ArrayList<ComponentKey> getTitleMatchResult(String query) {
// Run a fuzzy search on all available titles using the Winkler-Jaro algorithm
protected ArrayList<ComponentKey> 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<ComponentKey> result = new ArrayList<>();
final List<BoundExtractedResult<AppInfo>> matches = FuzzySearch.extractSorted(query.toLowerCase(), mApps,
item -> item.title.toString(), new WeightedRatio(), 65);
for (BoundExtractedResult<AppInfo> 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;
}