mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
parent
687949fbd5
commit
78d7693128
@ -1,5 +1,6 @@
|
||||
import AVFAudio
|
||||
import CoreMedia
|
||||
import Defaults
|
||||
import Foundation
|
||||
import Logging
|
||||
import SwiftUI
|
||||
@ -247,7 +248,13 @@ final class MPVBackend: PlayerBackend {
|
||||
client?.stop()
|
||||
}
|
||||
|
||||
func enterFullScreen() {}
|
||||
func enterFullScreen() {
|
||||
model.toggleFullscreen(controls?.playingFullscreen ?? false)
|
||||
|
||||
if Defaults[.lockLandscapeWhenEnteringFullscreen] {
|
||||
Orientation.lockOrientation(.landscape, andRotateTo: UIDevice.current.orientation.isLandscape ? nil : .landscapeRight)
|
||||
}
|
||||
}
|
||||
|
||||
func exitFullScreen() {}
|
||||
|
||||
|
@ -134,11 +134,11 @@ final class MPVClient: ObservableObject {
|
||||
}
|
||||
|
||||
var currentTime: CMTime {
|
||||
CMTime.secondsInDefaultTimescale(getDouble("time-pos"))
|
||||
CMTime.secondsInDefaultTimescale(mpv.isNil ? -1 : getDouble("time-pos"))
|
||||
}
|
||||
|
||||
var duration: CMTime {
|
||||
CMTime.secondsInDefaultTimescale(getDouble("duration"))
|
||||
CMTime.secondsInDefaultTimescale(mpv.isNil ? -1 : getDouble("duration"))
|
||||
}
|
||||
|
||||
func seek(relative time: CMTime, completionHandler: ((Bool) -> Void)? = nil) {
|
||||
|
@ -57,8 +57,6 @@ final class PlayerModel: ObservableObject {
|
||||
|
||||
@Published var preservedTime: CMTime?
|
||||
|
||||
@Published var playerNavigationLinkActive = false { didSet { handleNavigationViewPlayerPresentationChange() } }
|
||||
|
||||
@Published var sponsorBlock = SponsorBlockAPI()
|
||||
@Published var segmentRestorationTime: CMTime?
|
||||
@Published var lastSkipped: Segment? { didSet { rebuildTVMenu() } }
|
||||
@ -120,23 +118,24 @@ final class PlayerModel: ObservableObject {
|
||||
}
|
||||
|
||||
func show() {
|
||||
guard !presentingPlayer else {
|
||||
#if os(macOS)
|
||||
#if os(macOS)
|
||||
if presentingPlayer {
|
||||
Windows.player.focus()
|
||||
#endif
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
#endif
|
||||
|
||||
presentingPlayer = true
|
||||
|
||||
#if os(macOS)
|
||||
Windows.player.open()
|
||||
Windows.player.focus()
|
||||
#endif
|
||||
presentingPlayer = true
|
||||
}
|
||||
|
||||
func hide() {
|
||||
controls.playingFullscreen = false
|
||||
presentingPlayer = false
|
||||
playerNavigationLinkActive = false
|
||||
|
||||
#if os(iOS)
|
||||
if Defaults[.lockPortraitWhenBrowsing] {
|
||||
@ -206,18 +205,25 @@ final class PlayerModel: ObservableObject {
|
||||
backend.pause()
|
||||
}
|
||||
|
||||
func play(_ video: Video, at time: CMTime? = nil, inNavigationView: Bool = false) {
|
||||
playNow(video, at: time)
|
||||
func play(_ video: Video, at time: CMTime? = nil) {
|
||||
var delay = 0.0
|
||||
#if !os(macOS)
|
||||
delay = 0.3
|
||||
#endif
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.playNow(video, at: time)
|
||||
}
|
||||
|
||||
guard !playingInPictureInPicture else {
|
||||
return
|
||||
}
|
||||
|
||||
if inNavigationView {
|
||||
playerNavigationLinkActive = true
|
||||
} else {
|
||||
show()
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
func playStream(
|
||||
@ -297,7 +303,18 @@ final class PlayerModel: ObservableObject {
|
||||
}
|
||||
|
||||
private func handlePresentationChange() {
|
||||
backend.setNeedsDrawing(presentingPlayer)
|
||||
var delay = 0.0
|
||||
|
||||
#if os(iOS)
|
||||
if presentingPlayer {
|
||||
delay = 0.2
|
||||
}
|
||||
#endif
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
|
||||
self?.backend.setNeedsDrawing(self?.presentingPlayer ?? false)
|
||||
}
|
||||
|
||||
controls.hide()
|
||||
|
||||
#if !os(macOS)
|
||||
@ -323,17 +340,6 @@ final class PlayerModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleNavigationViewPlayerPresentationChange() {
|
||||
backend.setNeedsDrawing(playerNavigationLinkActive)
|
||||
controls.hide()
|
||||
|
||||
if pauseOnHidingPlayer, !playingInPictureInPicture, !playerNavigationLinkActive {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func changeActiveBackend(from: PlayerBackendType, to: PlayerBackendType) {
|
||||
Defaults[.activeBackend] = to
|
||||
self.activeBackend = to
|
||||
|
@ -8,7 +8,7 @@ extension PlayerModel {
|
||||
currentItem?.video
|
||||
}
|
||||
|
||||
func play(_ videos: [Video], shuffling: Bool = false, inNavigationView: Bool = false) {
|
||||
func play(_ videos: [Video], shuffling: Bool = false) {
|
||||
let videosToPlay = shuffling ? videos.shuffled() : videos
|
||||
|
||||
guard let first = videosToPlay.first else {
|
||||
@ -27,11 +27,7 @@ extension PlayerModel {
|
||||
}
|
||||
}
|
||||
|
||||
if inNavigationView {
|
||||
playerNavigationLinkActive = true
|
||||
} else {
|
||||
show()
|
||||
}
|
||||
show()
|
||||
}
|
||||
|
||||
func playNext(_ video: Video) {
|
||||
|
@ -1,10 +1,6 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
private struct InNavigationViewKey: EnvironmentKey {
|
||||
static let defaultValue = false
|
||||
}
|
||||
|
||||
private struct InChannelViewKey: EnvironmentKey {
|
||||
static let defaultValue = false
|
||||
}
|
||||
@ -40,11 +36,6 @@ private struct ScrollViewBottomPaddingKey: EnvironmentKey {
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
var inNavigationView: Bool {
|
||||
get { self[InNavigationViewKey.self] }
|
||||
set { self[InNavigationViewKey.self] = newValue }
|
||||
}
|
||||
|
||||
var inChannelView: Bool {
|
||||
get { self[InChannelViewKey.self] }
|
||||
set { self[InChannelViewKey.self] = newValue }
|
||||
|
@ -63,24 +63,6 @@ struct AppSidebarNavigation: View {
|
||||
}
|
||||
}
|
||||
.environment(\.navigationStyle, .sidebar)
|
||||
#if os(iOS)
|
||||
.background(
|
||||
EmptyView().fullScreenCover(isPresented: $player.presentingPlayer) {
|
||||
VideoPlayerView()
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(comments)
|
||||
.environmentObject(instances)
|
||||
.environmentObject(navigation)
|
||||
.environmentObject(player)
|
||||
.environmentObject(playerControls)
|
||||
.environmentObject(playlists)
|
||||
.environmentObject(recents)
|
||||
.environmentObject(subscriptions)
|
||||
.environmentObject(thumbnailsModel)
|
||||
.environment(\.navigationStyle, .sidebar)
|
||||
}
|
||||
)
|
||||
#endif
|
||||
}
|
||||
|
||||
var toolbarContent: some ToolbarContent {
|
||||
|
@ -51,14 +51,11 @@ struct AppTabNavigation: View {
|
||||
ChannelVideosView(channel: channel)
|
||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||
.environment(\.inChannelView, true)
|
||||
.environment(\.inNavigationView, true)
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(navigation)
|
||||
.environmentObject(player)
|
||||
.environmentObject(subscriptions)
|
||||
.environmentObject(thumbnailsModel)
|
||||
|
||||
.background(playerNavigationLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,25 +66,15 @@ struct AppTabNavigation: View {
|
||||
NavigationView {
|
||||
ChannelPlaylistView(playlist: playlist)
|
||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||
.environment(\.inNavigationView, true)
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(navigation)
|
||||
.environmentObject(player)
|
||||
.environmentObject(subscriptions)
|
||||
.environmentObject(thumbnailsModel)
|
||||
|
||||
.background(playerNavigationLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.background(
|
||||
EmptyView().fullScreenCover(isPresented: $player.presentingPlayer) {
|
||||
videoPlayer
|
||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
||||
.environment(\.navigationStyle, .tab)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private var favoritesNavigationView: some View {
|
||||
@ -172,15 +159,6 @@ struct AppTabNavigation: View {
|
||||
.tag(TabSelection.search)
|
||||
}
|
||||
|
||||
private var playerNavigationLink: some View {
|
||||
NavigationLink(isActive: $player.playerNavigationLinkActive, destination: {
|
||||
videoPlayer
|
||||
.environment(\.inNavigationView, true)
|
||||
}) {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
|
||||
private var videoPlayer: some View {
|
||||
VideoPlayerView()
|
||||
.environmentObject(accounts)
|
||||
|
@ -57,50 +57,54 @@ struct ContentView: View {
|
||||
.environmentObject(subscriptions)
|
||||
.environmentObject(thumbnailsModel)
|
||||
|
||||
// iOS 14 has problem with multiple sheets in one view
|
||||
// but it's ok when it's in background
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingWelcomeScreen) {
|
||||
WelcomeScreen()
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(navigation)
|
||||
}
|
||||
)
|
||||
#if !os(tvOS)
|
||||
.onOpenURL { OpenURLHandler(accounts: accounts, player: player).handle($0) }
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) {
|
||||
AddToPlaylistView(video: navigation.videoToAddToPlaylist)
|
||||
.environmentObject(playlists)
|
||||
}
|
||||
)
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingPlaylistForm) {
|
||||
PlaylistFormView(playlist: $navigation.editedPlaylist)
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(playlists)
|
||||
}
|
||||
)
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingSettings, onDismiss: openWelcomeScreenIfAccountEmpty) {
|
||||
SettingsView()
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(instances)
|
||||
.environmentObject(player)
|
||||
}
|
||||
)
|
||||
#if !os(macOS)
|
||||
.overlay(videoPlayer)
|
||||
#endif
|
||||
.alert(isPresented: $navigation.presentingUnsubscribeAlert) {
|
||||
Alert(
|
||||
title: Text(
|
||||
"Are you sure you want to unsubscribe from \(navigation.channelToUnsubscribe.name)?"
|
||||
),
|
||||
primaryButton: .destructive(Text("Unsubscribe")) {
|
||||
subscriptions.unsubscribe(navigation.channelToUnsubscribe.id)
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
|
||||
// iOS 14 has problem with multiple sheets in one view
|
||||
// but it's ok when it's in background
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingWelcomeScreen) {
|
||||
WelcomeScreen()
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(navigation)
|
||||
}
|
||||
)
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.onOpenURL { OpenURLHandler(accounts: accounts, player: player).handle($0) }
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingAddToPlaylist) {
|
||||
AddToPlaylistView(video: navigation.videoToAddToPlaylist)
|
||||
.environmentObject(playlists)
|
||||
}
|
||||
)
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingPlaylistForm) {
|
||||
PlaylistFormView(playlist: $navigation.editedPlaylist)
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(playlists)
|
||||
}
|
||||
)
|
||||
.background(
|
||||
EmptyView().sheet(isPresented: $navigation.presentingSettings, onDismiss: openWelcomeScreenIfAccountEmpty) {
|
||||
SettingsView()
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(instances)
|
||||
.environmentObject(player)
|
||||
}
|
||||
)
|
||||
#endif
|
||||
.alert(isPresented: $navigation.presentingUnsubscribeAlert) {
|
||||
Alert(
|
||||
title: Text(
|
||||
"Are you sure you want to unsubscribe from \(navigation.channelToUnsubscribe.name)?"
|
||||
),
|
||||
primaryButton: .destructive(Text("Unsubscribe")) {
|
||||
subscriptions.unsubscribe(navigation.channelToUnsubscribe.id)
|
||||
},
|
||||
secondaryButton: .cancel()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func configure() {
|
||||
@ -222,6 +226,21 @@ struct ContentView: View {
|
||||
|
||||
navigation.presentingWelcomeScreen = true
|
||||
}
|
||||
|
||||
var videoPlayer: some View {
|
||||
VideoPlayerView()
|
||||
.environmentObject(accounts)
|
||||
.environmentObject(comments)
|
||||
.environmentObject(instances)
|
||||
.environmentObject(navigation)
|
||||
.environmentObject(player)
|
||||
.environmentObject(playerControls)
|
||||
.environmentObject(playlists)
|
||||
.environmentObject(recents)
|
||||
.environmentObject(subscriptions)
|
||||
.environmentObject(thumbnailsModel)
|
||||
.environment(\.navigationStyle, .sidebar)
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView_Previews: PreviewProvider {
|
||||
|
@ -178,11 +178,7 @@ extension AppleAVPlayerViewController: AVPlayerViewControllerDelegate {
|
||||
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
|
||||
) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
if self.navigationModel.presentingChannel {
|
||||
self.playerModel.playerNavigationLinkActive = true
|
||||
} else {
|
||||
self.playerModel.show()
|
||||
}
|
||||
self.playerModel.show()
|
||||
|
||||
#if os(tvOS)
|
||||
if self.playerModel.playingInPictureInPicture {
|
||||
@ -198,7 +194,6 @@ extension AppleAVPlayerViewController: AVPlayerViewControllerDelegate {
|
||||
|
||||
func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) {
|
||||
playerModel.playingInPictureInPicture = true
|
||||
playerModel.playerNavigationLinkActive = false
|
||||
}
|
||||
|
||||
func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) {
|
||||
|
@ -240,7 +240,7 @@ struct PlayerControls: View {
|
||||
player.hide()
|
||||
player.closePiP()
|
||||
|
||||
var delay = 0.3
|
||||
var delay = 0.2
|
||||
#if os(macOS)
|
||||
delay = 0.0
|
||||
#endif
|
||||
|
@ -21,7 +21,6 @@ struct VideoDetails: View {
|
||||
@State private var currentPage = Page.info
|
||||
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
@Environment(\.inNavigationView) private var inNavigationView
|
||||
@Environment(\.navigationStyle) private var navigationStyle
|
||||
|
||||
@EnvironmentObject<AccountsModel> private var accounts
|
||||
@ -112,7 +111,6 @@ struct VideoDetails: View {
|
||||
.edgesIgnoringSafeArea(.horizontal)
|
||||
}
|
||||
}
|
||||
.padding(.top, inNavigationView && fullScreen ? 10 : 0)
|
||||
.onAppear {
|
||||
if video.isNil && !sidebarQueue {
|
||||
currentPage = .queue
|
||||
|
@ -37,6 +37,10 @@ struct VideoPlayerView: View {
|
||||
var mouseLocation: CGPoint { NSEvent.mouseLocation }
|
||||
#endif
|
||||
|
||||
#if !os(macOS)
|
||||
@State private var playerOffset = UIScreen.main.bounds.height
|
||||
#endif
|
||||
|
||||
@EnvironmentObject<AccountsModel> private var accounts
|
||||
@EnvironmentObject<PlayerControlsModel> private var playerControls
|
||||
@EnvironmentObject<PlayerModel> private var player
|
||||
@ -54,10 +58,6 @@ struct VideoPlayerView: View {
|
||||
content
|
||||
.onAppear {
|
||||
playerSize = geometry.size
|
||||
|
||||
#if os(iOS)
|
||||
configureOrientationUpdatesBasedOnAccelerometer()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
.onChange(of: geometry.size) { size in
|
||||
@ -70,22 +70,10 @@ struct VideoPlayerView: View {
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
|
||||
handleOrientationDidChangeNotification()
|
||||
}
|
||||
.onDisappear {
|
||||
guard !playerControls.playingFullscreen else {
|
||||
return // swiftlint:disable:this implicit_return
|
||||
}
|
||||
|
||||
if Defaults[.lockPortraitWhenBrowsing] {
|
||||
Orientation.lockOrientation(.portrait, andRotateTo: .portrait)
|
||||
} else {
|
||||
Orientation.lockOrientation(.allButUpsideDown)
|
||||
}
|
||||
|
||||
motionManager?.stopAccelerometerUpdates()
|
||||
motionManager = nil
|
||||
}
|
||||
#endif
|
||||
}
|
||||
.offset(y: playerOffset)
|
||||
.animation(.easeIn(duration: 0.2), value: playerOffset)
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -138,6 +126,59 @@ struct VideoPlayerView: View {
|
||||
hoveringPlayer = hovering
|
||||
hovering ? playerControls.show() : playerControls.hide()
|
||||
}
|
||||
#if !os(tvOS)
|
||||
.onChange(of: player.presentingPlayer) { newValue in
|
||||
if newValue {
|
||||
playerOffset = 0
|
||||
#if os(iOS)
|
||||
configureOrientationUpdatesBasedOnAccelerometer()
|
||||
#endif
|
||||
} else {
|
||||
#if !os(macOS)
|
||||
playerOffset = UIScreen.main.bounds.height
|
||||
|
||||
#if os(iOS)
|
||||
if Defaults[.lockPortraitWhenBrowsing] {
|
||||
Orientation.lockOrientation(.portrait, andRotateTo: .portrait)
|
||||
} else {
|
||||
Orientation.lockOrientation(.allButUpsideDown)
|
||||
}
|
||||
|
||||
motionManager?.stopAccelerometerUpdates()
|
||||
motionManager = nil
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
.gesture(
|
||||
DragGesture(minimumDistance: 0)
|
||||
.onChanged { value in
|
||||
guard !fullScreenLayout else {
|
||||
return
|
||||
}
|
||||
|
||||
player.backend.setNeedsDrawing(false)
|
||||
let drag = value.translation.height
|
||||
|
||||
guard drag > 0 else {
|
||||
return
|
||||
}
|
||||
|
||||
withAnimation(.easeIn(duration: 0.2)) {
|
||||
playerOffset = drag
|
||||
}
|
||||
}
|
||||
.onEnded { _ in
|
||||
if playerOffset > 100 {
|
||||
player.backend.setNeedsDrawing(true)
|
||||
player.hide()
|
||||
} else {
|
||||
player.show()
|
||||
playerOffset = 0
|
||||
}
|
||||
}
|
||||
)
|
||||
#endif
|
||||
#if os(macOS)
|
||||
.onAppear(perform: {
|
||||
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
|
||||
@ -406,7 +447,8 @@ struct VideoPlayerView: View {
|
||||
} else {
|
||||
guard abs(acceleration.z) <= 0.74,
|
||||
player.lockedOrientation.isNil,
|
||||
enterFullscreenInLandscape
|
||||
enterFullscreenInLandscape,
|
||||
!lockLandscapeOnRotation
|
||||
else {
|
||||
return
|
||||
}
|
||||
@ -421,6 +463,7 @@ struct VideoPlayerView: View {
|
||||
}
|
||||
|
||||
private func handleOrientationDidChangeNotification() {
|
||||
playerOffset = playerOffset == 0 ? 0 : UIScreen.main.bounds.height
|
||||
let newOrientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
|
||||
if newOrientation?.isLandscape ?? false,
|
||||
player.presentingPlayer,
|
||||
|
@ -6,7 +6,6 @@ import SwiftUI
|
||||
struct VideoCell: View {
|
||||
private var video: Video
|
||||
|
||||
@Environment(\.inNavigationView) private var inNavigationView
|
||||
@Environment(\.navigationStyle) private var navigationStyle
|
||||
|
||||
#if os(iOS)
|
||||
@ -46,11 +45,8 @@ struct VideoCell: View {
|
||||
.buttonStyle(.plain)
|
||||
.contentShape(RoundedRectangle(cornerRadius: thumbnailRoundingCornerRadius))
|
||||
.contextMenu {
|
||||
VideoContextMenuView(
|
||||
video: video,
|
||||
playerNavigationLinkActive: $player.playerNavigationLinkActive
|
||||
)
|
||||
.environmentObject(accounts)
|
||||
VideoContextMenuView(video: video)
|
||||
.environmentObject(accounts)
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +89,7 @@ struct VideoCell: View {
|
||||
|
||||
player.avPlayerBackend.startPictureInPictureOnPlay = player.playingInPictureInPicture
|
||||
|
||||
player.play(video, at: playAt, inNavigationView: inNavigationView)
|
||||
player.play(video, at: playAt)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@ struct ChannelPlaylistView: View {
|
||||
@StateObject private var store = Store<ChannelPlaylist>()
|
||||
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@Environment(\.inNavigationView) private var inNavigationView
|
||||
|
||||
@EnvironmentObject<AccountsModel> private var accounts
|
||||
@EnvironmentObject<PlayerModel> private var player
|
||||
@ -24,19 +23,9 @@ struct ChannelPlaylistView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
#if os(iOS)
|
||||
if inNavigationView {
|
||||
content
|
||||
} else {
|
||||
BrowserPlayerControls {
|
||||
content
|
||||
}
|
||||
}
|
||||
#else
|
||||
BrowserPlayerControls {
|
||||
content
|
||||
}
|
||||
#endif
|
||||
BrowserPlayerControls {
|
||||
content
|
||||
}
|
||||
}
|
||||
|
||||
var content: some View {
|
||||
@ -94,9 +83,6 @@ struct ChannelPlaylistView: View {
|
||||
}
|
||||
}
|
||||
.navigationTitle(playlist.title)
|
||||
#if os(iOS)
|
||||
.navigationBarHidden(player.playerNavigationLinkActive)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -110,7 +96,7 @@ struct ChannelPlaylistView: View {
|
||||
|
||||
private var playButton: some View {
|
||||
Button {
|
||||
player.play(videos, inNavigationView: inNavigationView)
|
||||
player.play(videos)
|
||||
} label: {
|
||||
Label("Play All", systemImage: "play")
|
||||
}
|
||||
@ -118,7 +104,7 @@ struct ChannelPlaylistView: View {
|
||||
|
||||
private var shuffleButton: some View {
|
||||
Button {
|
||||
player.play(videos, shuffling: true, inNavigationView: inNavigationView)
|
||||
player.play(videos, shuffling: true)
|
||||
} label: {
|
||||
Label("Shuffle", systemImage: "shuffle")
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ struct ChannelVideosView: View {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
#if os(iOS)
|
||||
@Environment(\.inNavigationView) private var inNavigationView
|
||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||
@EnvironmentObject<PlayerModel> private var player
|
||||
#endif
|
||||
@ -29,19 +28,9 @@ struct ChannelVideosView: View {
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
#if os(iOS)
|
||||
if inNavigationView {
|
||||
content
|
||||
} else {
|
||||
BrowserPlayerControls {
|
||||
content
|
||||
}
|
||||
}
|
||||
#else
|
||||
BrowserPlayerControls {
|
||||
content
|
||||
}
|
||||
#endif
|
||||
BrowserPlayerControls {
|
||||
content
|
||||
}
|
||||
}
|
||||
|
||||
var content: some View {
|
||||
@ -115,9 +104,6 @@ struct ChannelVideosView: View {
|
||||
resource.load()
|
||||
}
|
||||
}
|
||||
#if os(iOS)
|
||||
.navigationBarHidden(player.playerNavigationLinkActive)
|
||||
#endif
|
||||
.navigationTitle(navigationTitle)
|
||||
|
||||
return Group {
|
||||
|
@ -4,7 +4,6 @@ import SwiftUI
|
||||
struct PlaylistVideosView: View {
|
||||
let playlist: Playlist
|
||||
|
||||
@Environment(\.inNavigationView) private var inNavigationView
|
||||
@EnvironmentObject<PlayerModel> private var player
|
||||
@EnvironmentObject<PlaylistsModel> private var model
|
||||
|
||||
@ -66,13 +65,13 @@ struct PlaylistVideosView: View {
|
||||
FavoriteButton(item: FavoriteItem(section: .channelPlaylist(playlist.id, playlist.title)))
|
||||
|
||||
Button {
|
||||
player.play(videos, inNavigationView: inNavigationView)
|
||||
player.play(videos)
|
||||
} label: {
|
||||
Label("Play All", systemImage: "play")
|
||||
}
|
||||
|
||||
Button {
|
||||
player.play(videos, shuffling: true, inNavigationView: inNavigationView)
|
||||
player.play(videos, shuffling: true)
|
||||
} label: {
|
||||
Label("Shuffle", systemImage: "shuffle")
|
||||
}
|
||||
|
@ -5,9 +5,6 @@ import SwiftUI
|
||||
struct VideoContextMenuView: View {
|
||||
let video: Video
|
||||
|
||||
@Binding var playerNavigationLinkActive: Bool
|
||||
|
||||
@Environment(\.inNavigationView) private var inNavigationView
|
||||
@Environment(\.inChannelView) private var inChannelView
|
||||
@Environment(\.inChannelPlaylistView) private var inChannelPlaylistView
|
||||
@Environment(\.navigationStyle) private var navigationStyle
|
||||
@ -26,9 +23,8 @@ struct VideoContextMenuView: View {
|
||||
|
||||
private var viewContext: NSManagedObjectContext = PersistenceController.shared.container.viewContext
|
||||
|
||||
init(video: Video, playerNavigationLinkActive: Binding<Bool>) {
|
||||
init(video: Video) {
|
||||
self.video = video
|
||||
_playerNavigationLinkActive = playerNavigationLinkActive
|
||||
_watchRequest = video.watchFetchRequest
|
||||
}
|
||||
|
||||
@ -111,7 +107,7 @@ struct VideoContextMenuView: View {
|
||||
|
||||
private var continueButton: some View {
|
||||
Button {
|
||||
player.play(video, at: .secondsInDefaultTimescale(watch!.stoppedAt), inNavigationView: inNavigationView)
|
||||
player.play(video, at: .secondsInDefaultTimescale(watch!.stoppedAt))
|
||||
} label: {
|
||||
Label("Continue from \(watch!.stoppedAt.formattedAsPlaybackTime() ?? "where I left off")", systemImage: "playpause")
|
||||
}
|
||||
@ -131,7 +127,7 @@ struct VideoContextMenuView: View {
|
||||
|
||||
private var playNowButton: some View {
|
||||
Button {
|
||||
player.play(video, inNavigationView: inNavigationView)
|
||||
player.play(video)
|
||||
} label: {
|
||||
Label("Play Now", systemImage: "play")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user