- 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