Fixing too much. also, the OS is actually spawning and managing windows

This commit is contained in:
Dustin Swan 2026-02-12 16:13:00 -07:00
parent 62f6e202b0
commit db4abfa450
No known key found for this signature in database
GPG key ID: 30D46587E2100467
5 changed files with 168 additions and 130 deletions

View file

@ -2,20 +2,13 @@ import { render, hitTest } from './ui';
type UIValue = any;
type App = {
init: any;
update: (state: any) => (event: any) => any;
view: (state: any) => (viewport: any) => any;
}
type ComponentInstance = {
state: any;
update: (state: any) => (event: any) => any;
view: (state: any) => any;
};
export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
let state = app.init;
export function runAppCompiled(canvas: HTMLCanvasElement, store: any) {
const componentInstances = new Map<string, ComponentInstance>();
let focusedComponentKey: string | null = null;
@ -132,13 +125,10 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
}
function rerender() {
const viewport = { width: window.innerWidth, height: window.innerHeight };
const renderedKeys = new Set<string>();
try {
const uiValue = app.view(state)(viewport);
const ui = uiValue;
const expandedUI = expandStateful(ui, [], renderedKeys);
const expandedUI = expandStateful(store.os, [], renderedKeys);
// clean up unrendered instances
for (const key of componentInstances.keys()) {
@ -148,7 +138,16 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
}
if (focusedComponentKey && !renderedKeys.has(focusedComponentKey)) {
const parts = focusedComponentKey.split('.');
focusedComponentKey = null;
while (parts.length > 0) {
parts.pop();
const ancestor = parts.join('.');
if (ancestor && renderedKeys.has(ancestor)) {
focusedComponentKey = ancestor;
break;
}
}
}
render(expandedUI, canvas);
@ -182,7 +181,7 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
}
if (event._tag === 'Rebind') {
rt.rebind(event._0, event._1, event._2);
store.rebind(event._0, event._1, event._2);
return;
}
@ -193,14 +192,6 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
if (event._tag === 'NoOp')
return;
const result = app.update(state)(event);
state = result.state;
if (result.emit && Array.isArray(result.emit)) {
for (const e of result.emit) {
handleEvent(e);
}
}
}
canvas.addEventListener('click', (e) => {
@ -251,9 +242,6 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
}
}
// OS root
handleEvent(event);
e.preventDefault();
rerender();
});
@ -263,6 +251,7 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) {
cancelAnimationFrame(resizeRAF);
resizeRAF = requestAnimationFrame(() => {
setupCanvas();
store.viewport = { width: window.innerWidth, height: window.innerHeight };
rerender();
});
});