- Remove KVO on player.timeControlStatus (fires from CoreMedia bg threads)
- Stop accessing item.duration in timer callback (triggers FigNotificationCenter weak listener ops)
- Check player.rate in timer callback instead for isPlaying state
- Remove replaceCurrentItem(nil) from cleanup to prevent CoreMedia state inconsistency
- Use cachedDuration exclusively in time display updates
- Fix actor isolation warning in endObserver callback
- PlayerNSView: AVPlayerLayer as sublayer (not layer= replacement)
NSView internally manages a sublayer array; replacing the backing
layer directly causes dangling refs during autorelease pool drain
- cleanup(): only pause + remove observers, no replaceCurrentItem
CoreMedia internal state gets corrupted when item is replaced
during view teardown; let it release naturally with deinit
- Remove Combine import and cancellables
- Use NSKeyValueObservation for timeControlStatus (controlled teardown)
- Invalidate itemStatusObserver before replacing playerItem
- Store endObserver token for proper removal
- Add cleanup() method called on view disappear
- Proper deinit with direct property cleanup (nonisolated-safe)
- UI defined in player.json (Bricks JSON schema)
- Custom widgets: VideoPlayer (AVPlayer layer), ProgressSlider (seek bar)
- PlayerBridge connects AVPlayer to BricksEngine event bus
- All interactions via binds/events (no imperative UI code)
- Depends on SwiftBricks SPM package