From 86856e350628d90f0ee95b08765f96d04b804296 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Tue, 30 Jul 2024 15:10:24 -0700 Subject: [PATCH] Add rename/delete/send to cmd+k --- src-web/components/CommandPalette.tsx | 50 ++++++++++++++----- src-web/components/GlobalHooks.tsx | 6 ++- src-web/components/Sidebar.tsx | 31 ++---------- src-web/components/WorkspaceHeader.tsx | 9 ++++ src-web/hooks/useRenameRequest.tsx | 42 ++++++++++++++++ ...alette.tsx => useToggleCommandPalette.tsx} | 10 ++-- 6 files changed, 103 insertions(+), 45 deletions(-) create mode 100644 src-web/hooks/useRenameRequest.tsx rename src-web/hooks/{useCommandPalette.tsx => useToggleCommandPalette.tsx} (72%) diff --git a/src-web/components/CommandPalette.tsx b/src-web/components/CommandPalette.tsx index ccfbf7ad..11605698 100644 --- a/src-web/components/CommandPalette.tsx +++ b/src-web/components/CommandPalette.tsx @@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useActiveEnvironmentId } from '../hooks/useActiveEnvironmentId'; -import { useActiveRequestId } from '../hooks/useActiveRequestId'; +import { useActiveRequest } from '../hooks/useActiveRequest'; import { useActiveWorkspaceId } from '../hooks/useActiveWorkspaceId'; import { useAppRoutes } from '../hooks/useAppRoutes'; import { useCreateEnvironment } from '../hooks/useCreateEnvironment'; @@ -13,6 +13,7 @@ import { useCreateGrpcRequest } from '../hooks/useCreateGrpcRequest'; import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest'; import { useCreateWorkspace } from '../hooks/useCreateWorkspace'; import { useDebouncedState } from '../hooks/useDebouncedState'; +import { useDeleteRequest } from '../hooks/useDeleteRequest'; import { useEnvironments } from '../hooks/useEnvironments'; import type { HotkeyAction } from '../hooks/useHotKey'; import { useHotKey } from '../hooks/useHotKey'; @@ -20,7 +21,9 @@ import { useOpenWorkspace } from '../hooks/useOpenWorkspace'; import { useRecentEnvironments } from '../hooks/useRecentEnvironments'; import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces'; +import { useRenameRequest } from '../hooks/useRenameRequest'; import { useRequests } from '../hooks/useRequests'; +import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; import { useSidebarHidden } from '../hooks/useSidebarHidden'; import { useWorkspaces } from '../hooks/useWorkspaces'; import { fallbackRequestName } from '../lib/fallbackRequestName'; @@ -55,13 +58,12 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { const [selectedItemKey, setSelectedItemKey] = useState(null); const routes = useAppRoutes(); const activeEnvironmentId = useActiveEnvironmentId(); - const activeRequestId = useActiveRequestId(); - const active = useActiveWorkspaceId(); const workspaces = useWorkspaces(); const environments = useEnvironments(); const recentEnvironments = useRecentEnvironments(); const recentWorkspaces = useRecentWorkspaces(); const requests = useRequests(); + const activeRequest = useActiveRequest(); const recentRequests = useRecentRequests(); const openWorkspace = useOpenWorkspace(); const createWorkspace = useCreateWorkspace(); @@ -72,6 +74,9 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { const dialog = useDialog(); const workspaceId = useActiveWorkspaceId(); const activeEnvironment = useActiveEnvironment(); + const sendRequest = useSendAnyHttpRequest(); + const renameRequest = useRenameRequest(activeRequest?.id ?? null); + const deleteRequest = useDeleteRequest(activeRequest?.id ?? null); const [, setSidebarHidden] = useSidebarHidden(); const workspaceCommands = useMemo(() => { @@ -142,20 +147,48 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { onSelect: () => setSidebarHidden((h) => !h), }, ]; + + if (activeRequest?.model === 'http_request') { + commands.push({ + key: 'http_request.send', + action: 'http_request.send', + label: 'Send Request', + onSelect: () => sendRequest.mutateAsync(activeRequest.id), + }); + } + + if (activeRequest != null) { + commands.push({ + key: 'http_request.rename', + label: 'Rename Request', + onSelect: renameRequest.mutate, + }); + + commands.push({ + key: 'http_request.delete', + label: 'Delete Request', + onSelect: deleteRequest.mutate, + }); + } + return commands.sort((a, b) => ('searchText' in a ? a.searchText : a.label).localeCompare( 'searchText' in b ? b.searchText : b.label, ), ); }, [ - activeCookieJar, + activeCookieJar?.id, activeEnvironment, + activeRequest, createEnvironment.mutate, createGrpcRequest, createHttpRequest, createWorkspace.mutate, + deleteRequest.mutate, dialog, + renameRequest.mutate, routes.paths, + sendRequest, setSidebarHidden, workspaceId, ]); @@ -225,10 +258,6 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { }; for (const r of sortedRequests) { - if (r.id === activeRequestId) { - continue; - } - requestGroup.items.push({ key: `switch-request-${r.id}`, searchText: fallbackRequestName(r), @@ -272,9 +301,6 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { }; for (const w of sortedWorkspaces) { - if (w.id === active) { - continue; - } workspaceGroup.items.push({ key: `switch-workspace-${w.id}`, label: w.name, @@ -286,13 +312,11 @@ export function CommandPalette({ onClose }: { onClose: () => void }) { }, [ workspaceCommands, sortedRequests, - activeRequestId, routes, activeEnvironmentId, sortedEnvironments, activeEnvironment?.id, sortedWorkspaces, - active, openWorkspace, ]); diff --git a/src-web/components/GlobalHooks.tsx b/src-web/components/GlobalHooks.tsx index 669a9dae..9b829de9 100644 --- a/src-web/components/GlobalHooks.tsx +++ b/src-web/components/GlobalHooks.tsx @@ -3,7 +3,7 @@ import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'; import { useEffect } from 'react'; import { useAtiveWorkspaceChangedToast } from '../hooks/useAtiveWorkspaceChangedToast'; import { useClipboardText } from '../hooks/useClipboardText'; -import { useCommandPalette } from '../hooks/useCommandPalette'; +import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette'; import { cookieJarsQueryKey } from '../hooks/useCookieJars'; import { environmentsQueryKey } from '../hooks/useEnvironments'; import { foldersQueryKey } from '../hooks/useFolders'; @@ -42,10 +42,12 @@ export function GlobalHooks() { // Other useful things useSyncThemeToDocument(); - useCommandPalette(); useNotificationToast(); useAtiveWorkspaceChangedToast(); + const toggleCommandPalette = useToggleCommandPalette(); + useHotKey('command_palette.toggle', toggleCommandPalette); + const queryClient = useQueryClient(); const { wasUpdatedExternally } = useRequestUpdateKey(null); diff --git a/src-web/components/Sidebar.tsx b/src-web/components/Sidebar.tsx index f0735d6a..b9a43fe4 100644 --- a/src-web/components/Sidebar.tsx +++ b/src-web/components/Sidebar.tsx @@ -22,6 +22,7 @@ import { useLatestGrpcConnection } from '../hooks/useLatestGrpcConnection'; import { useLatestHttpResponse } from '../hooks/useLatestHttpResponse'; import { useMoveToWorkspace } from '../hooks/useMoveToWorkspace'; import { usePrompt } from '../hooks/usePrompt'; +import { useRenameRequest } from '../hooks/useRenameRequest'; import { useRequests } from '../hooks/useRequests'; import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; import { useSendManyRequests } from '../hooks/useSendFolder'; @@ -649,6 +650,7 @@ function SidebarItem({ const activeRequest = useActiveRequest(); const deleteFolder = useDeleteFolder(itemId); const deleteRequest = useDeleteRequest(itemId); + const renameRequest = useRenameRequest(itemId); const duplicateHttpRequest = useDuplicateHttpRequest({ id: itemId, navigateAfter: true }); const duplicateGrpcRequest = useDuplicateGrpcRequest({ id: itemId, navigateAfter: true }); const copyAsCurl = useCopyAsCurl(itemId); @@ -795,29 +797,7 @@ function SidebarItem({ key: 'renameRequest', label: 'Rename', leftSlot: , - onSelect: async () => { - const name = await prompt({ - id: 'rename-request', - title: 'Rename Request', - description: - itemName === '' ? ( - 'Enter a new name' - ) : ( - <> - Enter a new name for {itemName} - - ), - name: 'name', - label: 'Name', - placeholder: 'New Name', - defaultValue: itemName, - }); - if (itemModel === 'http_request') { - updateHttpRequest.mutate({ id: itemId, update: (r) => ({ ...r, name }) }); - } else { - updateGrpcRequest.mutate({ id: itemId, update: (r) => ({ ...r, name }) }); - } - }, + onSelect: renameRequest.mutate, }, { key: 'duplicateRequest', @@ -849,7 +829,7 @@ function SidebarItem({ } }, [ child.children, - copyAsCurl, + copyAsCurl.mutate, createDropdownItems, deleteFolder, deleteRequest, @@ -860,11 +840,10 @@ function SidebarItem({ itemName, moveToWorkspace.mutate, prompt, + renameRequest.mutate, sendManyRequests, sendRequest, updateAnyFolder, - updateGrpcRequest, - updateHttpRequest, workspaces.length, ]); diff --git a/src-web/components/WorkspaceHeader.tsx b/src-web/components/WorkspaceHeader.tsx index 9846a0b9..aa012857 100644 --- a/src-web/components/WorkspaceHeader.tsx +++ b/src-web/components/WorkspaceHeader.tsx @@ -1,7 +1,9 @@ import classNames from 'classnames'; import React, { memo } from 'react'; +import { useToggleCommandPalette } from '../hooks/useToggleCommandPalette'; import { CookieDropdown } from './CookieDropdown'; import { Icon } from './core/Icon'; +import { IconButton } from './core/IconButton'; import { HStack } from './core/Stacks'; import { EnvironmentActionsDropdown } from './EnvironmentActionsDropdown'; import { ImportCurlButton } from './ImportCurlButton'; @@ -16,6 +18,7 @@ interface Props { } export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Props) { + const togglePalette = useToggleCommandPalette(); return ( @@ -32,6 +35,12 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
+
diff --git a/src-web/hooks/useRenameRequest.tsx b/src-web/hooks/useRenameRequest.tsx new file mode 100644 index 00000000..1f1499c6 --- /dev/null +++ b/src-web/hooks/useRenameRequest.tsx @@ -0,0 +1,42 @@ +import { useMutation } from '@tanstack/react-query'; +import { InlineCode } from '../components/core/InlineCode'; +import { usePrompt } from './usePrompt'; +import { useRequests } from './useRequests'; +import { useUpdateAnyGrpcRequest } from './useUpdateAnyGrpcRequest'; +import { useUpdateAnyHttpRequest } from './useUpdateAnyHttpRequest'; + +export function useRenameRequest(requestId: string | null) { + const prompt = usePrompt(); + const updateHttpRequest = useUpdateAnyHttpRequest(); + const updateGrpcRequest = useUpdateAnyGrpcRequest(); + const requests = useRequests(); + + return useMutation({ + mutationFn: async () => { + const request = requests.find((r) => r.id === requestId); + if (request == null) return; + + const name = await prompt({ + id: 'rename-request', + title: 'Rename Request', + description: + request.name === '' ? ( + 'Enter a new name' + ) : ( + <> + Enter a new name for {request.name} + + ), + name: 'name', + label: 'Name', + placeholder: 'New Name', + defaultValue: request.name, + }); + if (request.model === 'http_request') { + updateHttpRequest.mutate({ id: request.id, update: (r) => ({ ...r, name }) }); + } else { + updateGrpcRequest.mutate({ id: request.id, update: (r) => ({ ...r, name }) }); + } + }, + }); +} diff --git a/src-web/hooks/useCommandPalette.tsx b/src-web/hooks/useToggleCommandPalette.tsx similarity index 72% rename from src-web/hooks/useCommandPalette.tsx rename to src-web/hooks/useToggleCommandPalette.tsx index ba7aad83..a445d14c 100644 --- a/src-web/hooks/useCommandPalette.tsx +++ b/src-web/hooks/useToggleCommandPalette.tsx @@ -1,10 +1,10 @@ +import { useCallback } from 'react'; import { CommandPalette } from '../components/CommandPalette'; import { useDialog } from '../components/DialogContext'; -import { useHotKey } from './useHotKey'; -export function useCommandPalette() { +export function useToggleCommandPalette() { const dialog = useDialog(); - useHotKey('command_palette.toggle', () => { + const togglePalette = useCallback(() => { dialog.toggle({ id: 'command_palette', size: 'dynamic', @@ -15,5 +15,7 @@ export function useCommandPalette() { noScroll: true, render: ({ hide }) => , }); - }); + }, [dialog]); + + return togglePalette; }