diff --git a/src/Core/Package.vala b/src/Core/Package.vala index d53075cea..296106453 100644 --- a/src/Core/Package.vala +++ b/src/Core/Package.vala @@ -95,6 +95,8 @@ public class AppCenterCore.Package : Object { public const string RUNTIME_UPDATES_ID = "xxx-runtime-updates"; public const string LOCAL_ID_SUFFIX = ".appcenter-local"; public const string DEFAULT_PRICE_DOLLARS = "1"; + public const uint EXACT_MATCH_SCORE = 100; + public const uint PARTIAL_MATCH_SCORE = 50; public string uid { get; construct; } @@ -599,8 +601,27 @@ public class AppCenterCore.Package : Object { var query_score = component.search_matches (query); if (query_score == 0) { - score = 0; - break; + var id_down = component.id.down (); + var name_down = component.name.down (); + var query_down = query.down (); + + /* + * Give extra score value if query is a substring, or if it + * matches exactly the component name or id. + * We multiply both by queries.length to negate the dilution made + * by cached_search_score when dividing by queries.length, thus + * making it a perfect EXACT_MATCH_SCORE or PARTIAL_MATCH_SCORE + * search value, since an exact or partial match should achieve + * the perfect score in any query token. + */ + if (query_down == name_down || query_down == id_down) { + query_score = EXACT_MATCH_SCORE * queries.length; + } else if ( + name_down.contains (query_down) || + id_down.contains (query_down) + ) { + query_score = PARTIAL_MATCH_SCORE * queries.length; + } } score += query_score; diff --git a/src/Core/SearchEngine.vala b/src/Core/SearchEngine.vala index 0d22c3eda..d98227689 100644 --- a/src/Core/SearchEngine.vala +++ b/src/Core/SearchEngine.vala @@ -57,6 +57,19 @@ public class AppCenterCore.SearchEngine : Object { public void search (string query, AppStream.Category? category) { this.query = pool.build_search_tokens (query); + /* + * If there are multiple tokens, add an additional joined query token. + * This is done because users tend to search queries for apps that have + * one name as separate with spaces. An example would be "LibreOffice", + * usually being searched as "Libre Office". Searching this shows the app + * as the 17th result instead of the first without a joined query. With + * the joined query (e.g. the search being "Libre Office LibreOffice") it + * will show up as the first search result. + */ + if (this.query.length > 1) { + var joined_query = query.replace (" ", ""); + this.query += joined_query; + } this.category = category; packages.items_changed (0, packages.n_items, packages.n_items); }