mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-19 23:31:21 +02:00
Refactor debounce and tauri event listeners
This commit is contained in:
@@ -605,6 +605,9 @@ fn create_window(handle: &AppHandle<Wry>) -> Window<Wry> {
|
|||||||
CustomMenuItem::new("toggle_sidebar".to_string(), "Toggle Sidebar")
|
CustomMenuItem::new("toggle_sidebar".to_string(), "Toggle Sidebar")
|
||||||
.accelerator("CmdOrCtrl+b"),
|
.accelerator("CmdOrCtrl+b"),
|
||||||
)
|
)
|
||||||
|
.add_item(
|
||||||
|
CustomMenuItem::new("focus_url".to_string(), "Focus URL").accelerator("CmdOrCtrl+l"),
|
||||||
|
)
|
||||||
.add_item(CustomMenuItem::new("new_window".to_string(), "New Window"));
|
.add_item(CustomMenuItem::new("new_window".to_string(), "New Window"));
|
||||||
if is_dev() {
|
if is_dev() {
|
||||||
test_menu = test_menu
|
test_menu = test_menu
|
||||||
@@ -647,8 +650,9 @@ fn create_window(handle: &AppHandle<Wry>) -> Window<Wry> {
|
|||||||
"zoom_in" => win2.emit("zoom", 1).unwrap(),
|
"zoom_in" => win2.emit("zoom", 1).unwrap(),
|
||||||
"zoom_out" => win2.emit("zoom", -1).unwrap(),
|
"zoom_out" => win2.emit("zoom", -1).unwrap(),
|
||||||
"toggle_sidebar" => win2.emit("toggle_sidebar", true).unwrap(),
|
"toggle_sidebar" => win2.emit("toggle_sidebar", true).unwrap(),
|
||||||
"refresh" => win2.emit("refresh", true).unwrap(),
|
"focus_url" => win2.emit("focus_url", true).unwrap(),
|
||||||
"send_request" => win2.emit("send_request", true).unwrap(),
|
"send_request" => win2.emit("send_request", true).unwrap(),
|
||||||
|
"refresh" => win2.eval("location.reload()").unwrap(),
|
||||||
"new_window" => _ = create_window(&handle2),
|
"new_window" => _ = create_window(&handle2),
|
||||||
"toggle_devtools" => {
|
"toggle_devtools" => {
|
||||||
if win2.is_devtools_open() {
|
if win2.is_devtools_open() {
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
|
import { invoke } from '@tauri-apps/api';
|
||||||
|
import { appWindow } from '@tauri-apps/api/window';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import { memo, useCallback, useMemo, useState } from 'react';
|
import { memo, useCallback, useMemo, useState } from 'react';
|
||||||
import { createGlobalState } from 'react-use';
|
import { createGlobalState } from 'react-use';
|
||||||
import { useActiveRequest } from '../hooks/useActiveRequest';
|
import { useActiveRequest } from '../hooks/useActiveRequest';
|
||||||
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
||||||
|
import { useTauriEvent } from '../hooks/useTauriEvent';
|
||||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||||
import { tryFormatJson } from '../lib/formatters';
|
import { tryFormatJson } from '../lib/formatters';
|
||||||
import type { HttpHeader, HttpRequest } from '../lib/models';
|
import type { HttpHeader, HttpRequest } from '../lib/models';
|
||||||
@@ -128,6 +131,16 @@ export const RequestPane = memo(function RequestPane({ style, fullHeight, classN
|
|||||||
[updateRequest],
|
[updateRequest],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useTauriEvent(
|
||||||
|
'send_request',
|
||||||
|
async ({ windowLabel }) => {
|
||||||
|
if (windowLabel !== appWindow.label) return;
|
||||||
|
console.log('SEND REQUEST', activeRequest?.url);
|
||||||
|
await invoke('send_request', { requestId: activeRequestId });
|
||||||
|
},
|
||||||
|
[activeRequestId],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={style}
|
style={style}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
|||||||
) : viewMode === 'pretty' && contentType.includes('json') ? (
|
) : viewMode === 'pretty' && contentType.includes('json') ? (
|
||||||
<Editor
|
<Editor
|
||||||
readOnly
|
readOnly
|
||||||
forceUpdateKey={activeResponse.updatedAt}
|
forceUpdateKey={`pretty::${activeResponse.updatedAt}`}
|
||||||
className="bg-gray-50 dark:!bg-gray-100"
|
className="bg-gray-50 dark:!bg-gray-100"
|
||||||
defaultValue={tryFormatJson(activeResponse?.body)}
|
defaultValue={tryFormatJson(activeResponse?.body)}
|
||||||
contentType={contentType}
|
contentType={contentType}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import type { EditorView } from 'codemirror';
|
||||||
import type { FormEvent } from 'react';
|
import type { FormEvent } from 'react';
|
||||||
import { memo, useCallback } from 'react';
|
import { memo, useCallback, useRef } from 'react';
|
||||||
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
|
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
|
||||||
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey';
|
||||||
import { useSendRequest } from '../hooks/useSendRequest';
|
import { useSendRequest } from '../hooks/useSendRequest';
|
||||||
|
import { useTauriEvent } from '../hooks/useTauriEvent';
|
||||||
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
import { useUpdateRequest } from '../hooks/useUpdateRequest';
|
||||||
import type { HttpRequest } from '../lib/models';
|
import type { HttpRequest } from '../lib/models';
|
||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
@@ -15,6 +17,7 @@ type Props = Pick<HttpRequest, 'id' | 'url' | 'method'> & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const UrlBar = memo(function UrlBar({ id: requestId, url, method, className }: Props) {
|
export const UrlBar = memo(function UrlBar({ id: requestId, url, method, className }: Props) {
|
||||||
|
const inputRef = useRef<EditorView>(null);
|
||||||
const sendRequest = useSendRequest(requestId);
|
const sendRequest = useSendRequest(requestId);
|
||||||
const updateRequest = useUpdateRequest(requestId);
|
const updateRequest = useUpdateRequest(requestId);
|
||||||
const handleMethodChange = useCallback(
|
const handleMethodChange = useCallback(
|
||||||
@@ -36,9 +39,14 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
|
|||||||
[sendRequest],
|
[sendRequest],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useTauriEvent('focus_url', () => {
|
||||||
|
inputRef.current?.focus();
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className={classnames('url-bar', className)}>
|
<form onSubmit={handleSubmit} className={classnames('url-bar', className)}>
|
||||||
<Input
|
<Input
|
||||||
|
ref={inputRef}
|
||||||
size="sm"
|
size="sm"
|
||||||
hideLabel
|
hideLabel
|
||||||
useTemplating
|
useTemplating
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|||||||
import { useWindowSize } from 'react-use';
|
import { useWindowSize } from 'react-use';
|
||||||
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
import { useSidebarHidden } from '../hooks/useSidebarHidden';
|
||||||
import { useSidebarWidth } from '../hooks/useSidebarWidth';
|
import { useSidebarWidth } from '../hooks/useSidebarWidth';
|
||||||
|
import { useTauriEvent } from '../hooks/useTauriEvent';
|
||||||
import { WINDOW_FLOATING_SIDEBAR_WIDTH } from '../lib/constants';
|
import { WINDOW_FLOATING_SIDEBAR_WIDTH } from '../lib/constants';
|
||||||
import { Button } from './core/Button';
|
import { Button } from './core/Button';
|
||||||
import { HStack } from './core/Stacks';
|
import { HStack } from './core/Stacks';
|
||||||
@@ -27,7 +28,7 @@ const drag = { gridArea: 'drag' };
|
|||||||
|
|
||||||
export default function Workspace() {
|
export default function Workspace() {
|
||||||
const { set: setWidth, value: width, reset: resetWidth } = useSidebarWidth();
|
const { set: setWidth, value: width, reset: resetWidth } = useSidebarWidth();
|
||||||
const { show, hide, hidden } = useSidebarHidden();
|
const { show, hide, hidden, toggle } = useSidebarHidden();
|
||||||
|
|
||||||
const windowSize = useWindowSize();
|
const windowSize = useWindowSize();
|
||||||
const [floating, setFloating] = useState<boolean>(false);
|
const [floating, setFloating] = useState<boolean>(false);
|
||||||
@@ -36,6 +37,8 @@ export default function Workspace() {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useTauriEvent('toggle_sidebar', toggle);
|
||||||
|
|
||||||
// float/un-float sidebar on window resize
|
// float/un-float sidebar on window resize
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const shouldHide = windowSize.width <= WINDOW_FLOATING_SIDEBAR_WIDTH;
|
const shouldHide = windowSize.width <= WINDOW_FLOATING_SIDEBAR_WIDTH;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
import type { EditorView } from 'codemirror';
|
||||||
import type { HTMLAttributes, ReactNode } from 'react';
|
import type { HTMLAttributes, ReactNode } from 'react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { forwardRef, useCallback, useMemo, useState } from 'react';
|
||||||
import type { EditorProps } from './Editor';
|
import type { EditorProps } from './Editor';
|
||||||
import { Editor } from './Editor';
|
import { Editor } from './Editor';
|
||||||
import { IconButton } from './IconButton';
|
import { IconButton } from './IconButton';
|
||||||
@@ -27,25 +28,28 @@ export type InputProps = Omit<HTMLAttributes<HTMLInputElement>, 'onChange' | 'on
|
|||||||
require?: boolean;
|
require?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Input({
|
export const Input = forwardRef<EditorView | undefined, InputProps>(function Input(
|
||||||
label,
|
{
|
||||||
type = 'text',
|
label,
|
||||||
hideLabel,
|
type = 'text',
|
||||||
className,
|
hideLabel,
|
||||||
containerClassName,
|
className,
|
||||||
labelClassName,
|
containerClassName,
|
||||||
onChange,
|
labelClassName,
|
||||||
placeholder,
|
onChange,
|
||||||
size = 'md',
|
placeholder,
|
||||||
name,
|
size = 'md',
|
||||||
leftSlot,
|
name,
|
||||||
rightSlot,
|
leftSlot,
|
||||||
defaultValue,
|
rightSlot,
|
||||||
validate,
|
defaultValue,
|
||||||
require,
|
validate,
|
||||||
forceUpdateKey,
|
require,
|
||||||
...props
|
forceUpdateKey,
|
||||||
}: InputProps) {
|
...props
|
||||||
|
}: InputProps,
|
||||||
|
ref,
|
||||||
|
) {
|
||||||
const [obscured, setObscured] = useState(type === 'password');
|
const [obscured, setObscured] = useState(type === 'password');
|
||||||
const [currentValue, setCurrentValue] = useState(defaultValue ?? '');
|
const [currentValue, setCurrentValue] = useState(defaultValue ?? '');
|
||||||
const id = `input-${name}`;
|
const id = `input-${name}`;
|
||||||
@@ -96,6 +100,7 @@ export function Input({
|
|||||||
>
|
>
|
||||||
{leftSlot}
|
{leftSlot}
|
||||||
<Editor
|
<Editor
|
||||||
|
ref={ref}
|
||||||
id={id}
|
id={id}
|
||||||
singleLine
|
singleLine
|
||||||
type={type === 'password' && !obscured ? 'text' : type}
|
type={type === 'password' && !obscured ? 'text' : type}
|
||||||
@@ -120,7 +125,7 @@ export function Input({
|
|||||||
</HStack>
|
</HStack>
|
||||||
</VStack>
|
</VStack>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
function validateRequire(v: string) {
|
function validateRequire(v: string) {
|
||||||
return v.length > 0;
|
return v.length > 0;
|
||||||
|
|||||||
12
src-web/hooks/useDebouncedSetState.ts
Normal file
12
src-web/hooks/useDebouncedSetState.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { Dispatch, SetStateAction } from 'react';
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import { debounce } from '../lib/debounce';
|
||||||
|
|
||||||
|
export function useDebouncedSetState<T extends string | number>(
|
||||||
|
defaultValue: T,
|
||||||
|
delay?: number,
|
||||||
|
): [T, Dispatch<SetStateAction<T>>] {
|
||||||
|
const [state, setState] = useState<T>(defaultValue);
|
||||||
|
const debouncedSetState = useMemo(() => debounce(setState, delay), [delay]);
|
||||||
|
return [state, debouncedSetState];
|
||||||
|
}
|
||||||
@@ -1,13 +1,8 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { useDebouncedSetState } from './useDebouncedSetState';
|
||||||
export function useDebouncedValue<T extends string | number>(value: T, delay = 1000) {
|
|
||||||
const [state, setState] = useState<T>(value);
|
|
||||||
const timeout = useRef<NodeJS.Timeout>();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
clearTimeout(timeout.current ?? 0);
|
|
||||||
timeout.current = setTimeout(() => setState(value), delay);
|
|
||||||
}, [value, delay]);
|
|
||||||
|
|
||||||
|
export function useDebouncedValue<T extends string | number>(value: T, delay?: number) {
|
||||||
|
const [state, setState] = useDebouncedSetState<T>(value, delay);
|
||||||
|
useEffect(() => setState(value), [setState, value]);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
22
src-web/hooks/useTauriEvent.ts
Normal file
22
src-web/hooks/useTauriEvent.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import type { EventCallback } from '@tauri-apps/api/event';
|
||||||
|
import { listen as tauriListen } from '@tauri-apps/api/event';
|
||||||
|
import type { DependencyList } from 'react';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
export function useTauriEvent<T>(event: string, fn: EventCallback<T>, deps: DependencyList = []) {
|
||||||
|
useEffect(() => {
|
||||||
|
let unMounted = false;
|
||||||
|
let unsubFn: (() => void) | undefined = undefined;
|
||||||
|
|
||||||
|
tauriListen(event, fn).then((unsub) => {
|
||||||
|
if (unMounted) unsub();
|
||||||
|
else unsubFn = unsub;
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unMounted = true;
|
||||||
|
unsubFn?.();
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [event, fn, ...deps]);
|
||||||
|
}
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { invoke } from '@tauri-apps/api';
|
|
||||||
import type { EventCallback } from '@tauri-apps/api/event';
|
|
||||||
import { listen as tauriListen } from '@tauri-apps/api/event';
|
|
||||||
import { appWindow } from '@tauri-apps/api/window';
|
import { appWindow } from '@tauri-apps/api/window';
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { matchPath } from 'react-router-dom';
|
|
||||||
import { DEFAULT_FONT_SIZE } from '../lib/constants';
|
import { DEFAULT_FONT_SIZE } from '../lib/constants';
|
||||||
import { debounce } from '../lib/debounce';
|
import { debounce } from '../lib/debounce';
|
||||||
import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
|
import { NAMESPACE_NO_SYNC } from '../lib/keyValueStore';
|
||||||
@@ -14,65 +9,44 @@ import { keyValueQueryKey } from './useKeyValue';
|
|||||||
import { requestsQueryKey } from './useRequests';
|
import { requestsQueryKey } from './useRequests';
|
||||||
import { useRequestUpdateKey } from './useRequestUpdateKey';
|
import { useRequestUpdateKey } from './useRequestUpdateKey';
|
||||||
import { responsesQueryKey } from './useResponses';
|
import { responsesQueryKey } from './useResponses';
|
||||||
import { routePaths } from './useRoutes';
|
import { useTauriEvent } from './useTauriEvent';
|
||||||
import { useSidebarHidden } from './useSidebarHidden';
|
|
||||||
import { workspacesQueryKey } from './useWorkspaces';
|
import { workspacesQueryKey } from './useWorkspaces';
|
||||||
|
|
||||||
const unsubFns: (() => void)[] = [];
|
|
||||||
export const UPDATE_DEBOUNCE_MILLIS = 100;
|
|
||||||
|
|
||||||
export function useTauriListeners() {
|
export function useTauriListeners() {
|
||||||
const { toggle } = useSidebarHidden();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { wasUpdatedExternally } = useRequestUpdateKey(null);
|
const { wasUpdatedExternally } = useRequestUpdateKey(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useTauriEvent<Model>('created_model', ({ payload, windowLabel }) => {
|
||||||
let unmounted = false;
|
if (windowLabel === appWindow.label && payload.model !== 'http_response') return;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
const queryKey =
|
||||||
function listen<T>(event: string, fn: EventCallback<T>) {
|
payload.model === 'http_request'
|
||||||
tauriListen(event, fn).then((unsub) => {
|
? requestsQueryKey(payload)
|
||||||
if (unmounted) unsub();
|
: payload.model === 'http_response'
|
||||||
else unsubFns.push(unsub);
|
? responsesQueryKey(payload)
|
||||||
});
|
: payload.model === 'workspace'
|
||||||
|
? workspacesQueryKey(payload)
|
||||||
|
: payload.model === 'key_value'
|
||||||
|
? keyValueQueryKey(payload)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (queryKey === null) {
|
||||||
|
if (payload.model) {
|
||||||
|
console.log('Unrecognized created model:', payload);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function listenDebounced<T>(event: string, fn: EventCallback<T>) {
|
const skipSync = payload.model === 'key_value' && payload.namespace === NAMESPACE_NO_SYNC;
|
||||||
listen(event, debounce(fn, UPDATE_DEBOUNCE_MILLIS));
|
|
||||||
|
if (!skipSync) {
|
||||||
|
queryClient.setQueryData<Model[]>(queryKey, (values) => [...(values ?? []), payload]);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
listen<void>('toggle_sidebar', toggle);
|
useTauriEvent<Model>(
|
||||||
listen<void>('refresh', () => location.reload());
|
'updated_model',
|
||||||
|
debounce(({ payload, windowLabel }) => {
|
||||||
listenDebounced<Model>('created_model', ({ payload, windowLabel }) => {
|
|
||||||
if (windowLabel === appWindow.label && payload.model !== 'http_response') return;
|
|
||||||
|
|
||||||
const queryKey =
|
|
||||||
payload.model === 'http_request'
|
|
||||||
? requestsQueryKey(payload)
|
|
||||||
: payload.model === 'http_response'
|
|
||||||
? responsesQueryKey(payload)
|
|
||||||
: payload.model === 'workspace'
|
|
||||||
? workspacesQueryKey(payload)
|
|
||||||
: payload.model === 'key_value'
|
|
||||||
? keyValueQueryKey(payload)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (queryKey === null) {
|
|
||||||
if (payload.model) {
|
|
||||||
console.log('Unrecognized created model:', payload);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const skipSync = payload.model === 'key_value' && payload.namespace === NAMESPACE_NO_SYNC;
|
|
||||||
|
|
||||||
if (!skipSync) {
|
|
||||||
queryClient.setQueryData<Model[]>(queryKey, (values) => [...(values ?? []), payload]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
listenDebounced<Model>('updated_model', ({ payload, windowLabel }) => {
|
|
||||||
if (windowLabel === appWindow.label && payload.model !== 'http_response') return;
|
if (windowLabel === appWindow.label && payload.model !== 'http_response') return;
|
||||||
|
|
||||||
const queryKey =
|
const queryKey =
|
||||||
@@ -104,57 +78,38 @@ export function useTauriListeners() {
|
|||||||
values?.map((v) => (modelsEq(v, payload) ? payload : v)),
|
values?.map((v) => (modelsEq(v, payload) ? payload : v)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}, 500),
|
||||||
|
);
|
||||||
|
|
||||||
listen<Model>('deleted_model', ({ payload }) => {
|
useTauriEvent<Model>('deleted_model', ({ payload }) => {
|
||||||
function removeById<T extends { id: string }>(model: T) {
|
function removeById<T extends { id: string }>(model: T) {
|
||||||
return (entries: T[] | undefined) => entries?.filter((e) => e.id !== model.id);
|
return (entries: T[] | undefined) => entries?.filter((e) => e.id !== model.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.model === 'workspace') {
|
if (payload.model === 'workspace') {
|
||||||
queryClient.setQueryData<Workspace[]>(workspacesQueryKey(), removeById(payload));
|
queryClient.setQueryData<Workspace[]>(workspacesQueryKey(), removeById(payload));
|
||||||
} else if (payload.model === 'http_request') {
|
} else if (payload.model === 'http_request') {
|
||||||
queryClient.setQueryData<HttpRequest[]>(requestsQueryKey(payload), removeById(payload));
|
queryClient.setQueryData<HttpRequest[]>(requestsQueryKey(payload), removeById(payload));
|
||||||
} else if (payload.model === 'http_response') {
|
} else if (payload.model === 'http_response') {
|
||||||
queryClient.setQueryData<HttpResponse[]>(responsesQueryKey(payload), removeById(payload));
|
queryClient.setQueryData<HttpResponse[]>(responsesQueryKey(payload), removeById(payload));
|
||||||
} else if (payload.model === 'key_value') {
|
} else if (payload.model === 'key_value') {
|
||||||
queryClient.setQueryData(keyValueQueryKey(payload), undefined);
|
queryClient.setQueryData(keyValueQueryKey(payload), undefined);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Just call this from the backend instead of this way
|
useTauriEvent<number>('zoom', ({ payload: zoomDelta, windowLabel }) => {
|
||||||
listen('send_request', async ({ windowLabel }) => {
|
if (windowLabel !== appWindow.label) return;
|
||||||
if (windowLabel !== appWindow.label) return;
|
const fontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize);
|
||||||
|
|
||||||
const params = matchPath(routePaths.request(), window.location.pathname);
|
let newFontSize;
|
||||||
const requestId = params?.params.requestId;
|
if (zoomDelta === 0) {
|
||||||
if (typeof requestId !== 'string') {
|
newFontSize = DEFAULT_FONT_SIZE;
|
||||||
return;
|
} else if (zoomDelta > 0) {
|
||||||
}
|
newFontSize = Math.min(fontSize * 1.1, DEFAULT_FONT_SIZE * 5);
|
||||||
await invoke('send_request', { requestId });
|
} else if (zoomDelta < 0) {
|
||||||
});
|
newFontSize = Math.max(fontSize * 0.9, DEFAULT_FONT_SIZE * 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
listen<number>('zoom', ({ payload: zoomDelta, windowLabel }) => {
|
document.documentElement.style.fontSize = `${newFontSize}px`;
|
||||||
if (windowLabel !== appWindow.label) return;
|
});
|
||||||
const fontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize);
|
|
||||||
|
|
||||||
let newFontSize;
|
|
||||||
if (zoomDelta === 0) {
|
|
||||||
newFontSize = DEFAULT_FONT_SIZE;
|
|
||||||
} else if (zoomDelta > 0) {
|
|
||||||
newFontSize = Math.min(fontSize * 1.1, DEFAULT_FONT_SIZE * 5);
|
|
||||||
} else if (zoomDelta < 0) {
|
|
||||||
newFontSize = Math.max(fontSize * 0.9, DEFAULT_FONT_SIZE * 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.documentElement.style.fontSize = `${newFontSize}px`;
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unmounted = true;
|
|
||||||
for (const unsub of unsubFns) {
|
|
||||||
unsub();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [queryClient, toggle, wasUpdatedExternally]);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export function debounce(fn: (...args: any[]) => void, delay: number) {
|
export function debounce(fn: (...args: any[]) => void, delay = 500) {
|
||||||
let timer: ReturnType<typeof setTimeout>;
|
let timer: ReturnType<typeof setTimeout>;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const result = function (...args: any[]) {
|
const result = function (...args: any[]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user