Skip to content

Commit f0e2d78

Browse files
committed
fix: update web ui and add some documentation
closes #188
1 parent 72e6dd4 commit f0e2d78

File tree

7 files changed

+971
-982
lines changed

7 files changed

+971
-982
lines changed

README.md

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,27 @@ Create a second automation or condition to call `rest_command.obegraensad_bright
653653

654654
**Structure:**
655655

656-
- `frontend/` - Web UI code
656+
- `frontend/` - Web UI code built with solidjs
657+
- `frontend/src/` - Source files
658+
- `frontend/dist/` - Built files (generated)
659+
660+
**Prerequisites:**
661+
662+
This project uses [pnpm](https://pnpm.io/) as the package manager. pnpm is an alternative to npm.
663+
664+
**Install pnpm:**
665+
666+
```bash
667+
# Using npm
668+
npm install -g pnpm
669+
670+
# Using Homebrew (macOS)
671+
brew install pnpm
672+
673+
# Using Corepack (Node.js 16.13+)
674+
corepack enable
675+
corepack prepare pnpm@latest --activate
676+
```
657677

658678
**Setup:**
659679

@@ -664,15 +684,35 @@ pnpm install
664684

665685
**Configuration:**
666686

667-
- Set device IP in `.env`
687+
Create a `.env` file in the `frontend/` directory and set your device IP:
688+
689+
```bash
690+
VITE_DEVICE_IP=192.168.178.50
691+
```
692+
693+
This allows the development server to proxy API requests to your device during development.
668694

669695
**Commands:**
670696

671-
- `pnpm dev` - Start development server
672-
- `pnpm build` - Build and generate `webgui.cpp`
697+
- `pnpm dev` - Start development server with hot reload (usually at `http://localhost:5173`)
698+
- `pnpm build` - Build optimized production bundle and generate `webgui.cpp` for ESP32
699+
- `pnpm preview` - Preview production build locally
700+
- `pnpm lint` - Run linter to check code quality
701+
- `pnpm format` - Format code with Prettier
702+
703+
**Development Workflow:**
704+
705+
1. Start the development server: `pnpm dev`
706+
2. Make changes to files in `frontend/src/`
707+
3. Changes will hot-reload in your browser
708+
4. Test your changes against a running device
709+
5. When ready, run `pnpm build` to generate the embedded web UI
710+
6. The build process creates `src/webgui.cpp` which is compiled into the firmware
673711

674712
**Docker Build:**
675713

714+
If you prefer using Docker instead of installing Node.js and pnpm locally:
715+
676716
```bash
677717
docker compose run node
678718
```

frontend/biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
33
"assist": {
44
"actions": {
55
"source": {

frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
"license": "MIT",
1212
"devDependencies": {
13-
"@biomejs/biome": "^2.3.10",
13+
"@biomejs/biome": "^2.3.11",
1414
"@gfx/zopfli": "^1.0.15",
1515
"@types/node": "^25.0.3",
1616
"@types/offscreencanvas": "^2019.7.3",
@@ -35,5 +35,5 @@
3535
"tailwind-merge": "^3.4.0",
3636
"tailwindcss-animate": "^1.0.7"
3737
},
38-
"packageManager": "pnpm@10.26.1"
38+
"packageManager": "pnpm@10.27.0"
3939
}

frontend/pnpm-lock.yaml

Lines changed: 37 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/src/app.tsx

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type Component, createMemo, onCleanup, Show } from "solid-js";
1+
import { type Component, createMemo, Show } from "solid-js";
22

33
import { Layout } from "./components/layout/layout";
44
import Sidebar from "./components/layout/sidebar";
@@ -12,56 +12,6 @@ export const App: Component = () => {
1212
const [store, actions] = useStore();
1313
const { toast } = useToast();
1414

15-
// Fix iOS Safari WebSocket hanging bug using alternating RAF/setTimeout pattern
16-
// Source - https://stackoverflow.com/a/42036303
17-
// iOS has a bug where rapid WebSocket sends during pointer events can hang the connection
18-
// Solution: alternate between requestAnimationFrame and setTimeout to break the pattern
19-
let scheduledId: number | undefined;
20-
let pendingLedData: { index: number; status: number } | null = null;
21-
let useRaf = true;
22-
let frametime = 0;
23-
let lastframe = Date.now();
24-
25-
const deferredLedSend = (data: { index: number; status: number }) => {
26-
pendingLedData = data;
27-
28-
if (scheduledId) return;
29-
30-
const sendLed = () => {
31-
frametime = Date.now() - lastframe;
32-
lastframe = Date.now();
33-
34-
if (pendingLedData) {
35-
actions.send(
36-
JSON.stringify({
37-
event: "led",
38-
...pendingLedData,
39-
}),
40-
);
41-
pendingLedData = null;
42-
}
43-
44-
scheduledId = undefined;
45-
useRaf = !useRaf;
46-
};
47-
48-
if (useRaf) {
49-
scheduledId = requestAnimationFrame(sendLed);
50-
} else {
51-
scheduledId = setTimeout(sendLed, Math.max(0, frametime)) as unknown as number;
52-
}
53-
};
54-
55-
onCleanup(() => {
56-
if (scheduledId) {
57-
if (useRaf) {
58-
cancelAnimationFrame(scheduledId);
59-
} else {
60-
clearTimeout(scheduledId);
61-
}
62-
}
63-
});
64-
6515
const rotatedMatrix = createMemo(() => rotateArray(store.indexMatrix, store.rotation));
6616

6717
const wsMessage = (
@@ -177,7 +127,7 @@ export const App: Component = () => {
177127
indexData={rotatedMatrix()}
178128
brightness={store.brightness ?? 255}
179129
onSetLed={(data) => {
180-
deferredLedSend(data);
130+
wsMessage("led", data);
181131
}}
182132
onSetMatrix={(data) => {
183133
actions?.setLeds([...data]);

frontend/src/components/led-matrix.tsx

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -169,31 +169,34 @@ export const LedMatrix: Component<Props> = (props) => {
169169

170170
return (
171171
<div
172-
ref={containerRef}
173-
class={`
174-
p-4 bg-[#111111]
175-
shadow-lg
176-
relative mx-auto
177-
transition-all duration-300
178-
${visible() ? "opacity-100" : "opacity-50"}
179-
${props.disabled ? "opacity-30" : ""}
180-
${isDrawing() ? "ring-2 ring-blue-500/50" : ""}
181-
max-w-full max-h-full
182-
aspect-9/13
183-
`}
172+
class="p-4 bg-[#111111] shadow-lg mx-auto"
184173
style={{
185174
width: "min(100%, 700px, (100vh - 16rem) * 9 / 13)",
186-
height: "auto",
187175
}}
188176
>
189-
<canvas
190-
ref={canvasRef}
191-
class="w-full h-full self-center"
192-
style={{
193-
"image-rendering": "pixelated",
194-
"touch-action": "none",
195-
}}
196-
/>
177+
<div
178+
ref={containerRef}
179+
class={`
180+
relative
181+
transition-all duration-300
182+
${visible() ? "opacity-100" : "opacity-50"}
183+
${props.disabled ? "opacity-30" : ""}
184+
${isDrawing() ? "ring-2 ring-blue-500/50" : ""}
185+
max-w-full max-h-full
186+
aspect-9/13
187+
`}
188+
>
189+
<canvas
190+
ref={canvasRef}
191+
class="w-full"
192+
style={{
193+
"image-rendering": "pixelated",
194+
"touch-action": "none",
195+
"aspect-ratio": "9 / 13",
196+
height: "auto",
197+
}}
198+
/>
199+
</div>
197200
</div>
198201
);
199202
};

0 commit comments

Comments
 (0)