riyadhafraa ec29657bf5 Task #461: Fix notification sounds on iPad (route via media channel)
Problem: User reported zero sound on iPad — even the "Test sound"
button in notification settings produced silence. YouTube and other
videos worked fine on the same iPad.

Root cause: The app's notification player used the Web Audio API
(AudioContext + BufferSource). On iOS Safari (iPad/iPhone), Web Audio
plays through the **ringer channel**, which is silenced by:
  - The hardware silent switch (older iPads),
  - Control Center's mute icon,
  - Or simply having ringer volume at 0 (independent of media volume).
HTMLAudioElement (the API behind <video> and YouTube) plays through
the **media channel**, which is what users actually have turned up.

Fix in artifacts/tx-os/src/lib/notification-sounds.ts:
- Added an HTMLAudioElement playback engine alongside the existing
  Web Audio engine. Engine selection is one-time per session via the
  existing `detectIos()` helper (handles iPadOS-as-Mac masquerade).
- iOS path: lazy `new Audio(url)` per sound id with preload="auto",
  primed in `unlock()` by play()-then-pause() at volume 0 inside the
  user gesture so each element is permanently allowed to play later
  out-of-gesture (iOS requirement). Real `play()` resets currentTime
  and plays at full volume; rejection of the play promise dispatches
  the existing autoplay-blocked hint.
- Non-iOS path: unchanged Web Audio behavior preserved verbatim.
- All public API preserved: `unlock()`, `play()`, `testPlay()`,
  `isUnlocked()`, `AUTOPLAY_BLOCKED_EVENT`. No changes needed to
  use-audio-unlock, use-autoplay-hint, use-notifications-socket, or
  notification-settings.
- Throttling (3s burst-coalesce), bypass for testPlay, vibration,
  test-only observability globals, and isIos hint flag all preserved.
- `__txosNotifCtxState` test hook now reports "running"/"suspended"
  on iOS based on `unlocked` flag (no AudioContext exists there).

Locale updates (ar.json + en.json):
- `notifSettings.autoplayHintIos` rewritten: now tells users to raise
  the **media** volume (same one that controls YouTube) instead of
  the old "turn off Silent Mute" advice — matches the new playback
  channel.

Verification: tsc --noEmit clean. Pre-existing `test` workflow failure
on unrelated executive-meetings.ts type errors is out of scope.
Out of scope per task: no PWA, no push notifications, no settings UI
redesign, no new sound files. Manual iPad QA needed before merging.
2026-05-10 11:40:07 +00:00
2026-04-21 12:16:59 +00:00
2026-04-18 02:00:09 +00:00
2026-04-18 02:00:09 +00:00
2026-04-18 02:00:09 +00:00
S
Description
No description provided
138 MiB
Languages
TypeScript 69.2%
JavaScript 29.2%
CSS 0.6%
Shell 0.6%
Dockerfile 0.2%
Other 0.2%