Improved querystring import on paste (#110)

This commit is contained in:
Gregory Schier
2024-09-25 08:03:19 -07:00
committed by GitHub
parent de7097ff1d
commit 7d97404c11
5 changed files with 36 additions and 25 deletions

View File

@@ -323,10 +323,11 @@ export const RequestPane = memo(function RequestPane({
url={activeRequest.url}
method={activeRequest.method}
placeholder="https://example.com"
onPaste={(text) => {
onPasteOverwrite={(text) => {
if (text.startsWith('curl ')) {
importCurl.mutate({ overwriteRequestId: activeRequestId, command: text });
} else {
// Only import query if pasted text contains entire querystring
importQuerystring.mutate(text);
}
}}

View File

@@ -17,6 +17,7 @@ type Props = Pick<HttpRequest, 'url'> & {
onSend: () => void;
onUrlChange: (url: string) => void;
onPaste?: (v: string) => void;
onPasteOverwrite?: (v: string) => void;
onCancel: () => void;
submitIcon?: IconProps['icon'] | null;
onMethodChange?: (method: string) => void;
@@ -37,6 +38,7 @@ export const UrlBar = memo(function UrlBar({
onCancel,
onMethodChange,
onPaste,
onPasteOverwrite,
submitIcon = 'send_horizontal',
autocomplete,
rightSlot,
@@ -77,6 +79,7 @@ export const UrlBar = memo(function UrlBar({
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onPaste={onPaste}
onPasteOverwrite={onPasteOverwrite}
onChange={onUrlChange}
defaultValue={url}
placeholder={placeholder}

View File

@@ -55,6 +55,7 @@ export interface EditorProps {
useTemplating?: boolean;
onChange?: (value: string) => void;
onPaste?: (value: string) => void;
onPasteOverwrite?: (value: string) => void;
onFocus?: () => void;
onBlur?: () => void;
onKeyDown?: (e: KeyboardEvent) => void;
@@ -83,6 +84,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
forceUpdateKey,
onChange,
onPaste,
onPasteOverwrite,
onFocus,
onBlur,
onKeyDown,
@@ -121,6 +123,12 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
handlePaste.current = onPaste;
}, [onPaste]);
// Use ref so we can update the handler without re-initializing the editor
const handlePasteOverwrite = useRef<EditorProps['onPasteOverwrite']>(onPaste);
useEffect(() => {
handlePasteOverwrite.current = onPasteOverwrite;
}, [onPasteOverwrite]);
// Use ref so we can update the handler without re-initializing the editor
const handleFocus = useRef<EditorProps['onFocus']>(onFocus);
useEffect(() => {
@@ -303,6 +311,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
singleLine,
onChange: handleChange,
onPaste: handlePaste,
onPasteOverwrite: handlePasteOverwrite,
onFocus: handleFocus,
onBlur: handleBlur,
onKeyDown: handleKeyDown,
@@ -420,6 +429,7 @@ function getExtensions({
singleLine,
onChange,
onPaste,
onPasteOverwrite,
onFocus,
onBlur,
onKeyDown,
@@ -427,6 +437,7 @@ function getExtensions({
container: HTMLDivElement | null;
onChange: MutableRefObject<EditorProps['onChange']>;
onPaste: MutableRefObject<EditorProps['onPaste']>;
onPasteOverwrite: MutableRefObject<EditorProps['onPasteOverwrite']>;
onFocus: MutableRefObject<EditorProps['onFocus']>;
onBlur: MutableRefObject<EditorProps['onBlur']>;
onKeyDown: MutableRefObject<EditorProps['onKeyDown']>;
@@ -449,8 +460,12 @@ function getExtensions({
keydown: (e) => {
onKeyDown.current?.(e);
},
paste: (e) => {
onPaste.current?.(e.clipboardData?.getData('text/plain') ?? '');
paste: (e, v) => {
const textData = e.clipboardData?.getData('text/plain') ?? '';
onPaste.current?.(textData);
if (v.state.selection.main.from === 0 && v.state.selection.main.to === v.state.doc.length) {
onPasteOverwrite.current?.(textData);
}
},
}),
tooltips({ parent }),

View File

@@ -35,6 +35,7 @@ export type InputProps = Omit<
onFocus?: () => void;
onBlur?: () => void;
onPaste?: (value: string) => void;
onPasteOverwrite?: (value: string) => void;
defaultValue?: string;
leftSlot?: ReactNode;
rightSlot?: ReactNode;
@@ -62,6 +63,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
onChange,
onFocus,
onPaste,
onPasteOverwrite,
placeholder,
require,
rightSlot,
@@ -179,6 +181,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
placeholder={placeholder}
onChange={handleChange}
onPaste={onPaste}
onPasteOverwrite={onPasteOverwrite}
className={editorClassName}
onFocus={handleFocus}
onBlur={handleBlur}

View File

@@ -14,31 +14,20 @@ export function useImportQuerystring(requestId: string) {
return useMutation({
mutationKey: ['import_querystring'],
mutationFn: async (url: string) => {
const [baseUrl, ...rest] = url.split('?');
if (rest.length === 0) return;
const split = url.split(/\?(.*)/s);
const baseUrl = split[0] ?? '';
const querystring = split[1] ?? '';
if (!querystring) return;
const request = await getHttpRequest(requestId);
if (request == null) return;
const querystring = rest.join('?');
const parsedParams = Array.from(new URLSearchParams(querystring).entries());
const additionalUrlParameters: HttpUrlParameter[] = parsedParams.map(
([name, value]): HttpUrlParameter => ({
name,
value,
enabled: true,
}),
);
const urlParameters: HttpUrlParameter[] = [...request.urlParameters];
for (const newParam of additionalUrlParameters) {
const index = urlParameters.findIndex((p) => p.name === newParam.name);
if (index >= 0) {
urlParameters[index]!.value = decodeURIComponent(newParam.value);
} else {
urlParameters.push(newParam);
}
}
const urlParameters: HttpUrlParameter[] = parsedParams.map(([name, value]) => ({
name,
value,
enabled: true,
}));
await updateRequest.mutateAsync({
id: requestId,
@@ -48,11 +37,11 @@ export function useImportQuerystring(requestId: string) {
},
});
if (additionalUrlParameters.length > 0) {
if (urlParameters.length > 0) {
toast.show({
id: 'querystring-imported',
color: 'info',
message: `Imported ${additionalUrlParameters.length} ${pluralize('param', additionalUrlParameters.length)} from URL`,
message: `Extracted ${urlParameters.length} ${pluralize('parameter', urlParameters.length)} from URL`,
});
}