e0b166ad60
ci / rust (push) Has been cancelled
Browser UI for the host's management REST API (mgmt.rs / docs/api/openapi.json). Stack, exactly as specified: - TanStack Start (Vite, SPA mode) — file-based routes, SSR shell + client hydration. - React Query via orval codegen from the checked-in OpenAPI spec: a custom fetch mutator (src/api/fetcher.ts) centralizes the base URL, the bearer token (Settings → localStorage), JSON, and a throwing ApiError; the query client skips retries on 4xx. orval returns the response body directly (includeHttpResponseReturnType:false) so a query's `.data` is the typed payload; GET→useQuery, POST/DELETE→useMutation by method. - shadcn/ui on Tailwind v4 (CSS-first tokens, dark-first) — button/card/badge/input/label/ table/skeleton primitives hand-authored from the canonical source. - Paraglide i18n (en + de) with a reactive useLocale() hook and a language switcher. Pages: dashboard (live status — video/audio/session/stream, stop-session + request-IDR, 2s polling), host (identity/codecs/ports), clients (paired list + unpair), pairing (PIN submit, polls pin_pending), settings (API token + language). Dev server proxies /api → 127.0.0.1:47990 (same-origin, no CORS; PUNKTFUNK_MGMT_URL to override). Generated code (orval client, paraglide runtime, routeTree) is gitignored and reproduced by `pnpm codegen` (prepare/pre* scripts). Validated live against `serve`: API shapes match, dev proxy works, SSR shell renders the localized nav, build + tsc green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
// Thin reactive layer over Paraglide. Paraglide's `m.*` message functions and
|
|
// `setLocale`/`getLocale` are framework-agnostic; this hook re-renders React when the
|
|
// locale changes (Paraglide's localStorage strategy persists the choice across reloads).
|
|
import { useSyncExternalStore } from 'react'
|
|
import { getLocale, setLocale, locales } from '@/paraglide/runtime'
|
|
|
|
/** The available locales as a union (`'en' | 'de'`), derived from Paraglide's `locales`. */
|
|
export type Locale = (typeof locales)[number]
|
|
|
|
const listeners = new Set<() => void>()
|
|
|
|
/** Switch locale and notify subscribers (Paraglide also persists it per its strategy). */
|
|
export function changeLocale(locale: Locale) {
|
|
// `reload: false` keeps the SPA mounted; we re-render via the store below.
|
|
setLocale(locale, { reload: false })
|
|
for (const l of listeners) l()
|
|
}
|
|
|
|
function subscribe(cb: () => void) {
|
|
listeners.add(cb)
|
|
return () => listeners.delete(cb)
|
|
}
|
|
|
|
/** Current locale, reactive — components using `m.*` should read this so they re-render. */
|
|
export function useLocale(): Locale {
|
|
return useSyncExternalStore(subscribe, getLocale, () => 'en' as Locale)
|
|
}
|
|
|
|
export { locales }
|