Skip to content

TT-7228bc adjust iPhone playing#337

Merged
sarahentzel merged 3 commits into
developfrom
TT-fix-record-loading-hang
May 29, 2026
Merged

TT-7228bc adjust iPhone playing#337
sarahentzel merged 3 commits into
developfrom
TT-fix-record-loading-hang

Conversation

@gtryus
Copy link
Copy Markdown
Contributor

@gtryus gtryus commented May 28, 2026

This PR fixes silent audio playback on iOS Safari by ensuring AudioContext.resume() happens synchronously within the user gesture. The core problem is that React state-driven playback introduces async hops (including a 100ms setTimeout) that lose the user gesture context, causing iOS Safari to silently block audio.

The fix:

  • Expose a controlsRef from WSAudioPlayer up through HiddenPlayer to MediaPlayer.
  • On play button tap, call wsControlsRef.current?.togglePlay() directly (synchronous within gesture).
  • Make togglePlay idempotent so the state-driven chain catching up later is a no-op.

Separately, error handling in MediaRecord is improved with proper logging and localized error messages.

Greg Trihus added 2 commits May 28, 2026 09:15
What changed in MediaRecord.tsx
handleLoadAudio:532-555 now wraps the whole load sequence in a single try/catch:

- If getGoodUrl() throws (waitForIt timeout — the main root cause), the catch calls blobError(ts.mediaError) which sets loading=false and shows the localized "Error loading audio" message.
- Same for any throw from loadBlobAsync.
- The thrown error is logged via logError/bugsnag so future failures aren't silent.
- Hardcoded English error strings replaced with ts.mediaError.

What this should fix on iOS for the tester

- Symptom 3 (infinite loading on Record-step revisit) — addressed directly.
- Symptom 1 (Play disabled after upload) — same root cause; should clear once load completes or fails.
- Symptom 2 (Audio tab toggles silent) — not addressed by this fix. That's a separate iOS Safari Web Audio gesture issue in MediaPlayer/HiddenPlayer that needs its own ticket.
What changed

- WSAudioPlayer.tsx:handlePlayStatus — added an idempotent early-return when play === playingRef.current (except when a region replay is intended). This lets the same handler be hit twice — once synchronously from the click, once via the state chain — without double-toggling.
- HiddenPlayer.tsx — accepts and forwards a controlsRef to its inner WSAudioPlayer.
- MediaPlayer.tsx:handlePlayPause — owns a wsControlsRef, passes it down to HiddenPlayer, and calls wsControlsRef.current?.togglePlay() synchronously inside the click handler before the React state updates run.

Why this fixes Symptom 2

togglePlay → togglePlayStatus → handlePlayStatus → wsTogglePlay → setPlayingx → wavesurferRef.current.play() are all synchronous. Calling it inside the click keeps wavesurfer.play() inside the user-gesture context iOS Safari requires for AudioContext resume. The pre-existing state-driven chain (with its 100ms setTimeout in usePlayerLogic) still runs but now hits the idempotent guard and no-ops. Pause works the same way (Safari doesn't gate pause on user gesture, so the existing chain is fine, but the synchronous call simplifies it).

Caveats

- This only fixes the click-driven play in MediaPlayer (the path the bug report describes — the Audio tab). The prop-driven path (parent sets requestPlay=true programmatically) was never going to play on iOS Safari anyway, since Safari blocks autoplay without a gesture.
- I left the 100ms setTimeout in usePlayerLogic alone — it predates this work and the comment hints at a race; removing it is a separate decision.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts WaveSurfer-backed audio playback behavior, especially for iPhone/iOS playback gesture handling and media load failure reporting.

Changes:

  • Adds idempotency handling in WSAudioPlayer play status updates.
  • Exposes hidden WaveSurfer controls through HiddenPlayer into MediaPlayer.
  • Updates MediaRecord blob loading error handling and logging.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/renderer/src/components/WSAudioPlayer.tsx Avoids redundant play-status toggles unless replaying a selected region.
src/renderer/src/components/MediaRecord.tsx Wraps URL/blob loading in a single try/catch and logs media load failures.
src/renderer/src/components/MediaPlayer.tsx Calls hidden WaveSurfer controls directly during the play button click path.
src/renderer/src/components/HiddenPlayer.tsx Threads an optional WaveSurfer controls ref through to WSAudioPlayer.

Comment thread src/renderer/src/components/MediaPlayer.tsx Outdated
Comment thread src/renderer/src/components/MediaRecord.tsx
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@gtryus gtryus requested a review from sarahentzel May 28, 2026 17:03
@sarahentzel sarahentzel merged commit 7594a23 into develop May 29, 2026
2 checks passed
@sarahentzel sarahentzel deleted the TT-fix-record-loading-hang branch May 29, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants