screentinker/docs
Claude e4c25c39df Describe a portrait video wall as portrait, and stop a wall hiding its screens
#236: the wall canvas was secretly framebuffer space rather than the wall as
the audience sees it. Invisible while every panel is the normal way up, and
actively misleading the moment one isn't — two portrait-mounted panels standing
side by side had to be STACKED VERTICALLY in the editor, with a pre-rotated copy
of every video, before the output came out right. It worked, but only after
trial and error, and it meant a portrait wall could never reuse content as-is.

Each panel now carries a mounting rotation (0/90/180/270 clockwise, the same
convention as the per-device orientation setting), the canvas means the physical
wall, and the player works out the mapping. The geometry lives in one place,
server/lib/wall-geometry.js, because four players have to agree on it to the
pixel across a seam.

Existing walls need no migration and do not move. Every wall in the field is
rotation 0, and that case takes the original expression verbatim on all three
players rather than the algebraically-equal centre-based one — the two differ in
the last float bit, and a float's worth of disagreement between two panels is a
hairline seam down a wall that was aligned yesterday. Pinned by the first test
in wall-geometry.test.js and by wall-payload.test.js.

While a display is in a wall its panel rotation replaces its own orientation:
both describe the same physical fact, so honouring both turned the content twice.

#235: a wall replaced its members' cards, so one dead panel of a four-panel wall
was invisible from the dashboard, and inspecting a single screen meant pulling it
out of the live wall and putting it back. The wall screen now lists its panels
with live online state, a per-panel screenshot request, and a link to each
device's page; the dashboard wall card carries per-member status chips that track
socket updates.

Tests: wall-geometry.test.js re-simulates the CSS box independently and asserts
each panel's viewport maps onto exactly its own rect of wall space, for every
rotation, plus a mixed wall and the Tizen player's hand-ported copy executed
against the canonical rule. Full server suite green (1260).

Not verified here: the Android and Tizen renders on real hardware. Kotlin
compiles clean; the maths is shared/tested, the view plumbing is not.
2026-08-06 09:46:31 -05:00
..
104-draft-preview-build-plan.md feat(preview): draft-aware device-free playlist preview via player reuse (#104) 2026-06-15 14:11:05 -05:00
109-android-pip-visibility.md fix(#109): render Android PiP overlay above the YouTube WebView video plane (#135) 2026-06-19 14:49:20 -05:00
134-device-reporting.md fix(#134): quiet false "reconnect" log + report HDMI output and UI render resolution (#136) 2026-06-19 15:32:11 -05:00
146-hardening-fallout.md feat(#146): always-on devices_connected + admin-toggleable /api/status debug block 2026-07-01 18:45:40 -05:00
146-hardening-plan.md docs(#146): event-loop hardening plan — blast-radius audit + failure model + sequenced plan 2026-06-30 20:44:46 -05:00
148-android-duplicate-socket-fix.md docs(#148): android duplicate-socket root-cause fix + verification spec 2026-07-02 19:29:50 -05:00
148-connection-lifecycle-analysis.md docs(#148): mass-disconnect + connection-lifecycle + half-open analyses 2026-07-02 14:59:25 -05:00
148-half-open-fix.md docs(#148): mass-disconnect + connection-lifecycle + half-open analyses 2026-07-02 14:59:25 -05:00
148-mass-disconnect-analysis.md docs(#148): mass-disconnect + connection-lifecycle + half-open analyses 2026-07-02 14:59:25 -05:00
148-server-eviction-storm-analysis.md docs(#148): server eviction-storm analysis (field-safe net spec) 2026-07-02 19:12:46 -05:00
android-troubleshooting.md feat(android): hidden settings menu with multi-tap BACK/ESC detection 2026-07-07 16:57:49 -04:00
billing-authz-plan.md feat(#146): billing:read scoped token — dual-path auth for the Usage Report (Option C) 2026-07-01 21:16:21 -05:00
billing.md feat(#146): owner-only CLI to mint billing:read tokens (scripts/mint-billing-token.js) 2026-07-01 21:31:11 -05:00
device-owner-provisioning.md feat(device-owner): tier foundation + QR provisioning + content-expiry & device enhancements (#168) 2026-07-12 19:41:07 -05:00
local-ai-setup.md docs: local AI setup guide for the Content Designer (#41) 2026-06-09 13:57:02 -05:00
maintenance-device-status-log.md docs(#142): 1.9.2-beta1 changelog + device_status_log VACUUM maintenance note 2026-06-27 19:59:17 -05:00
multi-tenancy-design.md Phase 1: multi-tenancy design doc + migration scripts 2026-05-11 19:37:15 -05:00
openapi.yaml Describe a portrait video wall as portrait, and stop a wall hiding its screens 2026-08-06 09:46:31 -05:00
player-parity.md Stop claiming offline cache on a runtime that refuses to run a service worker 2026-08-05 19:34:52 -05:00
seo-directory-listings.md feat(seo): IndexNow + landing-page optimization (schema, FAQ, CWV, content) (#177) 2026-07-13 11:22:37 -05:00