Skip to content

fix: improve Home, AirPlay handoffs and actor biographies - #33

Merged
blurbery merged 9 commits into
mainfrom
fix/ios-home-episode-runtime-pill
Sep 24, 2026
Merged

blurbery merged 9 commits into
mainfrom
fix/ios-home-episode-runtime-pill

Conversation

@blurbery

@blurbery blurbery commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

This fixes missing Home episode indicators, delayed Jellyfin Home updates, lost tvOS gradients and an audio-session race between episodes. Actor biographies on Apple TV also open in the same Liquid Glass panel as movie and series descriptions.

  • Restore the watched/runtime capsule on iOS Home episode cards, including runtime announcements for VoiceOver.
  • Refresh visible Jellyfin Home on foreground entry and every ten seconds after a completed refresh. Load independent requests concurrently and omit unused cast/chapter fields while preserving media sources, streams and user state.
  • Restore the persistent tvOS gradient across tabs, browsing, Settings, sign-in and profiles, while preserving the cinematic detail background.
  • Fix the previous episode’s asynchronous player teardown deactivating the next episode’s audio session. Vivid owns activation across loads; final cleanup waits for retired players across all player instances and checks that a newer load has not taken ownership. Native channel negotiation and compressed audio output are retained.
  • Make Apple TV actor biography previews selectable with the same focus ring as descriptions. Open the full biography in the shared Liquid Glass panel, with scrolling for long text and Back to dismiss. Preserve the existing preview layout and iPhone/iPad biography sheets.
  • Remove the session-ownership diagnostic logging added during the AirPlay investigation. Keep the audio fix and regression tests, and verify the patched native library through its functional option name.

Validation

At 5814e0c, whitespace and iOS/tvOS Swift syntax checks passed. Focused checks passed for 40 native transport decisions, 24 renderer replacement cases, 4 native session ownership cases, 15 track mappings and 10 app teardown cases. The cross-player regression failed before the shared teardown-group fix and passes for both completion orders. The native patch applies to the pinned source; four queue checks also passed for PCM and compressed stops called on and off the audio queue.

Playback testing before the final shared teardown-group change covered several episodes, movies and an automatic next-episode transition without reproducing the reported problems. That supports the tested playback behaviour, but does not prove every intermittent startup pause is eliminated. The final shared teardown-group change has not been tested on a device, and the biography panel has not yet been visually tested.

The iOS/tvOS regression run passed both the iOS tests and tvOS build. The tvOS native-driver build passed; native source is unchanged since that build. The native library and app must be rebuilt together to include the audio ownership fix and logging cleanup. Extended episode chaining and iOS device audio behaviour remain unverified.

Design and documentation

The episode capsule, tvOS gradient and clickable biography panel implement the requested design changes. Relevant Home, Jellyfin, design and player-engine documentation reflects the final behaviour and native-library requirements.

AI disclosure

Implemented these changes with Codex as a tool.

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

📝 Walkthrough

Walkthrough

Jellyfin Home refresh scheduling and request construction changed. iOS episode cards now show runtime status. tvOS backgrounds and biography presentation changed. MPV playback and audio-session handling changed, with associated tests and documentation.

Changes

Jellyfin Home refresh

Layer / File(s) Summary
Home refresh scheduling
iosApp/iosApp/Screens/Home/HomeViewModel.swift, iosApp/iosApp/Screens/Home/HomeView.swift, iosApp/Tests/HomeSectionsMutationTests.swift, docs/cores/jellyfin.md
Jellyfin Home refreshes on each entry. The tvOS loop uses a 10-second interval for Jellyfin and a 30-minute interval for Silo. The test checks consecutive entry refreshes and provider intervals.
Jellyfin Home requests
iosApp/iosApp/Networking/JellyfinProvider.swift, iosApp/Tests/JellyfinAdapterTests.swift
Home requests include media sources and streams while excluding people and chapters. Independent requests run concurrently, and latest-library rows are fetched in pairs in server order.

Episode runtime status

Layer / File(s) Summary
Episode card runtime status
iosApp/iosApp/Screens/Home/Feed/HomeFeedKit.swift
iOS episode cards display a runtime status overlay instead of the resume progress bar. They suppress the watched check and add runtime to accessibility descriptions.

tvOS navigation canvas

Layer / File(s) Summary
Navigation and screen backgrounds
iosApp/iosApp/ContentView.swift, iosApp/iosApp/Screens/Auth/*, iosApp/iosApp/Screens/Browse/BrowseView.swift, iosApp/iosApp/Screens/Collections/CollectionsView.swift, iosApp/iosApp/Screens/Detail/ItemDetailView.swift, iosApp/iosApp/Screens/Personal/*, iosApp/iosApp/Screens/Settings/SettingsBackdrop.swift, iosApp/iosApp/tvOS/Components/VividStartupView.swift, iosApp/iosApp/tvOS/Navigation/TVMainTabView.swift, iosApp/iosApp/tvOS/Profiles/TVSavedAccountViews.swift, docs/app-design.md
tvOS navigation, startup, profile selection and Settings use TVAppBackdrop; sign-in screens use transparent fills. Browse, collection and personal screens use vividBackground(). Detail pages retain a black background.

tvOS biography panel

Layer / File(s) Summary
Biography reading panel
iosApp/iosApp/Screens/People/PersonDetailView.swift, iosApp/iosApp/tvOS/Screens/Detail/TVExpandableSynopsis.swift, docs/app-design.md
The tvOS biography preview opens TVFullSynopsis with the title “Biography”. TVFullSynopsis accepts a configurable title and is no longer private.

MPV audio and session handling

Layer / File(s) Summary
Bounded PCM playback and recovery
patches/mpv/0001-avfoundation-resume-after-audio-eof.patch
The native patch adds bounded, timer-driven PCM feeding and sink recreation on tvOS. It updates compressed-feed handling and playback behaviour for seeks, pause, resume, EOF and renderer notifications.
Audio-session ownership and teardown
iosApp/iosApp/Playback/MPV/MpvPlayerCore.swift, iosApp/iosApp/Playback/MPV/MpvPlayerCoreBase.swift, iosApp/iosApp/Playback/MPV/VividMPVPlayer.swift, scripts/tests/compressed-audio-recovery-tests.py, scripts/tests/mpv-track-tests.py, .github/workflows/mpv-audio-driver.yml, docs/cores/player-engine.md
The player configures session ownership, waits for native-core teardown, then deactivates only when the releasing token still owns the session. Tests cover ownership and teardown. Build verification checks for the native session-management option.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Merge Risk: 🟡 Moderate · up to 9cd46

A tvOS audio-renderer restart can hang playback, and rapid player replacement can deactivate audio before earlier teardown finishes. Fix these playback paths before merging.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.52% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 25 files. (4 skipped: … 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.
Title check ✅ Passed The title clearly summarises the main changes to Home, audio handoffs and actor biographies.
Description check ✅ Passed The description directly covers the Home, Jellyfin, tvOS background, audio-session and actor biography changes.
Full details: Docstring Coverage

Explanation

Docstring coverage is 9.52% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 21 functions across 25 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@blurbery blurbery changed the title fix: show episode runtime pills in the iOS Home feed fix: correct iOS episode pills and Jellyfin Home refreshes Sep 24, 2026
@blurbery blurbery changed the title fix: correct iOS episode pills and Jellyfin Home refreshes fix: restore episode pills, Jellyfin refreshes and tvOS gradients Sep 24, 2026
@blurbery

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

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.

@blurbery blurbery changed the title fix: restore episode pills, Jellyfin refreshes and tvOS gradients fix: restore Home updates, tvOS gradients and AirPlay audio handoffs Sep 24, 2026
Remove the session-ownership diagnostic logging added during AirPlay investigation, preserving the audio fix and regression coverage.
@blurbery blurbery changed the title fix: restore Home updates, tvOS gradients and AirPlay audio handoffs fix: improve Home, AirPlay handoffs and actor biographies Sep 24, 2026
@blurbery

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟠 Major · Make stop(ao) safe on p->queue. · 0001-avfoundation-resume-after-audio-eof.patch:446-447

patches/mpv/0001-avfoundation-resume-after-audio-eof.patch:446-447
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Make stop(ao) safe on p->queue.

restart_block runs on p->queue. The bound stop(ao) implementation unconditionally calls dispatch_sync(p->queue, ...). This dispatch targets the queue that is already executing restart_block, so playback deadlocks before start(ao) runs. Execute the stop block inline when the current queue is p->queue, and dispatch synchronously only from other queues.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: blurbery/vivid/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: a5cae297-05a0-4680-8c58-485b355dfc5e

📥 Commits

Reviewing files that changed from the base of the PR and between 9b1287a and 9cd4648.

📒 Files selected for processing (23)
  • .github/workflows/mpv-audio-driver.yml
  • docs/app-design.md
  • docs/cores/player-engine.md
  • iosApp/iosApp/ContentView.swift
  • iosApp/iosApp/Playback/MPV/MpvPlayerCore.swift
  • iosApp/iosApp/Playback/MPV/MpvPlayerCoreBase.swift
  • iosApp/iosApp/Playback/MPV/VividMPVPlayer.swift
  • iosApp/iosApp/Screens/Auth/TVLoginView.swift
  • iosApp/iosApp/Screens/Auth/TVServerSetupView.swift
  • iosApp/iosApp/Screens/Browse/BrowseView.swift
  • iosApp/iosApp/Screens/Collections/CollectionsView.swift
  • iosApp/iosApp/Screens/Detail/ItemDetailView.swift
  • iosApp/iosApp/Screens/People/PersonDetailView.swift
  • iosApp/iosApp/Screens/Personal/FavoritesView.swift
  • iosApp/iosApp/Screens/Personal/WatchlistView.swift
  • iosApp/iosApp/Screens/Settings/SettingsBackdrop.swift
  • iosApp/iosApp/tvOS/Components/VividStartupView.swift
  • iosApp/iosApp/tvOS/Navigation/TVMainTabView.swift
  • iosApp/iosApp/tvOS/Profiles/TVSavedAccountViews.swift
  • iosApp/iosApp/tvOS/Screens/Detail/TVExpandableSynopsis.swift
  • patches/mpv/0001-avfoundation-resume-after-audio-eof.patch
  • scripts/tests/compressed-audio-recovery-tests.py
  • scripts/tests/mpv-track-tests.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread iosApp/iosApp/Playback/MPV/VividMPVPlayer.swift
@blurbery

Copy link
Copy Markdown
Owner Author

The outside-diff stop(ao) deadlock finding is a false positive for the pinned driver. The dependency patch already checks dispatch_get_specific(&avfoundation_queue_key) == p, executes stop_block() inline on that queue and uses dispatch_sync only from another queue. Vivid’s patch preserves this logic, and initialisation associates the queue key with p.

Verified against the reconstructed pinned source with Vivid’s patch applied. Four focused checks executed the actual stop() body with real serial queues and renderer doubles: PCM and compressed audio, each called on and off its queue. All completed within the timeout. No native code change is needed for this finding. This verifies dispatch behaviour, not physical-device playback.

The separate cross-player teardown finding was reproduced and fixed in 5814e0c, with a regression test covering both completion orders.

@blurbery
blurbery merged commit a0e0e9b into main Sep 24, 2026
3 checks passed
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