jellyflood/Swiftfin tvOS/Views/VideoPlayerContainerState/PlaybackControls/PlaybackControls.swift

102 lines
3.0 KiB
Swift

//
// Swiftfin is subject to the terms of the Mozilla Public
// License, v2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2025 Jellyfin & Jellyfin Contributors
//
import Defaults
import PreferencesView
import SwiftUI
import VLCUI
extension VideoPlayer {
struct PlaybackControls: View {
// since this view ignores safe area, it must
// get safe area insets from parent views
@Environment(\.safeAreaInsets)
private var safeAreaInsets
@EnvironmentObject
private var containerState: VideoPlayerContainerState
@EnvironmentObject
private var focusGuide: FocusGuide
@EnvironmentObject
private var manager: MediaPlayerManager
@OnPressEvent
private var onPressEvent
@Router
private var router
@State
private var contentSize: CGSize = .zero
@State
private var effectiveSafeArea: EdgeInsets = .zero
private var isPresentingOverlay: Bool {
containerState.isPresentingOverlay
}
private var isPresentingSupplement: Bool {
containerState.isPresentingSupplement
}
private var isScrubbing: Bool {
containerState.isScrubbing
}
@ViewBuilder
private var bottomContent: some View {
if !isPresentingSupplement {
NavigationBar()
.focusSection()
PlaybackProgress()
.focusGuide(focusGuide, tag: "playbackProgress")
// .isVisible(isScrubbing || isPresentingOverlay)
}
}
var body: some View {
VStack {
Spacer()
bottomContent
.edgePadding()
.background(alignment: .bottom) {
Color.black
.maskLinearGradient {
(location: 0, opacity: 0)
(location: 1, opacity: 0.5)
}
.isVisible(isScrubbing || isPresentingOverlay)
.animation(.linear(duration: 0.25), value: isPresentingOverlay)
}
}
.animation(.linear(duration: 0.1), value: isScrubbing)
.animation(.bouncy(duration: 0.4), value: isPresentingSupplement)
.animation(.bouncy(duration: 0.25), value: isPresentingOverlay)
.onReceive(onPressEvent) { press in
switch press {
case (.playPause, _):
manager.togglePlayPause()
case (.menu, _):
if isPresentingSupplement {
containerState.selectedSupplement = nil
} else {
manager.proxy?.stop()
router.dismiss()
}
default: ()
}
}
}
}
}