import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { type } from '@tauri-apps/plugin-os'; import { HeaderSize, Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow, TruncatedWideTableCell, } from '@yaakapp-internal/ui'; import classNames from 'classnames'; import { createStore, Provider, useAtomValue } from 'jotai'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { ActionButton } from './ActionButton'; import { Sidebar } from './Sidebar'; import './main.css'; import { initHotkeys } from './hotkeys'; import { listen, rpc } from './rpc'; import { useRpcQueryWithEvent } from './rpc-hooks'; import type { ProxyHeader } from '@yaakapp-internal/proxy-lib'; import { applyChange, dataAtom, httpExchangesAtom, replaceAll } from './store'; const queryClient = new QueryClient(); const jotaiStore = createStore(); // Load initial models from the database rpc('list_models', {}).then((res) => { jotaiStore.set(dataAtom, (prev) => replaceAll(prev, 'http_exchange', res.httpExchanges)); }); // Register hotkeys from action metadata initHotkeys(); // Subscribe to model change events from the backend listen('model_write', (payload) => { jotaiStore.set(dataAtom, (prev) => applyChange(prev, 'http_exchange', payload.model, payload.change), ); }); function App() { const osType = type(); const exchanges = useAtomValue(httpExchangesAtom); const { data: proxyState } = useRpcQueryWithEvent('get_proxy_state', {}, 'proxy_state_changed'); const isRunning = proxyState?.state === 'running'; return (
Yaak Proxy
{isRunning ? 'Running on :9090' : 'Stopped'}
{exchanges.length === 0 ? (

No traffic yet

) : ( Method URL Status Content-Type {exchanges.map((ex) => ( {ex.method} {ex.url} {getContentType(ex.resHeaders)} ))}
)}
); } function StatusBadge({ status, error }: { status: number | null; error: string | null }) { if (error) return Error; if (status == null) return ; const color = status >= 500 ? 'text-danger' : status >= 400 ? 'text-warning' : status >= 300 ? 'text-notice' : 'text-success'; return {status}; } function getContentType(headers: ProxyHeader[]): string { const ct = headers.find((h) => h.name.toLowerCase() === 'content-type')?.value; if (ct == null) return '—'; // Strip parameters (e.g. "; charset=utf-8") return ct.split(';')[0]?.trim() ?? ct; } createRoot(document.getElementById('root') as HTMLElement).render( , );