Skip to content

Commit cd00ada

Browse files
authored
feat: return sub-exts when extension type exts themselves are matched (#928)
Take the 'Spotify Control' extension as an example: - Spotify Control - Toggle Play/Pause - Next Track - Previous Track Previously, these sub-extensions were only returned when the query string matched them, and thus counterintuitively, searching for 'Spotify Control' would not hit them. This commit changes that behavior: when a main extension (of type Extension) matches the query, all of its sub-extensions are now included in the results.
1 parent be66111 commit cd00ada

5 files changed

Lines changed: 71 additions & 19 deletions

File tree

docs/content.en/docs/release-notes/_index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ feat: support switching groups via keyboard shortcuts #911
1717
feat: support opening logs from about page #915
1818
feat: support moving cursor with home and end keys #918
1919
feat: support pageup/pagedown to navigate search results #920
20+
feat: return sub-exts when extension type exts themselves are matched #928
2021

2122
### 🐛 Bug fix
2223

src-tauri/src/extension/built_in/window_management/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use tauri_plugin_global_shortcut::GlobalShortcutExt;
2828
use tauri_plugin_global_shortcut::ShortcutState;
2929

3030
pub(crate) const EXTENSION_ID: &str = "Window Management";
31+
pub(crate) const EXTENSION_NAME_LOWERCASE: &str = "window management";
3132

3233
/// JSON file for this extension.
3334
pub(crate) const PLUGIN_JSON_FILE: &str = include_str!("./plugin.json");

src-tauri/src/extension/built_in/window_management/search_source.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::EXTENSION_ID;
2+
use super::EXTENSION_NAME_LOWERCASE;
23
use crate::common::document::{DataSourceReference, Document};
34
use crate::common::{
45
error::SearchError,
@@ -81,6 +82,16 @@ impl SearchSource for WindowManagementSearchSource {
8182
}
8283
}
8384

85+
// An "extension" type extension should return all its
86+
// sub-extensions when the query string matches its name.
87+
// To do this, we score the extension name and take that
88+
// into account.
89+
if let Some(main_extension_score) =
90+
calculate_text_similarity(&query_string_lowercase, &EXTENSION_NAME_LOWERCASE)
91+
{
92+
score += main_extension_score;
93+
}
94+
8495
score
8596
};
8697

src-tauri/src/extension/third_party/mod.rs

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::common::search::QuerySource;
1515
use crate::common::search::SearchQuery;
1616
use crate::common::traits::SearchSource;
1717
use crate::extension::ExtensionBundleIdBorrowed;
18+
use crate::extension::ExtensionType;
1819
use crate::extension::calculate_text_similarity;
1920
use crate::extension::canonicalize_relative_page_path;
2021
use crate::util::platform::Platform;
@@ -757,21 +758,35 @@ impl SearchSource for ThirdPartyExtensionsSearchSource {
757758

758759
for extension in extensions_read_lock.iter().filter(|ext| ext.enabled) {
759760
if extension.r#type.contains_sub_items() {
761+
let opt_main_extension_lowercase_name =
762+
if extension.r#type == ExtensionType::Extension {
763+
Some(extension.name.to_lowercase())
764+
} else {
765+
// None if it is of type `ExtensionType::Group`
766+
None
767+
};
768+
760769
if let Some(ref commands) = extension.commands {
761770
for command in commands.iter().filter(|cmd| cmd.enabled) {
762-
if let Some(hit) =
763-
extension_to_hit(command, &query_lower, opt_data_source.as_deref())
764-
{
771+
if let Some(hit) = extension_to_hit(
772+
command,
773+
&query_lower,
774+
opt_data_source.as_deref(),
775+
opt_main_extension_lowercase_name.as_deref(),
776+
) {
765777
hits.push(hit);
766778
}
767779
}
768780
}
769781

770782
if let Some(ref scripts) = extension.scripts {
771783
for script in scripts.iter().filter(|script| script.enabled) {
772-
if let Some(hit) =
773-
extension_to_hit(script, &query_lower, opt_data_source.as_deref())
774-
{
784+
if let Some(hit) = extension_to_hit(
785+
script,
786+
&query_lower,
787+
opt_data_source.as_deref(),
788+
opt_main_extension_lowercase_name.as_deref(),
789+
) {
775790
hits.push(hit);
776791
}
777792
}
@@ -783,6 +798,7 @@ impl SearchSource for ThirdPartyExtensionsSearchSource {
783798
quicklink,
784799
&query_lower,
785800
opt_data_source.as_deref(),
801+
opt_main_extension_lowercase_name.as_deref(),
786802
) {
787803
hits.push(hit);
788804
}
@@ -791,16 +807,19 @@ impl SearchSource for ThirdPartyExtensionsSearchSource {
791807

792808
if let Some(ref views) = extension.views {
793809
for view in views.iter().filter(|link| link.enabled) {
794-
if let Some(hit) =
795-
extension_to_hit(view, &query_lower, opt_data_source.as_deref())
796-
{
810+
if let Some(hit) = extension_to_hit(
811+
view,
812+
&query_lower,
813+
opt_data_source.as_deref(),
814+
opt_main_extension_lowercase_name.as_deref(),
815+
) {
797816
hits.push(hit);
798817
}
799818
}
800819
}
801820
} else {
802821
if let Some(hit) =
803-
extension_to_hit(extension, &query_lower, opt_data_source.as_deref())
822+
extension_to_hit(extension, &query_lower, opt_data_source.as_deref(), None)
804823
{
805824
hits.push(hit);
806825
}
@@ -839,10 +858,18 @@ pub(crate) async fn uninstall_extension(
839858
.await
840859
}
841860

861+
/// Argument `opt_main_extension_lowercase_name`: If `extension` is a sub-extension
862+
/// of an `extension` type extension, then this argument contains the lowercase
863+
/// name of that extension. Otherwise, None.
864+
///
865+
/// This argument is needed as an "extension" type extension should return all its
866+
/// sub-extensions when the query string matches its name. To do this, we pass the
867+
/// extension name, score it and take that into account.
842868
pub(crate) fn extension_to_hit(
843869
extension: &Extension,
844870
query_lower: &str,
845871
opt_data_source: Option<&str>,
872+
opt_main_extension_lowercase_name: Option<&str>,
846873
) -> Option<(Document, f64)> {
847874
if !extension.searchable() {
848875
return None;
@@ -865,14 +892,26 @@ pub(crate) fn extension_to_hit(
865892
if let Some(title_score) =
866893
calculate_text_similarity(&query_lower, &extension.name.to_lowercase())
867894
{
868-
total_score += title_score * 1.0; // Weight for title
895+
total_score += title_score;
869896
}
870897

871898
// Score based on alias match if available
872899
// Alias is considered less important than title, so it gets a lower weight.
873900
if let Some(alias) = &extension.alias {
874901
if let Some(alias_score) = calculate_text_similarity(&query_lower, &alias.to_lowercase()) {
875-
total_score += alias_score * 0.7; // Weight for alias
902+
total_score += alias_score;
903+
}
904+
}
905+
906+
// An "extension" type extension should return all its
907+
// sub-extensions when the query string matches its ID.
908+
// To do this, we score the extension ID and take that
909+
// into account.
910+
if let Some(main_extension_lowercase_id) = opt_main_extension_lowercase_name {
911+
if let Some(main_extension_score) =
912+
calculate_text_similarity(&query_lower, main_extension_lowercase_id)
913+
{
914+
total_score += main_extension_score;
876915
}
877916
}
878917

src-tauri/src/search/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,6 @@ async fn query_coco_fusion_multi_query_sources(
265265
});
266266
}
267267

268-
/*
269-
* Re-rank the hits
270-
*/
271-
if n_sources > 1 {
272-
boosted_levenshtein_rerank(&query_keyword, &mut all_hits_grouped_by_source_id);
273-
}
274-
275268
/*
276269
* Sort hits within each source by score (descending) in case data sources
277270
* do not sort them
@@ -363,6 +356,13 @@ async fn query_coco_fusion_multi_query_sources(
363356
}
364357
}
365358

359+
/*
360+
* Re-rank the final hits
361+
*/
362+
if n_sources > 1 {
363+
boosted_levenshtein_rerank(&query_keyword, &mut final_hits_grouped_by_source_id);
364+
}
365+
366366
let mut final_hits = Vec::new();
367367
for (_source_id, hits) in final_hits_grouped_by_source_id {
368368
final_hits.extend(hits);

0 commit comments

Comments
 (0)