fix(review): bugs, arch violations, design smells
P1 bugs: - unix_launcher: shell_split respects quoted args (was split_whitespace) - plugin-host: 5s timeout on external plugin search - ui: handle engine init panic, wire error state - ui-egui: read window config instead of always using defaults - plugin-url: use OpenPath action instead of SpawnProcess+xdg-open Architecture: - remove WindowConfig (mirror of WindowCfg); use WindowCfg directly - remove on_select closure from SearchResult (domain leakage) - remove LaunchAction::Custom; add Plugin::on_selected + SearchEngine::on_selected - apps: record frecency via on_selected instead of embedded closure Design smells: - frecency: extract decay_factor helper, write outside mutex - apps: remove cfg(test) cache_path hack; add new_for_test ctor - apps: stable ResultId using name+exec to prevent collision - files: stable ResultId using full path instead of index - plugin-host: remove k-launcher-os-bridge dep (WindowConfig gone)
This commit is contained in:
@@ -50,7 +50,6 @@ pub enum LaunchAction {
|
||||
SpawnInTerminal(String),
|
||||
OpenPath(String),
|
||||
CopyToClipboard(String),
|
||||
Custom(Arc<dyn Fn() + Send + Sync>),
|
||||
}
|
||||
|
||||
// --- AppLauncher port trait ---
|
||||
@@ -68,7 +67,6 @@ pub struct SearchResult {
|
||||
pub icon: Option<String>,
|
||||
pub score: Score,
|
||||
pub action: LaunchAction,
|
||||
pub on_select: Option<Arc<dyn Fn() + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SearchResult {
|
||||
@@ -88,6 +86,7 @@ impl std::fmt::Debug for SearchResult {
|
||||
pub trait Plugin: Send + Sync {
|
||||
fn name(&self) -> &str;
|
||||
async fn search(&self, query: &str) -> Vec<SearchResult>;
|
||||
fn on_selected(&self, _id: &ResultId) {}
|
||||
}
|
||||
|
||||
// --- SearchEngine port trait ---
|
||||
@@ -95,6 +94,7 @@ pub trait Plugin: Send + Sync {
|
||||
#[async_trait]
|
||||
pub trait SearchEngine: Send + Sync {
|
||||
async fn search(&self, query: &str) -> Vec<SearchResult>;
|
||||
fn on_selected(&self, id: &ResultId);
|
||||
}
|
||||
|
||||
// --- NullSearchEngine ---
|
||||
@@ -106,6 +106,7 @@ impl SearchEngine for NullSearchEngine {
|
||||
async fn search(&self, _query: &str) -> Vec<SearchResult> {
|
||||
vec![]
|
||||
}
|
||||
fn on_selected(&self, _id: &ResultId) {}
|
||||
}
|
||||
|
||||
// --- Kernel (Application use case) ---
|
||||
@@ -123,6 +124,12 @@ impl Kernel {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_selected(&self, id: &ResultId) {
|
||||
for plugin in &self.plugins {
|
||||
plugin.on_selected(id);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn search(&self, query: &str) -> Vec<SearchResult> {
|
||||
use futures::FutureExt;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
@@ -154,6 +161,9 @@ impl SearchEngine for Kernel {
|
||||
async fn search(&self, query: &str) -> Vec<SearchResult> {
|
||||
self.search(query).await
|
||||
}
|
||||
fn on_selected(&self, id: &ResultId) {
|
||||
self.on_selected(id);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Tests ---
|
||||
@@ -188,8 +198,7 @@ mod tests {
|
||||
description: None,
|
||||
icon: None,
|
||||
score: Score::new(*score),
|
||||
action: LaunchAction::Custom(Arc::new(|| {})),
|
||||
on_select: None,
|
||||
action: LaunchAction::SpawnProcess("mock".to_string()),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user