Store appearance in k/v

This commit is contained in:
Gregory Schier
2023-03-16 11:01:30 -07:00
parent 0949de66bf
commit eee98f32b2
5 changed files with 40 additions and 24 deletions

View File

@@ -1,6 +1,7 @@
import classnames from 'classnames';
import { useActiveRequest } from '../hooks/useActiveRequest';
import { useIsResponseLoading } from '../hooks/useIsResponseLoading';
import { useKeyValues } from '../hooks/useKeyValues';
import { useSendRequest } from '../hooks/useSendRequest';
import { useUpdateRequest } from '../hooks/useUpdateRequest';
import { tryFormatJson } from '../lib/formatters';
@@ -20,6 +21,10 @@ export function RequestPane({ fullHeight, className }: Props) {
const updateRequest = useUpdateRequest(activeRequest);
const sendRequest = useSendRequest(activeRequest);
const responseLoading = useIsResponseLoading();
const activeTab = useKeyValues({
key: ['active_request_body_tab', activeRequest?.id ?? 'n/a'],
initialValue: 'body',
});
if (activeRequest === null) return null;
@@ -35,6 +40,8 @@ export function RequestPane({ fullHeight, className }: Props) {
loading={responseLoading}
/>
<Tabs
value={activeTab.value}
onChangeValue={activeTab.set}
tabs={[
{
value: 'body',

View File

@@ -1,7 +1,6 @@
import * as T from '@radix-ui/react-tabs';
import classnames from 'classnames';
import type { ReactNode } from 'react';
import { useState } from 'react';
import { Button } from '../Button';
import type { DropdownMenuRadioItem, DropdownMenuRadioProps } from '../Dropdown';
import { DropdownMenuRadio, DropdownMenuTrigger } from '../Dropdown';
@@ -13,6 +12,8 @@ import './Tabs.css';
interface Props {
defaultValue?: string;
label: string;
onChangeValue: (value: string) => void;
value: string;
tabs: {
value: string;
label: string;
@@ -27,12 +28,20 @@ interface Props {
children: ReactNode;
}
export function Tabs({ defaultValue, label, children, tabs, className, tabListClassName }: Props) {
const [value, setValue] = useState(defaultValue);
export function Tabs({
value,
onChangeValue,
defaultValue,
label,
children,
tabs,
className,
tabListClassName,
}: Props) {
return (
<T.Root
defaultValue={defaultValue}
onValueChange={setValue}
onValueChange={onChangeValue}
className={classnames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1')}
>
<T.List

View File

@@ -8,7 +8,7 @@ export function keyValueQueryKey({
namespace = DEFAULT_NAMESPACE,
key,
}: {
namespace: string;
namespace?: string;
key: string | string[];
}) {
return ['key_value', { namespace, key: buildKey(key) }];
@@ -19,7 +19,7 @@ export function useKeyValues({
key,
initialValue,
}: {
namespace: string;
namespace?: string;
key: string | string[];
initialValue: string;
}) {

View File

@@ -1,38 +1,31 @@
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect } from 'react';
import type { Appearance } from '../lib/theme/window';
import {
getAppearance,
setAppearance,
subscribeToPreferredAppearanceChange,
toggleAppearance,
} from '../lib/theme/window';
export function appearanceQueryKey() {
return ['theme', 'appearance'];
}
import { useKeyValues } from './useKeyValues';
export function useTheme() {
const queryClient = useQueryClient();
const appearance = useQuery({
queryKey: appearanceQueryKey(),
queryFn: getAppearance,
initialData: getAppearance(),
}).data;
const appearanceKv = useKeyValues({ key: 'appearance', initialValue: getAppearance() });
const themeChange = (appearance: Appearance) => {
setAppearance(appearance);
appearanceKv.set(appearance);
};
const handleToggleAppearance = async () => {
const newAppearance = toggleAppearance();
await queryClient.setQueryData(appearanceQueryKey(), newAppearance);
appearanceKv.set(appearanceKv.value === 'dark' ? 'light' : 'dark');
};
// Set appearance when preferred theme changes
useEffect(() => subscribeToPreferredAppearanceChange(themeChange), []);
// Sync appearance when k/v changes
useEffect(() => setAppearance(appearanceKv.value as Appearance), [appearanceKv.value]);
return {
appearance,
appearance: appearanceKv.value,
toggleAppearance: handleToggleAppearance,
};
}

View File

@@ -1,10 +1,17 @@
import { invoke } from '@tauri-apps/api';
import { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import { App } from './components/App';
import { setAppearance } from './lib/theme/window';
import type { KeyValue } from './lib/models';
import type { Appearance } from './lib/theme/window';
import { getPreferredAppearance, setAppearance } from './lib/theme/window';
import './main.css';
setAppearance();
const appearance: KeyValue = await invoke('get_key_value', {
namespace: 'app',
key: 'appearance',
});
setAppearance((appearance?.value ?? getPreferredAppearance()) as Appearance);
// root holds our app's root DOM Element:
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(