diff --git a/plugin-runtime-types/package.json b/plugin-runtime-types/package.json index 3af981fd..58dd5604 100644 --- a/plugin-runtime-types/package.json +++ b/plugin-runtime-types/package.json @@ -1,6 +1,6 @@ { "name": "@yaakapp/api", - "version": "0.2.7", + "version": "0.2.11", "main": "lib/index.js", "typings": "./lib/index.d.ts", "files": [ diff --git a/plugin-runtime-types/src/plugins/Context.ts b/plugin-runtime-types/src/plugins/Context.ts index 019624d9..fa85e68d 100644 --- a/plugin-runtime-types/src/plugins/Context.ts +++ b/plugin-runtime-types/src/plugins/Context.ts @@ -1,4 +1,9 @@ -import { TemplateRenderRequest, TemplateRenderResponse } from '@yaakapp-internal/plugin'; +import { + ShowPromptRequest, + ShowPromptResponse, + TemplateRenderRequest, + TemplateRenderResponse, +} from '@yaakapp-internal/plugin'; import { FindHttpResponsesRequest, FindHttpResponsesResponse, @@ -18,6 +23,9 @@ export type Context = { toast: { show(args: ShowToastRequest): void; }; + prompt: { + show(args: ShowPromptRequest): Promise; + }; httpRequest: { send(args: SendHttpRequestRequest): Promise; getById(args: GetHttpRequestByIdRequest): Promise; diff --git a/plugin-runtime/src/index.worker.ts b/plugin-runtime/src/index.worker.ts index 48f5aad8..9cb9c46b 100644 --- a/plugin-runtime/src/index.worker.ts +++ b/plugin-runtime/src/index.worker.ts @@ -13,6 +13,7 @@ import { InternalEvent, InternalEventPayload, SendHttpRequestResponse, + ShowPromptResponse, TemplateFunction, } from '@yaakapp/api'; import { HttpRequestActionPlugin } from '@yaakapp/api/lib/plugins/HttpRequestActionPlugin'; @@ -138,6 +139,15 @@ async function initialize() { await sendAndWaitForReply(event.windowContext, { type: 'show_toast_request', ...args }); }, }, + prompt: { + async show(args) { + const reply: ShowPromptResponse = await sendAndWaitForReply(event.windowContext, { + type: 'show_prompt_request', + ...args, + }); + return reply.value; + }, + }, httpResponse: { async find(args) { const payload = { type: 'find_http_responses_request', ...args } as const; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 7b15fe4b..0493c3cc 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -17,6 +17,7 @@ use fern::colors::ColoredLevelConfig; use log::{debug, error, info, warn}; use rand::random; use regex::Regex; +use serde::Serialize; use serde_json::{json, Value}; #[cfg(target_os = "macos")] use tauri::TitleBarStyle; @@ -62,7 +63,8 @@ use yaak_plugin_runtime::events::{ BootResponse, CallHttpRequestActionRequest, FilterResponse, FindHttpResponsesResponse, GetHttpRequestActionsResponse, GetHttpRequestByIdResponse, GetTemplateFunctionsResponse, Icon, InternalEvent, InternalEventPayload, RenderHttpRequestResponse, RenderPurpose, - SendHttpRequestResponse, ShowToastRequest, TemplateRenderResponse, WindowContext, + SendHttpRequestResponse, ShowPromptResponse, ShowToastRequest, TemplateRenderResponse, + WindowContext, }; use yaak_plugin_runtime::plugin_handle::PluginHandle; use yaak_templates::{Parser, Tokens}; @@ -2158,6 +2160,40 @@ fn monitor_plugin_events(app_handle: &AppHandle) { }); } +#[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] +struct FrontendCall { + args: T, + reply_id: String, +} + +async fn call_frontend( + window: WebviewWindow, + event_name: &str, + args: T, +) -> ShowPromptResponse { + let reply_id = format!("{event_name}_reply"); + let payload = FrontendCall { + args, + reply_id: reply_id.clone(), + }; + window.emit_to(window.label(), event_name, payload).unwrap(); + let (tx, mut rx) = tokio::sync::watch::channel(ShowPromptResponse::default()); + + let event_id = window.clone().listen(reply_id, move |ev| { + println!("GOT REPLY {ev:?}"); + let resp: ShowPromptResponse = serde_json::from_str(ev.payload()).unwrap(); + _ = tx.send(resp); + }); + + // When reply shows up, unlisten to events and return + _ = rx.changed().await; + window.unlisten(event_id); + + let foo = rx.borrow(); + foo.clone() +} + async fn handle_plugin_event( app_handle: &AppHandle, event: &InternalEvent, @@ -2184,6 +2220,12 @@ async fn handle_plugin_event( }; None } + InternalEventPayload::ShowPromptRequest(req) => { + let window = get_window_from_window_context(app_handle, &window_context) + .expect("Failed to find window for render"); + let resp = call_frontend(window, "show_prompt", req).await; + Some(InternalEventPayload::ShowPromptResponse(resp)) + } InternalEventPayload::FindHttpResponsesRequest(req) => { let http_responses = list_http_responses( app_handle, diff --git a/src-tauri/src/template_callback.rs b/src-tauri/src/template_callback.rs index 7e054215..d7cd3e48 100644 --- a/src-tauri/src/template_callback.rs +++ b/src-tauri/src/template_callback.rs @@ -55,6 +55,7 @@ impl TemplateCallback for PluginTemplateCallback { TemplateFunctionArg::Text(a) => a.base, TemplateFunctionArg::Select(a) => a.base, TemplateFunctionArg::Checkbox(a) => a.base, + TemplateFunctionArg::File(a) => a.base, TemplateFunctionArg::HttpRequest(a) => a.base, }; if let None = args_with_defaults.get(base.name.as_str()) { diff --git a/src-tauri/yaak_plugin_runtime/bindings/events.ts b/src-tauri/yaak_plugin_runtime/bindings/events.ts index 1db06ae0..24dd4f75 100644 --- a/src-tauri/yaak_plugin_runtime/bindings/events.ts +++ b/src-tauri/yaak_plugin_runtime/bindings/events.ts @@ -33,7 +33,7 @@ export type FilterRequest = { content: string, filter: string, }; export type FilterResponse = { content: string, }; -export type FindHttpResponsesRequest = { requestId: string, limit: number | null, }; +export type FindHttpResponsesRequest = { requestId: string, limit?: number, }; export type FindHttpResponsesResponse = { httpResponses: Array, }; @@ -47,9 +47,9 @@ export type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null, }; export type GetTemplateFunctionsResponse = { functions: Array, pluginRefId: string, }; -export type HttpRequestAction = { key: string, label: string, icon: string | null, }; +export type HttpRequestAction = { key: string, label: string, icon?: Icon, }; -export type Icon = "copy" | "info" | "check_circle" | "alert_triangle"; +export type Icon = "copy" | "info" | "check_circle" | "alert_triangle" | "_unknown"; export type ImportRequest = { content: string, }; @@ -59,7 +59,9 @@ export type ImportResponse = { resources: ImportResources, }; export type InternalEvent = { id: string, pluginRefId: string, replyId: string | null, payload: InternalEventPayload, windowContext: WindowContext, }; -export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } | { "type": "reload_response" } | { "type": "terminate_request" } | { "type": "terminate_response" } | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & GetHttpRequestActionsRequest | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "copy_text_request" } & CopyTextRequest | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" }; +export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } | { "type": "reload_response" } | { "type": "terminate_request" } | { "type": "terminate_response" } | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & GetHttpRequestActionsRequest | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "copy_text_request" } & CopyTextRequest | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_prompt_request" } & ShowPromptRequest | { "type": "show_prompt_response" } & ShowPromptResponse | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" }; + +export type OpenFileFilter = { name: string, extensions: Array, }; export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, }; @@ -71,23 +73,41 @@ export type SendHttpRequestRequest = { httpRequest: HttpRequest, }; export type SendHttpRequestResponse = { httpResponse: HttpResponse, }; -export type ShowToastRequest = { message: string, color?: Color | null, icon?: Icon | null, }; +export type ShowPromptRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string, +/** + * Text to add to the confirmation button + */ +confirmText?: string, +/** + * Text to add to the cancel button + */ +cancelText?: string, +/** + * Require the user to enter a non-empty value + */ +require?: boolean, }; -export type TemplateFunction = { name: string, aliases: Array, args: Array, }; +export type ShowPromptResponse = { value: string, }; -export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg; +export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, }; -export type TemplateFunctionBaseArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; +export type TemplateFunction = { name: string, aliases?: Array, args: Array, }; -export type TemplateFunctionCheckboxArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; +export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg | { "type": "file" } & TemplateFunctionFileArg; -export type TemplateFunctionHttpRequestArg = { name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; +export type TemplateFunctionBaseArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, }; -export type TemplateFunctionSelectArg = { options: Array, name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; +export type TemplateFunctionCheckboxArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, }; + +export type TemplateFunctionFileArg = { title: string, multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array, name: string, optional?: boolean, label?: string, defaultValue?: string, }; + +export type TemplateFunctionHttpRequestArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, }; + +export type TemplateFunctionSelectArg = { options: Array, name: string, optional?: boolean, label?: string, defaultValue?: string, }; export type TemplateFunctionSelectOption = { name: string, value: string, }; -export type TemplateFunctionTextArg = { placeholder?: string | null, name: string, optional?: boolean | null, label?: string | null, defaultValue?: string | null, }; +export type TemplateFunctionTextArg = { placeholder?: string, name: string, optional?: boolean, label?: string, defaultValue?: string, }; export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, }; diff --git a/src-tauri/yaak_plugin_runtime/src/events.rs b/src-tauri/yaak_plugin_runtime/src/events.rs index 6eb049aa..75cdf2fe 100644 --- a/src-tauri/yaak_plugin_runtime/src/events.rs +++ b/src-tauri/yaak_plugin_runtime/src/events.rs @@ -76,6 +76,9 @@ pub enum InternalEventPayload { ShowToastRequest(ShowToastRequest), + ShowPromptRequest(ShowPromptRequest), + ShowPromptResponse(ShowPromptResponse), + GetHttpRequestByIdRequest(GetHttpRequestByIdRequest), GetHttpRequestByIdResponse(GetHttpRequestByIdResponse), @@ -203,12 +206,46 @@ pub struct TemplateRenderResponse { #[ts(export, export_to = "events.ts")] pub struct ShowToastRequest { pub message: String, - #[ts(optional = nullable)] + #[ts(optional)] pub color: Option, - #[ts(optional = nullable)] + #[ts(optional)] pub icon: Option, } +#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] +#[serde(default, rename_all = "camelCase")] +#[ts(export, export_to = "events.ts")] +pub struct ShowPromptRequest { + // A unique ID to identify the prompt (eg. "enter-password") + pub id: String, + // Title to show on the prompt dialog + pub title: String, + // Text to show on the label above the input + pub label: String, + #[ts(optional)] + pub description: Option, + #[ts(optional)] + pub default_value: Option, + #[ts(optional)] + pub placeholder: Option, + /// Text to add to the confirmation button + #[ts(optional)] + pub confirm_text: Option, + /// Text to add to the cancel button + #[ts(optional)] + pub cancel_text: Option, + /// Require the user to enter a non-empty value + #[ts(optional)] + pub require: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] +#[serde(default, rename_all = "camelCase")] +#[ts(export, export_to = "events.ts")] +pub struct ShowPromptResponse { + pub value: String, +} + #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "snake_case")] #[ts(export, export_to = "events.ts")] @@ -238,6 +275,10 @@ pub enum Icon { Info, CheckCircle, AlertTriangle, + + #[serde(untagged)] + #[ts(type = "\"_unknown\"")] + _Unknown(String), } #[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] @@ -253,7 +294,8 @@ pub struct GetTemplateFunctionsResponse { #[ts(export, export_to = "events.ts")] pub struct TemplateFunction { pub name: String, - pub aliases: Vec, + #[ts(optional)] + pub aliases: Option>, pub args: Vec, } @@ -265,6 +307,7 @@ pub enum TemplateFunctionArg { Select(TemplateFunctionSelectArg), Checkbox(TemplateFunctionCheckboxArg), HttpRequest(TemplateFunctionHttpRequestArg), + File(TemplateFunctionFileArg), } #[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] @@ -272,11 +315,11 @@ pub enum TemplateFunctionArg { #[ts(export, export_to = "events.ts")] pub struct TemplateFunctionBaseArg { pub name: String, - #[ts(optional = nullable)] + #[ts(optional)] pub optional: Option, - #[ts(optional = nullable)] + #[ts(optional)] pub label: Option, - #[ts(optional = nullable)] + #[ts(optional)] pub default_value: Option, } @@ -286,7 +329,7 @@ pub struct TemplateFunctionBaseArg { pub struct TemplateFunctionTextArg { #[serde(flatten)] pub base: TemplateFunctionBaseArg, - #[ts(optional = nullable)] + #[ts(optional)] pub placeholder: Option, } @@ -298,6 +341,31 @@ pub struct TemplateFunctionHttpRequestArg { pub base: TemplateFunctionBaseArg, } +#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] +#[serde(default, rename_all = "camelCase")] +#[ts(export, export_to = "events.ts")] +pub struct TemplateFunctionFileArg { + #[serde(flatten)] + pub base: TemplateFunctionBaseArg, + pub title: String, + #[ts(optional)] + pub multiple: Option, + #[ts(optional)] + pub directory: Option, + #[ts(optional)] + pub default_path: Option, + #[ts(optional)] + pub filters: Option>, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] +#[serde(default, rename_all = "camelCase")] +#[ts(export, export_to = "events.ts")] +pub struct OpenFileFilter { + pub name: String, + pub extensions: Vec, +} + #[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] #[serde(default, rename_all = "camelCase")] #[ts(export, export_to = "events.ts")] @@ -379,7 +447,8 @@ pub struct GetHttpRequestActionsResponse { pub struct HttpRequestAction { pub key: String, pub label: String, - pub icon: Option, + #[ts(optional)] + pub icon: Option, } #[derive(Debug, Clone, Default, Serialize, Deserialize, TS)] @@ -417,6 +486,7 @@ pub struct GetHttpRequestByIdResponse { #[ts(export, export_to = "events.ts")] pub struct FindHttpResponsesRequest { pub request_id: String, + #[ts(optional)] pub limit: Option, } diff --git a/src-tauri/yaak_plugin_runtime/src/manager.rs b/src-tauri/yaak_plugin_runtime/src/manager.rs index f6e888a2..0557b889 100644 --- a/src-tauri/yaak_plugin_runtime/src/manager.rs +++ b/src-tauri/yaak_plugin_runtime/src/manager.rs @@ -212,7 +212,7 @@ impl PluginManager { }; let plugin_handle = PluginHandle::new(dir, tx.clone()); - // Add the new plugin + // Add the new plugin self.plugins.lock().await.push(plugin_handle.clone()); // Boot the plugin diff --git a/src-web/components/CookieDropdown.tsx b/src-web/components/CookieDropdown.tsx index 1e59b823..9448b416 100644 --- a/src-web/components/CookieDropdown.tsx +++ b/src-web/components/CookieDropdown.tsx @@ -59,8 +59,8 @@ export function CookieDropdown() { Enter a new name for {activeCookieJar?.name} ), - name: 'name', label: 'Name', + confirmText: 'Save', placeholder: 'New name', defaultValue: activeCookieJar?.name, }); diff --git a/src-web/components/EnvironmentEditDialog.tsx b/src-web/components/EnvironmentEditDialog.tsx index 44834730..7af3c72d 100644 --- a/src-web/components/EnvironmentEditDialog.tsx +++ b/src-web/components/EnvironmentEditDialog.tsx @@ -274,8 +274,8 @@ function SidebarButton({ Enter a new name for {environment.name} ), - name: 'name', label: 'Name', + confirmText: 'Save', placeholder: 'New Name', defaultValue: environment.name, }); diff --git a/src-web/components/GlobalHooks.tsx b/src-web/components/GlobalHooks.tsx index fd473e98..d7bcaf9f 100644 --- a/src-web/components/GlobalHooks.tsx +++ b/src-web/components/GlobalHooks.tsx @@ -1,6 +1,8 @@ import { useQueryClient } from '@tanstack/react-query'; +import { emit } from '@tauri-apps/api/event'; import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'; import type { AnyModel } from '@yaakapp-internal/models'; +import type { ShowPromptRequest, ShowPromptResponse } from '@yaakapp-internal/plugin'; import { useSetAtom } from 'jotai'; import { useEffect } from 'react'; import { useEnsureActiveCookieJar, useMigrateActiveCookieJarId } from '../hooks/useActiveCookieJar'; @@ -19,6 +21,7 @@ import { keyValueQueryKey } from '../hooks/useKeyValue'; import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent'; import { useNotificationToast } from '../hooks/useNotificationToast'; import { pluginsAtom } from '../hooks/usePlugins'; +import { usePrompt } from '../hooks/usePrompt'; import { useRecentCookieJars } from '../hooks/useRecentCookieJars'; import { useRecentEnvironments } from '../hooks/useRecentEnvironments'; import { useRecentRequests } from '../hooks/useRecentRequests'; @@ -176,6 +179,16 @@ export function GlobalHooks() { useHotKey('app.zoom_reset', zoom.zoomReset); useListenToTauriEvent('zoom_reset', zoom.zoomReset); + const prompt = usePrompt(); + useListenToTauriEvent<{ replyId: string; args: ShowPromptRequest }>( + 'show_prompt', + async (event) => { + const value = await prompt(event.payload.args); + const result: ShowPromptResponse = { value }; + await emit(event.payload.replyId, result); + }, + ); + const copy = useCopy(); useListenToTauriEvent('generate_theme_css', () => { const themesCss = [ diff --git a/src-web/components/RequestMethodDropdown.tsx b/src-web/components/RequestMethodDropdown.tsx index 23de4e9a..61575622 100644 --- a/src-web/components/RequestMethodDropdown.tsx +++ b/src-web/components/RequestMethodDropdown.tsx @@ -43,9 +43,9 @@ export const RequestMethodDropdown = memo(function RequestMethodDropdown({ const newMethod = await prompt({ id: 'custom-method', label: 'Http Method', - name: 'httpMethod', defaultValue: '', title: 'Custom Method', + confirmText: 'Save', description: 'Enter a custom method name', placeholder: 'CUSTOM', }); diff --git a/src-web/components/Sidebar.tsx b/src-web/components/Sidebar.tsx index 423eab1f..3582726e 100644 --- a/src-web/components/Sidebar.tsx +++ b/src-web/components/Sidebar.tsx @@ -762,7 +762,7 @@ function SidebarItem({ Enter a new name for {itemName} ), - name: 'name', + confirmText: 'Save', label: 'Name', placeholder: 'New Name', defaultValue: itemName, diff --git a/src-web/components/TemplateFunctionDialog.tsx b/src-web/components/TemplateFunctionDialog.tsx index 8bd42a0b..e6d287f3 100644 --- a/src-web/components/TemplateFunctionDialog.tsx +++ b/src-web/components/TemplateFunctionDialog.tsx @@ -93,6 +93,7 @@ export function TemplateFunctionDialog({ templateFunction, hide, initialTokens, return ( +

{templateFunction.name}(…)

{templateFunction.args.map((a: TemplateFunctionArg, i: number) => { switch (a.type) { diff --git a/src-web/components/WorkspaceActionsDropdown.tsx b/src-web/components/WorkspaceActionsDropdown.tsx index b54b839d..fc0bcba8 100644 --- a/src-web/components/WorkspaceActionsDropdown.tsx +++ b/src-web/components/WorkspaceActionsDropdown.tsx @@ -62,7 +62,6 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({ Enter a new name for {activeWorkspace?.name} ), - name: 'name', label: 'Name', placeholder: 'New Name', defaultValue: activeWorkspace?.name, diff --git a/src-web/components/core/Editor/twig/completion.ts b/src-web/components/core/Editor/twig/completion.ts index ab6471c2..276cb776 100644 --- a/src-web/components/core/Editor/twig/completion.ts +++ b/src-web/components/core/Editor/twig/completion.ts @@ -13,7 +13,7 @@ export type TwigCompletionOptionNamespace = { export type TwigCompletionOptionFunction = { args: { name: string }[]; - aliases: string[]; + aliases?: string[]; type: 'function'; }; @@ -65,7 +65,7 @@ export function twigCompletion({ options }: TwigCompletionConfig) { if (matchSegments.length < optionSegments.length) { return [ { - label: optionSegments.slice(0, matchSegments.length).join('.'), + label: optionSegments.slice(0, matchSegments.length).join('.') + '…', apply: optionSegments.slice(0, matchSegments.length).join('.'), type: 'namespace', }, diff --git a/src-web/components/core/Input.tsx b/src-web/components/core/Input.tsx index a5f74b6b..c2d19201 100644 --- a/src-web/components/core/Input.tsx +++ b/src-web/components/core/Input.tsx @@ -24,7 +24,7 @@ export type InputProps = Omit< | 'onKeyDown' | 'readOnly' > & { - name: string; + name?: string; type?: 'text' | 'password'; label: string; hideLabel?: boolean; @@ -41,7 +41,7 @@ export type InputProps = Omit< rightSlot?: ReactNode; size?: 'xs' | 'sm' | 'md' | 'auto'; className?: string; - placeholder: string; + placeholder?: string; validate?: boolean | ((v: string) => boolean); require?: boolean; wrapLines?: boolean; diff --git a/src-web/components/core/PairEditor.tsx b/src-web/components/core/PairEditor.tsx index e892afec..760fdc3b 100644 --- a/src-web/components/core/PairEditor.tsx +++ b/src-web/components/core/PairEditor.tsx @@ -519,8 +519,7 @@ function PairEditorRow({ label: 'Content-Type', placeholder: 'text/plain', defaultValue: pairContainer.pair.contentType ?? '', - name: 'content-type', - confirmLabel: 'Set', + confirmText: 'Set', description: 'Leave blank to auto-detect', }); handleChangeValueContentType(v); diff --git a/src-web/hooks/Prompt.tsx b/src-web/hooks/Prompt.tsx index 5714aa06..29669799 100644 --- a/src-web/hooks/Prompt.tsx +++ b/src-web/hooks/Prompt.tsx @@ -1,30 +1,25 @@ -import type { FormEvent } from 'react'; +import type { ShowPromptRequest } from '@yaakapp-internal/plugin'; +import type { FormEvent, ReactNode } from 'react'; import { useCallback, useState } from 'react'; import { Button } from '../components/core/Button'; -import type { InputProps } from '../components/core/Input'; import { PlainInput } from '../components/core/PlainInput'; import { HStack } from '../components/core/Stacks'; -export interface PromptProps { +export type PromptProps = Omit & { + description?: ReactNode; onHide: () => void; onResult: (value: string) => void; - label: InputProps['label']; - name: InputProps['name']; - defaultValue: InputProps['defaultValue']; - placeholder: InputProps['placeholder']; - require?: InputProps['require']; - confirmLabel?: string; -} +}; export function Prompt({ onHide, label, - name, defaultValue, placeholder, onResult, - require = true, - confirmLabel = 'Save', + require, + confirmText, + cancelText, }: PromptProps) { const [value, setValue] = useState(defaultValue ?? ''); const handleSubmit = useCallback( @@ -45,18 +40,17 @@ export function Prompt({ hideLabel autoSelect require={require} - placeholder={placeholder} + placeholder={placeholder ?? 'Enter text'} label={label} - name={name} defaultValue={defaultValue} onChange={setValue} /> diff --git a/src-web/hooks/useCreateCookieJar.ts b/src-web/hooks/useCreateCookieJar.ts index 906a1d5f..2a1f6879 100644 --- a/src-web/hooks/useCreateCookieJar.ts +++ b/src-web/hooks/useCreateCookieJar.ts @@ -17,9 +17,9 @@ export function useCreateCookieJar() { } const name = await prompt({ id: 'new-cookie-jar', - name: 'name', title: 'New CookieJar', placeholder: 'My Jar', + confirmText: 'Create', label: 'Name', defaultValue: 'My Jar', }); diff --git a/src-web/hooks/useCreateEnvironment.ts b/src-web/hooks/useCreateEnvironment.ts index d1d7ee31..f5738334 100644 --- a/src-web/hooks/useCreateEnvironment.ts +++ b/src-web/hooks/useCreateEnvironment.ts @@ -16,12 +16,12 @@ export function useCreateEnvironment() { mutationFn: async () => { const name = await prompt({ id: 'new-environment', - name: 'name', title: 'New Environment', description: 'Create multiple environments with different sets of variables', label: 'Name', placeholder: 'My Environment', defaultValue: 'My Environment', + confirmText: 'Create', }); return invokeCmd('cmd_create_environment', { name, diff --git a/src-web/hooks/useCreateFolder.ts b/src-web/hooks/useCreateFolder.ts index 4b149991..38358d5f 100644 --- a/src-web/hooks/useCreateFolder.ts +++ b/src-web/hooks/useCreateFolder.ts @@ -19,11 +19,10 @@ export function useCreateFolder() { patch.name || (await prompt({ id: 'new-folder', - name: 'name', label: 'Name', defaultValue: 'Folder', title: 'New Folder', - confirmLabel: 'Create', + confirmText: 'Create', placeholder: 'Name', })); patch.sortPriority = patch.sortPriority || -Date.now(); diff --git a/src-web/hooks/useCreateWorkspace.ts b/src-web/hooks/useCreateWorkspace.ts index 6b08e69f..61ebf3d1 100644 --- a/src-web/hooks/useCreateWorkspace.ts +++ b/src-web/hooks/useCreateWorkspace.ts @@ -12,12 +12,11 @@ export function useCreateWorkspace() { mutationFn: async () => { const name = await prompt({ id: 'new-workspace', - name: 'name', label: 'Name', defaultValue: 'My Workspace', title: 'New Workspace', - confirmLabel: 'Create', placeholder: 'My Workspace', + confirmText: 'Create', }); return invokeCmd('cmd_create_workspace', { name }); }, diff --git a/src-web/hooks/useHttpRequestActions.ts b/src-web/hooks/useHttpRequestActions.ts index ada41322..a59baf87 100644 --- a/src-web/hooks/useHttpRequestActions.ts +++ b/src-web/hooks/useHttpRequestActions.ts @@ -16,6 +16,7 @@ export function useHttpRequestActions() { const responses = (await invokeCmd( 'cmd_http_request_actions', )) as GetHttpRequestActionsResponse[]; + console.log('REQUEST ACTIONS', responses); return responses; }, }); diff --git a/src-web/hooks/usePrompt.ts b/src-web/hooks/usePrompt.ts index 98ba9f0a..4f208661 100644 --- a/src-web/hooks/usePrompt.ts +++ b/src-web/hooks/usePrompt.ts @@ -3,20 +3,12 @@ import { useDialog } from '../components/DialogContext'; import type { PromptProps } from './Prompt'; import { Prompt } from './Prompt'; +type Props = Pick & + Omit & { id: string }; + export function usePrompt() { const dialog = useDialog(); - return ({ - id, - title, - description, - name, - label, - defaultValue, - placeholder, - confirmLabel, - require, - }: Pick & - Omit & { id: string }) => + return ({ id, title, description, ...props }: Props) => new Promise((onResult: PromptProps['onResult']) => { dialog.show({ id, @@ -24,17 +16,7 @@ export function usePrompt() { description, hideX: true, size: 'sm', - render: ({ hide }) => - Prompt({ - onHide: hide, - onResult, - name, - label, - defaultValue, - placeholder, - confirmLabel, - require, - }), + render: ({ hide: onHide }) => Prompt({ onHide, onResult, ...props }), }); }); } diff --git a/src-web/hooks/useRenameRequest.tsx b/src-web/hooks/useRenameRequest.tsx index 34fc3a97..f049bd99 100644 --- a/src-web/hooks/useRenameRequest.tsx +++ b/src-web/hooks/useRenameRequest.tsx @@ -28,10 +28,10 @@ export function useRenameRequest(requestId: string | null) { Enter a new name for {request.name} ), - name: 'name', label: 'Name', placeholder: 'New Name', defaultValue: request.name, + confirmText: 'Save', }); if (request.model === 'http_request') { updateHttpRequest.mutate({ id: request.id, update: (r: HttpRequest) => ({ ...r, name }) });