Skip to content

Title: Fix a shuffle bug on iOS [fix]#6

Merged
UtopiaXC merged 1 commit into
masterfrom
just_audio_set_resource_refactor
Jan 30, 2026
Merged

Title: Fix a shuffle bug on iOS [fix]#6
UtopiaXC merged 1 commit into
masterfrom
just_audio_set_resource_refactor

Conversation

@UtopiaXC
Copy link
Copy Markdown
Owner

@UtopiaXC UtopiaXC commented Jan 30, 2026

Details: Fix a shuffle bug on iOS
Type: Bugfix.
Test: Local Passed.
Related Issue: N/A.

Summary by CodeRabbit

  • 错误修复
    • 修复了iOS应用恢复时的音频播放问题
    • 改进了播放模式切换时的索引处理,防止歌曲意外变化
    • 优化了iOS平台上队列更新的处理逻辑,提升稳定性和一致性

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

Details: Fix a shuffle bug on iOS
Type: Bugfix.
Test: Local Passed.
Related Issue: N/A.
@UtopiaXC UtopiaXC merged commit 42f3dea into master Jan 30, 2026
4 of 6 checks passed
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @UtopiaXC, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a shuffle-related bug on iOS by refining the audio player's queue management and index tracking. It introduces specific safeguards and an alternative queue update strategy for iOS devices to prevent the just_audio_media_kit plugin from misinterpreting playlist changes, ensuring a more stable and correct playback experience when switching between play modes or reordering songs.

Highlights

  • iOS Shuffle Bug Fix: Addresses a specific bug on iOS where shuffling or changing play modes could lead to incorrect song playback or index issues, particularly with the just_audio_media_kit plugin.
  • Audio Player Index Management: Implements a protective mechanism in the PlayerProvider to prevent the audio player from incorrectly changing the current song index during playlist reordering or play mode toggles. It now only accepts an _expectedIndexAfterToggle when a play mode change is in progress.
  • iOS-Specific Queue Handling: Modifies how the audio queue is updated on iOS within AudioPlayerService. Instead of in-place modifications, it now performs a full playWithQueue reload to avoid issues where just_audio_media_kit loses track of the correct index.
  • Removed iOS Audio Reload Logic: Comments out previous logic in lib/app.dart that attempted to reload the audio source on iOS when the app resumed, suggesting this logic was either problematic or no longer necessary for the intended fix.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 30, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

概述

该拉取请求对iOS应用生命周期处理进行了重构,移除了应用恢复时的音频源重加载逻辑。同时在播放器提供程序中添加了播放模式切换保护机制,并在音频播放服务中实现了队列更新期间的索引流抑制功能,防止并发操作导致的歌曲不匹配问题。

更改

队列 / 文件 摘要
iOS应用生命周期处理
lib/app.dart
移除了应用恢复时尝试重加载音频源的逻辑,该逻辑在播放器未播放且有效位置/时长时触发,现已注释掉。
播放模式切换保护
lib/providers/player_provider.dart
添加_isTogglingPlayMode_expectedIndexAfterToggle两个私有字段,实现播放模式切换期间的索引保护机制。在切换时禁用播放列表重新排序导致的错误歌曲变更,包括从数据库重加载、计算新索引和时间限制清理逻辑。
队列更新状态管理
lib/services/audio/audio_player_service.dart
引入_isUpdatingQueue标志以抑制队列原地更新期间的索引流事件。针对iOS特别处理,使用playWithQueue重加载队列,并通过延迟重置抑制标志来避免延迟的流事件冲突。

序列图

sequenceDiagram
    participant User as 用户
    participant PlayerProv as PlayerProvider
    participant AudioService as AudioPlayerService
    participant DB as 数据库
    participant JustAudio as JustAudio引擎

    User->>PlayerProv: togglePlayMode()
    PlayerProv->>PlayerProv: 检测队列顺序变化
    PlayerProv->>PlayerProv: _isTogglingPlayMode = true
    PlayerProv->>DB: 从数据库重加载播放列表
    DB-->>PlayerProv: 播放列表数据
    PlayerProv->>PlayerProv: 计算新索引位置
    PlayerProv->>PlayerProv: _expectedIndexAfterToggle = newIndex
    PlayerProv->>AudioService: updateQueueKeepPlaying(新队列)
    
    rect rgba(100, 150, 200, 0.5)
        Note over AudioService: iOS特殊处理
        AudioService->>AudioService: _isUpdatingQueue = true
        AudioService->>JustAudio: playWithQueue()
        JustAudio-->>AudioService: 队列已更新
        AudioService->>AudioService: 延迟100ms重置标志
    end

    AudioService-->>PlayerProv: 队列更新完成
    PlayerProv->>PlayerProv: _setPlayerLoopMode()
    
    par 索引验证等待
        PlayerProv->>PlayerProv: 等待1秒预期索引事件
    and 流事件处理
        JustAudio-->>AudioService: currentIndexStream事件
        AudioService->>AudioService: _isUpdatingQueue=true时跳过
    end

    PlayerProv->>PlayerProv: _isTogglingPlayMode = false
    PlayerProv->>PlayerProv: _expectedIndexAfterToggle = null
    PlayerProv-->>User: 播放模式切换完成
Loading

代码审查工作量估计

🎯 4 (复杂) | ⏱️ ~60 分钟

🐰 抖动的兔子带来变化: 🎵
索引锁定在队列舞蹈中,
iOS的护盾闪闪发光,
播放模式翻转不再迷茫,
音乐流继续轻声唱歌。

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch just_audio_set_resource_refactor

Tip

🧪 Unit Test Generation v2 is now available!

We have significantly improved our unit test generation capabilities.

To enable: Add this to your .coderabbit.yaml configuration:

reviews:
  finishing_touches:
    unit_tests:
      enabled: true

Try it out by using the @coderabbitai generate unit tests command on your code files or under ✨ Finishing Touches on the walkthrough!

Have feedback? Share your thoughts on our Discord thread!


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.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a shuffle bug on iOS by introducing new state management flags and adjusting the audio queue update logic. The changes in player_provider.dart correctly implement a mechanism to manage expected indices during play mode toggling. However, the _isUpdatingQueue flag in audio_player_service.dart, intended to prevent incorrect currentIndexStream events during queue updates, is not being set or reset correctly for iOS due to unreachable code blocks. This oversight could potentially undermine the intended fix for iOS.

Comment on lines +373 to +375
if (_isIOS) {
_isUpdatingQueue = true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The if (_isIOS) condition at line 373 makes the _isUpdatingQueue = true; statement unreachable for iOS devices. This is because the preceding if (_isIOS) block (lines 359-368) contains a return statement, which prevents execution from reaching this point. As a result, the _isUpdatingQueue flag, intended to prevent incorrect currentIndexStream events during queue updates, is never set for iOS in this path. This defeats the purpose of the flag for iOS.

    _isUpdatingQueue = true;

Comment on lines +450 to +453
if (_isIOS) {
await Future.delayed(const Duration(milliseconds: 100));
_isUpdatingQueue = false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Similar to the issue at line 373, the if (_isIOS) condition within this finally block makes the _isUpdatingQueue = false; statement unreachable for iOS devices. Since the iOS-specific logic in updateQueueKeepPlaying (lines 359-368) returns early, this finally block is never reached for iOS. This means that even if _isUpdatingQueue were somehow set for iOS, it would never be reset, potentially leaving the player in an incorrect state.

        await Future.delayed(const Duration(milliseconds: 100));
        _isUpdatingQueue = false;

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.

1 participant