Conversation
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Miniaturizing the auxiliary mini player leaves the playback WebView in a non-visible window, preventing reliable picker presentation from the still-visible main player.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review tier: Balanced
Findings: 1
New issues introduced by this change (1)
| Severity | Finding |
|---|---|
Sources/Kaset/Views/MainWindow.swift — isMiniPlayerVisible remains true when the custom Minimize action calls NSWindow.miniaturize, so… |
What changed in this PR
Improves AirPlay continuity, picker positioning, mini-player routing, and connection-state tracking for WebKit playback.
Changes:
- Preserves playback documents through SPA navigation with a longer recovery window.
- Anchors WebKit’s picker to main and mini-player controls.
- Adds AirPlay lifecycle and regression coverage.
| File | Description |
|---|---|
Tests/KasetTests/SingletonPlayerNavigationStateTests.swift |
Tests status clearing on valid commits. |
Tests/KasetTests/PlaybackWebViewTeardownTests.swift |
Tests teardown and process-loss resets. |
Tests/KasetTests/MusicPlaybackBridgeGenerationTests.swift |
Updates bridge payload expectations. |
Tests/KasetTests/Helpers/MusicPlaybackObserverTestContext.swift |
Supports observer setup customization. |
Tests/KasetTests/AirPlayStatusTests.swift |
Tests connection-state observation. |
Tests/KasetTests/AirPlayPickerTests.swift |
Tests picker coordinates and event order. |
Tests/KasetTests/AirPlayNavigationTests.swift |
Tests SPA and full-page routing decisions. |
Sources/Kaset/Views/SingletonPlayerWebView+PlaybackControls.swift |
Anchors the WebKit picker. |
Sources/Kaset/Views/SingletonPlayerWebView+ObserverScript.swift |
Tracks current media AirPlay state. |
Sources/Kaset/Views/SingletonPlayerWebView+NavigationState.swift |
Clears status on document replacement. |
Sources/Kaset/Views/PlayerBar.swift |
Supplies the main-button anchor. |
Sources/Kaset/Views/MiniPlayerWebView+Coordinator.swift |
Simplifies AirPlay bridge handling. |
Sources/Kaset/Views/MiniPlayerWebView.swift |
Revises navigation recovery and lifecycle resets. |
Sources/Kaset/Views/MiniPlayerViews.swift |
Hosts playback and picker controls in the mini player. |
Sources/Kaset/Views/MiniPlayerGlassControls.swift |
Removes the ineffective AVKit picker. |
Sources/Kaset/Views/MainWindow.swift |
Transfers WebView ownership to auxiliary windows. |
Sources/Kaset/Views/AirPlayPickerAnchor.swift |
Adds native button-position tracking. |
Sources/Kaset/Services/Player/PlayerService+PlaybackControls.swift |
Forwards anchored picker requests. |
Sources/Kaset/Services/Player/PlayerService.swift |
Removes obsolete request state. |
docs/adr/0010-airplay-fix.md |
Documents findings, design, and limitations. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0073ebd149
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It changes WebKit navigation, native event anchoring, and cross-window ownership, while runtime validation covers only one receiver and macOS version.
Review tier: Balanced
Findings: None
Issues resolved since last review (1)
| Severity | Finding |
|---|---|
Sources/Kaset/Views/MainWindow.swift — isMiniPlayerVisible remains true when the custom Minimize action calls NSWindow.miniaturize, so… View resolved comment |
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
|
Works perfectly for me, including picker's location ! Thanks a lot. |

Description
AirPlay could disconnect when track navigation or queue recovery replaced the YouTube Music playback document. YouTube could also leave the requested track unstarted and advance its own radio queue, so Kaset showed the selected song while different media played. The eventual full-page fallback then lost the route.
Keep recoverable track changes in the existing document and retry a stalled AirPlay target once. Both playback windows also use WebKit's picker, anchored at the invoking button. Relates to #42.
Changes made
Testing
KASET_SIGNING=adhoc Scripts/build-app.sh debugandScripts/verify-release-app.sh .build/app/Kaset.apppassed. The clean local bundle identifies commit598e9bf0.swift test --skip KasetUITests --no-parallel: all 3,344 Swift tests and 14 XCTest cases passed across the app and supporting targets.swift test --skip KasetUITests --filter 'AirPlayNavigationScriptTests|AirPlayNavigationTests': 27 tests passed, including delayed identity/readiness, missing state callbacks, rapid skips, advertisements, cancellation, and the full-page timeout.swiftlint --strictandswiftformat --lint .passed.Remaining verification and limits
The final state-based retry still needs a packaged receiver check. The prototype's receiver audio and display were not independently confirmed, and the minimize/restore receiver handoff has unit coverage only.
A stalled router can take 12 seconds longer to fall back than the previous three-second deadline. Full document or process recovery and receiver disappearance can still require reopening the picker. Route retention does not guarantee gapless audio; other receivers and macOS versions need runtime verification.