Better curl import

This commit is contained in:
Gregory Schier
2024-08-10 07:53:26 -07:00
parent 2f9532cf53
commit 08ea48b996
8 changed files with 72 additions and 78 deletions

View File

@@ -1,4 +1,4 @@
import { useClipboardText } from '../hooks/useClipboardText';
import { useCopy } from '../hooks/useCopy';
import { useTimedBoolean } from '../hooks/useTimedBoolean';
import type { ButtonProps } from './core/Button';
import { Button } from './core/Button';
@@ -8,7 +8,7 @@ interface Props extends ButtonProps {
}
export function CopyButton({ text, ...props }: Props) {
const [, copy] = useClipboardText({ disableToast: true });
const copy = useCopy({ disableToast: true });
const [copied, setCopied] = useTimedBoolean();
return (
<Button

View File

@@ -3,9 +3,8 @@ import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
import type { Model } from '@yaakapp/api';
import { useEffect } from 'react';
import { useAtiveWorkspaceChangedToast } from '../hooks/useAtiveWorkspaceChangedToast';
import { useClipboardText } from '../hooks/useClipboardText';
import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette';
import { cookieJarsQueryKey } from '../hooks/useCookieJars';
import { useCopy } from '../hooks/useCopy';
import { environmentsQueryKey } from '../hooks/useEnvironments';
import { foldersQueryKey } from '../hooks/useFolders';
import { grpcConnectionsQueryKey } from '../hooks/useGrpcConnections';
@@ -23,6 +22,7 @@ import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces';
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
import { settingsQueryKey, useSettings } from '../hooks/useSettings';
import { useSyncThemeToDocument } from '../hooks/useSyncThemeToDocument';
import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette';
import { workspacesQueryKey } from '../hooks/useWorkspaces';
import { useZoom } from '../hooks/useZoom';
import { modelsEq } from '../lib/models';
@@ -159,7 +159,7 @@ export function GlobalHooks() {
useHotKey('app.zoom_reset', () => zoom.zoomReset);
useListenToTauriEvent('zoom_reset', () => zoom.zoomReset);
const [, copy] = useClipboardText();
const copy = useCopy();
useListenToTauriEvent('generate_theme_css', () => {
const themesCss = [
yaakDark,

View File

@@ -1,15 +1,22 @@
import { clear, readText } from '@tauri-apps/plugin-clipboard-manager';
import { motion } from 'framer-motion';
import React, { useState } from 'react';
import { useClipboardText } from '../hooks/useClipboardText';
import React, { useEffect, useState } from 'react';
import { useImportCurl } from '../hooks/useImportCurl';
import { useWindowFocus } from '../hooks/useWindowFocus';
import { Button } from './core/Button';
import { Icon } from './core/Icon';
export function ImportCurlButton() {
const [clipboardText] = useClipboardText();
const importCurl = useImportCurl({ clearClipboard: true });
const focused = useWindowFocus();
const [clipboardText, setClipboardText] = useState('');
const importCurl = useImportCurl();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
readText().then(setClipboardText);
}, [focused]);
if (!clipboardText?.trim().startsWith('curl ')) {
return null;
}
@@ -26,14 +33,17 @@ export function ImportCurlButton() {
color="primary"
leftSlot={<Icon icon="paste" size="sm" />}
isLoading={isLoading}
onClick={() => {
onClick={async () => {
setIsLoading(true);
importCurl
.mutateAsync({
requestId: null, // Create request
command: clipboardText,
})
.finally(() => setIsLoading(false));
try {
await importCurl.mutateAsync({ command: clipboardText });
await clear(); // Clear the clipboard so the button goes away
setClipboardText('');
} catch (e) {
// Nothing
} finally {
setIsLoading(false);
}
}}
>
Import Curl

View File

@@ -1,3 +1,4 @@
import type { HttpRequest, HttpRequestHeader, HttpUrlParameter } from '@yaakapp/api';
import classNames from 'classnames';
import type { CSSProperties } from 'react';
import React, { memo, useCallback, useMemo, useState } from 'react';
@@ -12,7 +13,6 @@ import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import { tryFormatJson } from '../lib/formatters';
import type { HttpRequest, HttpRequestHeader, HttpUrlParameter } from '@yaakapp/api';
import {
AUTH_TYPE_BASIC,
AUTH_TYPE_BEARER,
@@ -268,7 +268,7 @@ export const RequestPane = memo(function RequestPane({
const isLoading = useIsResponseLoading(activeRequestId ?? null);
const { updateKey } = useRequestUpdateKey(activeRequestId ?? null);
const importCurl = useImportCurl({ clearClipboard: true });
const importCurl = useImportCurl();
return (
<div
@@ -282,11 +282,11 @@ export const RequestPane = memo(function RequestPane({
url={activeRequest.url}
method={activeRequest.method}
placeholder="https://example.com"
onPaste={async (command) => {
onPaste={(command) => {
if (!command.startsWith('curl ')) {
return;
}
importCurl.mutate({ requestId: activeRequestId, command });
importCurl.mutate({ overwriteRequestId: activeRequestId, command });
}}
autocomplete={{
minMatch: 3,

View File

@@ -1,43 +0,0 @@
import { clear, readText, writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useCallback, useEffect } from 'react';
import { createGlobalState } from 'react-use';
import { useToast } from '../components/ToastContext';
import { useWindowFocus } from './useWindowFocus';
const useClipboardTextState = createGlobalState<string>('');
export function useClipboardText({ disableToast }: { disableToast?: boolean } = {}) {
const [value, setValue] = useClipboardTextState();
const focused = useWindowFocus();
const toast = useToast();
useEffect(() => {
readText()
.then(setValue)
.catch(() => {
// Clipboard probably empty
setValue('');
});
}, [focused, setValue]);
const setText = useCallback(
(text: string | null) => {
if (text == null) {
clear().catch(console.error);
} else {
writeText(text).catch(console.error);
}
if (text != '' && !disableToast) {
toast.show({
id: 'copied',
variant: 'copied',
message: 'Copied to clipboard',
});
}
setValue(text || '');
},
[disableToast, setValue, toast],
);
return [value, setText] as const;
}

27
src-web/hooks/useCopy.ts Normal file
View File

@@ -0,0 +1,27 @@
import { clear, writeText } from '@tauri-apps/plugin-clipboard-manager';
import { useCallback } from 'react';
import { useToast } from '../components/ToastContext';
export function useCopy({ disableToast }: { disableToast?: boolean } = {}) {
const toast = useToast();
const copy = useCallback(
(text: string | null) => {
if (text == null) {
clear().catch(console.error);
} else {
writeText(text).catch(console.error);
}
if (text != '' && !disableToast) {
toast.show({
id: 'copied',
variant: 'copied',
message: 'Copied to clipboard',
});
}
},
[disableToast, toast],
);
return copy;
}

View File

@@ -1,10 +1,10 @@
import { useMutation } from '@tanstack/react-query';
import { invokeCmd } from '../lib/tauri';
import { useActiveEnvironmentId } from './useActiveEnvironmentId';
import { useClipboardText } from './useClipboardText';
import { useCopy } from './useCopy';
export function useCopyAsCurl(requestId: string) {
const [, copy] = useClipboardText();
const copy = useCopy();
const environmentId = useActiveEnvironmentId();
return useMutation({
mutationKey: ['copy_as_curl', requestId],

View File

@@ -1,23 +1,27 @@
import { useMutation } from '@tanstack/react-query';
import { useToast } from '../components/ToastContext';
import { invokeCmd } from '../lib/tauri';
import { useActiveWorkspaceId } from './useActiveWorkspaceId';
import { useCreateHttpRequest } from './useCreateHttpRequest';
import { useRequestUpdateKey } from './useRequestUpdateKey';
import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest';
import { useToast } from '../components/ToastContext';
import { useCreateHttpRequest } from './useCreateHttpRequest';
import { useClipboardText } from './useClipboardText';
export function useImportCurl({ clearClipboard }: { clearClipboard?: boolean } = {}) {
export function useImportCurl() {
const workspaceId = useActiveWorkspaceId();
const updateRequest = useUpdateAnyHttpRequest();
const createRequest = useCreateHttpRequest();
const { wasUpdatedExternally } = useRequestUpdateKey(null);
const toast = useToast();
const [, setClipboardText] = useClipboardText();
return useMutation({
mutationKey: ['import_curl'],
mutationFn: async ({ requestId, command }: { requestId: string | null; command: string }) => {
mutationFn: async ({
overwriteRequestId,
command,
}: {
overwriteRequestId?: string;
command: string;
}) => {
const request: Record<string, unknown> = await invokeCmd('cmd_curl_to_request', {
command,
workspaceId,
@@ -25,23 +29,19 @@ export function useImportCurl({ clearClipboard }: { clearClipboard?: boolean } =
delete request.id;
let verb;
if (requestId == null) {
if (overwriteRequestId == null) {
verb = 'Created';
await createRequest.mutateAsync(request);
} else {
verb = 'Updated';
await updateRequest.mutateAsync({ id: requestId, update: request });
setTimeout(() => wasUpdatedExternally(requestId), 100);
await updateRequest.mutateAsync({ id: overwriteRequestId, update: request });
setTimeout(() => wasUpdatedExternally(overwriteRequestId), 100);
}
toast.show({
variant: 'success',
message: `${verb} request from Curl`,
});
if (clearClipboard) {
setClipboardText(null);
}
},
});
}