From 7742cde11adc6d7127f04914bdcf1d4dab0fec28 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Tue, 21 Nov 2023 22:35:28 -0800 Subject: [PATCH] Env dialog hotkey --- src-web/components/DialogContext.tsx | 10 +++++++-- .../components/EnvironmentActionsDropdown.tsx | 6 +++++- src-web/components/UrlBar.tsx | 8 ++++++- .../responseViewers/ImageViewer.tsx | 21 +++++++++++++++++++ src-web/hooks/useHotkey.ts | 7 ++++--- 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src-web/components/DialogContext.tsx b/src-web/components/DialogContext.tsx index 64c67779..d4531b6b 100644 --- a/src-web/components/DialogContext.tsx +++ b/src-web/components/DialogContext.tsx @@ -16,6 +16,7 @@ interface State { interface Actions { show: (d: DialogEntryOptionalId) => void; + toggle: (d: DialogEntry) => void; hide: (id: string) => void; } @@ -26,15 +27,20 @@ export const DialogProvider = ({ children }: { children: React.ReactNode }) => { const [dialogs, setDialogs] = useState([]); const actions = useMemo( () => ({ - show: ({ id: oid, ...props }: DialogEntryOptionalId) => { + show({ id: oid, ...props }: DialogEntryOptionalId) { const id = oid ?? Math.random().toString(36).slice(2); setDialogs((a) => [...a.filter((d) => d.id !== id), { id, ...props }]); }, + toggle({ id: oid, ...props }: DialogEntryOptionalId) { + const id = oid ?? Math.random().toString(36).slice(2); + if (dialogs.some((d) => d.id === id)) this.hide(id); + else this.show({ id, ...props }); + }, hide: (id: string) => { setDialogs((a) => a.filter((d) => d.id !== id)); }, }), - [], + [dialogs], ); const state: State = { diff --git a/src-web/components/EnvironmentActionsDropdown.tsx b/src-web/components/EnvironmentActionsDropdown.tsx index 376eb497..91d2c51f 100644 --- a/src-web/components/EnvironmentActionsDropdown.tsx +++ b/src-web/components/EnvironmentActionsDropdown.tsx @@ -3,6 +3,7 @@ import { memo, useCallback, useMemo } from 'react'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useAppRoutes } from '../hooks/useAppRoutes'; import { useEnvironments } from '../hooks/useEnvironments'; +import { useHotkey } from '../hooks/useHotkey'; import type { ButtonProps } from './core/Button'; import { Button } from './core/Button'; import type { DropdownItem } from './core/Dropdown'; @@ -25,12 +26,15 @@ export const EnvironmentActionsDropdown = memo(function EnvironmentActionsDropdo const routes = useAppRoutes(); const showEnvironmentDialog = useCallback(() => { - dialog.show({ + dialog.toggle({ + id: 'environment-editor', title: 'Manage Environments', render: () => , }); }, [dialog, activeEnvironment]); + useHotkey('environmentEditor.show', showEnvironmentDialog); + const items: DropdownItem[] = useMemo( () => [ ...environments.map( diff --git a/src-web/components/UrlBar.tsx b/src-web/components/UrlBar.tsx index 38532359..3207059b 100644 --- a/src-web/components/UrlBar.tsx +++ b/src-web/components/UrlBar.tsx @@ -40,7 +40,13 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa [sendRequest], ); - useHotkey('url.focus', () => inputRef.current?.focus()); + useHotkey('urlBar.focus', () => { + const head = inputRef.current?.state.doc.length ?? 0; + inputRef.current?.dispatch({ + selection: { anchor: 0, head }, + }); + inputRef.current?.focus(); + }); return (
diff --git a/src-web/components/responseViewers/ImageViewer.tsx b/src-web/components/responseViewers/ImageViewer.tsx index 2fd7b0ed..4b94a581 100644 --- a/src-web/components/responseViewers/ImageViewer.tsx +++ b/src-web/components/responseViewers/ImageViewer.tsx @@ -1,5 +1,6 @@ import { convertFileSrc } from '@tauri-apps/api/tauri'; import classNames from 'classnames'; +import { useState } from 'react'; import type { HttpResponse } from '../../lib/models'; interface Props { @@ -8,11 +9,31 @@ interface Props { } export function ImageViewer({ response, className }: Props) { + const bytes = response.contentLength ?? 0; + const [show, setShow] = useState(bytes < 3 * 1000 * 1000); + if (response.bodyPath === null) { return
Empty response body
; } const src = convertFileSrc(response.bodyPath); + if (!show) { + return ( + <> +
+ Response body is too large to preview.{' '} + +
+ + ); + } + return ( = { 'request.send': ['Meta+Enter', 'Meta+r'], @@ -14,7 +15,8 @@ const hotkeys: Record = { 'request.duplicate': ['Meta+d'], 'sidebar.toggle': ['Meta+b'], 'sidebar.focus': ['Meta+1'], - 'url.focus': ['Meta+l'], + 'urlBar.focus': ['Meta+l'], + 'environmentEditor.show': ['Meta+e'], }; export function useHotkey(action: HotkeyAction | null, callback: (e: KeyboardEvent) => void) { @@ -27,7 +29,6 @@ export function useHotkey(action: HotkeyAction | null, callback: (e: KeyboardEve useEffect(() => { const down = (e: KeyboardEvent) => { - console.log('KEY DOWN', e.key); currentKeys.current.add(e.key); for (const [hkAction, hkKeys] of Object.entries(hotkeys)) { for (const hkKey of hkKeys) {