Add rename/delete/send to cmd+k

This commit is contained in:
Gregory Schier
2024-07-30 15:10:24 -07:00
parent a75b1a3472
commit 86856e3506
6 changed files with 103 additions and 45 deletions

View File

@@ -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<string | null>(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<CommandPaletteItem[]>(() => {
@@ -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,
]);

View File

@@ -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);

View File

@@ -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: <Icon icon="pencil" />,
onSelect: async () => {
const name = await prompt({
id: 'rename-request',
title: 'Rename Request',
description:
itemName === '' ? (
'Enter a new name'
) : (
<>
Enter a new name for <InlineCode>{itemName}</InlineCode>
</>
),
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,
]);

View File

@@ -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 (
<HStack space={2} justifyContent="center" className={classNames(className, 'w-full h-full')}>
<HStack space={0.5} className="flex-1 pointer-events-none">
@@ -32,6 +35,12 @@ export const WorkspaceHeader = memo(function WorkspaceHeader({ className }: Prop
</div>
<div className="flex-1 flex gap-1 items-center h-full justify-end pointer-events-none pr-0.5">
<ImportCurlButton />
<IconButton
icon="search"
title="Search or execute a command"
size="sm"
onClick={togglePalette}
/>
<SettingsDropdown />
<WindowControls />
</div>

View File

@@ -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 <InlineCode>{request.name}</InlineCode>
</>
),
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 }) });
}
},
});
}

View File

@@ -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 }) => <CommandPalette onClose={hide} />,
});
});
}, [dialog]);
return togglePalette;
}