Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions desktop/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
7 changes: 7 additions & 0 deletions desktop/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules/
coverage/
.pnpm-store/
pnpm-lock.yaml
package-lock.json
pnpm-lock.yaml
yarn.lock
11 changes: 11 additions & 0 deletions desktop/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"endOfLine": "lf",
"semi": false,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80,
"plugins": ["prettier-plugin-tailwindcss"],
"tailwindStylesheet": "src/index.css",
"tailwindFunctions": ["cn", "cva"]
}
32 changes: 32 additions & 0 deletions desktop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# React + TypeScript + Vite + shadcn/ui

This is a template for a new Vite project with React, TypeScript, and shadcn/ui.
Comment on lines +1 to +3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the remaining Vite scaffold identity.

The documentation and browser metadata still present this project as a generic Vite application. Update both locations so the operator console has one product name and one setup description.

  • desktop/README.md#L1-L3: Document the desktop operator console, supported commands, and current destinations.
  • desktop/index.html#L5-L7: Replace vite.svg and vite-app with the shipped product favicon and title.
📍 Affects 2 files
  • desktop/README.md#L1-L3 (this comment)
  • desktop/index.html#L5-L7
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@desktop/README.md` around lines 1 - 3, Update desktop/README.md lines 1-3 to
describe the desktop operator console, its supported commands, and current
destinations instead of the generic Vite scaffold. Update desktop/index.html
lines 5-7 to reference the shipped product favicon and use the same product
title, replacing vite.svg and vite-app.


## b0 compatibility adaptation

The requested shadcn `b0` preset was translated into this existing Vite/Tauri
desktop app instead of converting it to Next.js or a monorepo. Compact b0
tokens (neutral dark surfaces, tight radii, thin borders, restrained elevation),
Base UI primitives, pointer-sized controls, and RTL-safe layout rules live in
`src/index.css` and the generated `src/components/ui/*` primitives.
`components.json` keeps the supported `base-nova` style name so future shadcn
CLI updates remain compatible, while `rtl: true` keeps generated components
RTL-ready. No new routes or media ownership are introduced by this adaptation.

## Adding components

To add components to your app, run the following command:

```bash
npx shadcn@latest add button
```

This will place the ui components in the `src/components` directory.

## Using components

To use the components in your app, import them as follows:

```tsx
import { Button } from "@/components/ui/button"
```
1,321 changes: 1,321 additions & 0 deletions desktop/bun.lock

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions desktop/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": true,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
30 changes: 30 additions & 0 deletions desktop/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
globals: globals.browser,
},
},
{
files: ['src/components/ui/**/*.{ts,tsx}'],
rules: { 'react-refresh/only-export-components': 'off' },
},
{
files: ['src/hooks/use-mobile.ts'],
rules: { 'react-hooks/set-state-in-effect': 'off' },
},
])
13 changes: 13 additions & 0 deletions desktop/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>vite-app</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
52 changes: 52 additions & 0 deletions desktop/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "desktop",
"private": true,
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"format": "prettier --write \"**/*.{ts,tsx}\"",
"test": "vitest run",
"typecheck": "tsc --noEmit",
"preview": "vite preview"
},
"dependencies": {
"@base-ui/react": "^1.6.0",
"@fontsource-variable/geist": "^5.3.0",
"@tailwindcss/vite": "^4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^1.28.0",
"next-themes": "^0.4.6",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"recharts": "3.8.0",
"shadcn": "^4.16.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.6.0",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0"
},
"devDependencies": {
"@eslint/js": "^10",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@types/node": "^24",
"@types/react": "^19",
"@types/react-dom": "^19",
"@vitejs/plugin-react": "^6",
"eslint": "^10",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17",
"jsdom": "^30.0.1",
"prettier": "^3.8.3",
"prettier-plugin-tailwindcss": "^0.8.0",
"typescript": "~6",
"typescript-eslint": "^8",
"vite": "^8",
"vitest": "^4.1.10"
}
}
1 change: 1 addition & 0 deletions desktop/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions desktop/src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { fireEvent, render, screen } from "@testing-library/react"
import { beforeEach, describe, expect, it } from "vitest"
import { App } from "./App"
import { DeterministicStudioAdapter } from "./studio-adapter"

describe("operator routes",()=>{
beforeEach(()=>{location.hash=""})
it("navigates to each of the four destinations",()=>{render(<App/>);for(const name of ["Cameras","Audio","Studio","Dashboard"]){fireEvent.click(screen.getByRole("button",{name:new RegExp(name)}));expect(screen.getByRole("heading",{name,level:1})).toBeInTheDocument()}})
it("renders capability and command authority states",()=>{location.hash="#/cameras";render(<App/>);fireEvent.click(screen.getByRole("button",{name:/Camera 4, idle/}));expect(screen.getByText("Unsupported")).toBeInTheDocument();expect(screen.getByText("No torch on active lens")).toBeInTheDocument()})
it("requires explicit audio routing",()=>{const adapter=new DeterministicStudioAdapter();location.hash="#/audio";render(<App adapter={adapter}/>);const routes=screen.getAllByRole("switch",{name:/Route to Program/});expect(routes.filter(r=>r.getAttribute("aria-checked")==="true")).toHaveLength(1);fireEvent.click(routes[1]);expect(adapter.getSnapshot().audio[1].routed).toBe(true)})
it("exposes non-colour-only failure feedback and keyboard cut",()=>{const adapter=new DeterministicStudioAdapter();location.hash="#/studio";render(<App adapter={adapter}/>);fireEvent.click(screen.getByRole("button",{name:/Simulate live failure/}));expect(screen.getAllByText(/LAST FRAME HELD/).length).toBeGreaterThan(0);const before=adapter.getSnapshot().programId;fireEvent.keyDown(window,{key:" "});expect(adapter.getSnapshot().programId).not.toBe(before)})
})
Loading
Loading