2021-07-18 22:32:46 +00:00
|
|
|
import AVKit
|
2021-10-05 20:20:09 +00:00
|
|
|
import Defaults
|
2021-07-18 22:32:46 +00:00
|
|
|
import Siesta
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
struct VideoPlayerView: View {
|
2021-09-18 20:36:42 +00:00
|
|
|
static let defaultAspectRatio: Double = 1.77777778
|
|
|
|
static var defaultMinimumHeightLeft: Double {
|
2021-08-22 19:13:33 +00:00
|
|
|
#if os(macOS)
|
|
|
|
300
|
|
|
|
#else
|
|
|
|
200
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-10-05 20:20:09 +00:00
|
|
|
@State private var playerSize: CGSize = .zero
|
|
|
|
@State private var fullScreen = false
|
2021-07-18 22:32:46 +00:00
|
|
|
|
2021-08-22 19:13:33 +00:00
|
|
|
#if os(iOS)
|
2021-10-05 20:20:09 +00:00
|
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
2021-08-22 19:13:33 +00:00
|
|
|
@Environment(\.verticalSizeClass) private var verticalSizeClass
|
|
|
|
#endif
|
2021-08-16 22:46:18 +00:00
|
|
|
|
2021-10-05 20:20:09 +00:00
|
|
|
@EnvironmentObject<PlayerModel> private var player
|
2021-09-25 08:18:22 +00:00
|
|
|
|
2021-10-05 20:20:09 +00:00
|
|
|
var body: some View {
|
|
|
|
#if os(macOS)
|
|
|
|
HSplitView {
|
|
|
|
content
|
|
|
|
}
|
|
|
|
.frame(idealWidth: 1000, maxWidth: 1100, minHeight: 700)
|
|
|
|
#else
|
|
|
|
HStack(spacing: 0) {
|
|
|
|
content
|
|
|
|
}
|
|
|
|
#if os(iOS)
|
|
|
|
.navigationBarHidden(true)
|
|
|
|
#endif
|
|
|
|
#endif
|
2021-07-18 22:32:46 +00:00
|
|
|
}
|
|
|
|
|
2021-10-05 20:20:09 +00:00
|
|
|
var content: some View {
|
|
|
|
Group {
|
2021-10-28 17:14:55 +00:00
|
|
|
Group {
|
2021-10-05 20:20:09 +00:00
|
|
|
#if os(tvOS)
|
2021-10-28 17:14:55 +00:00
|
|
|
player.playerView
|
2021-10-05 20:20:09 +00:00
|
|
|
#else
|
|
|
|
GeometryReader { geometry in
|
|
|
|
VStack(spacing: 0) {
|
|
|
|
#if os(iOS)
|
|
|
|
if verticalSizeClass == .regular {
|
|
|
|
PlaybackBar()
|
|
|
|
}
|
|
|
|
#elseif os(macOS)
|
|
|
|
PlaybackBar()
|
|
|
|
#endif
|
2021-07-18 22:32:46 +00:00
|
|
|
|
2021-10-05 20:20:09 +00:00
|
|
|
if player.currentItem.isNil {
|
|
|
|
playerPlaceholder(geometry: geometry)
|
|
|
|
} else {
|
2021-10-28 17:14:55 +00:00
|
|
|
player.playerView
|
|
|
|
.modifier(VideoPlayerSizeModifier(geometry: geometry))
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
}
|
2021-08-22 19:13:33 +00:00
|
|
|
#if os(iOS)
|
2021-10-05 20:20:09 +00:00
|
|
|
.onSwipeGesture(
|
|
|
|
up: {
|
|
|
|
withAnimation {
|
|
|
|
fullScreen = true
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
},
|
|
|
|
down: { dismiss() }
|
|
|
|
)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
.background(.black)
|
|
|
|
.onAppear {
|
|
|
|
self.playerSize = geometry.size
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
.onChange(of: geometry.size) { size in
|
|
|
|
self.playerSize = size
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
|
|
|
|
Group {
|
|
|
|
#if os(iOS)
|
|
|
|
if verticalSizeClass == .regular {
|
|
|
|
VideoDetails(sidebarQueue: sidebarQueueBinding, fullScreen: $fullScreen)
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
VideoDetails(fullScreen: $fullScreen)
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
.background()
|
|
|
|
.modifier(VideoDetailsPaddingModifier(geometry: geometry, fullScreen: fullScreen))
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#if os(macOS)
|
|
|
|
.frame(minWidth: 650)
|
|
|
|
#endif
|
|
|
|
#if os(iOS)
|
|
|
|
if sidebarQueue {
|
|
|
|
PlayerQueueView(fullScreen: $fullScreen)
|
|
|
|
.frame(maxWidth: 350)
|
2021-07-18 22:32:46 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
#elseif os(macOS)
|
|
|
|
PlayerQueueView(fullScreen: $fullScreen)
|
|
|
|
.frame(minWidth: 250)
|
2021-07-18 22:32:46 +00:00
|
|
|
#endif
|
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func playerPlaceholder(geometry: GeometryProxy) -> some View {
|
|
|
|
HStack {
|
|
|
|
Spacer()
|
|
|
|
VStack {
|
|
|
|
Spacer()
|
|
|
|
VStack(spacing: 10) {
|
|
|
|
#if !os(tvOS)
|
|
|
|
Image(systemName: "ticket")
|
2021-10-19 21:27:04 +00:00
|
|
|
.font(.system(size: 120))
|
2021-10-05 20:20:09 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
.foregroundColor(.gray)
|
|
|
|
Spacer()
|
2021-07-18 22:32:46 +00:00
|
|
|
}
|
2021-10-05 20:20:09 +00:00
|
|
|
.contentShape(Rectangle())
|
|
|
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: geometry.size.width / VideoPlayerView.defaultAspectRatio)
|
2021-07-18 22:32:46 +00:00
|
|
|
}
|
2021-08-22 19:13:33 +00:00
|
|
|
|
2021-10-05 20:20:09 +00:00
|
|
|
#if os(iOS)
|
|
|
|
var sidebarQueue: Bool {
|
|
|
|
horizontalSizeClass == .regular && playerSize.width > 750
|
|
|
|
}
|
|
|
|
|
|
|
|
var sidebarQueueBinding: Binding<Bool> {
|
|
|
|
Binding(
|
|
|
|
get: { self.sidebarQueue },
|
|
|
|
set: { _ in }
|
|
|
|
)
|
|
|
|
}
|
|
|
|
#endif
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct VideoPlayerView_Previews: PreviewProvider {
|
|
|
|
static var previews: some View {
|
2021-10-05 20:20:09 +00:00
|
|
|
VideoPlayerView()
|
|
|
|
.injectFixtureEnvironmentObjects()
|
|
|
|
|
|
|
|
VideoPlayerView()
|
|
|
|
.injectFixtureEnvironmentObjects()
|
|
|
|
.previewInterfaceOrientation(.landscapeRight)
|
2021-08-22 19:13:33 +00:00
|
|
|
}
|
2021-07-18 22:32:46 +00:00
|
|
|
}
|