Backspace to delete selected in sidebar

This commit is contained in:
Gregory Schier
2025-01-08 06:42:32 -08:00
parent 7a9c2e2223
commit d745e91f80
5 changed files with 49 additions and 30 deletions

View File

@@ -10,7 +10,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 { useDeleteAnyRequest } from '../hooks/useDeleteAnyRequest';
import { useEnvironments } from '../hooks/useEnvironments';
import type { HotkeyAction } from '../hooks/useHotKey';
import { useHotKey } from '../hooks/useHotKey';
@@ -66,18 +66,18 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
const recentWorkspaces = useRecentWorkspaces();
const requests = useRequests();
const activeRequest = useActiveRequest();
const [recentRequests] = useRecentRequests();
const openWorkspace = useOpenWorkspace();
const createHttpRequest = useCreateHttpRequest();
const activeCookieJar = useActiveCookieJar();
const createGrpcRequest = useCreateGrpcRequest();
const createEnvironment = useCreateEnvironment();
const sendRequest = useSendAnyHttpRequest();
const renameRequest = useRenameRequest(activeRequest?.id ?? null);
const deleteRequest = useDeleteRequest(activeRequest?.id ?? null);
const [recentRequests] = useRecentRequests();
const [, setSidebarHidden] = useSidebarHidden();
const openSettings = useOpenSettings();
const { baseEnvironment } = useEnvironments();
const { mutate: openSettings } = useOpenSettings();
const { mutate: openWorkspace } = useOpenWorkspace();
const { mutate: createHttpRequest } = useCreateHttpRequest();
const { mutate: createGrpcRequest } = useCreateGrpcRequest();
const { mutate: createEnvironment } = useCreateEnvironment();
const { mutate: sendRequest } = useSendAnyHttpRequest();
const { mutate: renameRequest } = useRenameRequest(activeRequest?.id ?? null);
const { mutate: deleteRequest } = useDeleteAnyRequest();
const workspaceCommands = useMemo<CommandPaletteItem[]>(() => {
const commands: CommandPaletteItem[] = [
@@ -85,7 +85,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
key: 'settings.open',
label: 'Open Settings',
action: 'settings.show',
onSelect: openSettings.mutate,
onSelect: openSettings,
},
{
key: 'app.create',
@@ -95,7 +95,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
{
key: 'http_request.create',
label: 'Create HTTP Request',
onSelect: () => createHttpRequest.mutate({}),
onSelect: () => createHttpRequest({}),
},
{
key: 'folder.create',
@@ -117,7 +117,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
{
key: 'grpc_request.create',
label: 'Create GRPC Request',
onSelect: () => createGrpcRequest.mutate({}),
onSelect: () => createGrpcRequest({}),
},
{
key: 'environment.edit',
@@ -136,7 +136,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
{
key: 'environment.create',
label: 'Create Environment',
onSelect: () => createEnvironment.mutate(baseEnvironment),
onSelect: () => createEnvironment(baseEnvironment),
},
{
key: 'sidebar.toggle',
@@ -151,7 +151,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
key: 'http_request.send',
action: 'http_request.send',
label: 'Send Request',
onSelect: () => sendRequest.mutateAsync(activeRequest.id),
onSelect: () => sendRequest(activeRequest.id),
});
for (const a of httpRequestActions) {
commands.push({
@@ -166,13 +166,13 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
commands.push({
key: 'http_request.rename',
label: 'Rename Request',
onSelect: renameRequest.mutate,
onSelect: renameRequest,
});
commands.push({
key: 'http_request.delete',
label: 'Delete Request',
onSelect: deleteRequest.mutate,
onSelect: () => deleteRequest(activeRequest.id),
});
}
@@ -190,10 +190,10 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
createGrpcRequest,
createHttpRequest,
createWorkspace,
deleteRequest.mutate,
deleteRequest,
httpRequestActions,
openSettings.mutate,
renameRequest.mutate,
openSettings,
renameRequest,
sendRequest,
setSidebarHidden,
]);
@@ -315,7 +315,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
workspaceGroup.items.push({
key: `switch-workspace-${w.id}`,
label: w.name,
onSelect: () => openWorkspace.mutate({ workspaceId: w.id, inNewWindow: false }),
onSelect: () => openWorkspace({ workspaceId: w.id, inNewWindow: false }),
});
}

View File

@@ -6,6 +6,7 @@ import { useKey, useKeyPressEvent } from 'react-use';
import { getActiveRequest } from '../hooks/useActiveRequest';
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
import { useCreateDropdownItems } from '../hooks/useCreateDropdownItems';
import { useDeleteAnyRequest } from '../hooks/useDeleteAnyRequest';
import { useGrpcConnections } from '../hooks/useGrpcConnections';
import { useHotKey } from '../hooks/useHotKey';
import { useHttpResponses } from '../hooks/useHttpResponses';
@@ -123,6 +124,17 @@ export function Sidebar({ className }: Props) {
}, [focusActiveRequest, hasFocus]);
const handleBlur = useCallback(() => setHasFocus(false), [setHasFocus]);
const deleteRequest = useDeleteAnyRequest();
useHotKey(
'http_request.delete',
async () => {
// Delete only works if a request is focused
if (selectedId == null) return;
deleteRequest.mutate(selectedId);
},
{ enable: hasFocus },
);
useHotKey('sidebar.focus', async () => {
// Hide the sidebar if it's already focused

View File

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { useCreateDropdownItems } from '../hooks/useCreateDropdownItems';
import { useDeleteFolder } from '../hooks/useDeleteFolder';
import { useDeleteRequest } from '../hooks/useDeleteRequest';
import { useDeleteAnyRequest } from '../hooks/useDeleteAnyRequest';
import { useDuplicateFolder } from '../hooks/useDuplicateFolder';
import { useDuplicateGrpcRequest } from '../hooks/useDuplicateGrpcRequest';
import { useDuplicateHttpRequest } from '../hooks/useDuplicateHttpRequest';
@@ -33,7 +33,7 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
const httpRequestActions = useHttpRequestActions();
const sendRequest = useSendAnyHttpRequest();
const workspaces = useWorkspaces();
const deleteRequest = useDeleteRequest(child.id);
const deleteRequest = useDeleteAnyRequest();
const renameRequest = useRenameRequest(child.id);
const duplicateHttpRequest = useDuplicateHttpRequest({ id: child.id, navigateAfter: true });
const duplicateGrpcRequest = useDuplicateGrpcRequest({ id: child.id, navigateAfter: true });
@@ -134,8 +134,10 @@ export function SidebarItemContextMenu({ child, show, close }: Props) {
key: 'delete-request',
variant: 'danger',
label: 'Delete',
hotKeyAction: 'http_request.delete',
hotKeyLabelOnly: true,
leftSlot: <Icon icon="trash" />,
onSelect: () => deleteRequest.mutate(),
onSelect: () => deleteRequest.mutate(child.id),
},
];
}

View File

@@ -2,13 +2,13 @@ import { useDeleteAnyGrpcRequest } from './useDeleteAnyGrpcRequest';
import { useDeleteAnyHttpRequest } from './useDeleteAnyHttpRequest';
import { useFastMutation } from './useFastMutation';
export function useDeleteRequest(id: string | null) {
export function useDeleteAnyRequest() {
const deleteAnyHttpRequest = useDeleteAnyHttpRequest();
const deleteAnyGrpcRequest = useDeleteAnyGrpcRequest();
return useFastMutation<void, string>({
mutationKey: ['delete_request', id],
mutationFn: async () => {
return useFastMutation<void, string, string>({
mutationKey: ['delete_request'],
mutationFn: async (id) => {
if (id == null) return;
// We don't know what type it is based on the ID, so just try deleting both
deleteAnyHttpRequest.mutate(id);

View File

@@ -15,6 +15,7 @@ export type HotkeyAction =
| 'grpc_request.send'
| 'hotkeys.showHelp'
| 'http_request.create'
| 'http_request.delete'
| 'http_request.duplicate'
| 'http_request.send'
| 'request_switcher.next'
@@ -34,6 +35,7 @@ const hotkeys: Record<HotkeyAction, string[]> = {
'grpc_request.send': ['CmdCtrl+Enter', 'CmdCtrl+r'],
'hotkeys.showHelp': ['CmdCtrl+Shift+/'],
'http_request.create': ['CmdCtrl+n'],
'http_request.delete': ['Backspace'],
'http_request.duplicate': ['CmdCtrl+d'],
'http_request.send': ['CmdCtrl+Enter', 'CmdCtrl+r'],
'request_switcher.next': ['Control+Shift+Tab'],
@@ -54,6 +56,7 @@ const hotkeyLabels: Record<HotkeyAction, string> = {
'grpc_request.send': 'Send Message',
'hotkeys.showHelp': 'Show Keyboard Shortcuts',
'http_request.create': 'New Request',
'http_request.delete': 'Delete Request',
'http_request.duplicate': 'Duplicate Request',
'http_request.send': 'Send Request',
'request_switcher.next': 'Go To Previous Request',
@@ -95,8 +98,8 @@ export function useHotKey(
}
// Don't add key if not holding modifier
const isHoldingModifier = e.altKey || e.ctrlKey || e.metaKey || e.shiftKey;
if (!isHoldingModifier) {
const isValidKeymapKey = e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.key === 'Backspace';
if (!isValidKeymapKey) {
return;
}
@@ -189,6 +192,8 @@ export function useFormattedHotkey(action: HotkeyAction | null): string[] | null
labelParts.push('↩');
} else if (p === 'Tab') {
labelParts.push('⇥');
} else if (p === 'Backspace') {
labelParts.push('⌫');
} else {
labelParts.push(capitalize(p));
}