diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index 59e8c534..486d6ac4 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -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() {} diff --git a/Model/Player/Backends/MPVClient.swift b/Model/Player/Backends/MPVClient.swift index 972a68ae..60710d57 100644 --- a/Model/Player/Backends/MPVClient.swift +++ b/Model/Player/Backends/MPVClient.swift @@ -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) { diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift index 3a08a6d0..cd06e5b2 100644 --- a/Model/Player/PlayerModel.swift +++ b/Model/Player/PlayerModel.swift @@ -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 diff --git a/Model/Player/PlayerQueue.swift b/Model/Player/PlayerQueue.swift index 2512c655..71d838be 100644 --- a/Model/Player/PlayerQueue.swift +++ b/Model/Player/PlayerQueue.swift @@ -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) { diff --git a/Shared/EnvironmentValues.swift b/Shared/EnvironmentValues.swift index 3094aa88..237de395 100644 --- a/Shared/EnvironmentValues.swift +++ b/Shared/EnvironmentValues.swift @@ -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 } diff --git a/Shared/Navigation/AppSidebarNavigation.swift b/Shared/Navigation/AppSidebarNavigation.swift index ec3e58fe..7b75c720 100644 --- a/Shared/Navigation/AppSidebarNavigation.swift +++ b/Shared/Navigation/AppSidebarNavigation.swift @@ -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 { diff --git a/Shared/Navigation/AppTabNavigation.swift b/Shared/Navigation/AppTabNavigation.swift index 2c7dd5ae..f14a7649 100644 --- a/Shared/Navigation/AppTabNavigation.swift +++ b/Shared/Navigation/AppTabNavigation.swift @@ -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) diff --git a/Shared/Navigation/ContentView.swift b/Shared/Navigation/ContentView.swift index ca808e58..2847681d 100644 --- a/Shared/Navigation/ContentView.swift +++ b/Shared/Navigation/ContentView.swift @@ -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 { diff --git a/Shared/Player/AppleAVPlayerViewController.swift b/Shared/Player/AppleAVPlayerViewController.swift index acfbdb92..d341c696 100644 --- a/Shared/Player/AppleAVPlayerViewController.swift +++ b/Shared/Player/AppleAVPlayerViewController.swift @@ -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) { diff --git a/Shared/Player/Controls/PlayerControls.swift b/Shared/Player/Controls/PlayerControls.swift index ea79bf40..9bac8841 100644 --- a/Shared/Player/Controls/PlayerControls.swift +++ b/Shared/Player/Controls/PlayerControls.swift @@ -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 diff --git a/Shared/Player/VideoDetails.swift b/Shared/Player/VideoDetails.swift index bacf42e7..45970f76 100644 --- a/Shared/Player/VideoDetails.swift +++ b/Shared/Player/VideoDetails.swift @@ -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 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 diff --git a/Shared/Player/VideoPlayerView.swift b/Shared/Player/VideoPlayerView.swift index e71a28d3..39fc970a 100644 --- a/Shared/Player/VideoPlayerView.swift +++ b/Shared/Player/VideoPlayerView.swift @@ -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 private var accounts @EnvironmentObject private var playerControls @EnvironmentObject 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, diff --git a/Shared/Videos/VideoCell.swift b/Shared/Videos/VideoCell.swift index 1e417062..15cd1ae4 100644 --- a/Shared/Videos/VideoCell.swift +++ b/Shared/Videos/VideoCell.swift @@ -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) } } diff --git a/Shared/Views/ChannelPlaylistView.swift b/Shared/Views/ChannelPlaylistView.swift index e38fa805..fecedbfb 100644 --- a/Shared/Views/ChannelPlaylistView.swift +++ b/Shared/Views/ChannelPlaylistView.swift @@ -10,7 +10,6 @@ struct ChannelPlaylistView: View { @StateObject private var store = Store() @Environment(\.colorScheme) private var colorScheme - @Environment(\.inNavigationView) private var inNavigationView @EnvironmentObject private var accounts @EnvironmentObject 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") } diff --git a/Shared/Views/ChannelVideosView.swift b/Shared/Views/ChannelVideosView.swift index f672e9c3..87dcbe0e 100644 --- a/Shared/Views/ChannelVideosView.swift +++ b/Shared/Views/ChannelVideosView.swift @@ -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 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 { diff --git a/Shared/Views/PlaylistVideosView.swift b/Shared/Views/PlaylistVideosView.swift index 7399c769..e0c7d11d 100644 --- a/Shared/Views/PlaylistVideosView.swift +++ b/Shared/Views/PlaylistVideosView.swift @@ -4,7 +4,6 @@ import SwiftUI struct PlaylistVideosView: View { let playlist: Playlist - @Environment(\.inNavigationView) private var inNavigationView @EnvironmentObject private var player @EnvironmentObject 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") } diff --git a/Shared/Views/VideoContextMenuView.swift b/Shared/Views/VideoContextMenuView.swift index 054e2b83..16f03e68 100644 --- a/Shared/Views/VideoContextMenuView.swift +++ b/Shared/Views/VideoContextMenuView.swift @@ -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) { + 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") }