Skip to content

fix: prevent progress bar regression & add debounce to PlayButton#153

Merged
roitium merged 3 commits into
bbplayer-app:devfrom
longlin10086:dev
Jan 23, 2026
Merged

fix: prevent progress bar regression & add debounce to PlayButton#153
roitium merged 3 commits into
bbplayer-app:devfrom
longlin10086:dev

Conversation

@longlin10086
Copy link
Copy Markdown
Contributor

@longlin10086 longlin10086 commented Jan 23, 2026

修复两个小问题:

  • 暂停状态时拖动进度条时进度会回退;
  • 拖动进度条时「暂停/播放」按钮短暂闪烁;

修复前:

2026-01-23.17.25.39.mp4

修复后:

2026-01-23.17.25.44.mp4

Summary by CodeRabbit

Bug Fixes

  • 优化播放指示器稳定性,防止寻道和状态转换时的图标闪烁
  • 改进寻道功能精确性,确保获取实际播放位置

✏️ Tip: You can customize this high-level summary in your review settings.

@safedep
Copy link
Copy Markdown

safedep Bot commented Jan 23, 2026

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

No dependency changes detected. Nothing to scan.

This report is generated by SafeDep Github App

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 23, 2026

总体说明

该PR在播放器控制组件中引入了防抖状态处理机制,防止短暂的UI闪烁,并改进了播放条拖拽后的位置同步逻辑,通过获取实际播放位置来确保状态一致性。

变更清单

文件组 / 文件(s) 变更摘要
播放器UI状态稳定化
src/features/player/components/PlayerControls.tsx
添加了两个独立的防抖状态(debouncedBuffering 和 debouncedIsPlaying,各200ms延迟)以及对应的定时器引用,使用 finalPlayingIndicator 替代直接使用 PlaybackState.BUFFERING 和 isPlaying,防止状态切换和拖拽时的UI图标闪烁(+52/-3)
拖拽定位同步优化
src/features/player/components/PlayerSlider.tsx
在拖拽定位后的超时回调中新增了通过 Orpheus.getPosition() 获取实际播放位置的逻辑,并在清除拖拽状态前更新共享位置值,扩展了 useCallback 的依赖数组至包含 position(+7/-3)

审查工作量评估

🎯 2 (Simple) | ⏱️ ~12 分钟

可能相关的PR

建议标签

bug

兔兔之诗

🐰 防抖妙法轻轻落,
闪烁图标消无踪,
定位真实终对齐,
播放流畅如春风,
小小改进大欢喜!🎵

🚥 Pre-merge checks | ✅ 2 | ❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰地总结了 PR 的两个主要变更:修复进度条回滚问题和为播放按钮添加防抖。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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

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

@roitium
Copy link
Copy Markdown
Collaborator

roitium commented Jan 23, 2026

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/features/player/components/PlayerSlider.tsx`:
- Around line 106-113: The current timeout handler calls Orpheus.getPosition()
but lacks error handling, which can leave isSeeking true and
seekTimeoutRef.current non-null if the promise rejects; update the timeout
callback to await or handle the promise with try/catch (or .then/.catch) and
ensure that regardless of success or failure you call isSeeking.set(false) and
set seekTimeoutRef.current = null, while on error optionally logging the error;
target the anonymous timeout callback that references Orpheus.getPosition(),
seekTimeoutRef, isSeeking, and position.

Comment on lines 106 to 113
seekTimeoutRef.current = setTimeout(() => {
isSeeking.set(false)
seekTimeoutRef.current = null
// 获取实际播放位置并同步,避免暂停状态下 position 未更新导致进度条回退
void Orpheus.getPosition().then((actualPosition) => {
position.set(actualPosition)
isSeeking.set(false)
seekTimeoutRef.current = null
})
}, 5000)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

核心修复逻辑正确,建议添加错误处理

通过在清除 isSeeking 之前先获取实际播放位置并同步 position 值,有效解决了暂停状态下拖动进度条后回退的问题。

但是 Orpheus.getPosition() 是异步调用,如果失败可能导致 isSeeking 永远不会被清除,进度条会卡在 seek 位置。建议添加错误处理:

🔧 建议的错误处理
 			seekTimeoutRef.current = setTimeout(() => {
 				// 获取实际播放位置并同步,避免暂停状态下 position 未更新导致进度条回退
 				void Orpheus.getPosition().then((actualPosition) => {
 					position.set(actualPosition)
 					isSeeking.set(false)
 					seekTimeoutRef.current = null
+				}).catch(() => {
+					// 获取位置失败时,仍需清除 seeking 状态,使用当前 seekPosition 作为回退
+					isSeeking.set(false)
+					seekTimeoutRef.current = null
 				})
 			}, 5000)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
seekTimeoutRef.current = setTimeout(() => {
isSeeking.set(false)
seekTimeoutRef.current = null
// 获取实际播放位置并同步,避免暂停状态下 position 未更新导致进度条回退
void Orpheus.getPosition().then((actualPosition) => {
position.set(actualPosition)
isSeeking.set(false)
seekTimeoutRef.current = null
})
}, 5000)
seekTimeoutRef.current = setTimeout(() => {
// 获取实际播放位置并同步,避免暂停状态下 position 未更新导致进度条回退
void Orpheus.getPosition().then((actualPosition) => {
position.set(actualPosition)
isSeeking.set(false)
seekTimeoutRef.current = null
}).catch(() => {
// 获取位置失败时,仍需清除 seeking 状态,使用当前 seekPosition 作为回退
isSeeking.set(false)
seekTimeoutRef.current = null
})
}, 5000)
🤖 Prompt for AI Agents
In `@src/features/player/components/PlayerSlider.tsx` around lines 106 - 113, The
current timeout handler calls Orpheus.getPosition() but lacks error handling,
which can leave isSeeking true and seekTimeoutRef.current non-null if the
promise rejects; update the timeout callback to await or handle the promise with
try/catch (or .then/.catch) and ensure that regardless of success or failure you
call isSeeking.set(false) and set seekTimeoutRef.current = null, while on error
optionally logging the error; target the anonymous timeout callback that
references Orpheus.getPosition(), seekTimeoutRef, isSeeking, and position.

@roitium roitium merged commit 90d8b6c into bbplayer-app:dev Jan 23, 2026
@roitium
Copy link
Copy Markdown
Collaborator

roitium commented Jan 23, 2026

谢谢你的贡献喵!

roitium added a commit that referenced this pull request Jan 25, 2026
Co-authored-by: roitium <roitium@users.noreply.github.com>
Co-authored-by: Roitium. <65794453+roitium@users.noreply.github.com>
Co-authored-by: longlin li <gnulonglin@gmail.com>
fix: prevent progress bar regression & add debounce to PlayButton (#153)
fix: improve error message for failed lyric providers (BBPLAYER-5Q) (#157)
fix: update PlaySlide info after song's change (#159)
fix: prevent re-playing when click same track. (#168)
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