mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-12 05:21:38 +01:00
Compare commits
1 Commits
wip/yaak-p
...
v2026.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8ba35e268 |
@@ -1383,13 +1383,12 @@ async fn cmd_reload_plugins<R: Runtime>(
|
||||
app_handle: AppHandle<R>,
|
||||
window: WebviewWindow<R>,
|
||||
plugin_manager: State<'_, PluginManager>,
|
||||
) -> YaakResult<()> {
|
||||
) -> YaakResult<Vec<(String, String)>> {
|
||||
let plugins = app_handle.db().list_plugins()?;
|
||||
let plugin_context =
|
||||
PluginContext::new(Some(window.label().to_string()), window.workspace_id());
|
||||
let _errors = plugin_manager.initialize_all_plugins(plugins, &plugin_context).await;
|
||||
// Note: errors are returned but we don't show toasts here since this is a manual reload
|
||||
Ok(())
|
||||
let errors = plugin_manager.initialize_all_plugins(plugins, &plugin_context).await;
|
||||
Ok(errors)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -1731,6 +1730,7 @@ pub fn run() {
|
||||
git_ext::cmd_git_rm_remote,
|
||||
//
|
||||
// Plugin commands
|
||||
plugins_ext::cmd_plugin_init_errors,
|
||||
plugins_ext::cmd_plugins_install_from_directory,
|
||||
plugins_ext::cmd_plugins_search,
|
||||
plugins_ext::cmd_plugins_install,
|
||||
|
||||
@@ -198,6 +198,13 @@ pub async fn cmd_plugins_uninstall<R: Runtime>(
|
||||
Ok(delete_and_uninstall(plugin_manager, &query_manager, &plugin_context, plugin_id).await?)
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn cmd_plugin_init_errors(
|
||||
plugin_manager: State<'_, PluginManager>,
|
||||
) -> Result<Vec<(String, String)>> {
|
||||
Ok(plugin_manager.take_init_errors().await)
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub async fn cmd_plugins_updates<R: Runtime>(
|
||||
app_handle: AppHandle<R>,
|
||||
@@ -306,7 +313,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
dev_mode,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to initialize plugins");
|
||||
.expect("Failed to start plugin runtime");
|
||||
|
||||
app_handle_clone.manage(manager);
|
||||
});
|
||||
|
||||
@@ -50,6 +50,8 @@ pub struct PluginManager {
|
||||
vendored_plugin_dir: PathBuf,
|
||||
pub(crate) installed_plugin_dir: PathBuf,
|
||||
dev_mode: bool,
|
||||
/// Errors from plugin initialization, retrievable once via `take_init_errors`.
|
||||
init_errors: Arc<Mutex<Vec<(String, String)>>>,
|
||||
}
|
||||
|
||||
/// Callback for plugin initialization events (e.g., toast notifications)
|
||||
@@ -93,6 +95,7 @@ impl PluginManager {
|
||||
vendored_plugin_dir,
|
||||
installed_plugin_dir,
|
||||
dev_mode,
|
||||
init_errors: Default::default(),
|
||||
};
|
||||
|
||||
// Forward events to subscribers
|
||||
@@ -183,17 +186,21 @@ impl PluginManager {
|
||||
|
||||
let init_errors = plugin_manager.initialize_all_plugins(plugins, plugin_context).await;
|
||||
if !init_errors.is_empty() {
|
||||
let joined = init_errors
|
||||
.into_iter()
|
||||
.map(|(dir, err)| format!("{dir}: {err}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("; ");
|
||||
return Err(PluginErr(format!("Failed to initialize plugin(s): {joined}")));
|
||||
for (dir, err) in &init_errors {
|
||||
warn!("Plugin failed to initialize: {dir}: {err}");
|
||||
}
|
||||
*plugin_manager.init_errors.lock().await = init_errors;
|
||||
}
|
||||
|
||||
Ok(plugin_manager)
|
||||
}
|
||||
|
||||
/// Take any initialization errors, clearing them from the manager.
|
||||
/// Returns a list of `(plugin_directory, error_message)` pairs.
|
||||
pub async fn take_init_errors(&self) -> Vec<(String, String)> {
|
||||
std::mem::take(&mut *self.init_errors.lock().await)
|
||||
}
|
||||
|
||||
/// Get the vendored plugin directory path (resolves dev mode path if applicable)
|
||||
pub fn get_plugins_dir(&self) -> PathBuf {
|
||||
if self.dev_mode {
|
||||
|
||||
@@ -123,6 +123,39 @@ export function initGlobalListeners() {
|
||||
console.log('Got plugin updates event', payload);
|
||||
showPluginUpdatesToast(payload);
|
||||
});
|
||||
|
||||
// Check for plugin initialization errors
|
||||
invokeCmd<[string, string][]>('cmd_plugin_init_errors').then((errors) => {
|
||||
for (const [dir, message] of errors) {
|
||||
const dirBasename = dir.split('/').pop() ?? dir;
|
||||
showToast({
|
||||
id: `plugin-init-error-${dirBasename}`,
|
||||
color: 'warning',
|
||||
timeout: null,
|
||||
message: (
|
||||
<VStack>
|
||||
<h2 className="font-semibold">Plugin failed to load</h2>
|
||||
<p className="text-text-subtle text-sm">
|
||||
{dirBasename}: {message}
|
||||
</p>
|
||||
</VStack>
|
||||
),
|
||||
action: ({ hide }) => (
|
||||
<Button
|
||||
size="xs"
|
||||
color="warning"
|
||||
variant="border"
|
||||
onClick={() => {
|
||||
hide();
|
||||
openSettings.mutate('plugins:installed');
|
||||
}}
|
||||
>
|
||||
View Plugins
|
||||
</Button>
|
||||
),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showUpdateInstalledToast(version: string) {
|
||||
|
||||
@@ -42,6 +42,7 @@ type TauriCmd =
|
||||
| 'cmd_new_child_window'
|
||||
| 'cmd_new_main_window'
|
||||
| 'cmd_plugin_info'
|
||||
| 'cmd_plugin_init_errors'
|
||||
| 'cmd_reload_plugins'
|
||||
| 'cmd_render_template'
|
||||
| 'cmd_save_response'
|
||||
|
||||
Reference in New Issue
Block a user