mirror of
https://github.com/yattee/yattee.git
synced 2026-07-31 04:12:03 +00:00
Harden player view detach and time-update gate heal from #957
Guard the deinit detach by superview so a container whose render view was stolen by a newer, not-yet-windowed container cannot rip the shared view out of it. Narrow the loading-gate heal to .ready only: the old video still playing during the details/streams fetch can emit .playing, which would open the gate to stale time updates and break the stale-error suppression in play()'s catch.
This commit is contained in:
@@ -2852,10 +2852,14 @@ extension PlayerService: PlayerBackendDelegate {
|
||||
func backend(_ backend: any PlayerBackend, didChangeState playbackState: PlaybackState) {
|
||||
LoggingService.shared.debug("Backend state changed to: \(playbackState)", category: .player)
|
||||
|
||||
// Clear the time-update gate once playback is ready/playing, in case the
|
||||
// load flow exited before doing so (issue #956). Safe: stale updates from a
|
||||
// previous video can only arrive before the new video's ready transition.
|
||||
if playbackState == .ready || playbackState == .playing, loadingVideoID != nil {
|
||||
// Clear the time-update gate once the new video is loaded, in case the load
|
||||
// flow wedged before doing so (issue #956). Only .ready: it comes from mpv's
|
||||
// file-loaded event, which only the new load can emit. The previous video
|
||||
// (still playing on the reused backend during the details/streams fetch) can
|
||||
// emit .playing via buffering recovery or unpause — healing on that would
|
||||
// open the gate to stale time updates and break the stale-error check in
|
||||
// play()'s catch, silently swallowing genuine load failures.
|
||||
if playbackState == .ready, loadingVideoID != nil {
|
||||
loadingVideoID = nil
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,11 @@ private class MPVContainerView: UIView {
|
||||
// deallocating container: otherwise SwiftUI keeps reconciling a
|
||||
// half-alive view and spins the main-thread trait update loop (100%
|
||||
// CPU hang when opening a settings detail during playback, issue #956).
|
||||
playerView.removeFromSuperview()
|
||||
// Guard by superview: currentPlayerView is a stale weak ref when another
|
||||
// (not yet windowed) container has stolen the view — don't rip it out.
|
||||
if playerView.superview === self {
|
||||
playerView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user