lecodes-web-player
v2.0.3
Published
The web player of LeCodes: a page that runs a compiled app in the browser (Filament, creator-2d, the tree UI) — a static folder, driven by its url and by messages
Readme
lecodes-web-player
A page that runs a compiled LeCodes app in the browser: the runtime as WebAssembly (Filament,
creator-2d, the tree UI) and the web halves of the plugins. The package is its built folder,
dist/ — static files with relative paths, served from any path of any site.
dist/
index.html
player.js the entry, under a name a page can write down
assets/ the runtime's modules, the archives, the font, a chunk per plugin
VERSION.jsonThe app fills the window. The page draws nothing around it: a phone is the browser's responsive mode, a desktop app runs as it is.
Running a bundle
player/?src=/apps/demo/app.jssrc is a bundle of the player's own origin. What the bundle needs is read from its header: the
runtime profile (a UI app downloads no engine, a 2D app no Filament), the materials archives, the
fonts, the plugins.
lecodes dev --web opens the player on the project of the current folder, with reload on save and
the browser's console in the terminal.
In an <iframe>
<iframe src="/player/?src=/apps/demo/app.js" allow="camera; geolocation"></iframe>frame.contentWindow.postMessage({ type: "lecodes:run", src: "/apps/other/app.js" }, origin)
window.addEventListener("message", (e) => {
if (e.source === frame.contentWindow && e.data?.type === "lecodes:error") show(e.data.error)
})| to the player | |
|---|---|
| lecodes:run { src } | run this bundle in place of the current one |
| lecodes:reload | run the current bundle again, fetched again |
| lecodes:safe-area { insets } | { top, right, bottom, left, bars? } in px — what the page drew over the player's edges; null = the browser's own insets |
| lecodes:language { language } | device.language; the bundle runs again in it |
| lecodes:inspect { request, question } | a question about the app's UI: { ask: "tree" }, { ask: "text" }, { ask: "at", x, y }, { ask: "node", node } |
| lecodes:capture { request, pixelRatio? } | the app's picture |
| from the player | |
|---|---|
| lecodes:ready { src } | the bundle is running |
| lecodes:error { error } | the bundle could not start, or threw — mapped to its source |
| lecodes:log { level, text } | the console |
| lecodes:orientation { mode } | the app called app.setOrientation |
| lecodes:inspected { request, answer } | the answer to a question |
| lecodes:captured { request, image, width, height } | the picture as a data:image/png url (null: nothing painted, or not readable), its size in logical px |
A message is accepted from the parent frame only.
In a page of your own
A page that IS the app — a published link opened on a phone — loads the player's module into
itself: no frame, no <iframe>. The page has the elements the player fills (#app, and
optionally #loader, #error), says what to run before the module does, and drives it through
window.lecodesPlayer:
<div id="app"></div>
<script>window.lecodesPlayerConfig = { src: "/apps/demo/app.js", language: "en", safeArea: { top: 48, right: 0, bottom: 0, left: 0 } }</script>
<script type="module" src="/player/player.js"></script>lecodesPlayer.setSafeArea({ top: 0, right: 0, bottom: 0, left: 0 }) // the page's banner went away
lecodesPlayer.run("/apps/other/app.js")
const png = await lecodesPlayer.capture()Trust
A bundle runs in the page's own realm: it reaches window, localStorage and the cookies of the
origin the player is served from. Serve the player from an origin that holds nothing a bundle must
not read.
Development
bun run dev the page from the sources (vite)
bun run build dist/
bun run smoke:check the player in headless Chromium: UI, transitions, 3D, 2D, native views, a fieldThe plugins' web halves are built from the plugin repo (hosts/plugins), by their manifests
(build/plugins.ts). The library under the page is lecodes-web-host.
