Add switches to static card

This commit is contained in:
2024-05-07 22:44:48 +01:00
parent 9beae6c2fa
commit d656e06193
11 changed files with 65 additions and 24 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -10,6 +10,7 @@
},
"dependencies": {
"@tanstack/react-query": "^5.32.0",
"jotai": "^2.8.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},

View File

@@ -10,7 +10,7 @@
background-color: var(--color-background0);
padding: 16px;
width: 100%;
height: max-content;
min-height: max-content;
overflow: hidden;
}
@@ -20,18 +20,17 @@
@media (min-width: 640px) {
@media (min-height: 640px) {
height: 100vh;
> div {
height: 100%;
}
.chart {
min-height: unset;
}
@media (orientation: landscape) {
grid-template-columns: repeat(3, 1fr);
height: 100vh;
> div {
height: 100%;
}
}
@media (orientation: portrait) {

View File

@@ -0,0 +1,4 @@
import { atom } from 'jotai';
export const highFpsAtom = atom(true);
export const siAtom = atom(false);

View File

@@ -8,7 +8,6 @@ import { YAxis } from './y-axis';
const stepWindow = Number(import.meta.env.CLIENT_GRAPH_STEPS);
const stepPeriod = Number(import.meta.env.CLIENT_REFETCH_INTERVAL);
const xMargin = 4;
const fps = 30;
type Props = {
total: number;
@@ -33,7 +32,7 @@ export const CanvasChart = ({ total, hueOffset = 0, domain, hardDomain, data, fo
}
if (!domain || historyMax > domain[1]) {
return 1.25 * historyMax;
return historyMax;
}
return domain[1];
@@ -129,7 +128,7 @@ export const CanvasChart = ({ total, hueOffset = 0, domain, hardDomain, data, fo
drawSeries('fill');
drawSeries('stroke');
}, fps);
});
return (
<div className='chart'>

View File

@@ -1,8 +1,11 @@
import { siAtom } from '@/atoms';
import { useQuery } from '@tanstack/react-query';
import { useAtomValue } from 'jotai';
import { ChartCard } from './common/card';
export const Disks = () => {
const { data: dynamicData } = useQuery<DynamicData>({ queryKey: ['dynamic'] });
const isSi = useAtomValue(siAtom);
if (!dynamicData) {
return <div />;
@@ -15,7 +18,7 @@ export const Disks = () => {
labels: ['Read', 'Write'],
}}
hueOffset={120}
formatOptions={{ units: 'B/s' }}
formatOptions={{ units: 'B/s', ...(isSi && { si: true }) }}
data={[dynamicData.disks.read, dynamicData.disks.write]}
total={2}
/>

View File

@@ -1,20 +1,22 @@
import { siAtom } from '@/atoms';
import { formatValue } from '@/utils/format';
import { useQuery } from '@tanstack/react-query';
import { useAtomValue } from 'jotai';
import { useMemo } from 'react';
import { ChartCard } from './common/card';
const formatOptions = { units: 'B' };
export const Memory = () => {
const { data: staticData } = useQuery<StaticData>({ queryKey: ['static'] });
const { data: dynamicData } = useQuery<DynamicData>({ queryKey: ['dynamic'] });
const isSi = useAtomValue(siAtom);
const formatOptions = { units: 'B', ...(isSi && { si: true }) };
const formatedTotals = useMemo(() => {
if (!staticData) {
return [];
}
return [formatValue(staticData.total_memory, formatOptions), formatValue(staticData.total_swap, formatOptions)];
}, [staticData]);
}, [staticData, formatOptions]);
if (!staticData || !dynamicData) {
return <div />;

View File

@@ -1,8 +1,11 @@
import { siAtom } from '@/atoms';
import { useQuery } from '@tanstack/react-query';
import { useAtomValue } from 'jotai';
import { ChartCard } from './common/card';
export const Network = () => {
const { data: dynamicData } = useQuery<DynamicData>({ queryKey: ['dynamic'] });
const isSi = useAtomValue(siAtom);
if (!dynamicData) {
return <div />;
@@ -15,7 +18,7 @@ export const Network = () => {
labels: ['Down', 'Up'],
}}
hueOffset={60}
formatOptions={{ units: 'B/s' }}
formatOptions={{ units: 'B/s', ...(isSi && { si: true }) }}
data={[dynamicData.network.down, dynamicData.network.up]}
total={2}
/>

View File

@@ -0,0 +1,7 @@
.switches {
display: flex;
flex-direction: column;
flex-wrap: wrap;
gap: 8px;
padding: 4px 0px;
}

View File

@@ -1,7 +1,10 @@
import { highFpsAtom, siAtom } from '@/atoms';
import { Switch } from '@/components/switch';
import { useAnimationFrame } from '@/hooks/use-animation-frame';
import { useQuery } from '@tanstack/react-query';
import { useAtom } from 'jotai';
import { useEffect, useRef, useState } from 'react';
import { Switch } from '../switch';
import './static.css';
const formatUptime = (value: number) => {
const seconds = String(Math.floor(value % 60)).padStart(2, '0');
@@ -40,6 +43,8 @@ export const Static = () => {
const { data: staticData } = useQuery<StaticData>({ queryKey: ['static'] });
const root = useRef(document.getElementById('root')!);
const [dark, setDark] = useState(window.matchMedia('(prefers-color-scheme: dark)').matches);
const [highFps, setHighFps] = useAtom(highFpsAtom);
const [isSi, setIsSi] = useAtom(siAtom);
useEffect(() => {
root.current.setAttribute('data-theme', dark ? 'dark' : 'light');
@@ -59,11 +64,25 @@ export const Static = () => {
<h3>{staticData.kernel_version}</h3>
{staticData.boot_time && <Uptime boot_time={staticData.boot_time} />}
<Switch
checked={dark}
label={`${dark ? 'Dark' : 'Light'} theme`}
onChange={({ target }) => setDark(target.checked)}
/>
<div className='switches'>
<Switch
checked={dark}
label={`${dark ? 'Dark' : 'Light'} theme`}
onChange={({ target }) => setDark(target.checked)}
/>
<Switch
checked={highFps}
label={`${highFps ? 'High' : 'Low'} FPS`}
onChange={({ target }) => setHighFps(target.checked)}
/>
<Switch
checked={isSi}
label={`Powers of ${isSi ? 10 : 2}`}
onChange={({ target }) => setIsSi(target.checked)}
/>
</div>
</div>
)
);

View File

@@ -1,9 +1,13 @@
import { highFpsAtom } from '@/atoms';
import { useAtomValue } from 'jotai';
import { useEffect, useRef } from 'react';
export const useAnimationFrame = (callback: (dt: number) => void, fps = 60) => {
export const useAnimationFrame = (callback: (dt: number) => void, fps?: number) => {
const ignored = useRef(0);
const requestRef = useRef<number>();
const previousTimeRef = useRef<number>();
const highFps = useAtomValue(highFpsAtom);
const autoFps = fps ?? (highFps ? 30 : 4);
useEffect(() => {
const animate: FrameRequestCallback = time => {
@@ -11,7 +15,7 @@ export const useAnimationFrame = (callback: (dt: number) => void, fps = 60) => {
const deltaTime = time - previousTimeRef.current;
ignored.current += deltaTime;
if (ignored.current > 1000 / fps) {
if (ignored.current > 1000 / autoFps) {
ignored.current = 0;
callback(deltaTime);
}
@@ -26,5 +30,5 @@ export const useAnimationFrame = (callback: (dt: number) => void, fps = 60) => {
cancelAnimationFrame(requestRef.current);
}
};
}, [callback, fps]);
}, [callback, autoFps]);
};