- Rewrote artifacts/tx-os/src/lib/notification-sounds.ts to use the
Web Audio API (lazy AudioContext + decoded AudioBuffer cache) instead
of HTMLAudioElement. unlock() resumes the ctx for any non-running
state (handles iOS `interrupted`), plays a 1-sample silent buffer to
satisfy iOS Safari's gesture requirement, and pre-warms decodes.
decodeAudioData wrapped to support both Promise and callback forms
for older WebKit.
- play() dispatches an AUTOPLAY_BLOCKED_EVENT with `{ isIos }` detail
when ctx isn't running. Throttle is 3 s; new bypassThrottle option
(used by testPlay) skips the gate AND avoids advancing lastPlayAt
so settings previews can't suppress real socket chimes.
- use-audio-unlock.ts keeps gesture listeners attached and re-calls
unlock() on every gesture (handles iPad ctx auto-suspend on
background / AirPlay).
- use-autoplay-hint.ts reads detail.isIos and switches between
notifSettings.autoplayHint and notifSettings.autoplayHintIos
(added to en.json + ar.json with Control Center / silent-switch
guidance).
- notification-settings.tsx per-sound preview button now calls
notificationPlayer.testPlay(id).
- Test globals __txosNotifPlayCount/__txosNotifLastSound preserved;
added __txosNotifCtxState() accessor (dev/test-only, gated by
import.meta.env.MODE).
- Added tests/notification-sound-webaudio.spec.mjs covering the
preview button gesture path: counter increments, throttle bypass
works, singleton AudioContext reaches `running` state.
Notes:
- Pre-existing api-server tsc errors in executive-meetings.ts and the
failing `test` workflow are unrelated to this task and out of scope.