MiniPlayer/Sources/VideoPlayerView.swift
Hermes Agent c69ec38dc3 refactor: rewrite MiniPlayer using SwiftBricks framework
- 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
2026-06-21 17:48:06 +08:00

98 lines
2.5 KiB
Swift

import SwiftUI
import AVFoundation
import SwiftBricks
/// VideoPlayerWidget BricksEngine"VideoPlayer"
struct VideoPlayerWidget: View {
let bridge: PlayerBridge
let schema: ControlSchema
@ObservedObject var engine: BricksEngine
var body: some View {
VideoPlayerRepresentable(player: bridge.player)
.background(Color.black)
.frame(maxWidth: .infinity)
.aspectRatio(16/9, contentMode: .fit)
.onTapGesture(count: 2) {
bridge.toggleFullscreen()
}
}
}
// MARK: - AVPlayer
#if os(iOS)
import UIKit
struct VideoPlayerRepresentable: UIViewRepresentable {
let player: AVPlayer
func makeUIView(context: Context) -> PlayerUIView {
let view = PlayerUIView()
view.player = player
return view
}
func updateUIView(_ uiView: PlayerUIView, context: Context) {
uiView.player = player
}
}
class PlayerUIView: UIView {
override static var layerClass: AnyClass { AVPlayerLayer.self }
var player: AVPlayer? {
get { (layer as? AVPlayerLayer)?.player }
set { (layer as? AVPlayerLayer)?.player = newValue }
}
override var contentMode: UIView.ContentMode {
get { (layer as? AVPlayerLayer)?.videoGravity == .resizeAspectFill ? .scaleAspectFill : .scaleAspectFit }
set {
(layer as? AVPlayerLayer)?.videoGravity = newValue == .scaleAspectFill ? .resizeAspectFill : .resizeAspect
}
}
}
#elseif os(macOS)
import AppKit
struct VideoPlayerRepresentable: NSViewRepresentable {
let player: AVPlayer
func makeNSView(context: Context) -> PlayerNSView {
let view = PlayerNSView()
view.player = player
return view
}
func updateNSView(_ nsView: PlayerNSView, context: Context) {
nsView.player = player
}
}
class PlayerNSView: NSView {
override init(frame: NSRect) {
super.init(frame: frame)
wantsLayer = true
let playerLayer = AVPlayerLayer()
playerLayer.videoGravity = .resizeAspect
layer = playerLayer
}
required init?(coder: NSCoder) {
fatalError()
}
override func layout() {
super.layout()
(layer as? AVPlayerLayer)?.frame = bounds
}
var player: AVPlayer? {
get { (layer as? AVPlayerLayer)?.player }
set { (layer as? AVPlayerLayer)?.player = newValue }
}
}
#endif