Initial functionality of player items queue

Fix environment objects

Hide video player placeholder on tvOS

Queue improvements
This commit is contained in:
Arkadiusz Fal
2021-10-05 22:20:09 +02:00
parent d6b3c6637d
commit 70c089e696
44 changed files with 1711 additions and 689 deletions

View File

@@ -1,6 +1,10 @@
import AVKit
import Defaults
import Siesta
import SwiftUI
#if !os(tvOS)
import SwiftUIKit
#endif
struct VideoPlayerView: View {
static let defaultAspectRatio: Double = 1.77777778
@@ -12,103 +16,154 @@ struct VideoPlayerView: View {
#endif
}
@StateObject private var store = Store<Video>()
@State private var playerSize: CGSize = .zero
@State private var fullScreen = false
#if os(iOS)
@Environment(\.dismiss) private var dismiss
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@Environment(\.verticalSizeClass) private var verticalSizeClass
#endif
@EnvironmentObject<InvidiousAPI> private var api
@EnvironmentObject<PlaybackModel> private var playback
var resource: Resource {
api.video(video.id)
}
var video: Video
init(_ video: Video) {
self.video = video
}
@EnvironmentObject<PlayerModel> private var player
var body: some View {
VStack(spacing: 0) {
#if os(tvOS)
Player(video: video)
.environmentObject(playback)
#else
GeometryReader { geometry in
VStack(spacing: 0) {
#if os(iOS)
if verticalSizeClass == .regular {
PlaybackBar(video: video)
}
#elseif os(macOS)
PlaybackBar(video: video)
#endif
#if os(macOS)
HSplitView {
content
}
.frame(idealWidth: 1000, maxWidth: 1100, minHeight: 700)
#else
HStack(spacing: 0) {
content
}
#if os(iOS)
.navigationBarHidden(true)
#endif
#endif
}
Player(video: video)
.environmentObject(playback)
.modifier(VideoPlayerSizeModifier(geometry: geometry, aspectRatio: playback.aspectRatio))
}
.background(.black)
VStack(spacing: 0) {
#if os(iOS)
if verticalSizeClass == .regular {
ScrollView(.vertical, showsIndicators: showScrollIndicators) {
if let video = store.item {
VideoDetails(video: video)
} else {
VideoDetails(video: video)
}
var content: some View {
Group {
VStack(alignment: .leading, spacing: 0) {
#if os(tvOS)
player()
#else
GeometryReader { geometry in
VStack(spacing: 0) {
#if os(iOS)
if verticalSizeClass == .regular {
PlaybackBar()
}
}
#else
if let video = store.item {
VideoDetails(video: video)
#elseif os(macOS)
PlaybackBar()
#endif
if player.currentItem.isNil {
playerPlaceholder(geometry: geometry)
} else {
VideoDetails(video: video)
player(geometry: geometry)
}
}
#if os(iOS)
.onSwipeGesture(
up: {
withAnimation {
fullScreen = true
}
},
down: { dismiss() }
)
#endif
.background(.black)
.onAppear {
self.playerSize = geometry.size
}
.onChange(of: geometry.size) { size in
self.playerSize = size
}
Group {
#if os(iOS)
if verticalSizeClass == .regular {
VideoDetails(sidebarQueue: sidebarQueueBinding, fullScreen: $fullScreen)
}
#else
VideoDetails(fullScreen: $fullScreen)
#endif
}
.background()
.modifier(VideoDetailsPaddingModifier(geometry: geometry, fullScreen: fullScreen))
}
.modifier(VideoDetailsPaddingModifier(geometry: geometry, aspectRatio: playback.aspectRatio))
#endif
}
#if os(macOS)
.frame(minWidth: 650)
#endif
#if os(iOS)
if sidebarQueue {
PlayerQueueView(fullScreen: $fullScreen)
.frame(maxWidth: 350)
}
.animation(.linear(duration: 0.2), value: playback.aspectRatio)
#elseif os(macOS)
PlayerQueueView(fullScreen: $fullScreen)
.frame(minWidth: 250)
#endif
}
.onAppear {
resource.addObserver(store)
resource.loadIfNeeded()
}
func playerPlaceholder(geometry: GeometryProxy) -> some View {
HStack {
Spacer()
VStack {
Spacer()
VStack(spacing: 10) {
#if !os(tvOS)
Image(systemName: "ticket")
.font(.system(size: 80))
Text("What are we watching next?")
#endif
}
Spacer()
}
.foregroundColor(.gray)
Spacer()
}
.onDisappear {
resource.removeObservers(ownedBy: store)
resource.invalidate()
}
#if os(macOS)
.frame(maxWidth: 1000, minHeight: 700)
#elseif os(iOS)
.navigationBarHidden(true)
.contentShape(Rectangle())
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: geometry.size.width / VideoPlayerView.defaultAspectRatio)
}
func player(geometry: GeometryProxy? = nil) -> some View {
Player()
#if !os(tvOS)
.modifier(VideoPlayerSizeModifier(geometry: geometry))
#endif
}
var showScrollIndicators: Bool {
#if os(macOS)
false
#else
true
#endif
}
#if os(iOS)
var sidebarQueue: Bool {
horizontalSizeClass == .regular && playerSize.width > 750
}
var sidebarQueueBinding: Binding<Bool> {
Binding(
get: { self.sidebarQueue },
set: { _ in }
)
}
#endif
}
struct VideoPlayerView_Previews: PreviewProvider {
static var previews: some View {
VStack {
Spacer()
}
.sheet(isPresented: .constant(true)) {
VideoPlayerView(Video.fixture)
.injectFixtureEnvironmentObjects()
}
VideoPlayerView()
// .frame(minWidth: 1200, minHeight: 1400)
.injectFixtureEnvironmentObjects()
VideoPlayerView()
.injectFixtureEnvironmentObjects()
.previewInterfaceOrientation(.landscapeRight)
}
}