feat(editor): F4.6d the web browser and web server on a computer's desktop

The oracle BrowserWindowRun uses Java's browser and web server windows as a
person does; the room keeps a browser window per computer and sends a
program window's view, the start names the person's language. The editor
shows the page in a sandboxed frame, links and forms go to the room, the web
server has its button, virtual hosts and lines. Better than Java: relative
images and links count from the page's folder, a mark stays in the page, the
error page from Java's template, the virtual hosts' file with complete rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 16:09:05 +00:00
co-authored by Claude Opus 5.5
parent f0e7c73ec7
commit aa54e5400e
31 changed files with 2773 additions and 55 deletions
+3 -2
View File
@@ -20,7 +20,7 @@ import { Palette, type PaletteKind } from './design/Palette.js';
import { RouterDialog } from './design/RouterDialog.js';
import { DeviceSheet } from './sheet/DeviceSheet.js';
import { DesktopWindow, type DesktopWindowName } from './desktop/DesktopWindow.js';
import { useTranslate } from './i18n/i18n.js';
import { useLanguage, useTranslate } from './i18n/i18n.js';
import { ModeBar } from './simulation/ModeBar.js';
import { useSimulation, type SimHostFactory } from './simulation/useSimulation.js';
@@ -90,6 +90,7 @@ const toFront = (open: readonly OpenDesktop[], id: string): readonly OpenDesktop
export function Editor({ doc, createSimHost }: { readonly doc: Y.Doc; readonly createSimHost?: SimHostFactory }) {
const t = useTranslate();
const language = useLanguage();
const view = useTopologyView(doc);
const simulation = useSimulation(doc, createSimHost);
const simulating = simulation.mode === 'simulation';
@@ -285,7 +286,7 @@ export function Editor({ doc, createSimHost }: { readonly doc: Y.Doc; readonly c
}}
/>
<div role="toolbar" style={{ position: 'absolute', left: 12, top: 12, zIndex: 50, display: 'flex', gap: 6, alignItems: 'center' }}>
<ModeBar mode={simulation.mode} speed={simulation.speed} onMode={(mode) => (mode === 'simulation' ? simulation.start() : simulation.stop())} onSpeed={simulation.setSpeed} />
<ModeBar mode={simulation.mode} speed={simulation.speed} onMode={(mode) => (mode === 'simulation' ? simulation.start(language) : simulation.stop())} onSpeed={simulation.setSpeed} />
{simulating ? null : (
<>
<button type="button" style={toolButton} disabled={!canUndo} onClick={() => manager?.undo()} aria-label={t('design.undo')} title={t('design.undo')}>