- Skip BricksView, render video directly in SwiftUI (fixes 1/3 height) - Fullscreen uses plain NSView+AVPlayerLayer (fixes objc_release crash) - Remove NSApp.hide(nil) (fixes fullscreen not showing) - Add volume +/- buttons and volume slider indicator - Add iOS/iPadOS support with #if os guards - ProgressSlider decoupled from BricksEngine - PlayerBridge no longer depends on player.ui JSON
80 lines
1.9 KiB
Swift
80 lines
1.9 KiB
Swift
import SwiftUI
|
|
import AVFoundation
|
|
|
|
// 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
|