Unify Vec<u8> usage to ArrayBuffer in js. Fixes icon in EntrypointGenerator requiring number[]

This commit is contained in:
Exidex 2025-04-20 16:15:08 +02:00
parent 61eca05f42
commit b8f07d5028
No known key found for this signature in database
GPG key ID: AC63AA86DD4F2D45
13 changed files with 94 additions and 46 deletions

View file

@ -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'

View file

@ -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)
}
}
}

View file

@ -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<string | undefined> {
return await clipboard_read_text()
},
write: async function (data: { "text/plain"?: string | undefined; "image/png"?: ArrayBuffer | undefined; }): Promise<void> {
write: async function (data: { "text/plain"?: string | undefined; "image/png"?: Uint8Array | undefined; }): Promise<void> {
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)

View file

@ -117,13 +117,11 @@ export function useGauntletContext() {
}
export async function getAssetData(path: string): Promise<ArrayBuffer> {
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<string, any> {

View file

@ -219,8 +219,8 @@ declare module "ext:core/ops" {
function op_log_error(target: string, message: string): void;
function op_component_model(): Record<string, Component>;
function asset_data(path: string): Promise<number[]>;
function asset_data_blocking(path: string): number[];
function asset_data(path: string): Promise<ArrayBuffer>;
function asset_data_blocking(path: string): ArrayBuffer;
function op_inline_view_entrypoint_id(): string | null;
function op_entrypoint_names(): Record<string, string | undefined>;
@ -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<string | undefined>;
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<string | undefined>;
function clipboard_write(data: { text_data?: string, png_data?: number[] }): Promise<void>;
function clipboard_write(data: { text_data?: string, png_data?: ArrayBuffer }): Promise<void>;
function clipboard_write_text(data: string): Promise<void>;
function clipboard_clear(): Promise<void>;

View file

@ -43,6 +43,6 @@ pub fn asset_data_blocking(state: Rc<RefCell<OpState>>, #[string] path: String)
outer_handle.block_on(async {
let data = api.get_asset_data(&path).await?;
Ok(data)
Ok(data.into())
})
}

View file

@ -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<String>,
png_data: Option<Vec<u8>>,
}
use crate::DenoInClipboardData;
use crate::DenoOutClipboardData;
use crate::JsClipboardData;
#[op2(async)]
#[serde]
pub async fn clipboard_read(state: Rc<RefCell<OpState>>) -> anyhow::Result<JSClipboardData> {
pub async fn clipboard_read(state: Rc<RefCell<OpState>>) -> anyhow::Result<DenoOutClipboardData> {
let api = {
let state = state.borrow();
@ -29,9 +23,9 @@ pub async fn clipboard_read(state: Rc<RefCell<OpState>>) -> anyhow::Result<JSCli
let result = api.clipboard_read().await?;
Ok(JSClipboardData {
Ok(DenoOutClipboardData {
text_data: result.text_data,
png_data: result.png_data,
png_data: result.png_data.map(|buffer| buffer.into()),
})
}
@ -50,7 +44,7 @@ pub async fn clipboard_read_text(state: Rc<RefCell<OpState>>) -> anyhow::Result<
}
#[op2(async)]
pub async fn clipboard_write(state: Rc<RefCell<OpState>>, #[serde] data: JSClipboardData) -> anyhow::Result<()> {
pub async fn clipboard_write(state: Rc<RefCell<OpState>>, #[serde] data: DenoInClipboardData) -> anyhow::Result<()> {
let api = {
let state = state.borrow();
@ -61,7 +55,7 @@ pub async fn clipboard_write(state: Rc<RefCell<OpState>>, #[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

View file

@ -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<ToJsBuffer>,
pub entrypoint_actions: Vec<JsGeneratedSearchItemAction>,
pub entrypoint_accessories: Vec<JsGeneratedSearchItemAccessory>,
}
#[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<JsBuffer>,
pub entrypoint_actions: Vec<JsGeneratedSearchItemAction>,
pub entrypoint_accessories: Vec<JsGeneratedSearchItemAccessory>,
}
#[derive(Debug, Deserialize, Serialize, Encode, Decode)]
pub struct JsGeneratedSearchItemAction {
pub id: Option<String>,
@ -236,8 +260,20 @@ pub enum JsGeneratedSearchItemAccessory {
},
}
#[derive(Debug, Serialize, Deserialize, Encode, Decode)]
#[derive(Debug, Encode, Decode)]
pub struct JsClipboardData {
pub text_data: Option<String>,
pub png_data: Option<Vec<u8>>,
}
#[derive(Serialize)]
pub struct DenoOutClipboardData {
pub text_data: Option<String>,
pub png_data: Option<ToJsBuffer>,
}
#[derive(Deserialize)]
pub struct DenoInClipboardData {
pub text_data: Option<String>,
pub png_data: Option<JsBuffer>,
}

View file

@ -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<Vec<u8>>,
icon: Option<ToJsBuffer>,
startup_wm_class: Option<String>,
}
@ -55,7 +56,7 @@ pub struct DesktopApplication {
pub struct DesktopApplication {
name: String,
path: String,
icon: Option<Vec<u8>>,
icon: Option<ToJsBuffer>,
}
#[cfg(target_os = "windows")]
@ -63,7 +64,7 @@ pub struct DesktopApplication {
pub struct DesktopApplication {
name: String,
path: String,
icon: Option<Vec<u8>>,
icon: Option<ToJsBuffer>,
}
#[cfg(target_os = "macos")]
@ -71,7 +72,7 @@ pub struct DesktopApplication {
pub struct DesktopSettingsPre13Data {
name: String,
path: String,
icon: Option<Vec<u8>>,
icon: Option<ToJsBuffer>,
}
#[cfg(target_os = "macos")]
@ -79,7 +80,7 @@ pub struct DesktopSettingsPre13Data {
pub struct DesktopSettings13AndPostData {
name: String,
preferences_id: String,
icon: Option<Vec<u8>>,
icon: Option<ToJsBuffer>,
}
#[op2]

View file

@ -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<DesktopApplication> {
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(),

View file

@ -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<Vec<u8>> {
fn get_application_icon(app_path: &Path) -> anyhow::Result<ToJsBuffer> {
unsafe {
let workspace = NSWorkspace::sharedWorkspace();
@ -478,7 +479,7 @@ fn get_application_icon(app_path: &Path) -> anyhow::Result<Vec<u8>> {
let bytes = resize_ns_image(&image, 40, 40).ok_or(anyhow!("Unable to resize the image"))?;
Ok(bytes)
Ok(bytes.into())
}
}

View file

@ -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<Option<De
}
}
fn extract_icon(file_path: &str) -> anyhow::Result<Vec<u8>> {
fn extract_icon(file_path: &str) -> anyhow::Result<ToJsBuffer> {
unsafe {
let mut shfileinfow = Shell::SHFILEINFOW::default();
@ -188,7 +189,7 @@ fn extract_icon(file_path: &str) -> anyhow::Result<Vec<u8>> {
let data = resize_icon(data)?;
Ok(data)
Ok(data.into())
}
}

View file

@ -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<RefCell<OpState>>,
#[serde] generated_entrypoints: Vec<JsGeneratedSearchItem>,
#[serde] generated_entrypoints: Vec<DenoInGeneratedSearchItem>,
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?;