Refactor new actions apis

This commit is contained in:
Gregory Schier
2025-12-28 14:27:39 -08:00
parent 07d743db21
commit 3855058d8f
16 changed files with 540 additions and 170 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
import type { Context } from './Context';
import type { Folder } from '../bindings/gen_models';
import type { Icon } from '../bindings/gen_events';
export type FolderAction = { label: string; icon?: Icon };
export type CallFolderActionArgs = { folder: Folder };
export type FolderActionPlugin = FolderAction & {
onSelect(ctx: Context, args: CallFolderActionArgs): Promise<void> | void;
};

View File

@@ -1,11 +0,0 @@
import type { Context } from './Context';
import type { Folder, Workspace } from '../bindings/gen_models';
import type { Icon } from '../bindings/gen_events';
export type HttpCollectionAction = { label: string; icon?: Icon };
export type CallHttpCollectionActionArgs = { folder?: Folder; workspace?: Workspace };
export type HttpCollectionActionPlugin = HttpCollectionAction & {
onSelect(ctx: Context, args: CallHttpCollectionActionArgs): Promise<void> | void;
};

View File

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

View File

@@ -0,0 +1,11 @@
import type { Context } from './Context';
import type { Workspace } from '../bindings/gen_models';
import type { Icon } from '../bindings/gen_events';
export type WorkspaceAction = { label: string; icon?: Icon };
export type CallWorkspaceActionArgs = { workspace: Workspace };
export type WorkspaceActionPlugin = WorkspaceAction & {
onSelect(ctx: Context, args: CallWorkspaceActionArgs): Promise<void> | void;
};

View File

@@ -4,7 +4,9 @@ import type { Context } from './Context';
import type { FilterPlugin } from './FilterPlugin';
import { GrpcRequestActionPlugin } from './GrpcRequestActionPlugin';
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
import type { HttpCollectionActionPlugin } from './HttpCollectionActionPlugin';
import type { WebSocketRequestActionPlugin } from './WebSocketRequestActionPlugin';
import type { WorkspaceActionPlugin } from './WorkspaceActionPlugin';
import type { FolderActionPlugin } from './FolderActionPlugin';
import type { ImporterPlugin } from './ImporterPlugin';
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
import type { ThemePlugin } from './ThemePlugin';
@@ -13,7 +15,8 @@ export type { Context };
export type { DynamicTemplateFunctionArg } from './TemplateFunctionPlugin';
export type { DynamicAuthenticationArg } from './AuthenticationPlugin';
export type { TemplateFunctionPlugin };
export type { HttpCollectionActionPlugin } from './HttpCollectionActionPlugin';
export type { WorkspaceActionPlugin } from './WorkspaceActionPlugin';
export type { FolderActionPlugin } from './FolderActionPlugin';
/**
* The global structure of a Yaak plugin
@@ -26,7 +29,9 @@ export type PluginDefinition = {
filter?: FilterPlugin;
authentication?: AuthenticationPlugin;
httpRequestActions?: HttpRequestActionPlugin[];
httpCollectionActions?: HttpCollectionActionPlugin[];
websocketRequestActions?: WebSocketRequestActionPlugin[];
workspaceActions?: WorkspaceActionPlugin[];
folderActions?: FolderActionPlugin[];
grpcRequestActions?: GrpcRequestActionPlugin[];
templateFunctions?: TemplateFunctionPlugin[];
};

View File

@@ -174,16 +174,49 @@ export class PluginInstance {
}
if (
payload.type === 'get_http_collection_actions_request' &&
Array.isArray(this.#mod?.httpCollectionActions)
payload.type === 'get_websocket_request_actions_request' &&
Array.isArray(this.#mod?.websocketRequestActions)
) {
const reply: HttpRequestAction[] = this.#mod.httpCollectionActions.map((a) => ({
const reply = this.#mod.websocketRequestActions.map((a) => ({
...a,
// Add everything except onSelect
onSelect: undefined,
}));
const replyPayload: InternalEventPayload = {
type: 'get_http_collection_actions_response',
type: 'get_websocket_request_actions_response',
pluginRefId: this.#workerData.pluginRefId,
actions: reply,
};
this.#sendPayload(context, replyPayload, replyId);
return;
}
if (
payload.type === 'get_workspace_actions_request' &&
Array.isArray(this.#mod?.workspaceActions)
) {
const reply = this.#mod.workspaceActions.map((a) => ({
...a,
onSelect: undefined,
}));
const replyPayload: InternalEventPayload = {
type: 'get_workspace_actions_response',
pluginRefId: this.#workerData.pluginRefId,
actions: reply,
};
this.#sendPayload(context, replyPayload, replyId);
return;
}
if (
payload.type === 'get_folder_actions_request' &&
Array.isArray(this.#mod?.folderActions)
) {
const reply = this.#mod.folderActions.map((a) => ({
...a,
onSelect: undefined,
}));
const replyPayload: InternalEventPayload = {
type: 'get_folder_actions_response',
pluginRefId: this.#workerData.pluginRefId,
actions: reply,
};
@@ -322,10 +355,34 @@ export class PluginInstance {
}
if (
payload.type === 'call_http_collection_action_request' &&
Array.isArray(this.#mod.httpCollectionActions)
payload.type === 'call_websocket_request_action_request' &&
Array.isArray(this.#mod.websocketRequestActions)
) {
const action = this.#mod.httpCollectionActions[payload.index];
const action = this.#mod.websocketRequestActions[payload.index];
if (typeof action?.onSelect === 'function') {
await action.onSelect(ctx, payload.args);
this.#sendEmpty(context, replyId);
return;
}
}
if (
payload.type === 'call_workspace_action_request' &&
Array.isArray(this.#mod.workspaceActions)
) {
const action = this.#mod.workspaceActions[payload.index];
if (typeof action?.onSelect === 'function') {
await action.onSelect(ctx, payload.args);
this.#sendEmpty(context, replyId);
return;
}
}
if (
payload.type === 'call_folder_action_request' &&
Array.isArray(this.#mod.folderActions)
) {
const action = this.#mod.folderActions[payload.index];
if (typeof action?.onSelect === 'function') {
await action.onSelect(ctx, payload.args);
this.#sendEmpty(context, replyId);

View File

@@ -41,13 +41,15 @@ use yaak_models::models::{
use yaak_models::query_manager::QueryManagerExt;
use yaak_models::util::{BatchUpsertResult, UpdateSource, get_workspace_export_resources};
use yaak_plugins::events::{
CallGrpcRequestActionArgs, CallGrpcRequestActionRequest, CallHttpRequestActionArgs,
CallHttpRequestActionRequest, Color, FilterResponse, GetGrpcRequestActionsResponse,
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
GetHttpRequestActionsResponse, GetHttpCollectionActionsResponse,
CallHttpCollectionActionArgs, CallHttpCollectionActionRequest, GetTemplateFunctionConfigResponse,
GetTemplateFunctionSummaryResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
PluginContext, RenderPurpose, ShowToastRequest,
CallFolderActionArgs, CallFolderActionRequest, CallGrpcRequestActionArgs,
CallGrpcRequestActionRequest, CallHttpRequestActionArgs, CallHttpRequestActionRequest,
CallWebSocketRequestActionArgs, CallWebSocketRequestActionRequest, CallWorkspaceActionArgs,
CallWorkspaceActionRequest, Color, FilterResponse, GetFolderActionsResponse,
GetGrpcRequestActionsResponse, GetHttpAuthenticationConfigResponse,
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
GetTemplateFunctionConfigResponse, GetTemplateFunctionSummaryResponse,
GetWebSocketRequestActionsResponse, GetWorkspaceActionsResponse, InternalEvent,
InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose, ShowToastRequest,
};
use yaak_plugins::manager::PluginManager;
use yaak_plugins::plugin_meta::PluginMetadata;
@@ -875,39 +877,77 @@ async fn cmd_http_request_actions<R: Runtime>(
}
#[tauri::command]
async fn cmd_http_collection_actions<R: Runtime>(
async fn cmd_websocket_request_actions<R: Runtime>(
window: WebviewWindow<R>,
plugin_manager: State<'_, PluginManager>,
) -> YaakResult<Vec<GetHttpCollectionActionsResponse>> {
Ok(plugin_manager.get_http_collection_actions(&window).await?)
) -> YaakResult<Vec<GetWebSocketRequestActionsResponse>> {
Ok(plugin_manager.get_websocket_request_actions(&window).await?)
}
#[tauri::command]
async fn cmd_call_http_collection_action<R: Runtime>(
async fn cmd_call_websocket_request_action<R: Runtime>(
window: WebviewWindow<R>,
req: CallHttpCollectionActionRequest,
req: CallWebSocketRequestActionRequest,
plugin_manager: State<'_, PluginManager>,
) -> YaakResult<()> {
let folder = match &req.args.folder {
Some(f) => Some(window.db().get_folder(&f.id)?),
None => None,
};
let workspace = match &req.args.workspace {
Some(w) => Some(window.db().get_workspace(&w.id)?),
None => None,
};
let websocket_request = window.db().get_websocket_request(&req.args.websocket_request.id)?;
Ok(plugin_manager
.call_http_collection_action(
.call_websocket_request_action(
&window,
CallHttpCollectionActionRequest {
args: CallHttpCollectionActionArgs { folder, workspace },
CallWebSocketRequestActionRequest {
args: CallWebSocketRequestActionArgs { websocket_request },
..req
},
)
.await?)
}
#[tauri::command]
async fn cmd_workspace_actions<R: Runtime>(
window: WebviewWindow<R>,
plugin_manager: State<'_, PluginManager>,
) -> YaakResult<Vec<GetWorkspaceActionsResponse>> {
Ok(plugin_manager.get_workspace_actions(&window).await?)
}
#[tauri::command]
async fn cmd_call_workspace_action<R: Runtime>(
window: WebviewWindow<R>,
req: CallWorkspaceActionRequest,
plugin_manager: State<'_, PluginManager>,
) -> YaakResult<()> {
let workspace = window.db().get_workspace(&req.args.workspace.id)?;
Ok(plugin_manager
.call_workspace_action(
&window,
CallWorkspaceActionRequest { args: CallWorkspaceActionArgs { workspace }, ..req },
)
.await?)
}
#[tauri::command]
async fn cmd_folder_actions<R: Runtime>(
window: WebviewWindow<R>,
plugin_manager: State<'_, PluginManager>,
) -> YaakResult<Vec<GetFolderActionsResponse>> {
Ok(plugin_manager.get_folder_actions(&window).await?)
}
#[tauri::command]
async fn cmd_call_folder_action<R: Runtime>(
window: WebviewWindow<R>,
req: CallFolderActionRequest,
plugin_manager: State<'_, PluginManager>,
) -> YaakResult<()> {
let folder = window.db().get_folder(&req.args.folder.id)?;
Ok(plugin_manager
.call_folder_action(
&window,
CallFolderActionRequest { args: CallFolderActionArgs { folder }, ..req },
)
.await?)
}
#[tauri::command]
async fn cmd_grpc_request_actions<R: Runtime>(
window: WebviewWindow<R>,
@@ -1496,7 +1536,9 @@ pub fn run() {
.invoke_handler(tauri::generate_handler![
cmd_call_http_authentication_action,
cmd_call_http_request_action,
cmd_call_http_collection_action,
cmd_call_websocket_request_action,
cmd_call_workspace_action,
cmd_call_folder_action,
cmd_call_grpc_request_action,
cmd_check_for_updates,
cmd_create_grpc_request,
@@ -1518,7 +1560,9 @@ pub fn run() {
cmd_grpc_reflect,
cmd_grpc_request_actions,
cmd_http_request_actions,
cmd_http_collection_actions,
cmd_websocket_request_actions,
cmd_workspace_actions,
cmd_folder_actions,
cmd_import_data,
cmd_install_plugin,
cmd_metadata,

File diff suppressed because one or more lines are too long

View File

@@ -89,10 +89,21 @@ pub enum InternalEventPayload {
GetHttpRequestActionsRequest(EmptyPayload),
GetHttpRequestActionsResponse(GetHttpRequestActionsResponse),
CallHttpRequestActionRequest(CallHttpRequestActionRequest),
// HTTP Collection Actions
GetHttpCollectionActionsRequest(EmptyPayload),
GetHttpCollectionActionsResponse(GetHttpCollectionActionsResponse),
CallHttpCollectionActionRequest(CallHttpCollectionActionRequest),
// WebSocket Request Actions
GetWebSocketRequestActionsRequest(EmptyPayload),
GetWebSocketRequestActionsResponse(GetWebSocketRequestActionsResponse),
CallWebSocketRequestActionRequest(CallWebSocketRequestActionRequest),
// Workspace Actions
GetWorkspaceActionsRequest(EmptyPayload),
GetWorkspaceActionsResponse(GetWorkspaceActionsResponse),
CallWorkspaceActionRequest(CallWorkspaceActionRequest),
// Folder Actions
GetFolderActionsRequest(EmptyPayload),
GetFolderActionsResponse(GetFolderActionsResponse),
CallFolderActionRequest(CallFolderActionRequest),
// Grpc Request Actions
GetGrpcRequestActionsRequest(EmptyPayload),
@@ -1104,14 +1115,6 @@ pub struct GetHttpRequestActionsResponse {
pub plugin_ref_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct GetHttpCollectionActionsResponse {
pub actions: Vec<HttpCollectionAction>,
pub plugin_ref_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
@@ -1121,15 +1124,6 @@ pub struct HttpRequestAction {
pub icon: Option<Icon>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct HttpCollectionAction {
pub label: String,
#[ts(optional)]
pub icon: Option<Icon>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
@@ -1139,15 +1133,6 @@ pub struct CallHttpRequestActionRequest {
pub args: CallHttpRequestActionArgs,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallHttpCollectionActionRequest {
pub index: i32,
pub plugin_ref_id: String,
pub args: CallHttpCollectionActionArgs,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
@@ -1158,11 +1143,100 @@ pub struct CallHttpRequestActionArgs {
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallHttpCollectionActionArgs {
pub struct GetWebSocketRequestActionsResponse {
pub actions: Vec<WebSocketRequestAction>,
pub plugin_ref_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct WebSocketRequestAction {
pub label: String,
#[ts(optional)]
pub folder: Option<Folder>,
pub icon: Option<Icon>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallWebSocketRequestActionRequest {
pub index: i32,
pub plugin_ref_id: String,
pub args: CallWebSocketRequestActionArgs,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallWebSocketRequestActionArgs {
pub websocket_request: WebsocketRequest,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct GetWorkspaceActionsResponse {
pub actions: Vec<WorkspaceAction>,
pub plugin_ref_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct WorkspaceAction {
pub label: String,
#[ts(optional)]
pub workspace: Option<Workspace>,
pub icon: Option<Icon>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallWorkspaceActionRequest {
pub index: i32,
pub plugin_ref_id: String,
pub args: CallWorkspaceActionArgs,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallWorkspaceActionArgs {
pub workspace: Workspace,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct GetFolderActionsResponse {
pub actions: Vec<FolderAction>,
pub plugin_ref_id: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct FolderAction {
pub label: String,
#[ts(optional)]
pub icon: Option<Icon>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallFolderActionRequest {
pub index: i32,
pub plugin_ref_id: String,
pub args: CallFolderActionArgs,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]
#[serde(default, rename_all = "camelCase")]
#[ts(export, export_to = "gen_events.ts")]
pub struct CallFolderActionArgs {
pub folder: Folder,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]

View File

@@ -3,18 +3,18 @@ use crate::error::Error::{
};
use crate::error::Result;
use crate::events::{
BootRequest, CallGrpcRequestActionRequest, CallHttpAuthenticationActionArgs,
CallHttpAuthenticationActionRequest, CallHttpAuthenticationRequest,
CallHttpAuthenticationResponse, CallHttpRequestActionRequest, CallTemplateFunctionArgs,
CallTemplateFunctionRequest, CallTemplateFunctionResponse, EmptyPayload, ErrorResponse,
FilterRequest, FilterResponse, GetGrpcRequestActionsResponse,
BootRequest, CallFolderActionRequest, CallGrpcRequestActionRequest,
CallHttpAuthenticationActionArgs, CallHttpAuthenticationActionRequest,
CallHttpAuthenticationRequest, CallHttpAuthenticationResponse, CallHttpRequestActionRequest,
CallTemplateFunctionArgs, CallTemplateFunctionRequest, CallTemplateFunctionResponse,
CallWebSocketRequestActionRequest, CallWorkspaceActionRequest, EmptyPayload, ErrorResponse,
FilterRequest, FilterResponse, GetFolderActionsResponse, GetGrpcRequestActionsResponse,
GetHttpAuthenticationConfigRequest, GetHttpAuthenticationConfigResponse,
GetHttpAuthenticationSummaryResponse, GetHttpRequestActionsResponse,
GetHttpCollectionActionsResponse, CallHttpCollectionActionRequest,
GetTemplateFunctionConfigRequest, GetTemplateFunctionConfigResponse,
GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse, ImportRequest,
ImportResponse, InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext,
RenderPurpose,
GetTemplateFunctionSummaryResponse, GetThemesRequest, GetThemesResponse,
GetWebSocketRequestActionsResponse, GetWorkspaceActionsResponse, ImportRequest, ImportResponse,
InternalEvent, InternalEventPayload, JsonPrimitive, PluginContext, RenderPurpose,
};
use crate::native_template_functions::{template_function_keyring, template_function_secure};
use crate::nodejs::start_nodejs_plugin_runtime;
@@ -483,20 +483,62 @@ impl PluginManager {
Ok(all_actions)
}
pub async fn get_http_collection_actions<R: Runtime>(
pub async fn get_websocket_request_actions<R: Runtime>(
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<GetHttpCollectionActionsResponse>> {
) -> Result<Vec<GetWebSocketRequestActionsResponse>> {
let reply_events = self
.send_and_wait(
&PluginContext::new(window),
&InternalEventPayload::GetHttpCollectionActionsRequest(EmptyPayload {}),
&InternalEventPayload::GetWebSocketRequestActionsRequest(EmptyPayload {}),
)
.await?;
let mut all_actions = Vec::new();
for event in reply_events {
if let InternalEventPayload::GetHttpCollectionActionsResponse(resp) = event.payload {
if let InternalEventPayload::GetWebSocketRequestActionsResponse(resp) = event.payload {
all_actions.push(resp.clone());
}
}
Ok(all_actions)
}
pub async fn get_workspace_actions<R: Runtime>(
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<GetWorkspaceActionsResponse>> {
let reply_events = self
.send_and_wait(
&PluginContext::new(window),
&InternalEventPayload::GetWorkspaceActionsRequest(EmptyPayload {}),
)
.await?;
let mut all_actions = Vec::new();
for event in reply_events {
if let InternalEventPayload::GetWorkspaceActionsResponse(resp) = event.payload {
all_actions.push(resp.clone());
}
}
Ok(all_actions)
}
pub async fn get_folder_actions<R: Runtime>(
&self,
window: &WebviewWindow<R>,
) -> Result<Vec<GetFolderActionsResponse>> {
let reply_events = self
.send_and_wait(
&PluginContext::new(window),
&InternalEventPayload::GetFolderActionsRequest(EmptyPayload {}),
)
.await?;
let mut all_actions = Vec::new();
for event in reply_events {
if let InternalEventPayload::GetFolderActionsResponse(resp) = event.payload {
all_actions.push(resp.clone());
}
}
@@ -586,17 +628,51 @@ impl PluginManager {
Ok(())
}
pub async fn call_http_collection_action<R: Runtime>(
pub async fn call_websocket_request_action<R: Runtime>(
&self,
window: &WebviewWindow<R>,
req: CallHttpCollectionActionRequest,
req: CallWebSocketRequestActionRequest,
) -> Result<()> {
let ref_id = req.plugin_ref_id.clone();
let plugin =
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
let event = plugin.build_event_to_send(
&PluginContext::new(window),
&InternalEventPayload::CallHttpCollectionActionRequest(req),
&InternalEventPayload::CallWebSocketRequestActionRequest(req),
None,
);
plugin.send(&event).await?;
Ok(())
}
pub async fn call_workspace_action<R: Runtime>(
&self,
window: &WebviewWindow<R>,
req: CallWorkspaceActionRequest,
) -> Result<()> {
let ref_id = req.plugin_ref_id.clone();
let plugin =
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
let event = plugin.build_event_to_send(
&PluginContext::new(window),
&InternalEventPayload::CallWorkspaceActionRequest(req),
None,
);
plugin.send(&event).await?;
Ok(())
}
pub async fn call_folder_action<R: Runtime>(
&self,
window: &WebviewWindow<R>,
req: CallFolderActionRequest,
) -> Result<()> {
let ref_id = req.plugin_ref_id.clone();
let plugin =
self.get_plugin_by_ref_id(ref_id.as_str()).await.ok_or(PluginNotFoundErr(ref_id))?;
let event = plugin.build_event_to_send(
&PluginContext::new(window),
&InternalEventPayload::CallFolderActionRequest(req),
None,
);
plugin.send(&event).await?;

View File

@@ -37,7 +37,8 @@ import { getCreateDropdownItems } from '../hooks/useCreateDropdownItems';
import { getGrpcRequestActions } from '../hooks/useGrpcRequestActions';
import { useHotKey } from '../hooks/useHotKey';
import { getHttpRequestActions } from '../hooks/useHttpRequestActions';
import { getHttpCollectionActions } from '../hooks/useHttpCollectionActions';
import { getWorkspaceActions } from '../hooks/useWorkspaceActions';
import { getFolderActions } from '../hooks/useFolderActions';
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
import { getModelAncestors } from '../hooks/useModelAncestors';
import { sendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
@@ -375,8 +376,8 @@ function Sidebar({ className }: { className?: string }) {
if (request != null) await a.call(request);
},
})),
...(items.length === 1 && (child.model === 'folder' || child.model === 'workspace')
? await getHttpCollectionActions()
...(items.length === 1 && child.model === 'workspace'
? await getWorkspaceActions()
: []
).map((a) => ({
label: a.label,
@@ -386,6 +387,16 @@ function Sidebar({ className }: { className?: string }) {
if (model != null) await a.call(model as any);
},
})),
...(items.length === 1 && child.model === 'folder' ? await getFolderActions() : []).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);
},
}),
),
];
const modelCreationItems: DropdownItem[] =
items.length === 1 && child.model === 'folder'

View File

@@ -0,0 +1,50 @@
import { useQuery } from '@tanstack/react-query';
import type { Folder } from '@yaakapp-internal/models';
import type {
CallFolderActionRequest,
GetFolderActionsResponse,
FolderAction,
} from '@yaakapp-internal/plugins';
import { useMemo } from 'react';
import { invokeCmd } from '../lib/tauri';
import { usePluginsKey } from './usePlugins';
export type CallableFolderAction = Pick<FolderAction, 'label' | 'icon'> & {
call: (folder: Folder) => Promise<void>;
};
export function useFolderActions() {
const pluginsKey = usePluginsKey();
const actionsResult = useQuery<CallableFolderAction[]>({
queryKey: ['folder_actions', pluginsKey],
queryFn: () => getFolderActions(),
});
// biome-ignore lint/correctness/useExhaustiveDependencies: none
const actions = useMemo(() => {
return actionsResult.data ?? [];
}, [JSON.stringify(actionsResult.data)]);
return actions;
}
export async function getFolderActions() {
const responses = await invokeCmd<GetFolderActionsResponse[]>('cmd_folder_actions');
const actions = responses.flatMap((r) =>
r.actions.map((a, i) => ({
label: a.label,
icon: a.icon,
call: async (folder: Folder) => {
const payload: CallFolderActionRequest = {
index: i,
pluginRefId: r.pluginRefId,
args: { folder },
};
await invokeCmd('cmd_call_folder_action', { req: payload });
},
})),
);
return actions;
}

View File

@@ -1,50 +0,0 @@
import { useQuery } from '@tanstack/react-query';
import type { Folder, Workspace } from '@yaakapp-internal/models';
import type {
CallHttpCollectionActionRequest,
GetHttpCollectionActionsResponse,
HttpCollectionAction,
} from '@yaakapp-internal/plugins';
import { useMemo } from 'react';
import { invokeCmd } from '../lib/tauri';
import { usePluginsKey } from './usePlugins';
export type CallableHttpCollectionAction = Pick<HttpCollectionAction, 'label' | 'icon'> & {
call: (model: Folder | Workspace) => Promise<void>;
};
export function useHttpCollectionActions() {
const pluginsKey = usePluginsKey();
const actionsResult = useQuery<CallableHttpCollectionAction[]>({
queryKey: ['http_collection_actions', pluginsKey],
queryFn: () => getHttpCollectionActions(),
});
// biome-ignore lint/correctness/useExhaustiveDependencies: none
const actions = useMemo(() => {
return actionsResult.data ?? [];
}, [JSON.stringify(actionsResult.data)]);
return actions;
}
export async function getHttpCollectionActions() {
const responses = await invokeCmd<GetHttpCollectionActionsResponse[]>('cmd_http_collection_actions');
const actions = responses.flatMap((r) =>
r.actions.map((a, i) => ({
label: a.label,
icon: a.icon,
call: async (model: Folder | Workspace) => {
const payload: CallHttpCollectionActionRequest = {
index: i,
pluginRefId: r.pluginRefId,
args: (model as any).model === 'folder' ? { folder: model as Folder } : { workspace: model as Workspace },
} as any;
await invokeCmd('cmd_call_http_collection_action', { req: payload });
},
})),
);
return actions;
}

View File

@@ -0,0 +1,50 @@
import { useQuery } from '@tanstack/react-query';
import type { Workspace } from '@yaakapp-internal/models';
import type {
CallWorkspaceActionRequest,
GetWorkspaceActionsResponse,
WorkspaceAction,
} from '@yaakapp-internal/plugins';
import { useMemo } from 'react';
import { invokeCmd } from '../lib/tauri';
import { usePluginsKey } from './usePlugins';
export type CallableWorkspaceAction = Pick<WorkspaceAction, 'label' | 'icon'> & {
call: (workspace: Workspace) => Promise<void>;
};
export function useWorkspaceActions() {
const pluginsKey = usePluginsKey();
const actionsResult = useQuery<CallableWorkspaceAction[]>({
queryKey: ['workspace_actions', pluginsKey],
queryFn: () => getWorkspaceActions(),
});
// biome-ignore lint/correctness/useExhaustiveDependencies: none
const actions = useMemo(() => {
return actionsResult.data ?? [];
}, [JSON.stringify(actionsResult.data)]);
return actions;
}
export async function getWorkspaceActions() {
const responses = await invokeCmd<GetWorkspaceActionsResponse[]>('cmd_workspace_actions');
const actions = responses.flatMap((r) =>
r.actions.map((a, i) => ({
label: a.label,
icon: a.icon,
call: async (workspace: Workspace) => {
const payload: CallWorkspaceActionRequest = {
index: i,
pluginRefId: r.pluginRefId,
args: { workspace },
};
await invokeCmd('cmd_call_workspace_action', { req: payload });
},
})),
);
return actions;
}

View File

@@ -5,7 +5,9 @@ type TauriCmd =
| 'cmd_call_grpc_request_action'
| 'cmd_call_http_authentication_action'
| 'cmd_call_http_request_action'
| 'cmd_call_http_collection_action'
| 'cmd_call_websocket_request_action'
| 'cmd_call_workspace_action'
| 'cmd_call_folder_action'
| 'cmd_check_for_updates'
| 'cmd_create_grpc_request'
| 'cmd_curl_to_request'
@@ -26,7 +28,9 @@ type TauriCmd =
| 'cmd_grpc_reflect'
| 'cmd_grpc_request_actions'
| 'cmd_http_request_actions'
| 'cmd_http_collection_actions'
| 'cmd_websocket_request_actions'
| 'cmd_workspace_actions'
| 'cmd_folder_actions'
| 'cmd_http_request_body'
| 'cmd_http_response_body'
| 'cmd_import_data'