Skip to content

fix(audio): allow gesture resume after blocked autoplay - #3112

Closed
luzhuang wants to merge 1 commit into
dev/2.0from
fix/audio-resume-user-gesture
Closed

luzhuang wants to merge 1 commit into
dev/2.0from
fix/audio-resume-user-gesture

Conversation

@luzhuang

@luzhuang luzhuang commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

No description provided.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 4ae58f12-0a2e-45c2-a89b-0f14d5e279c2

📥 Commits

Reviewing files that changed from the base of the PR and between 1d06406 and 052910f.

📒 Files selected for processing (2)
  • packages/core/src/audio/AudioManager.ts
  • tests/src/core/audio/AudioSourcePendingPlayback.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


Walkthrough

AudioManager.resume() no longer coalesces concurrent calls through _resumePromise. Each call reaches the native audio context, and tests verify overlapping automatic and gesture-triggered resume attempts.

Changes

Audio resume behavior

Layer / File(s) Summary
Direct audio context resume
packages/core/src/audio/AudioManager.ts
Removed _resumePromise. Each resume() call now invokes getContext().resume() directly.
Concurrent resume validation
tests/src/core/audio/AudioSourcePendingPlayback.test.ts
Updated lifecycle tests to expect separate native resume attempts during overlapping calls and click storms.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 05291

Audio can retry native resume after autoplay blocks an earlier attempt, allowing playback to recover on a later user gesture. The updated behavior is covered by audio lifecycle tests and presents no remaining merge-blocking risk.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: enabling gesture-based audio resume after autoplay blocks the initial resume attempt.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/audio-resume-user-gesture

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit taps the audio gate
Each resume call proceeds straight
No shared promise holds the line
Ten quick clicks all now align
The context wakes, one try at a time

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.75%. Comparing base (1d06406) to head (052910f).

Additional details and impacted files
@@             Coverage Diff             @@
##           dev/2.0    #3112      +/-   ##
===========================================
- Coverage    85.94%   85.75%   -0.19%     
===========================================
  Files          811      811              
  Lines        94826    94745      -81     
  Branches     11620    11623       +3     
===========================================
- Hits         81497    81249     -248     
- Misses       13239    13404     +165     
- Partials        90       92       +2     
Flag Coverage Δ
unittests 85.75% <100.00%> (-0.19%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@GuoLei1990 GuoLei1990 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🫧 尘小沫

结论

阻塞级别:P1。实际 review 动作:REQUEST_CHANGES(未批准)。目标 HEAD:052910f1ed9d2ffa8e411e79795b04e69741aa46。
自动 CR 不替代人工 Reviewer 的合入门禁。

问题

  • P1 — 首次 autoplay 的 pending 恢复不会被后续手势重新提交
    • 位置:packages/core/src/audio/AudioManager.ts:34
    • AudioSource.play() 在非 running context 中把自身置为 _pendingPlay 后只调用一次 AudioManager.resume()(AudioSource.ts:150-165);若该原生调用因缺少 activation 而长期 pending,后续 play() 会被 _pendingPlay 早退。
    • 虽然 getContext() 已注册 document 的 click/touch fallback,但 _resumeAfterInterruption() 只有 _needsUserGestureResume 为 true 才会再次调用 resume()(AudioManager.ts:129-137)。这个 flag 目前仅由前后台恢复路径写入(AudioManager.ts:107-119),首次 autoplay 路径没有写入它。因此普通后续手势不会发起新的 native context.resume();删除 _resumePromise 仅在业务侧恰好再次直接调用 AudioManager.resume() 时才生效,无法独立修复 PR 所述的 pending AudioSource 场景。
    • 请让 AudioManager 保持唯一 owner:将“有一次尚未成功、需要手势重试的 resume”收口到现有 _needsUserGestureResume,在非 running context 发起 resume 时同步 arm、成功时清除,并继续由 _suspendedByCaller / _recovering 约束该 fallback。不要在每个 AudioSource 上再挂监听器、镜像 pending 状态或恢复旧的共享 Promise。
    • 补一条用户链路回归:非手势 AudioSource.play() 的第一次 resume 保持 pending,随后 dispatch 真实 document gesture,断言 native resume() 的调用数增加,并在首次 Promise 落定后断言原 AudioSource 开始播放。该用例应在当前提交失败,同时保留“明确 reject 的 one-shot playback 不回放”的既有契约。

架构、熵增与测试治理

  • 浏览器 AudioContext 是实际运行状态与 activation 的权威 owner;AudioManager 应独占全局 resume 意图和手势 fallback,AudioSource 只拥有单个播放请求的 _pendingPlay。本 PR 删除 _resumePromise、其 finally 和对应测试清理,方向上消除了把浏览器调用资格镜像为全局 Promise 的重复 owner;不应把它加回。
  • 但目前 AudioSource 的 pending 请求与 AudioManager 的手势重试 flag 没有在首次 autoplay 控制流上接通,形成两段平行状态。应在 Manager 内复用并统一该 flag 的语义,而非把重试责任转移到业务或新增第二条同步路径。
  • 更新后的测试覆盖了两次直接 AudioManager.resume() 以及既有前后台恢复已 arm flag 的场景,未覆盖上述 AudioSource.play() -> pending -> 后续真实手势 路径。GitHub CI 的 lint、三平台 build、codecov 与四组 e2e 均通过;codecov/project 仅报告整体覆盖率下降,不能证明这条控制流已经闭合。

@GuoLei1990

Copy link
Copy Markdown
Member

由 #3098 替代,关闭本 PR(不合并、保留分支)。

已对照本 PR 的 052910f 与 #3098 的 32199b3:两者都针对旧非手势 resume pending 阻止后续手势重新调用 native resume 的问题。#3098 已覆盖首次手势恢复和前后台恢复后的手势接管,并保留兼容请求合流,无需同时合入本 PR 的全量取消合流方案。

#3098 还接通了首次自动播放 pending 后的 document 手势入口,修复同源再次 play 被旧 pending 拦住的问题;Source 通过自身 Promise 身份处理取消,并按等待时间补偿播放位置。相关修复与策略已在 #3098 中说明,后续评审和验证统一在那里继续。

这里的关闭表示修复方案已被另一 PR 承接,不表示代码已合入或 iPhone 真机验收完成。

@GuoLei1990 GuoLei1990 closed this Sep 28, 2026
@GuoLei1990
GuoLei1990 deleted the fix/audio-resume-user-gesture branch October 16, 2026 03:51
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.

2 participants