// The editor's page. Embedded in the dashboard (F6) it gets its document and // language over the bridge; on its own — for development and the browser // tests — it opens one of FILIUS' examples, an empty project or a file // (`?example=` opens that example at once, `?example=new` an empty // project, `?lang=en` and `?theme=dark` set the rest). import { StrictMode, useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import * as Y from 'yjs'; import { desktopView, deviceSheet, emptyProject, topologyView, writeProject } from '@mdg-filius/doc'; import { openProjectArchive } from '@mdg-filius/fls'; import { startBridge } from './bridge/dashboardBridge.js'; import { Editor } from './Editor.js'; import { LanguageProvider, translate, type Language } from './i18n/i18n.js'; import './theme/tokens.css'; const EXAMPLES = import.meta.glob('../../../corpus/java-examples/*.fls', { query: '?url', import: 'default', eager: true }) as Record; /** `?example=new`: an empty project. */ const NEW_PROJECT = 'new'; const exampleUrl = (name: string) => Object.entries(EXAMPLES).find(([path]) => path.endsWith(`/${name}`))?.[1]; function docOf(bytes: Uint8Array): Y.Doc { const doc = new Y.Doc(); writeProject(doc, openProjectArchive(bytes, () => crypto.randomUUID())); return doc; } function App() { const params = new URLSearchParams(window.location.search); const [language, setLanguage] = useState(params.get('lang') === 'en' ? 'en' : 'de'); const [doc, setDoc] = useState(null); const [example, setExample] = useState(params.get('example') ?? ''); useEffect(() => { if (params.get('theme') === 'dark') document.documentElement.dataset.theme = 'dark'; const parent = params.get('parent'); if (parent === null) return undefined; return startBridge(window, parent, { onLocale: (locale) => setLanguage(locale.startsWith('en') ? 'en' : 'de'), onTheme: (theme, tokens) => { document.documentElement.dataset.theme = theme; for (const [name, value] of Object.entries(tokens)) document.documentElement.style.setProperty(name, value); }, }); // The page's parameters are read once. // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { if (example === NEW_PROJECT) { const doc = new Y.Doc(); writeProject(doc, emptyProject()); setDoc(doc); return; } const url = exampleUrl(example); if (url === undefined) return; void fetch(url) .then((response) => response.arrayBuffer()) .then((buffer) => setDoc(docOf(new Uint8Array(buffer)))); }, [example]); // The development page lets its browser tests read the document's drawing (never the editor embedded in the dashboard). useEffect(() => { (window as unknown as { filiusDev?: unknown }).filiusDev = doc === null ? undefined : { view: () => topologyView(doc), sheet: (id: string) => deviceSheet(doc, id), desktop: (id: string) => desktopView(doc, id) }; }, [doc]); const t = (key: string) => translate(language, key); return (
{t('dev.title')}
{doc === null ? null : }
); } createRoot(document.getElementById('root')!).render( , );