Get everything working

This commit is contained in:
Gregory Schier
2025-12-28 15:01:15 -08:00
parent 7446d62e39
commit 3c45464e34
11 changed files with 51 additions and 90 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
import type { CallWebSocketRequestActionArgs, WebSocketRequestAction } from '../bindings/gen_events'; import type { CallWebsocketRequestActionArgs, WebsocketRequestAction } from '../bindings/gen_events';
import type { Context } from './Context'; import type { Context } from './Context';
export type WebSocketRequestActionPlugin = WebSocketRequestAction & { export type WebsocketRequestActionPlugin = WebsocketRequestAction & {
onSelect(ctx: Context, args: CallWebSocketRequestActionArgs): Promise<void> | void; onSelect(ctx: Context, args: CallWebsocketRequestActionArgs): Promise<void> | void;
}; };

View File

@@ -4,7 +4,7 @@ import type { Context } from './Context';
import type { FilterPlugin } from './FilterPlugin'; import type { FilterPlugin } from './FilterPlugin';
import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin'; import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin';
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin'; import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
import type { WebSocketRequestActionPlugin } from './WebSocketRequestActionPlugin'; import type { WebsocketRequestActionPlugin } from './WebSocketRequestActionPlugin';
import type { WorkspaceActionPlugin } from './WorkspaceActionPlugin'; import type { WorkspaceActionPlugin } from './WorkspaceActionPlugin';
import type { FolderActionPlugin } from './FolderActionPlugin'; import type { FolderActionPlugin } from './FolderActionPlugin';
import type { ImporterPlugin } from './ImporterPlugin'; import type { ImporterPlugin } from './ImporterPlugin';
@@ -29,7 +29,7 @@ export type PluginDefinition = {
filter?: FilterPlugin; filter?: FilterPlugin;
authentication?: AuthenticationPlugin; authentication?: AuthenticationPlugin;
httpRequestActions?: HttpRequestActionPlugin[]; httpRequestActions?: HttpRequestActionPlugin[];
websocketRequestActions?: WebSocketRequestActionPlugin[]; websocketRequestActions?: WebsocketRequestActionPlugin[];
workspaceActions?: WorkspaceActionPlugin[]; workspaceActions?: WorkspaceActionPlugin[];
folderActions?: FolderActionPlugin[]; folderActions?: FolderActionPlugin[];
grpcRequestActions?: GrpcRequestActionPlugin[]; grpcRequestActions?: GrpcRequestActionPlugin[];

View File

@@ -22,45 +22,6 @@ export const plugin: PluginDefinition = {
}, },
}, },
], ],
websocketRequestActions: [
{
label: 'Test WebSocket Action',
icon: 'bug',
async onSelect(ctx, args) {
await ctx.toast.show({
message: `WebSocket action called for: ${args.websocketRequest.name}`,
icon: 'bug',
color: 'info',
});
},
},
],
workspaceActions: [
{
label: 'Test Workspace Action',
icon: 'bug',
async onSelect(ctx, args) {
await ctx.toast.show({
message: `Workspace action called for: ${args.workspace.name}`,
icon: 'bug',
color: 'info',
});
},
},
],
folderActions: [
{
label: 'Test Folder Action',
icon: 'bug',
async onSelect(ctx, args) {
await ctx.toast.show({
message: `Folder action called for: ${args.folder.name}`,
icon: 'bug',
color: 'info',
});
},
},
],
}; };
export async function convertToCurl(request: Partial<HttpRequest>) { export async function convertToCurl(request: Partial<HttpRequest>) {

View File

@@ -43,12 +43,12 @@ use yaak_models::util::{BatchUpsertResult, UpdateSource, get_workspace_export_re
use yaak_plugins::events::{ use yaak_plugins::events::{
CallFolderActionArgs, CallFolderActionRequest, CallGrpcRequestActionArgs, CallFolderActionArgs, CallFolderActionRequest, CallGrpcRequestActionArgs,
CallGrpcRequestActionRequest, CallHttpRequestActionArgs, CallHttpRequestActionRequest, CallGrpcRequestActionRequest, CallHttpRequestActionArgs, CallHttpRequestActionRequest,
CallWebSocketRequestActionArgs, CallWebSocketRequestActionRequest, CallWorkspaceActionArgs, CallWebsocketRequestActionArgs, CallWebsocketRequestActionRequest, CallWorkspaceActionArgs,
CallWorkspaceActionRequest, Color, FilterResponse, GetFolderActionsResponse, CallWorkspaceActionRequest, Color, FilterResponse, GetFolderActionsResponse,
GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse, GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse,
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse, GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
GetTemplateFunctionConfigResponse, GetTemplateFunctionSummaryResponse, GetTemplateFunctionConfigResponse, GetTemplateFunctionSummaryResponse,
GetWebSocketRequestActionsResponse, GetWorkspaceActionsResponse, InternalEvent, GetWebsocketRequestActionsResponse, GetWorkspaceActionsResponse, InternalEvent,
InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose, ShowToastRequest, InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose, ShowToastRequest,
}; };
use yaak_plugins::manager::PluginManager; use yaak_plugins::manager::PluginManager;
@@ -880,22 +880,22 @@ async fn cmd_http_request_actions<R: Runtime>(
async fn cmd_websocket_request_actions<R: Runtime>( async fn cmd_websocket_request_actions<R: Runtime>(
window: WebviewWindow<R>, window: WebviewWindow<R>,
plugin_manager: State<'_, PluginManager>, plugin_manager: State<'_, PluginManager>,
) -> YaakResult<Vec<GetWebSocketRequestActionsResponse>> { ) -> YaakResult<Vec<GetWebsocketRequestActionsResponse>> {
Ok(plugin_manager.get_websocket_request_actions(&window).await?) Ok(plugin_manager.get_websocket_request_actions(&window).await?)
} }
#[tauri::command] #[tauri::command]
async fn cmd_call_websocket_request_action<R: Runtime>( async fn cmd_call_websocket_request_action<R: Runtime>(
window: WebviewWindow<R>, window: WebviewWindow<R>,
req: CallWebSocketRequestActionRequest, req: CallWebsocketRequestActionRequest,
plugin_manager: State<'_, PluginManager>, plugin_manager: State<'_, PluginManager>,
) -> YaakResult<()> { ) -> YaakResult<()> {
let websocket_request = window.db().get_websocket_request(&req.args.websocket_request.id)?; let websocket_request = window.db().get_websocket_request(&req.args.websocket_request.id)?;
Ok(plugin_manager Ok(plugin_manager
.call_websocket_request_action( .call_websocket_request_action(
&window, &window,
CallWebSocketRequestActionRequest { CallWebsocketRequestActionRequest {
args: CallWebSocketRequestActionArgs { websocket_request }, args: CallWebsocketRequestActionArgs { websocket_request },
..req ..req
}, },
) )

File diff suppressed because one or more lines are too long

View File

@@ -91,9 +91,9 @@ pub enum InternalEventPayload {
CallHttpRequestActionRequest(CallHttpRequestActionRequest), CallHttpRequestActionRequest(CallHttpRequestActionRequest),
// WebSocket Request Actions // WebSocket Request Actions
GetWebSocketRequestActionsRequest(EmptyPayload), GetWebsocketRequestActionsRequest(EmptyPayload),
GetWebSocketRequestActionsResponse(GetWebSocketRequestActionsResponse), GetWebsocketRequestActionsResponse(GetWebsocketRequestActionsResponse),
CallWebSocketRequestActionRequest(CallWebSocketRequestActionRequest), CallWebsocketRequestActionRequest(CallWebsocketRequestActionRequest),
// Workspace Actions // Workspace Actions
GetWorkspaceActionsRequest(EmptyPayload), GetWorkspaceActionsRequest(EmptyPayload),
@@ -1143,15 +1143,15 @@ pub struct CallHttpRequestActionArgs {
#[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")]
pub struct GetWebSocketRequestActionsResponse { pub struct GetWebsocketRequestActionsResponse {
pub actions: Vec<WebSocketRequestAction>, pub actions: Vec<WebsocketRequestAction>,
pub plugin_ref_id: String, pub plugin_ref_id: 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")]
pub struct WebSocketRequestAction { pub struct WebsocketRequestAction {
pub label: String, pub label: String,
#[ts(optional)] #[ts(optional)]
pub icon: Option<Icon>, pub icon: Option<Icon>,
@@ -1160,16 +1160,16 @@ pub struct WebSocketRequestAction {
#[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")]
pub struct CallWebSocketRequestActionRequest { pub struct CallWebsocketRequestActionRequest {
pub index: i32, pub index: i32,
pub plugin_ref_id: String, pub plugin_ref_id: String,
pub args: CallWebSocketRequestActionArgs, pub args: CallWebsocketRequestActionArgs,
} }
#[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")]
pub struct CallWebSocketRequestActionArgs { pub struct CallWebsocketRequestActionArgs {
pub websocket_request: WebsocketRequest, pub websocket_request: WebsocketRequest,
} }

View File

@@ -7,13 +7,13 @@ use crate::events::{
CallHttpAuthenticationActionArgs, CallHttpAuthenticationActionRequest, CallHttpAuthenticationActionArgs, CallHttpAuthenticationActionRequest,
CallHttpAuthenticationRequest, CallHttpAuthenticationResponse, CallHttpRequestActionRequest, CallHttpAuthenticationRequest, CallHttpAuthenticationResponse, CallHttpRequestActionRequest,
CallTemplateFunctionArgs, CallTemplateFunctionRequest, CallTemplateFunctionResponse, CallTemplateFunctionArgs, CallTemplateFunctionRequest, CallTemplateFunctionResponse,
CallWebSocketRequestActionRequest, CallWorkspaceActionRequest, EmptyPayload, ErrorResponse, CallWebsocketRequestActionRequest, CallWorkspaceActionRequest, EmptyPayload, ErrorResponse,
FilterRequest, FilterResponse, GetFolderActionsResponse, GetGrpcRequestActionsResponse, FilterRequest, FilterResponse, GetFolderActionsResponse, GetGrpcRequestActionsResponse,
GetHttpAuthenticationConfigRequest, GetHttpAuthenticationConfigResponse, GetHttpAuthenticationConfigRequest, GetHttpAuthenticationConfigResponse,
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse, GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
GetTemplateFunctionConfigRequest, GetTemplateFunctionConfigResponse, GetTemplateFunctionConfigRequest, GetTemplateFunctionConfigResponse,
GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse, GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse,
GetWebSocketRequestActionsResponse, GetWorkspaceActionsResponse, ImportRequest, ImportResponse, GetWebsocketRequestActionsResponse, GetWorkspaceActionsResponse, ImportRequest, ImportResponse,
InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose, InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose,
}; };
use crate::native_template_functions::{template_function_keyring, template_function_secure}; use crate::native_template_functions::{template_function_keyring, template_function_secure};
@@ -486,17 +486,17 @@ impl PluginManager {
pub async fn get_websocket_request_actions<R: Runtime>( pub async fn get_websocket_request_actions<R: Runtime>(
&self, &self,
window: &WebviewWindow<R>, window: &WebviewWindow<R>,
) -> Result<Vec<GetWebSocketRequestActionsResponse>> { ) -> Result<Vec<GetWebsocketRequestActionsResponse>> {
let reply_events = self let reply_events = self
.send_and_wait( .send_and_wait(
&PluginContext::new(window), &PluginContext::new(window),
&InternalEventPayload::GetWebSocketRequestActionsRequest(EmptyPayload {}), &InternalEventPayload::GetWebsocketRequestActionsRequest(EmptyPayload {}),
) )
.await?; .await?;
let mut all_actions = Vec::new(); let mut all_actions = Vec::new();
for event in reply_events { for event in reply_events {
if let InternalEventPayload::GetWebSocketRequestActionsResponse(resp) = event.payload { if let InternalEventPayload::GetWebsocketRequestActionsResponse(resp) = event.payload {
all_actions.push(resp.clone()); all_actions.push(resp.clone());
} }
} }
@@ -631,14 +631,14 @@ impl PluginManager {
pub async fn call_websocket_request_action<R: Runtime>( pub async fn call_websocket_request_action<R: Runtime>(
&self, &self,
window: &WebviewWindow<R>, window: &WebviewWindow<R>,
req: CallWebSocketRequestActionRequest, req: CallWebsocketRequestActionRequest,
) -> Result<()> { ) -> Result<()> {
let ref_id = req.plugin_ref_id.clone(); let ref_id = req.plugin_ref_id.clone();
let plugin = let plugin =
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?; self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
let event = plugin.build_event_to_send( let event = plugin.build_event_to_send(
&PluginContext::new(window), &PluginContext::new(window),
&InternalEventPayload::CallWebSocketRequestActionRequest(req), &InternalEventPayload::CallWebsocketRequestActionRequest(req),
None, None,
); );
plugin.send(&event).await?; plugin.send(&event).await?;

View File

@@ -38,7 +38,6 @@ import { getGrpcRequestActions } from '../hooks/useGrpcRequestActions';
import { useHotKey } from '../hooks/useHotKey'; import { useHotKey } from '../hooks/useHotKey';
import { getHttpRequestActions } from '../hooks/useHttpRequestActions'; import { getHttpRequestActions } from '../hooks/useHttpRequestActions';
import { getWebSocketRequestActions } from '../hooks/useWebSocketRequestActions'; import { getWebSocketRequestActions } from '../hooks/useWebSocketRequestActions';
import { getWorkspaceActions } from '../hooks/useWorkspaceActions';
import { getFolderActions } from '../hooks/useFolderActions'; import { getFolderActions } from '../hooks/useFolderActions';
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent'; import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
import { getModelAncestors } from '../hooks/useModelAncestors'; import { getModelAncestors } from '../hooks/useModelAncestors';
@@ -388,24 +387,13 @@ function Sidebar({ className }: { className?: string }) {
if (request != null) await a.call(request); if (request != null) await a.call(request);
}, },
})), })),
...(items.length === 1 && child.model === 'workspace'
? await getWorkspaceActions()
: []
).map((a) => ({
label: a.label,
leftSlot: <Icon icon={a.icon ?? 'empty'} />,
onSelect: async () => {
const model = getModel(child.model, child.id);
if (model != null) await a.call(model as any);
},
})),
...(items.length === 1 && child.model === 'folder' ? await getFolderActions() : []).map( ...(items.length === 1 && child.model === 'folder' ? await getFolderActions() : []).map(
(a) => ({ (a) => ({
label: a.label, label: a.label,
leftSlot: <Icon icon={a.icon ?? 'empty'} />, leftSlot: <Icon icon={a.icon ?? 'empty'} />,
onSelect: async () => { onSelect: async () => {
const model = getModel(child.model, child.id); const model = getModel('folder', child.id);
if (model != null) await a.call(model as any); if (model != null) await a.call(model);
}, },
}), }),
), ),

View File

@@ -14,6 +14,7 @@ import {
} from '../hooks/useActiveWorkspace'; } from '../hooks/useActiveWorkspace';
import { useCreateWorkspace } from '../hooks/useCreateWorkspace'; import { useCreateWorkspace } from '../hooks/useCreateWorkspace';
import { useDeleteSendHistory } from '../hooks/useDeleteSendHistory'; import { useDeleteSendHistory } from '../hooks/useDeleteSendHistory';
import { useWorkspaceActions } from '../hooks/useWorkspaceActions';
import { showDialog } from '../lib/dialog'; import { showDialog } from '../lib/dialog';
import { jotaiStore } from '../lib/jotai'; import { jotaiStore } from '../lib/jotai';
import { revealInFinderText } from '../lib/reveal'; import { revealInFinderText } from '../lib/reveal';
@@ -36,6 +37,7 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
const createWorkspace = useCreateWorkspace(); const createWorkspace = useCreateWorkspace();
const workspaceMeta = useAtomValue(activeWorkspaceMetaAtom); const workspaceMeta = useAtomValue(activeWorkspaceMetaAtom);
const { mutate: deleteSendHistory } = useDeleteSendHistory(); const { mutate: deleteSendHistory } = useDeleteSendHistory();
const workspaceActions = useWorkspaceActions();
const { workspaceItems, itemsAfter } = useMemo<{ const { workspaceItems, itemsAfter } = useMemo<{
workspaceItems: RadioDropdownItem[]; workspaceItems: RadioDropdownItem[];
@@ -49,6 +51,14 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
})); }));
const itemsAfter: DropdownItem[] = [ const itemsAfter: DropdownItem[] = [
...workspaceActions.map((a) => ({
label: a.label,
leftSlot: <Icon icon={a.icon ?? 'empty'} />,
onSelect: async () => {
if (workspace != null) await a.call(workspace);
},
})),
...(workspaceActions.length > 0 ? [{ type: 'separator' as const }] : []),
{ {
label: 'Workspace Settings', label: 'Workspace Settings',
leftSlot: <Icon icon="settings" />, leftSlot: <Icon icon="settings" />,

View File

@@ -1,3 +1,5 @@
// biome-ignore-all lint/suspicious/noTemplateCurlyInString: We're testing this, specifically
import { describe, expect, test } from 'vitest'; import { describe, expect, test } from 'vitest';
import { parser } from './twig'; import { parser } from './twig';