diff --git a/src-web/components/App.tsx b/src-web/components/App.tsx
index c6ce8d2f..b7acdb52 100644
--- a/src-web/components/App.tsx
+++ b/src-web/components/App.tsx
@@ -1,5 +1,6 @@
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { persistQueryClient } from '@tanstack/react-query-persist-client';
import { MotionConfig } from 'framer-motion';
import { Suspense } from 'react';
@@ -45,7 +46,7 @@ export function App() {
- {/**/}
+
diff --git a/src-web/components/ResponsePane.tsx b/src-web/components/ResponsePane.tsx
index e23f1914..0f83db69 100644
--- a/src-web/components/ResponsePane.tsx
+++ b/src-web/components/ResponsePane.tsx
@@ -78,7 +78,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
label: viewMode === 'pretty' ? 'View Raw' : 'View Prettified',
onSelect: toggleViewMode,
},
- { type: 'separator' },
+ { type: 'separator', label: 'Actions' },
{
label: 'Clear Response',
onSelect: deleteResponse.mutate,
@@ -90,7 +90,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
hidden: responses.length <= 1,
disabled: responses.length === 0,
},
- { type: 'separator' },
+ { type: 'separator', label: 'History' },
...responses.slice(0, 10).map((r) => ({
label: r.status + ' - ' + r.elapsed + ' ms',
leftSlot: activeResponse?.id === r.id ? : <>>,
diff --git a/src-web/components/SidebarActions.tsx b/src-web/components/SidebarActions.tsx
index 9fcb399b..7b8df0d7 100644
--- a/src-web/components/SidebarActions.tsx
+++ b/src-web/components/SidebarActions.tsx
@@ -1,10 +1,10 @@
import { memo, useCallback } from 'react';
import { useCreateRequest } from '../hooks/useCreateRequest';
-import { useSidebarDisplay } from '../hooks/useSidebarDisplay';
+import { useSidebarHidden } from '../hooks/useSidebarHidden';
import { IconButton } from './core/IconButton';
export const SidebarActions = memo(function SidebarDisplayToggle() {
- const sidebarDisplay = useSidebarDisplay();
+ const { hidden, toggle } = useSidebarHidden();
const createRequest = useCreateRequest({ navigateAfter: true });
const handleCreateRequest = useCallback(() => {
createRequest.mutate({ name: 'New Request' });
@@ -13,11 +13,11 @@ export const SidebarActions = memo(function SidebarDisplayToggle() {
return (
<>
(false);
const [isResizing, setIsResizing] = useState(false);
@@ -35,14 +38,17 @@ export default function Workspace() {
// float/un-float sidebar on window resize
useEffect(() => {
- if (windowSize.width <= WINDOW_FLOATING_SIDEBAR_WIDTH) {
+ const shouldHide = windowSize.width <= WINDOW_FLOATING_SIDEBAR_WIDTH;
+ if (shouldHide && !hidden) {
setFloating(true);
- sidebar.hide();
- } else {
+ hide();
+ } else if (!shouldHide && hidden) {
setFloating(false);
- sidebar.show();
+ show();
}
- }, [sidebar, windowSize.width]);
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [windowSize.width]);
const unsub = () => {
if (moveState.current !== null) {
@@ -53,15 +59,15 @@ export default function Workspace() {
const handleResizeStart = useCallback(
(e: ReactMouseEvent) => {
- if (sidebar.width === undefined) return;
+ if (width === undefined) return;
unsub();
const mouseStartX = e.clientX;
- const startWidth = sidebar.width;
+ const startWidth = width;
moveState.current = {
move: async (e: MouseEvent) => {
e.preventDefault(); // Prevent text selection and things
- sidebar.set(startWidth + (e.clientX - mouseStartX));
+ setWidth(startWidth + (e.clientX - mouseStartX));
},
up: (e: MouseEvent) => {
e.preventDefault();
@@ -73,10 +79,10 @@ export default function Workspace() {
document.documentElement.addEventListener('mouseup', moveState.current.up);
setIsResizing(true);
},
- [sidebar],
+ [setWidth, width],
);
- const sideWidth = sidebar.hidden ? 0 : sidebar.width;
+ const sideWidth = hidden ? 0 : width;
const styles = useMemo(
() => ({
gridTemplate: floating
@@ -118,7 +124,7 @@ export default function Workspace() {
{floating ? (
-
+
>
)}
diff --git a/src-web/hooks/useIntrospectGraphQL.ts b/src-web/hooks/useIntrospectGraphQL.ts
index 152b909a..51b2fa82 100644
--- a/src-web/hooks/useIntrospectGraphQL.ts
+++ b/src-web/hooks/useIntrospectGraphQL.ts
@@ -11,9 +11,12 @@ const introspectionRequestBody = JSON.stringify({
});
export function useIntrospectGraphQL(baseRequest: HttpRequest) {
- const url = useDebouncedValue(baseRequest.url);
+ // Debounce the URL because it can change rapidly, and we don't
+ // want to send so many requests.
+ const debouncedUrl = useDebouncedValue(baseRequest.url);
+
return useQuery({
- queryKey: ['introspectGraphQL', { url }],
+ queryKey: ['introspectGraphQL', { url: debouncedUrl }],
refetchOnWindowFocus: true,
// staleTime: 1000 * 60 * 60, // 1 hour
refetchInterval: 1000 * 60, // Refetch every minute
diff --git a/src-web/hooks/useSidebarDisplay.ts b/src-web/hooks/useSidebarDisplay.ts
deleted file mode 100644
index dc65c5c6..00000000
--- a/src-web/hooks/useSidebarDisplay.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { useCallback, useMemo } from 'react';
-import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
-import { useKeyValue } from './useKeyValue';
-
-const START_WIDTH = 200;
-const MIN_WIDTH = 150;
-const COLLAPSE_WIDTH = MIN_WIDTH * 0.25;
-
-export const sidebarDisplayKey = 'sidebar_display';
-export const sidebarDisplayDefaultValue: SidebarDisplay = { hidden: false, width: START_WIDTH };
-
-export interface SidebarDisplay {
- hidden: boolean;
- width: number;
-}
-
-export function useSidebarDisplay() {
- const display = useKeyValue({
- namespace: NAMESPACE_NO_SYNC,
- key: sidebarDisplayKey,
- defaultValue: sidebarDisplayDefaultValue,
- });
- const hidden = display.value?.hidden ?? false;
- const width = display.value?.width ?? START_WIDTH;
-
- const set = useCallback(
- (width: number) => {
- const hidden = width < COLLAPSE_WIDTH;
- display.set({ hidden, width: Math.max(MIN_WIDTH, width) });
- },
- [display],
- );
- const hide = useCallback(() => display.set((v) => ({ ...v, hidden: true })), [display]);
- const show = useCallback(() => display.set((v) => ({ ...v, hidden: false })), [display]);
- const toggle = useCallback(() => display.set((v) => ({ ...v, hidden: !v.hidden })), [display]);
- const reset = display.reset;
-
- return useMemo(
- () => ({ width, hidden, set, reset, hide, show, toggle }),
- [hidden, hide, reset, set, show, toggle, width],
- );
-}
diff --git a/src-web/hooks/useSidebarHidden.ts b/src-web/hooks/useSidebarHidden.ts
new file mode 100644
index 00000000..a64f1cca
--- /dev/null
+++ b/src-web/hooks/useSidebarHidden.ts
@@ -0,0 +1,20 @@
+import { useMemo } from 'react';
+import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
+import { useKeyValue } from './useKeyValue';
+
+export function useSidebarHidden() {
+ const { set, value } = useKeyValue({
+ namespace: NAMESPACE_NO_SYNC,
+ key: 'sidebar_hidden',
+ defaultValue: false,
+ });
+
+ return useMemo(() => {
+ return {
+ show: () => set(false),
+ hide: () => set(true),
+ toggle: () => set((h) => !h),
+ hidden: value,
+ };
+ }, [set, value]);
+}
diff --git a/src-web/hooks/useSidebarWidth.ts b/src-web/hooks/useSidebarWidth.ts
new file mode 100644
index 00000000..9c54f6c1
--- /dev/null
+++ b/src-web/hooks/useSidebarWidth.ts
@@ -0,0 +1,10 @@
+import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
+import { useKeyValue } from './useKeyValue';
+
+export function useSidebarWidth() {
+ return useKeyValue({
+ namespace: NAMESPACE_NO_SYNC,
+ key: 'sidebar_width',
+ defaultValue: 200,
+ });
+}
diff --git a/src-web/hooks/useTauriListeners.ts b/src-web/hooks/useTauriListeners.ts
index b1594d2e..4c01a4b2 100644
--- a/src-web/hooks/useTauriListeners.ts
+++ b/src-web/hooks/useTauriListeners.ts
@@ -15,14 +15,14 @@ import { requestsQueryKey } from './useRequests';
import { useRequestUpdateKey } from './useRequestUpdateKey';
import { responsesQueryKey } from './useResponses';
import { routePaths } from './useRoutes';
-import { useSidebarDisplay } from './useSidebarDisplay';
+import { useSidebarHidden } from './useSidebarHidden';
import { workspacesQueryKey } from './useWorkspaces';
const unsubFns: (() => void)[] = [];
export const UPDATE_DEBOUNCE_MILLIS = 100;
export function useTauriListeners() {
- const sidebarDisplay = useSidebarDisplay();
+ const { toggle } = useSidebarHidden();
const queryClient = useQueryClient();
const { wasUpdatedExternally } = useRequestUpdateKey(null);
@@ -41,7 +41,7 @@ export function useTauriListeners() {
listen(event, debounce(fn, UPDATE_DEBOUNCE_MILLIS));
}
- listen('toggle_sidebar', sidebarDisplay.toggle);
+ listen('toggle_sidebar', toggle);
listen('refresh', () => location.reload());
listenDebounced('created_model', ({ payload, windowLabel }) => {
@@ -156,5 +156,5 @@ export function useTauriListeners() {
unsub();
}
};
- }, [queryClient, sidebarDisplay.toggle, wasUpdatedExternally]);
+ }, [queryClient, toggle, wasUpdatedExternally]);
}