diff --git a/bundled_plugins/gauntlet/gauntlet.toml b/bundled_plugins/gauntlet/gauntlet.toml index 28bc064..1859162 100644 --- a/bundled_plugins/gauntlet/gauntlet.toml +++ b/bundled_plugins/gauntlet/gauntlet.toml @@ -29,7 +29,7 @@ enum_values = [ [[entrypoint]] id = 'windows' -name = 'All Open Windows' +name = 'Open Windows' path = 'src/windows.tsx' type = 'view' description = 'Show all open windows' diff --git a/bundled_plugins/gauntlet/src/window/shared.tsx b/bundled_plugins/gauntlet/src/window/shared.tsx index 136d25d..eecb927 100644 --- a/bundled_plugins/gauntlet/src/window/shared.tsx +++ b/bundled_plugins/gauntlet/src/window/shared.tsx @@ -18,7 +18,6 @@ export function ListOfWindows({ windows, focus }: { windows: OpenWindowData[], f onAction={(id: string | undefined) => { if (id) { focus(id) - console.log("focus: " + id) return { close: true } } }} @@ -123,9 +122,9 @@ export function applicationAccessories(id: string, experimentalWindowTracking: b if (appWindows.length == 0) { return [] } else if (appWindows.length == 1) { - return [{ text: "1 window open" }] + return [{ text: "1 window" }] } else if (appWindows.length > 1) { - return [{ text: `${appWindows.length} windows open` }] + return [{ text: `${appWindows.length} windows` }] } else { return [] } @@ -182,4 +181,4 @@ export function openLinuxApplication(appId: string) { return () => { linux_open_application(appId) } -} \ No newline at end of file +} diff --git a/js/api/src/helpers.ts b/js/api/src/helpers.ts index fa9c3b4..b662267 100644 --- a/js/api/src/helpers.ts +++ b/js/api/src/helpers.ts @@ -84,7 +84,7 @@ export const Clipboard: Clipboard = { } if (data.png_data) { - result["image/png"] = new Uint8Array(data.png_data).buffer; + result["image/png"] = data.png_data; } return result @@ -92,18 +92,18 @@ export const Clipboard: Clipboard = { readText: async function (): Promise { return await clipboard_read_text() }, - write: async function (data: { "text/plain"?: string | undefined; "image/png"?: ArrayBuffer | undefined; }): Promise { + write: async function (data: { "text/plain"?: string | undefined; "image/png"?: Uint8Array | undefined; }): Promise { const text_data = data["text/plain"]; const png_data = data["image/png"]; - const write_data: { text_data?: string, png_data?: number[] } = {}; + const write_data: { text_data?: string, png_data?: ArrayBuffer } = {}; if (text_data) { write_data.text_data = text_data; } if (png_data) { - write_data.png_data = Array.from(new Uint8Array(png_data)); + write_data.png_data = png_data; } return await clipboard_write(write_data) diff --git a/js/react_renderer/src/renderer.ts b/js/react_renderer/src/renderer.ts index 0ac0984..6e8fb7a 100644 --- a/js/react_renderer/src/renderer.ts +++ b/js/react_renderer/src/renderer.ts @@ -117,13 +117,11 @@ export function useGauntletContext() { } export async function getAssetData(path: string): Promise { - const vecU8 = await asset_data(path); - return new Uint8Array(vecU8).buffer; // FIXME move array creation into rust if possible + return await asset_data(path); } export function getAssetDataSync(path: string): ArrayBuffer { - const vecU8 = asset_data_blocking(path); - return new Uint8Array(vecU8).buffer; + return asset_data_blocking(path); } export function getPluginPreferences(): Record { diff --git a/js/typings/index.d.ts b/js/typings/index.d.ts index 4f8652a..66c0542 100644 --- a/js/typings/index.d.ts +++ b/js/typings/index.d.ts @@ -219,8 +219,8 @@ declare module "ext:core/ops" { function op_log_error(target: string, message: string): void; function op_component_model(): Record; - function asset_data(path: string): Promise; - function asset_data_blocking(path: string): number[]; + function asset_data(path: string): Promise; + function asset_data_blocking(path: string): ArrayBuffer; function op_inline_view_entrypoint_id(): string | null; function op_entrypoint_names(): Record; @@ -246,9 +246,9 @@ declare module "ext:core/ops" { function fetch_action_id_for_shortcut(entrypointId: string, key: string, modifierShift: boolean, modifierControl: boolean, modifierAlt: boolean, modifierMeta: boolean): Promise; - function clipboard_read(): Promise<{ text_data?: string, png_data?: number[] }>; + function clipboard_read(): Promise<{ text_data?: string, png_data?: ArrayBuffer }>; function clipboard_read_text(): Promise; - function clipboard_write(data: { text_data?: string, png_data?: number[] }): Promise; + function clipboard_write(data: { text_data?: string, png_data?: ArrayBuffer }): Promise; function clipboard_write_text(data: string): Promise; function clipboard_clear(): Promise; diff --git a/rust/plugin_runtime/src/assets.rs b/rust/plugin_runtime/src/assets.rs index cfa8aee..89a2090 100644 --- a/rust/plugin_runtime/src/assets.rs +++ b/rust/plugin_runtime/src/assets.rs @@ -43,6 +43,6 @@ pub fn asset_data_blocking(state: Rc>, #[string] path: String) outer_handle.block_on(async { let data = api.get_asset_data(&path).await?; - Ok(data) + Ok(data.into()) }) } diff --git a/rust/plugin_runtime/src/clipboard.rs b/rust/plugin_runtime/src/clipboard.rs index 22e8298..cad0bb4 100644 --- a/rust/plugin_runtime/src/clipboard.rs +++ b/rust/plugin_runtime/src/clipboard.rs @@ -3,22 +3,16 @@ use std::rc::Rc; use deno_core::op2; use deno_core::OpState; -use serde::Deserialize; -use serde::Serialize; use crate::api::BackendForPluginRuntimeApi; use crate::api::BackendForPluginRuntimeApiProxy; -use crate::model::JsClipboardData; - -#[derive(Debug, Serialize, Deserialize)] -struct JSClipboardData { - text_data: Option, - png_data: Option>, -} +use crate::DenoInClipboardData; +use crate::DenoOutClipboardData; +use crate::JsClipboardData; #[op2(async)] #[serde] -pub async fn clipboard_read(state: Rc>) -> anyhow::Result { +pub async fn clipboard_read(state: Rc>) -> anyhow::Result { let api = { let state = state.borrow(); @@ -29,9 +23,9 @@ pub async fn clipboard_read(state: Rc>) -> anyhow::Result>) -> anyhow::Result< } #[op2(async)] -pub async fn clipboard_write(state: Rc>, #[serde] data: JSClipboardData) -> anyhow::Result<()> { +pub async fn clipboard_write(state: Rc>, #[serde] data: DenoInClipboardData) -> anyhow::Result<()> { let api = { let state = state.borrow(); @@ -61,7 +55,7 @@ pub async fn clipboard_write(state: Rc>, #[serde] data: JSClipb let clipboard_data = JsClipboardData { text_data: data.text_data, - png_data: data.png_data, + png_data: data.png_data.map(|buffer| buffer.to_vec()), }; api.clipboard_write(clipboard_data).await diff --git a/rust/plugin_runtime/src/model.rs b/rust/plugin_runtime/src/model.rs index 1294429..108dacf 100644 --- a/rust/plugin_runtime/src/model.rs +++ b/rust/plugin_runtime/src/model.rs @@ -3,6 +3,8 @@ use std::fmt; use bincode::Decode; use bincode::Encode; +use deno_core::JsBuffer; +use deno_core::ToJsBuffer; use gauntlet_common::model::EntrypointId; use gauntlet_common::model::Icons; use gauntlet_common::model::PluginId; @@ -174,7 +176,7 @@ pub enum JsRequest { }, } -#[derive(Deserialize, Serialize, Encode, Decode)] +#[derive(Encode, Decode)] pub struct JsGeneratedSearchItem { pub entrypoint_name: String, pub generator_entrypoint_id: String, @@ -199,6 +201,28 @@ impl fmt::Debug for JsGeneratedSearchItem { } } +#[derive(Serialize)] +pub struct DenoOutGeneratedSearchItem { + pub entrypoint_name: String, + pub generator_entrypoint_id: String, + pub entrypoint_id: String, + pub entrypoint_uuid: String, + pub entrypoint_icon: Option, + pub entrypoint_actions: Vec, + pub entrypoint_accessories: Vec, +} + +#[derive(Deserialize)] +pub struct DenoInGeneratedSearchItem { + pub entrypoint_name: String, + pub generator_entrypoint_id: String, + pub entrypoint_id: String, + pub entrypoint_uuid: String, + pub entrypoint_icon: Option, + pub entrypoint_actions: Vec, + pub entrypoint_accessories: Vec, +} + #[derive(Debug, Deserialize, Serialize, Encode, Decode)] pub struct JsGeneratedSearchItemAction { pub id: Option, @@ -236,8 +260,20 @@ pub enum JsGeneratedSearchItemAccessory { }, } -#[derive(Debug, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Encode, Decode)] pub struct JsClipboardData { pub text_data: Option, pub png_data: Option>, } + +#[derive(Serialize)] +pub struct DenoOutClipboardData { + pub text_data: Option, + pub png_data: Option, +} + +#[derive(Deserialize)] +pub struct DenoInClipboardData { + pub text_data: Option, + pub png_data: Option, +} diff --git a/rust/plugin_runtime/src/plugins/applications.rs b/rust/plugin_runtime/src/plugins/applications.rs index 264622b..0d7dd23 100644 --- a/rust/plugin_runtime/src/plugins/applications.rs +++ b/rust/plugin_runtime/src/plugins/applications.rs @@ -5,6 +5,7 @@ use std::rc::Rc; use anyhow::anyhow; use deno_core::op2; use deno_core::OpState; +use deno_core::ToJsBuffer; use gauntlet_common::detached_process::CommandExt; use image::imageops::FilterType; use image::ImageFormat; @@ -46,7 +47,7 @@ pub enum DesktopPathAction { pub struct DesktopApplication { name: String, desktop_file_path: String, - icon: Option>, + icon: Option, startup_wm_class: Option, } @@ -55,7 +56,7 @@ pub struct DesktopApplication { pub struct DesktopApplication { name: String, path: String, - icon: Option>, + icon: Option, } #[cfg(target_os = "windows")] @@ -63,7 +64,7 @@ pub struct DesktopApplication { pub struct DesktopApplication { name: String, path: String, - icon: Option>, + icon: Option, } #[cfg(target_os = "macos")] @@ -71,7 +72,7 @@ pub struct DesktopApplication { pub struct DesktopSettingsPre13Data { name: String, path: String, - icon: Option>, + icon: Option, } #[cfg(target_os = "macos")] @@ -79,7 +80,7 @@ pub struct DesktopSettingsPre13Data { pub struct DesktopSettings13AndPostData { name: String, preferences_id: String, - icon: Option>, + icon: Option, } #[op2] diff --git a/rust/plugin_runtime/src/plugins/applications/linux/mod.rs b/rust/plugin_runtime/src/plugins/applications/linux/mod.rs index 2e1f195..7b64a1b 100644 --- a/rust/plugin_runtime/src/plugins/applications/linux/mod.rs +++ b/rust/plugin_runtime/src/plugins/applications/linux/mod.rs @@ -8,6 +8,7 @@ use std::rc::Rc; use deno_core::op2; use deno_core::OpState; +use deno_core::ToJsBuffer; use freedesktop_entry_parser::parse_entry; use freedesktop_icons::lookup; use gauntlet_common::detached_process::CommandExt; @@ -267,7 +268,8 @@ fn create_app_entry(desktop_file_path: &Path) -> Option { res.inspect_err(|err| tracing::warn!("error processing icon of {:?}: {:?}", desktop_file_path, err)) .ok() }) - .flatten(); + .flatten() + .map(|buffer| buffer.into()); Some(DesktopApplication { name: name.to_string(), diff --git a/rust/plugin_runtime/src/plugins/applications/macos.rs b/rust/plugin_runtime/src/plugins/applications/macos.rs index 9db37c3..59af25b 100644 --- a/rust/plugin_runtime/src/plugins/applications/macos.rs +++ b/rust/plugin_runtime/src/plugins/applications/macos.rs @@ -11,6 +11,7 @@ use cacao::filesystem::FileManager; use cacao::filesystem::SearchPathDirectory; use cacao::filesystem::SearchPathDomainMask; use cacao::url::Url; +use deno_core::ToJsBuffer; use objc2::ClassType; use objc2_app_kit::NSBitmapImageRep; use objc2_app_kit::NSCalibratedWhiteColorSpace; @@ -464,7 +465,7 @@ unsafe fn resize_ns_image(source_image: &NSImage, width: NSInteger, height: NSIn Some(data.bytes().to_vec()) } -fn get_application_icon(app_path: &Path) -> anyhow::Result> { +fn get_application_icon(app_path: &Path) -> anyhow::Result { unsafe { let workspace = NSWorkspace::sharedWorkspace(); @@ -478,7 +479,7 @@ fn get_application_icon(app_path: &Path) -> anyhow::Result> { let bytes = resize_ns_image(&image, 40, 40).ok_or(anyhow!("Unable to resize the image"))?; - Ok(bytes) + Ok(bytes.into()) } } diff --git a/rust/plugin_runtime/src/plugins/applications/windows.rs b/rust/plugin_runtime/src/plugins/applications/windows.rs index febb913..9d6a25c 100644 --- a/rust/plugin_runtime/src/plugins/applications/windows.rs +++ b/rust/plugin_runtime/src/plugins/applications/windows.rs @@ -7,6 +7,7 @@ use std::ptr; use anyhow::anyhow; use anyhow::Context; use deno_core::op2; +use deno_core::ToJsBuffer; use image::RgbaImage; use tokio::task::spawn_blocking; use windows::core::GUID; @@ -89,7 +90,7 @@ fn windows_app_from_path_blocking(file_path: String) -> anyhow::Result anyhow::Result> { +fn extract_icon(file_path: &str) -> anyhow::Result { unsafe { let mut shfileinfow = Shell::SHFILEINFOW::default(); @@ -188,7 +189,7 @@ fn extract_icon(file_path: &str) -> anyhow::Result> { let data = resize_icon(data)?; - Ok(data) + Ok(data.into()) } } diff --git a/rust/plugin_runtime/src/search.rs b/rust/plugin_runtime/src/search.rs index aa0f560..0c999f8 100644 --- a/rust/plugin_runtime/src/search.rs +++ b/rust/plugin_runtime/src/search.rs @@ -6,12 +6,13 @@ use deno_core::OpState; use crate::api::BackendForPluginRuntimeApi; use crate::api::BackendForPluginRuntimeApiProxy; -use crate::model::JsGeneratedSearchItem; +use crate::DenoInGeneratedSearchItem; +use crate::JsGeneratedSearchItem; #[op2(async)] pub async fn reload_search_index( state: Rc>, - #[serde] generated_entrypoints: Vec, + #[serde] generated_entrypoints: Vec, refresh_search_list: bool, ) -> anyhow::Result<()> { let api = { @@ -22,6 +23,21 @@ pub async fn reload_search_index( api }; + let generated_entrypoints = generated_entrypoints + .into_iter() + .map(|item| { + JsGeneratedSearchItem { + entrypoint_name: item.entrypoint_name, + generator_entrypoint_id: item.generator_entrypoint_id, + entrypoint_id: item.entrypoint_id, + entrypoint_uuid: item.entrypoint_uuid, + entrypoint_icon: item.entrypoint_icon.map(|buffer| buffer.to_vec()), + entrypoint_actions: item.entrypoint_actions, + entrypoint_accessories: item.entrypoint_accessories, + } + }) + .collect(); + api.reload_search_index(generated_entrypoints, refresh_search_list) .await?;