fix: improve YouTube playback reliability - #408
Conversation
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
There was a problem hiding this comment.
Pull request overview
Improves YouTube playback reliability across navigation, Shorts, loading recovery, audio, and window surfaces.
Changes:
- Adds bounded loading/media-error recovery and live-stream handling.
- Hardens WebView navigation, audio ownership, scrolling, and surface handoff.
- Expands parser, localization, and playback regression coverage.
Show a summary per file
| File | Description |
|---|---|
AGENTS.md |
Documents localization synchronization. |
Sources/Kaset/Services/API/Parsers/YouTube/YouTubeItemParser.swift |
Handles nested thumbnails. |
Sources/Kaset/Services/Player/WebPlaybackDocumentGeneration.swift |
Preserves trusted form submissions. |
Sources/Kaset/Services/Player/YouTubePlayerService.swift |
Adds loading, error, live, and quality state. |
Sources/Kaset/Services/Player/YouTubePlayerService+Seeking.swift |
Avoids terminal live seeks. |
Sources/Kaset/Views/YouTube/ScrollForwardingWebView.swift |
Forwards wheel events. |
Sources/Kaset/Views/YouTube/YouTubePlayerBar.swift |
Improves compact layout and quality selection. |
Sources/Kaset/Views/YouTube/YouTubeShortsView.swift |
Stabilizes paging and surface ownership. |
Sources/Kaset/Views/YouTube/YouTubeVideoWindowController.swift |
Hardens fullscreen and frame restoration. |
Sources/Kaset/Views/YouTube/YouTubeWatchSurfaceView.swift |
Guards shared-surface claims. |
Sources/Kaset/Views/YouTube/YouTubeWatchWebView.swift |
Uses scroll forwarding and guarded attachment. |
Sources/Kaset/Views/YouTube/YouTubeWatchWebView+Coordinator.swift |
Handles bridge state and interstitial navigation. |
Sources/Kaset/Views/YouTube/YouTubeWatchWebView+DocumentGeneration.swift |
Adds document-start audio gating. |
Sources/Kaset/Views/YouTube/YouTubeWatchWebView+Scripts.swift |
Reports errors/live state and enforces volume. |
Sources/Kaset/Resources/it.lproj/Localizable.strings |
Corrects Italian translations. |
Tests/KasetTests/AppLocalizationTests.swift |
Updates Italian expectation. |
Tests/KasetTests/LocalizationCatalogParityTests.swift |
Adds catalog/mirror parity validation. |
Tests/KasetTests/VideoSupportTests.swift |
Tests fullscreen state. |
Tests/KasetTests/WebPlaybackDocumentGenerationTests.swift |
Tests trusted POST handling. |
Tests/KasetTests/YouTubeDocumentStartAudioGuardTests.swift |
Tests early audio gating. |
Tests/KasetTests/YouTubeInterstitialScriptContractTests.swift |
Tests interstitial reveal contract. |
Tests/KasetTests/YouTubeItemParserTests.swift |
Tests nested and recorded thumbnails. |
Tests/KasetTests/YouTubePlayerLoadingTimeoutTests.swift |
Tests bounded loading behavior. |
Tests/KasetTests/YouTubePlayerMediaErrorTests.swift |
Tests media-error recovery. |
Tests/KasetTests/YouTubePlayerRecoveryTests.swift |
Covers advertisement loading state. |
Tests/KasetTests/YouTubePlayerServiceTests.swift |
Covers quality and live metadata. |
Tests/KasetTests/YouTubeWatchScriptTests.swift |
Verifies new bridge fields. |
Tests/KasetTests/YouTubeWatchSurfaceOwnershipTests.swift |
Tests surface handoff ownership. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 28/28 changed files
- Comments generated: 2
- Review effort level: Medium
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2e10dd70e6
ℹ️ 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00b1decc3b
ℹ️ 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 60f55e1367
ℹ️ 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63327f83c3
ℹ️ 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>
Signed-off-by: Sertac Ozercan <sozercan@gmail.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Records upstream/main as merged so the fork is no longer reported 'behind', without importing any upstream files. We deliberately keep the fork's own appcast.xml (Sparkle points at Yoddikko/kasetPlus, not sozercan/kaset), README, and CI. Upstream's playback-reliability work (sozercan#408) will be integrated BY HAND in a dedicated session — this ours-merge does not bring its code in. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Integrate upstream sozercan#408 playback reliability (hand-merged onto the fork) Cherry-pick of upstream sozercan/kaset dfdb4ba ("fix: improve YouTube playback reliability"), hand-resolved against the fork's 175-commit divergence and reconciled with the fork's own #19 (⌘R refresh + network auto-retry). Taken from sozercan#408 (the reliability core): - Loading-timeout + media-error recovery in YouTubePlayerService (finishPlaybackLoadingIfReady / deferMediaErrorIfNeeded, ready-media based), replacing the fork's duration>0 loading-clear proxy. Kept the fork's sozercan#374 conditional-assignment perf optimization and ad-skip/live-edge fields. - Runtime liveness (currentMediaIsLive) for URL launches / SPA drift; adopted in the seek-to-end guard. - ScrollForwardingWebView (only forwards wheel events off the extracted watch doc, not off consent/sign-in/CAPTCHA interstitials). - Generalized interstitial handling (isTrustedIntermediaryURL + revealInterstitialScript) in the watch coordinator; kept the fork's clearPlaybackLoadingForInterstitial() call. - YouTubeItemParser thumbnail helpers; new document-generation/loading-timeout/ media-error test suites. Kept the fork's version (superseded upstream's incidental UI changes): - YouTubePlayerBar, YouTubeShortsView, YouTubeVideoWindowController — the fork deliberately reworked these (overflow menu, shorts rail, PiP always-on-top). - Subscribe strings retranslated to the free-subscribe sense ("Iscriviti"), matching the app's abbonati(paid)/iscriviti(free) terminology. Notes: - Dropped upstream's YouTubeVideoWindowFrameAutosaveState/FullscreenIntent refactor (fork handles fullscreen-frame persistence inline + keeps PiP posture) and its extraction-script test harness (fork extracts differently). - Scoped LocalizationCatalogParityTests to the fork's shipped locale subset. - Pre-existing test-target failures on main (AppLocalizationTests bundle loading, SettingsManager/ListenBrainz, storyboard flake) are unchanged; no playback/reliability test regressed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Fix Shorts loading + watch-page scroll lag from the sozercan#408 integration - Restore the fork's duration>0 loading-finish signal (the Shorts thumbnail cover gates on isPlaybackLoading) alongside sozercan#408's stricter ready-media check, excluding ads/media-error frames so recovery is unaffected. - ScrollForwardingWebView forwards to nextResponder (the fork's long-standing behaviour) instead of enclosingScrollView, which the SwiftUI ScrollView host bypasses and lags. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Sertaç Özercan <852750+sozercan@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Validation
swiftlint --strictswiftformat --lint .