screentinker/server
ScreenTinker cf1124d687
Some checks are pending
CI / Unit tests (node --test) (push) Waiting to run
CI / OpenAPI spec lint (push) Waiting to run
CI / Android unit tests (Kotlin schedule evaluator vectors) (push) Waiting to run
CI / Boot smoke + version check (push) Waiting to run
Mute reaches YouTube items — it never did, and failed opposite ways per player
Muting was implemented three times and agreed nowhere. A YouTube item is a
cross-origin iframe, so `el.muted` reaches nothing; only the IFrame API can
touch it. Both browser-family players got this wrong, in opposite directions:

  web    playerVars.mute was `userHasInteracted ? 0 : 1` — autoplay policy and
         NOTHING else. An item an operator muted in the admin console played
         WITH SOUND, a wall follower blared alongside its leader, and the
         real-time device:mute-changed toggle only ever touched `<video>`.
         onReady then unmuted unconditionally, and the click-to-unmute overlay
         appeared on deliberately-muted items and undid the operator's setting.

  tizen  the embed URL hardcoded `mute=1`, so YouTube there was PERMANENTLY
         silent: the per-item flag was never read and nothing could unmute it.
         device:mute-changed did nothing at all, because it dereferenced a
         <video> that is null for a YouTube item.

Android was already correct and is unchanged — it is the reference here.

The rule now lives once, in server/lib/media-mute.js, served to the web player
from its single source the same way schedule-eval.js is, and mirrored in Tizen
(which ships inside the .wgt and cannot import it). The ORDER is the substance:
a wall follower is always silent (one wall, one audio source) > autoplay policy,
which is a hard constraint rather than a preference because unmuted playback
without a gesture is refused outright and costs the VIDEO > a live operator
toggle, who is looking at the screen > the item's stored flag.

shouldOfferUnmute() exists so the prompt only appears when a gesture is the ONLY
thing in the way. Prompting on a muted item trains viewers to click a button
that undoes an operator's decision.

Tizen gains enablejsapi + a postMessage bridge so a live toggle flips the embed
without reloading it — reloading would restart the video from zero every time
someone touched the control.

11 new tests pinning each precedence step separately; 1055 pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uaeo9MvzKoyXuN6ZsbhtkL
2026-08-05 10:50:59 -05:00
..
config fix(logging): gate CF-Connecting-IP on a Cloudflare peer, not any trusted proxy 2026-07-26 10:23:04 -05:00
db Merge: BrightSign real telemetry and hardware identity 2026-08-05 10:18:06 -05:00
lib Mute reaches YouTube items — it never did, and failed opposite ways per player 2026-08-05 10:50:59 -05:00
middleware Merge branch 'fix/recovery-grants' into release/auth-campaign 2026-07-26 16:22:59 -05:00
player Mute reaches YouTube items — it never did, and failed opposite ways per player 2026-08-05 10:50:59 -05:00
routes Wire BrightSign native sync end to end, chosen per group 2026-08-05 10:06:18 -05:00
scripts fix(content+android): rotation-aware media — portrait upright on dashboard AND player (#170) (#172) 2026-07-12 22:05:11 -05:00
services Make a recurring schedule respect its start and end dates 2026-07-30 22:22:59 -05:00
test Mute reaches YouTube items — it never did, and failed opposite ways per player 2026-08-05 10:50:59 -05:00
ws Merge: BrightSign real telemetry and hardware identity 2026-08-05 10:18:06 -05:00
.gitignore feat(email): Microsoft Graph send + alert spam protection + preferences UI 2026-05-12 18:16:40 -05:00
config.js Add an operator override for self-update on MDM-managed panels 2026-07-28 23:07:30 -05:00
package-lock.json chore(release): v1.9.29-rc2 2026-08-05 00:06:20 -05:00
package.json chore(release): v1.9.29-rc2 2026-08-05 00:06:20 -05:00
server.js Mute reaches YouTube items — it never did, and failed opposite ways per player 2026-08-05 10:50:59 -05:00
smoke-ui.js Keep the smoke test out of npm test, and update the lockfile 2026-07-28 20:34:34 -05:00
version.js chore(version): single-source VERSION, env-configurable data paths, bump tooling 2026-06-10 12:56:03 -05:00