mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-19 15:21:23 +02:00
Make prompt() to return null on cancel
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
"start": "npm run app-dev",
|
"start": "npm run app-dev",
|
||||||
"app-build": "tauri build",
|
"app-build": "tauri build",
|
||||||
"app-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
"app-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
|
||||||
"bootstrap": "run-p bootstrap:* && npm run --workspace plugin-runtime build",
|
"bootstrap": "run-p bootstrap:* && npm run --workspaces --if-present bootstrap",
|
||||||
"bootstrap:vendor-node": "node scripts/vendor-node.cjs",
|
"bootstrap:vendor-node": "node scripts/vendor-node.cjs",
|
||||||
"bootstrap:vendor-plugins": "node scripts/vendor-plugins.cjs",
|
"bootstrap:vendor-plugins": "node scripts/vendor-plugins.cjs",
|
||||||
"bootstrap:vendor-protoc": "node scripts/vendor-protoc.cjs",
|
"bootstrap:vendor-protoc": "node scripts/vendor-protoc.cjs",
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@yaakapp/api",
|
"name": "@yaakapp/api",
|
||||||
"version": "0.2.13",
|
"version": "0.2.15",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"typings": "./lib/index.d.ts",
|
"typings": "./lib/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"lib/**/*"
|
"lib/**/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"bootstrap": "npm run build",
|
||||||
"build": "run-s build:copy-types build:tsc",
|
"build": "run-s build:copy-types build:tsc",
|
||||||
"build:tsc": "tsc",
|
"build:tsc": "tsc",
|
||||||
"build:copy-types": "run-p build:copy-types:*",
|
"build:copy-types": "run-p build:copy-types:*",
|
||||||
|
|||||||
@@ -59,21 +59,15 @@ export type ImportResponse = { resources: ImportResources, };
|
|||||||
|
|
||||||
export type InternalEvent = { id: string, pluginRefId: string, replyId: string | null, payload: InternalEventPayload, windowContext: WindowContext, };
|
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": "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 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": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "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<string>, };
|
export type OpenFileFilter = { name: string,
|
||||||
|
/**
|
||||||
|
* File extensions to require
|
||||||
|
*/
|
||||||
|
extensions: Array<string>, };
|
||||||
|
|
||||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
export type PromptTextRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
|
||||||
|
|
||||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type RenderPurpose = "send" | "preview";
|
|
||||||
|
|
||||||
export type SendHttpRequestRequest = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
|
||||||
|
|
||||||
export type ShowPromptRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
|
|
||||||
/**
|
/**
|
||||||
* Text to add to the confirmation button
|
* Text to add to the confirmation button
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +81,17 @@ cancelText?: string,
|
|||||||
*/
|
*/
|
||||||
require?: boolean, };
|
require?: boolean, };
|
||||||
|
|
||||||
export type ShowPromptResponse = { value: string, };
|
export type PromptTextResponse = { value: string | null, };
|
||||||
|
|
||||||
|
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
||||||
|
|
||||||
|
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
||||||
|
|
||||||
|
export type RenderPurpose = "send" | "preview";
|
||||||
|
|
||||||
|
export type SendHttpRequestRequest = { httpRequest: HttpRequest, };
|
||||||
|
|
||||||
|
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
||||||
|
|
||||||
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
|
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
|
||||||
|
|
||||||
@@ -95,19 +99,131 @@ export type TemplateFunction = { name: string, aliases?: Array<string>, args: Ar
|
|||||||
|
|
||||||
export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg | { "type": "file" } & TemplateFunctionFileArg;
|
export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg | { "type": "file" } & TemplateFunctionFileArg;
|
||||||
|
|
||||||
export type TemplateFunctionBaseArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionBaseArg = {
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionCheckboxArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionCheckboxArg = {
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionFileArg = { title: string, multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<OpenFileFilter>, name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionFileArg = {
|
||||||
|
/**
|
||||||
|
* The title of the file selection window
|
||||||
|
*/
|
||||||
|
title: string,
|
||||||
|
/**
|
||||||
|
* Allow selecting multiple files
|
||||||
|
*/
|
||||||
|
multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<OpenFileFilter>,
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionHttpRequestArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionHttpRequestArg = {
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionSelectArg = { options: Array<TemplateFunctionSelectOption>, name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionSelectArg = {
|
||||||
|
/**
|
||||||
|
* The options that will be available in the select input
|
||||||
|
*/
|
||||||
|
options: Array<TemplateFunctionSelectOption>,
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionSelectOption = { name: string, value: string, };
|
export type TemplateFunctionSelectOption = { label: string, value: string, };
|
||||||
|
|
||||||
export type TemplateFunctionTextArg = { placeholder?: string, name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionTextArg = {
|
||||||
|
/**
|
||||||
|
* Placeholder for the text input
|
||||||
|
*/
|
||||||
|
placeholder?: string,
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
|
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
ShowPromptRequest,
|
|
||||||
ShowPromptResponse,
|
|
||||||
TemplateRenderRequest,
|
|
||||||
TemplateRenderResponse,
|
|
||||||
FindHttpResponsesRequest,
|
FindHttpResponsesRequest,
|
||||||
FindHttpResponsesResponse,
|
FindHttpResponsesResponse,
|
||||||
GetHttpRequestByIdRequest,
|
GetHttpRequestByIdRequest,
|
||||||
GetHttpRequestByIdResponse,
|
GetHttpRequestByIdResponse,
|
||||||
|
PromptTextRequest,
|
||||||
|
PromptTextResponse,
|
||||||
RenderHttpRequestRequest,
|
RenderHttpRequestRequest,
|
||||||
RenderHttpRequestResponse,
|
RenderHttpRequestResponse,
|
||||||
SendHttpRequestRequest,
|
SendHttpRequestRequest,
|
||||||
SendHttpRequestResponse,
|
SendHttpRequestResponse,
|
||||||
ShowToastRequest,
|
ShowToastRequest,
|
||||||
|
TemplateRenderRequest,
|
||||||
|
TemplateRenderResponse,
|
||||||
} from '..';
|
} from '..';
|
||||||
|
|
||||||
export type Context = {
|
export type Context = {
|
||||||
@@ -22,7 +22,7 @@ export type Context = {
|
|||||||
show(args: ShowToastRequest): void;
|
show(args: ShowToastRequest): void;
|
||||||
};
|
};
|
||||||
prompt: {
|
prompt: {
|
||||||
show(args: ShowPromptRequest): Promise<ShowPromptResponse['value']>;
|
text(args: PromptTextRequest): Promise<PromptTextResponse['value']>;
|
||||||
};
|
};
|
||||||
httpRequest: {
|
httpRequest: {
|
||||||
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@yaakapp-internal/plugin-runtime",
|
"name": "@yaakapp-internal/plugin-runtime",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"bootstrap": "npm run build",
|
||||||
"build": "run-p build:*",
|
"build": "run-p build:*",
|
||||||
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=../src-tauri/vendored/plugin-runtime/index.cjs",
|
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=../src-tauri/vendored/plugin-runtime/index.cjs",
|
||||||
"build:worker": "esbuild src/index.worker.ts --bundle --platform=node --outfile=../src-tauri/vendored/plugin-runtime/index.worker.cjs",
|
"build:worker": "esbuild src/index.worker.ts --bundle --platform=node --outfile=../src-tauri/vendored/plugin-runtime/index.worker.cjs",
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
import {
|
|
||||||
RenderHttpRequestResponse,
|
|
||||||
TemplateRenderResponse,
|
|
||||||
WindowContext,
|
|
||||||
} from '@yaakapp-internal/plugin';
|
|
||||||
import {
|
import {
|
||||||
BootRequest,
|
BootRequest,
|
||||||
Context,
|
|
||||||
FindHttpResponsesResponse,
|
FindHttpResponsesResponse,
|
||||||
GetHttpRequestByIdResponse,
|
GetHttpRequestByIdResponse,
|
||||||
HttpRequestAction,
|
HttpRequestAction,
|
||||||
ImportResponse,
|
ImportResponse,
|
||||||
InternalEvent,
|
InternalEvent,
|
||||||
InternalEventPayload,
|
InternalEventPayload,
|
||||||
|
PromptTextResponse,
|
||||||
|
RenderHttpRequestResponse,
|
||||||
SendHttpRequestResponse,
|
SendHttpRequestResponse,
|
||||||
ShowPromptResponse,
|
|
||||||
TemplateFunction,
|
TemplateFunction,
|
||||||
} from '@yaakapp/api';
|
TemplateRenderResponse,
|
||||||
|
WindowContext,
|
||||||
|
} from '@yaakapp-internal/plugin';
|
||||||
|
import { Context } from '@yaakapp/api';
|
||||||
import { HttpRequestActionPlugin } from '@yaakapp/api/lib/plugins/HttpRequestActionPlugin';
|
import { HttpRequestActionPlugin } from '@yaakapp/api/lib/plugins/HttpRequestActionPlugin';
|
||||||
import { TemplateFunctionPlugin } from '@yaakapp/api/lib/plugins/TemplateFunctionPlugin';
|
import { TemplateFunctionPlugin } from '@yaakapp/api/lib/plugins/TemplateFunctionPlugin';
|
||||||
import interceptStdout from 'intercept-stdout';
|
import interceptStdout from 'intercept-stdout';
|
||||||
@@ -140,9 +138,9 @@ async function initialize() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
prompt: {
|
prompt: {
|
||||||
async show(args) {
|
async text(args) {
|
||||||
const reply: ShowPromptResponse = await sendAndWaitForReply(event.windowContext, {
|
const reply: PromptTextResponse = await sendAndWaitForReply(event.windowContext, {
|
||||||
type: 'show_prompt_request',
|
type: 'prompt_text_request',
|
||||||
...args,
|
...args,
|
||||||
});
|
});
|
||||||
return reply.value;
|
return reply.value;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ pub async fn send_http_request<R: Runtime>(
|
|||||||
&WindowContext::from_window(window),
|
&WindowContext::from_window(window),
|
||||||
RenderPurpose::Send,
|
RenderPurpose::Send,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rendered_request =
|
let rendered_request =
|
||||||
render_http_request(&request, &workspace, environment.as_ref(), &cb).await;
|
render_http_request(&request, &workspace, environment.as_ref(), &cb).await;
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ use yaak_plugin_runtime::events::{
|
|||||||
BootResponse, CallHttpRequestActionRequest, FilterResponse, FindHttpResponsesResponse,
|
BootResponse, CallHttpRequestActionRequest, FilterResponse, FindHttpResponsesResponse,
|
||||||
GetHttpRequestActionsResponse, GetHttpRequestByIdResponse, GetTemplateFunctionsResponse, Icon,
|
GetHttpRequestActionsResponse, GetHttpRequestByIdResponse, GetTemplateFunctionsResponse, Icon,
|
||||||
InternalEvent, InternalEventPayload, RenderHttpRequestResponse, RenderPurpose,
|
InternalEvent, InternalEventPayload, RenderHttpRequestResponse, RenderPurpose,
|
||||||
SendHttpRequestResponse, ShowPromptResponse, ShowToastRequest, TemplateRenderResponse,
|
SendHttpRequestResponse, PromptTextResponse, ShowToastRequest, TemplateRenderResponse,
|
||||||
WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
use yaak_plugin_runtime::plugin_handle::PluginHandle;
|
use yaak_plugin_runtime::plugin_handle::PluginHandle;
|
||||||
@@ -1081,6 +1081,18 @@ async fn cmd_send_http_request(
|
|||||||
// that has not yet been saved in the DB.
|
// that has not yet been saved in the DB.
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
) -> Result<HttpResponse, String> {
|
) -> Result<HttpResponse, String> {
|
||||||
|
let response = create_default_http_response(&window, &request.id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let (cancel_tx, mut cancel_rx) = tokio::sync::watch::channel(false);
|
||||||
|
window.listen_any(
|
||||||
|
format!("cancel_http_response_{}", response.id),
|
||||||
|
move |_event| {
|
||||||
|
let _ = cancel_tx.send(true);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let environment = match environment_id {
|
let environment = match environment_id {
|
||||||
Some(id) => match get_environment(&window, id).await {
|
Some(id) => match get_environment(&window, id).await {
|
||||||
Ok(env) => Some(env),
|
Ok(env) => Some(env),
|
||||||
@@ -1101,18 +1113,6 @@ async fn cmd_send_http_request(
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = create_default_http_response(&window, &request.id)
|
|
||||||
.await
|
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
|
|
||||||
let (cancel_tx, mut cancel_rx) = tokio::sync::watch::channel(false);
|
|
||||||
window.listen_any(
|
|
||||||
format!("cancel_http_response_{}", response.id),
|
|
||||||
move |_event| {
|
|
||||||
let _ = cancel_tx.send(true);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
send_http_request(
|
send_http_request(
|
||||||
&window,
|
&window,
|
||||||
&request,
|
&request,
|
||||||
@@ -2171,18 +2171,18 @@ async fn call_frontend<T: Serialize + Clone, R: Runtime>(
|
|||||||
window: WebviewWindow<R>,
|
window: WebviewWindow<R>,
|
||||||
event_name: &str,
|
event_name: &str,
|
||||||
args: T,
|
args: T,
|
||||||
) -> ShowPromptResponse {
|
) -> PromptTextResponse {
|
||||||
let reply_id = format!("{event_name}_reply");
|
let reply_id = format!("{event_name}_reply");
|
||||||
let payload = FrontendCall {
|
let payload = FrontendCall {
|
||||||
args,
|
args,
|
||||||
reply_id: reply_id.clone(),
|
reply_id: reply_id.clone(),
|
||||||
};
|
};
|
||||||
window.emit_to(window.label(), event_name, payload).unwrap();
|
window.emit_to(window.label(), event_name, payload).unwrap();
|
||||||
let (tx, mut rx) = tokio::sync::watch::channel(ShowPromptResponse::default());
|
let (tx, mut rx) = tokio::sync::watch::channel(PromptTextResponse::default());
|
||||||
|
|
||||||
let event_id = window.clone().listen(reply_id, move |ev| {
|
let event_id = window.clone().listen(reply_id, move |ev| {
|
||||||
println!("GOT REPLY {ev:?}");
|
println!("GOT REPLY {ev:?}");
|
||||||
let resp: ShowPromptResponse = serde_json::from_str(ev.payload()).unwrap();
|
let resp: PromptTextResponse = serde_json::from_str(ev.payload()).unwrap();
|
||||||
_ = tx.send(resp);
|
_ = tx.send(resp);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2220,11 +2220,11 @@ async fn handle_plugin_event<R: Runtime>(
|
|||||||
};
|
};
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
InternalEventPayload::ShowPromptRequest(req) => {
|
InternalEventPayload::PromptTextRequest(req) => {
|
||||||
let window = get_window_from_window_context(app_handle, &window_context)
|
let window = get_window_from_window_context(app_handle, &window_context)
|
||||||
.expect("Failed to find window for render");
|
.expect("Failed to find window for render");
|
||||||
let resp = call_frontend(window, "show_prompt", req).await;
|
let resp = call_frontend(window, "show_prompt", req).await;
|
||||||
Some(InternalEventPayload::ShowPromptResponse(resp))
|
Some(InternalEventPayload::PromptTextResponse(resp))
|
||||||
}
|
}
|
||||||
InternalEventPayload::FindHttpResponsesRequest(req) => {
|
InternalEventPayload::FindHttpResponsesRequest(req) => {
|
||||||
let http_responses = list_http_responses(
|
let http_responses = list_http_responses(
|
||||||
|
|||||||
@@ -59,21 +59,15 @@ export type ImportResponse = { resources: ImportResources, };
|
|||||||
|
|
||||||
export type InternalEvent = { id: string, pluginRefId: string, replyId: string | null, payload: InternalEventPayload, windowContext: WindowContext, };
|
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": "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 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": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "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<string>, };
|
export type OpenFileFilter = { name: string,
|
||||||
|
/**
|
||||||
|
* File extensions to require
|
||||||
|
*/
|
||||||
|
extensions: Array<string>, };
|
||||||
|
|
||||||
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
export type PromptTextRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
|
||||||
|
|
||||||
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type RenderPurpose = "send" | "preview";
|
|
||||||
|
|
||||||
export type SendHttpRequestRequest = { httpRequest: HttpRequest, };
|
|
||||||
|
|
||||||
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
|
||||||
|
|
||||||
export type ShowPromptRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
|
|
||||||
/**
|
/**
|
||||||
* Text to add to the confirmation button
|
* Text to add to the confirmation button
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +81,17 @@ cancelText?: string,
|
|||||||
*/
|
*/
|
||||||
require?: boolean, };
|
require?: boolean, };
|
||||||
|
|
||||||
export type ShowPromptResponse = { value: string, };
|
export type PromptTextResponse = { value: string | null, };
|
||||||
|
|
||||||
|
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
|
||||||
|
|
||||||
|
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
|
||||||
|
|
||||||
|
export type RenderPurpose = "send" | "preview";
|
||||||
|
|
||||||
|
export type SendHttpRequestRequest = { httpRequest: HttpRequest, };
|
||||||
|
|
||||||
|
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
|
||||||
|
|
||||||
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
|
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
|
||||||
|
|
||||||
@@ -95,19 +99,131 @@ export type TemplateFunction = { name: string, aliases?: Array<string>, args: Ar
|
|||||||
|
|
||||||
export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg | { "type": "file" } & TemplateFunctionFileArg;
|
export type TemplateFunctionArg = { "type": "text" } & TemplateFunctionTextArg | { "type": "select" } & TemplateFunctionSelectArg | { "type": "checkbox" } & TemplateFunctionCheckboxArg | { "type": "http_request" } & TemplateFunctionHttpRequestArg | { "type": "file" } & TemplateFunctionFileArg;
|
||||||
|
|
||||||
export type TemplateFunctionBaseArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionBaseArg = {
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionCheckboxArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionCheckboxArg = {
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionFileArg = { title: string, multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<OpenFileFilter>, name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionFileArg = {
|
||||||
|
/**
|
||||||
|
* The title of the file selection window
|
||||||
|
*/
|
||||||
|
title: string,
|
||||||
|
/**
|
||||||
|
* Allow selecting multiple files
|
||||||
|
*/
|
||||||
|
multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<OpenFileFilter>,
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionHttpRequestArg = { name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionHttpRequestArg = {
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionSelectArg = { options: Array<TemplateFunctionSelectOption>, name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionSelectArg = {
|
||||||
|
/**
|
||||||
|
* The options that will be available in the select input
|
||||||
|
*/
|
||||||
|
options: Array<TemplateFunctionSelectOption>,
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateFunctionSelectOption = { name: string, value: string, };
|
export type TemplateFunctionSelectOption = { label: string, value: string, };
|
||||||
|
|
||||||
export type TemplateFunctionTextArg = { placeholder?: string, name: string, optional?: boolean, label?: string, defaultValue?: string, };
|
export type TemplateFunctionTextArg = {
|
||||||
|
/**
|
||||||
|
* Placeholder for the text input
|
||||||
|
*/
|
||||||
|
placeholder?: string,
|
||||||
|
/**
|
||||||
|
* The name of the argument. Should be `camelCase` format
|
||||||
|
*/
|
||||||
|
name: string,
|
||||||
|
/**
|
||||||
|
* Whether the user must fill in the argument
|
||||||
|
*/
|
||||||
|
optional?: boolean,
|
||||||
|
/**
|
||||||
|
* The label of the input
|
||||||
|
*/
|
||||||
|
label?: string,
|
||||||
|
/**
|
||||||
|
* The default value
|
||||||
|
*/
|
||||||
|
defaultValue?: string, };
|
||||||
|
|
||||||
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
|
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ pub enum InternalEventPayload {
|
|||||||
|
|
||||||
ShowToastRequest(ShowToastRequest),
|
ShowToastRequest(ShowToastRequest),
|
||||||
|
|
||||||
ShowPromptRequest(ShowPromptRequest),
|
PromptTextRequest(PromptTextRequest),
|
||||||
ShowPromptResponse(ShowPromptResponse),
|
PromptTextResponse(PromptTextResponse),
|
||||||
|
|
||||||
GetHttpRequestByIdRequest(GetHttpRequestByIdRequest),
|
GetHttpRequestByIdRequest(GetHttpRequestByIdRequest),
|
||||||
GetHttpRequestByIdResponse(GetHttpRequestByIdResponse),
|
GetHttpRequestByIdResponse(GetHttpRequestByIdResponse),
|
||||||
@@ -215,7 +215,7 @@ pub struct ShowToastRequest {
|
|||||||
#[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 = "events.ts")]
|
#[ts(export, export_to = "events.ts")]
|
||||||
pub struct ShowPromptRequest {
|
pub struct PromptTextRequest {
|
||||||
// A unique ID to identify the prompt (eg. "enter-password")
|
// A unique ID to identify the prompt (eg. "enter-password")
|
||||||
pub id: String,
|
pub id: String,
|
||||||
// Title to show on the prompt dialog
|
// Title to show on the prompt dialog
|
||||||
@@ -242,8 +242,8 @@ pub struct ShowPromptRequest {
|
|||||||
#[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 = "events.ts")]
|
#[ts(export, export_to = "events.ts")]
|
||||||
pub struct ShowPromptResponse {
|
pub struct PromptTextResponse {
|
||||||
pub value: String,
|
pub value: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||||
@@ -294,6 +294,9 @@ pub struct GetTemplateFunctionsResponse {
|
|||||||
#[ts(export, export_to = "events.ts")]
|
#[ts(export, export_to = "events.ts")]
|
||||||
pub struct TemplateFunction {
|
pub struct TemplateFunction {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
|
/// Also support alternative names. This is useful for not breaking existing
|
||||||
|
/// tags when changing the `name` property
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub aliases: Option<Vec<String>>,
|
pub aliases: Option<Vec<String>>,
|
||||||
pub args: Vec<TemplateFunctionArg>,
|
pub args: Vec<TemplateFunctionArg>,
|
||||||
@@ -314,11 +317,18 @@ pub enum TemplateFunctionArg {
|
|||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "events.ts")]
|
#[ts(export, export_to = "events.ts")]
|
||||||
pub struct TemplateFunctionBaseArg {
|
pub struct TemplateFunctionBaseArg {
|
||||||
|
/// The name of the argument. Should be `camelCase` format
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
|
/// Whether the user must fill in the argument
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub optional: Option<bool>,
|
pub optional: Option<bool>,
|
||||||
|
|
||||||
|
/// The label of the input
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub label: Option<String>,
|
pub label: Option<String>,
|
||||||
|
|
||||||
|
/// The default value
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub default_value: Option<String>,
|
pub default_value: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -329,6 +339,8 @@ pub struct TemplateFunctionBaseArg {
|
|||||||
pub struct TemplateFunctionTextArg {
|
pub struct TemplateFunctionTextArg {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub base: TemplateFunctionBaseArg,
|
pub base: TemplateFunctionBaseArg,
|
||||||
|
|
||||||
|
/// Placeholder for the text input
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub placeholder: Option<String>,
|
pub placeholder: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -347,13 +359,23 @@ pub struct TemplateFunctionHttpRequestArg {
|
|||||||
pub struct TemplateFunctionFileArg {
|
pub struct TemplateFunctionFileArg {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub base: TemplateFunctionBaseArg,
|
pub base: TemplateFunctionBaseArg,
|
||||||
|
|
||||||
|
/// The title of the file selection window
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
|
||||||
|
/// Allow selecting multiple files
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub multiple: Option<bool>,
|
pub multiple: Option<bool>,
|
||||||
|
|
||||||
|
// Select a directory, not a file
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub directory: Option<bool>,
|
pub directory: Option<bool>,
|
||||||
|
|
||||||
|
// Default file path for selection dialog
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub default_path: Option<String>,
|
pub default_path: Option<String>,
|
||||||
|
|
||||||
|
// Specify to only allow selection of certain file extensions
|
||||||
#[ts(optional)]
|
#[ts(optional)]
|
||||||
pub filters: Option<Vec<OpenFileFilter>>,
|
pub filters: Option<Vec<OpenFileFilter>>,
|
||||||
}
|
}
|
||||||
@@ -363,6 +385,7 @@ pub struct TemplateFunctionFileArg {
|
|||||||
#[ts(export, export_to = "events.ts")]
|
#[ts(export, export_to = "events.ts")]
|
||||||
pub struct OpenFileFilter {
|
pub struct OpenFileFilter {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// File extensions to require
|
||||||
pub extensions: Vec<String>,
|
pub extensions: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +395,8 @@ pub struct OpenFileFilter {
|
|||||||
pub struct TemplateFunctionSelectArg {
|
pub struct TemplateFunctionSelectArg {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub base: TemplateFunctionBaseArg,
|
pub base: TemplateFunctionBaseArg,
|
||||||
|
|
||||||
|
/// The options that will be available in the select input
|
||||||
pub options: Vec<TemplateFunctionSelectOption>,
|
pub options: Vec<TemplateFunctionSelectOption>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +412,7 @@ pub struct TemplateFunctionCheckboxArg {
|
|||||||
#[serde(default, rename_all = "camelCase")]
|
#[serde(default, rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "events.ts")]
|
#[ts(export, export_to = "events.ts")]
|
||||||
pub struct TemplateFunctionSelectOption {
|
pub struct TemplateFunctionSelectOption {
|
||||||
pub name: String,
|
pub label: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export function CookieDropdown() {
|
|||||||
placeholder: 'New name',
|
placeholder: 'New name',
|
||||||
defaultValue: activeCookieJar?.name,
|
defaultValue: activeCookieJar?.name,
|
||||||
});
|
});
|
||||||
|
if (name == null) return;
|
||||||
updateCookieJar.mutate({ name });
|
updateCookieJar.mutate({ name });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Dialog } from './core/Dialog';
|
|||||||
type DialogEntry = {
|
type DialogEntry = {
|
||||||
id: string;
|
id: string;
|
||||||
render: ({ hide }: { hide: () => void }) => React.ReactNode;
|
render: ({ hide }: { hide: () => void }) => React.ReactNode;
|
||||||
} & Omit<DialogProps, 'onClose' | 'open' | 'children'>;
|
} & Omit<DialogProps, 'open' | 'children'>;
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
dialogs: DialogEntry[];
|
dialogs: DialogEntry[];
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ function SidebarButton({
|
|||||||
placeholder: 'New Name',
|
placeholder: 'New Name',
|
||||||
defaultValue: environment.name,
|
defaultValue: environment.name,
|
||||||
});
|
});
|
||||||
|
if (name == null) return;
|
||||||
updateEnvironment.mutate({ name });
|
updateEnvironment.mutate({ name });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useQueryClient } from '@tanstack/react-query';
|
|||||||
import { emit } from '@tauri-apps/api/event';
|
import { emit } from '@tauri-apps/api/event';
|
||||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||||
import type { AnyModel } from '@yaakapp-internal/models';
|
import type { AnyModel } from '@yaakapp-internal/models';
|
||||||
import type { ShowPromptRequest, ShowPromptResponse } from '@yaakapp-internal/plugin';
|
import type { PromptTextRequest, PromptTextResponse } from '@yaakapp-internal/plugin';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useEnsureActiveCookieJar, useMigrateActiveCookieJarId } from '../hooks/useActiveCookieJar';
|
import { useEnsureActiveCookieJar, useMigrateActiveCookieJarId } from '../hooks/useActiveCookieJar';
|
||||||
@@ -180,11 +180,11 @@ export function GlobalHooks() {
|
|||||||
useListenToTauriEvent('zoom_reset', zoom.zoomReset);
|
useListenToTauriEvent('zoom_reset', zoom.zoomReset);
|
||||||
|
|
||||||
const prompt = usePrompt();
|
const prompt = usePrompt();
|
||||||
useListenToTauriEvent<{ replyId: string; args: ShowPromptRequest }>(
|
useListenToTauriEvent<{ replyId: string; args: PromptTextRequest }>(
|
||||||
'show_prompt',
|
'show_prompt',
|
||||||
async (event) => {
|
async (event) => {
|
||||||
const value = await prompt(event.payload.args);
|
const value = await prompt(event.payload.args);
|
||||||
const result: ShowPromptResponse = { value };
|
const result: PromptTextResponse = { value };
|
||||||
await emit(event.payload.replyId, result);
|
await emit(event.payload.replyId, result);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export const RequestMethodDropdown = memo(function RequestMethodDropdown({
|
|||||||
description: 'Enter a custom method name',
|
description: 'Enter a custom method name',
|
||||||
placeholder: 'CUSTOM',
|
placeholder: 'CUSTOM',
|
||||||
});
|
});
|
||||||
|
if (newMethod == null) return;
|
||||||
onChange(newMethod);
|
onChange(newMethod);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -767,6 +767,7 @@ function SidebarItem({
|
|||||||
placeholder: 'New Name',
|
placeholder: 'New Name',
|
||||||
defaultValue: itemName,
|
defaultValue: itemName,
|
||||||
});
|
});
|
||||||
|
if (name == null) return;
|
||||||
updateAnyFolder.mutate({ id: itemId, update: (f) => ({ ...f, name }) });
|
updateAnyFolder.mutate({ id: itemId, update: (f) => ({ ...f, name }) });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import type {
|
|||||||
TemplateFunction,
|
TemplateFunction,
|
||||||
TemplateFunctionArg,
|
TemplateFunctionArg,
|
||||||
TemplateFunctionCheckboxArg,
|
TemplateFunctionCheckboxArg,
|
||||||
|
TemplateFunctionFileArg,
|
||||||
TemplateFunctionHttpRequestArg,
|
TemplateFunctionHttpRequestArg,
|
||||||
TemplateFunctionSelectArg,
|
TemplateFunctionSelectArg,
|
||||||
TemplateFunctionTextArg,
|
TemplateFunctionTextArg,
|
||||||
} from '@yaakapp-internal/plugin';
|
} from '@yaakapp-internal/plugin';
|
||||||
import type { FnArg, Tokens } from '@yaakapp-internal/template';
|
import type { FnArg, Tokens } from '@yaakapp-internal/template';
|
||||||
|
import classNames from 'classnames';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||||
import { useDebouncedValue } from '../hooks/useDebouncedValue';
|
import { useDebouncedValue } from '../hooks/useDebouncedValue';
|
||||||
@@ -20,6 +22,7 @@ import { InlineCode } from './core/InlineCode';
|
|||||||
import { PlainInput } from './core/PlainInput';
|
import { PlainInput } from './core/PlainInput';
|
||||||
import { Select } from './core/Select';
|
import { Select } from './core/Select';
|
||||||
import { VStack } from './core/Stacks';
|
import { VStack } from './core/Stacks';
|
||||||
|
import { SelectFile } from './SelectFile';
|
||||||
|
|
||||||
const NULL_ARG = '__NULL__';
|
const NULL_ARG = '__NULL__';
|
||||||
|
|
||||||
@@ -50,8 +53,8 @@ export function TemplateFunctionDialog({ templateFunction, hide, initialTokens,
|
|||||||
return initial;
|
return initial;
|
||||||
});
|
});
|
||||||
|
|
||||||
const setArgValue = useCallback((name: string, value: string | boolean) => {
|
const setArgValue = useCallback((name: string, value: string | boolean | null) => {
|
||||||
setArgValues((v) => ({ ...v, [name]: value }));
|
setArgValues((v) => ({ ...v, [name]: value == null ? '__NULL__' : value }));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const tokens: Tokens = useMemo(() => {
|
const tokens: Tokens = useMemo(() => {
|
||||||
@@ -90,6 +93,7 @@ export function TemplateFunctionDialog({ templateFunction, hide, initialTokens,
|
|||||||
|
|
||||||
const debouncedTagText = useDebouncedValue(tagText.data ?? '', 200);
|
const debouncedTagText = useDebouncedValue(tagText.data ?? '', 200);
|
||||||
const rendered = useRenderTemplate(debouncedTagText);
|
const rendered = useRenderTemplate(debouncedTagText);
|
||||||
|
const tooLarge = (rendered.data ?? '').length > 10000;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VStack className="pb-3" space={4}>
|
<VStack className="pb-3" space={4}>
|
||||||
@@ -133,10 +137,29 @@ export function TemplateFunctionDialog({ templateFunction, hide, initialTokens,
|
|||||||
value={argValues[a.name] ? String(argValues[a.name]) : '__ERROR__'}
|
value={argValues[a.name] ? String(argValues[a.name]) : '__ERROR__'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
case 'file':
|
||||||
|
return (
|
||||||
|
<FileArg
|
||||||
|
key={i}
|
||||||
|
arg={a}
|
||||||
|
onChange={(v) => setArgValue(a.name, v)}
|
||||||
|
filePath={argValues[a.name] ? String(argValues[a.name]) : '__ERROR__'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
</VStack>
|
</VStack>
|
||||||
<InlineCode className="select-text cursor-text">{rendered.data || <> </>}</InlineCode>
|
<VStack className="w-full">
|
||||||
|
<div className="text-sm text-text-subtle">Preview</div>
|
||||||
|
<InlineCode
|
||||||
|
className={classNames(
|
||||||
|
'whitespace-pre select-text cursor-text max-h-[10rem] overflow-y-auto hide-scrollbars',
|
||||||
|
tooLarge && 'italic text-danger',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{tooLarge ? 'too large to preview' : rendered.data || <> </>}
|
||||||
|
</InlineCode>
|
||||||
|
</VStack>
|
||||||
<Button color="primary" onClick={handleDone}>
|
<Button color="primary" onClick={handleDone}>
|
||||||
Done
|
Done
|
||||||
</Button>
|
</Button>
|
||||||
@@ -165,7 +188,13 @@ function TextArg({
|
|||||||
name={arg.name}
|
name={arg.name}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
defaultValue={value === NULL_ARG ? '' : value}
|
defaultValue={value === NULL_ARG ? '' : value}
|
||||||
label={arg.label ?? arg.name}
|
require={!arg.optional}
|
||||||
|
label={
|
||||||
|
<>
|
||||||
|
{arg.label ?? arg.name}
|
||||||
|
{arg.optional && <span> (optional)</span>}
|
||||||
|
</>
|
||||||
|
}
|
||||||
hideLabel={arg.label == null}
|
hideLabel={arg.label == null}
|
||||||
placeholder={arg.placeholder ?? arg.defaultValue ?? ''}
|
placeholder={arg.placeholder ?? arg.defaultValue ?? ''}
|
||||||
/>
|
/>
|
||||||
@@ -197,6 +226,24 @@ function SelectArg({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function FileArg({
|
||||||
|
arg,
|
||||||
|
filePath,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
arg: TemplateFunctionFileArg;
|
||||||
|
filePath: string;
|
||||||
|
onChange: (v: string | null) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SelectFile
|
||||||
|
onChange={({ filePath }) => onChange(filePath)}
|
||||||
|
filePath={filePath === '__NULL__' ? null : filePath}
|
||||||
|
directory={!!arg.directory}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function HttpRequestArg({
|
function HttpRequestArg({
|
||||||
arg,
|
arg,
|
||||||
value,
|
value,
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export function TemplateVariableDialog({ hide, onChange, initialTokens }: Props)
|
|||||||
/>
|
/>
|
||||||
</VStack>
|
</VStack>
|
||||||
<VStack>
|
<VStack>
|
||||||
<div className="text-sm text-text-subtle">Render Preview</div>
|
<div className="text-sm text-text-subtle">Preview</div>
|
||||||
<InlineCode className="select-text cursor-text">{rendered.data}</InlineCode>
|
<InlineCode className="select-text cursor-text">{rendered.data}</InlineCode>
|
||||||
</VStack>
|
</VStack>
|
||||||
<Button color="primary" onClick={handleDone}>
|
<Button color="primary" onClick={handleDone}>
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export const WorkspaceActionsDropdown = memo(function WorkspaceActionsDropdown({
|
|||||||
placeholder: 'New Name',
|
placeholder: 'New Name',
|
||||||
defaultValue: activeWorkspace?.name,
|
defaultValue: activeWorkspace?.name,
|
||||||
});
|
});
|
||||||
|
if (name == null) return;
|
||||||
updateWorkspace.mutate({ name });
|
updateWorkspace.mutate({ name });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { IconButton } from './IconButton';
|
|||||||
export interface DialogProps {
|
export interface DialogProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose?: () => void;
|
||||||
title?: ReactNode;
|
title?: ReactNode;
|
||||||
description?: ReactNode;
|
description?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -44,7 +44,7 @@ export function Dialog({
|
|||||||
'Escape',
|
'Escape',
|
||||||
() => {
|
() => {
|
||||||
if (!open) return;
|
if (!open) return;
|
||||||
onClose();
|
onClose?.();
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
[open],
|
[open],
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export type InputProps = Omit<
|
|||||||
> & {
|
> & {
|
||||||
name?: string;
|
name?: string;
|
||||||
type?: 'text' | 'password';
|
type?: 'text' | 'password';
|
||||||
label: string;
|
label: ReactNode;
|
||||||
hideLabel?: boolean;
|
hideLabel?: boolean;
|
||||||
labelPosition?: 'top' | 'left';
|
labelPosition?: 'top' | 'left';
|
||||||
labelClassName?: string;
|
labelClassName?: string;
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ function PairEditorRow({
|
|||||||
leftSlot: <Icon icon="pencil" />,
|
leftSlot: <Icon icon="pencil" />,
|
||||||
hidden: !pairContainer.pair.isFile,
|
hidden: !pairContainer.pair.isFile,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
const v = await prompt({
|
const contentType = await prompt({
|
||||||
id: 'content-type',
|
id: 'content-type',
|
||||||
require: false,
|
require: false,
|
||||||
title: 'Override Content-Type',
|
title: 'Override Content-Type',
|
||||||
@@ -522,7 +522,8 @@ function PairEditorRow({
|
|||||||
confirmText: 'Set',
|
confirmText: 'Set',
|
||||||
description: 'Leave blank to auto-detect',
|
description: 'Leave blank to auto-detect',
|
||||||
});
|
});
|
||||||
handleChangeValueContentType(v);
|
if (contentType == null) return;
|
||||||
|
handleChangeValueContentType(contentType);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { HStack } from '../components/core/Stacks';
|
|||||||
export type PromptProps = Omit<ShowPromptRequest, 'id' | 'title' | 'description'> & {
|
export type PromptProps = Omit<ShowPromptRequest, 'id' | 'title' | 'description'> & {
|
||||||
description?: ReactNode;
|
description?: ReactNode;
|
||||||
onHide: () => void;
|
onHide: () => void;
|
||||||
onResult: (value: string) => void;
|
onResult: (value: string | null) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Prompt({
|
export function Prompt({
|
||||||
|
|||||||
@@ -9,24 +9,30 @@ export function useCreateFolder() {
|
|||||||
const workspace = useActiveWorkspace();
|
const workspace = useActiveWorkspace();
|
||||||
const prompt = usePrompt();
|
const prompt = usePrompt();
|
||||||
|
|
||||||
return useMutation<Folder, unknown, Partial<Pick<Folder, 'name' | 'sortPriority' | 'folderId'>>>({
|
return useMutation<void, unknown, Partial<Pick<Folder, 'name' | 'sortPriority' | 'folderId'>>>({
|
||||||
mutationKey: ['create_folder'],
|
mutationKey: ['create_folder'],
|
||||||
mutationFn: async (patch) => {
|
mutationFn: async (patch) => {
|
||||||
if (workspace === null) {
|
if (workspace === null) {
|
||||||
throw new Error("Cannot create folder when there's no active workspace");
|
throw new Error("Cannot create folder when there's no active workspace");
|
||||||
}
|
}
|
||||||
patch.name =
|
|
||||||
patch.name ||
|
if (!patch.name) {
|
||||||
(await prompt({
|
const name = await prompt({
|
||||||
id: 'new-folder',
|
id: 'new-folder',
|
||||||
label: 'Name',
|
label: 'Name',
|
||||||
defaultValue: 'Folder',
|
defaultValue: 'Folder',
|
||||||
title: 'New Folder',
|
title: 'New Folder',
|
||||||
confirmText: 'Create',
|
confirmText: 'Create',
|
||||||
placeholder: 'Name',
|
placeholder: 'Name',
|
||||||
}));
|
});
|
||||||
|
if (name == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
patch.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
patch.sortPriority = patch.sortPriority || -Date.now();
|
patch.sortPriority = patch.sortPriority || -Date.now();
|
||||||
return invokeCmd('cmd_create_folder', { workspaceId: workspace.id, ...patch });
|
await invokeCmd('cmd_create_folder', { workspaceId: workspace.id, ...patch });
|
||||||
},
|
},
|
||||||
onSettled: () => trackEvent('folder', 'create'),
|
onSettled: () => trackEvent('folder', 'create'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,19 +4,27 @@ import type { PromptProps } from './Prompt';
|
|||||||
import { Prompt } from './Prompt';
|
import { Prompt } from './Prompt';
|
||||||
|
|
||||||
type Props = Pick<DialogProps, 'title' | 'description'> &
|
type Props = Pick<DialogProps, 'title' | 'description'> &
|
||||||
Omit<PromptProps, 'onResult' | 'onHide'> & { id: string };
|
Omit<PromptProps, 'onClose' | 'onHide' | 'onResult'> & { id: string };
|
||||||
|
|
||||||
export function usePrompt() {
|
export function usePrompt() {
|
||||||
const dialog = useDialog();
|
const dialog = useDialog();
|
||||||
return ({ id, title, description, ...props }: Props) =>
|
return ({ id, title, description, ...props }: Props) =>
|
||||||
new Promise((onResult: PromptProps['onResult']) => {
|
new Promise((resolve: PromptProps['onResult']) => {
|
||||||
dialog.show({
|
dialog.show({
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
hideX: true,
|
hideX: true,
|
||||||
size: 'sm',
|
size: 'sm',
|
||||||
render: ({ hide: onHide }) => Prompt({ onHide, onResult, ...props }),
|
render: ({ hide }) =>
|
||||||
|
Prompt({
|
||||||
|
onHide: () => {
|
||||||
|
hide();
|
||||||
|
resolve(null);
|
||||||
|
},
|
||||||
|
onResult: resolve,
|
||||||
|
...props,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ export function useRenameRequest(requestId: string | null) {
|
|||||||
defaultValue: request.name,
|
defaultValue: request.name,
|
||||||
confirmText: 'Save',
|
confirmText: 'Save',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (name == null) return;
|
||||||
|
|
||||||
if (request.model === 'http_request') {
|
if (request.model === 'http_request') {
|
||||||
updateHttpRequest.mutate({ id: request.id, update: (r: HttpRequest) => ({ ...r, name }) });
|
updateHttpRequest.mutate({ id: request.id, update: (r: HttpRequest) => ({ ...r, name }) });
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user