Files
wadamesh/web/shell/icons/render.mjs
T
Kaj SchittecatandClaude Opus 5.5 2fc2288879 web: phones and tablets get a UI that fills the screen
- the canvas is sized from the space below the bar at about one CSS pixel per
  canvas pixel, whole device pixels where possible (crisp): iPhone 14 390x616,
  Pixel 7 360x692, iPad 540x686; landscape by height and the window's aspect
  (664x358, 734x330, 720x506). A computer keeps the framed 800x480. Same
  large-screen layouts, which size themselves from the display.
- a turn restarts the UI in the other layout only when the aspect flips and
  the width changes (a keyboard is no turn), never while typing
- the phone keyboard: no focus ring or tab hotkey letters for it
  (CAP_NATIVE_KEYBOARD in the nav-keys block), keeps up while tapping the UI
  mid-edit; IME composition followed live
- the page: slim one-row bar (slimmer on its side), safe areas, link help as
  an overlay, home-screen icons (icons/app-icon.svg + render.mjs, maskable)
- tests: web/build.sh mobiletest (iPhone 14, Pixel 7, iPad): fill > 90 %,
  UTF-8 + emoji through the hidden field, IME composition, send, turn and
  back with the message kept, chooser, manifest. Labels found by text
  (wadamesh.findText) so taps work at any size; the UTF-8 storage check
  searches bytes. webtest's phone step checks the portrait canvas.
- WEB_BUILD.md "Phones and tablets"; the stray docs/tmp shots removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:12:46 +02:00

19 lines
1.0 KiB
JavaScript

// web/shell/icons/render.mjs: app-icon.svg -> the PNGs the manifest and iOS use.
// node web/shell/icons/render.mjs (needs Playwright, like the web tests)
// The PNGs are committed; run this again only when the SVG changes.
import { createRequire } from 'node:module';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
const pw = createRequire(path.join(here, '..', '..', 'package.json'))('playwright');
const svg = fs.readFileSync(path.join(here, 'app-icon.svg'), 'utf8');
const b = await pw.chromium.launch();
for (const [name, px] of [['icon-180.png', 180], ['icon-192.png', 192], ['icon-512.png', 512]]) {
const p = await b.newPage({ viewport: { width: px, height: px } });
await p.setContent(`<body style="margin:0">${svg.replace('<svg ', `<svg width="${px}" height="${px}" `)}</body>`);
await p.screenshot({ path: path.join(here, name), clip: { x: 0, y: 0, width: px, height: px } });
await p.close();
}
await b.close();