mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-22 08:38:29 +02:00
Add plugin API to open URL in external browser (#340)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -53,6 +53,7 @@ export interface Context {
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
},
|
},
|
||||||
): Promise<{ close: () => void }>;
|
): Promise<{ close: () => void }>;
|
||||||
|
openExternalUrl(url: string): Promise<void>;
|
||||||
};
|
};
|
||||||
cookies: {
|
cookies: {
|
||||||
listNames(): Promise<ListCookieNamesResponse['names']>;
|
listNames(): Promise<ListCookieNamesResponse['names']>;
|
||||||
|
|||||||
@@ -646,6 +646,12 @@ export class PluginInstance {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
openExternalUrl: async (url) => {
|
||||||
|
await this.#sendForReply(context, {
|
||||||
|
type: 'open_external_url_request',
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
prompt: {
|
prompt: {
|
||||||
text: async (args) => {
|
text: async (args) => {
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ pub enum Error {
|
|||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ClipboardError(#[from] tauri_plugin_clipboard_manager::Error),
|
ClipboardError(#[from] tauri_plugin_clipboard_manager::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
OpenerError(#[from] tauri_plugin_opener::Error),
|
||||||
|
|
||||||
#[error("Updater error: {0}")]
|
#[error("Updater error: {0}")]
|
||||||
UpdaterError(#[from] tauri_plugin_updater::Error),
|
UpdaterError(#[from] tauri_plugin_updater::Error),
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use cookie::Cookie;
|
|||||||
use log::error;
|
use log::error;
|
||||||
use tauri::{AppHandle, Emitter, Manager, Runtime};
|
use tauri::{AppHandle, Emitter, Manager, Runtime};
|
||||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||||
|
use tauri_plugin_opener::OpenerExt;
|
||||||
use yaak_common::window::WorkspaceWindowTrait;
|
use yaak_common::window::WorkspaceWindowTrait;
|
||||||
use yaak_models::blob_manager::BlobManagerExt;
|
use yaak_models::blob_manager::BlobManagerExt;
|
||||||
use yaak_models::models::{AnyModel, HttpResponse, Plugin};
|
use yaak_models::models::{AnyModel, HttpResponse, Plugin};
|
||||||
@@ -370,6 +371,10 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
|||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
InternalEventPayload::OpenExternalUrlRequest(req) => {
|
||||||
|
app_handle.opener().open_url(&req.url, None::<&str>)?;
|
||||||
|
Ok(Some(InternalEventPayload::OpenExternalUrlResponse(EmptyPayload {})))
|
||||||
|
}
|
||||||
InternalEventPayload::SetKeyValueRequest(req) => {
|
InternalEventPayload::SetKeyValueRequest(req) => {
|
||||||
let name = plugin_handle.info().name;
|
let name = plugin_handle.info().name;
|
||||||
app_handle.db().set_plugin_key_value(&name, &req.key, &req.value);
|
app_handle.db().set_plugin_key_value(&name, &req.key, &req.value);
|
||||||
|
|||||||
4
src-tauri/yaak-plugins/bindings/gen_events.ts
generated
4
src-tauri/yaak-plugins/bindings/gen_events.ts
generated
File diff suppressed because one or more lines are too long
@@ -153,6 +153,9 @@ pub enum InternalEventPayload {
|
|||||||
WindowCloseEvent,
|
WindowCloseEvent,
|
||||||
CloseWindowRequest(CloseWindowRequest),
|
CloseWindowRequest(CloseWindowRequest),
|
||||||
|
|
||||||
|
OpenExternalUrlRequest(OpenExternalUrlRequest),
|
||||||
|
OpenExternalUrlResponse(EmptyPayload),
|
||||||
|
|
||||||
ShowToastRequest(ShowToastRequest),
|
ShowToastRequest(ShowToastRequest),
|
||||||
ShowToastResponse(EmptyPayload),
|
ShowToastResponse(EmptyPayload),
|
||||||
|
|
||||||
@@ -492,6 +495,13 @@ pub struct OpenWindowRequest {
|
|||||||
pub data_dir_key: Option<String>,
|
pub data_dir_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
pub struct OpenExternalUrlRequest {
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
|
||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "gen_events.ts")]
|
#[ts(export, export_to = "gen_events.ts")]
|
||||||
|
|||||||
@@ -195,7 +195,24 @@ impl PluginManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(app_handle.db().list_plugins()?)
|
// Filter to only "available" plugins for this runtime context.
|
||||||
|
// The database stores all plugins globally (to persist enabled/disabled state),
|
||||||
|
// but we only want to load plugins that are actually present:
|
||||||
|
// 1. Bundled plugins from the current build/worktree
|
||||||
|
// 2. User-installed plugins (always available)
|
||||||
|
// This prevents duplicate plugin loading when switching between worktrees or builds.
|
||||||
|
let all_plugins = app_handle.db().list_plugins()?;
|
||||||
|
let available_plugins: Vec<Plugin> = all_plugins
|
||||||
|
.into_iter()
|
||||||
|
.filter(|plugin| {
|
||||||
|
let dir_path = Path::new(&plugin.directory);
|
||||||
|
let is_bundled = bundled_plugin_dirs.contains(&plugin.directory);
|
||||||
|
let is_installed = dir_path.starts_with(self.installed_plugin_dir.as_path());
|
||||||
|
is_bundled || is_installed
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(available_plugins)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
|
pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &str) -> Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user