mirror of
				https://github.com/yattee/yattee.git
				synced 2025-10-31 04:31:54 +00:00 
			
		
		
		
	PiP and UI improvements
This commit is contained in:
		| @@ -47,8 +47,12 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable { | ||||
|         URLComponents(string: apiURL)! | ||||
|     } | ||||
|  | ||||
|     var frontendHost: String { | ||||
|         URLComponents(string: frontendURL!)!.host! | ||||
|     var frontendHost: String? { | ||||
|         guard let url = app == .invidious ? apiURL : frontendURL else { | ||||
|             return nil | ||||
|         } | ||||
|  | ||||
|         return URLComponents(string: url)?.host | ||||
|     } | ||||
|  | ||||
|     func hash(into hasher: inout Hasher) { | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
|  | ||||
| import Defaults | ||||
| import Foundation | ||||
|  | ||||
|   | ||||
| @@ -26,7 +26,7 @@ protocol VideosAPI { | ||||
|     func channelPlaylist(_ id: String) -> Resource? | ||||
|  | ||||
|     func loadDetails(_ item: PlayerQueueItem, completionHandler: @escaping (PlayerQueueItem) -> Void) | ||||
|     func shareURL(_ item: ContentItem) -> URL | ||||
|     func shareURL(_ item: ContentItem) -> URL? | ||||
| } | ||||
|  | ||||
| extension VideosAPI { | ||||
| @@ -48,9 +48,13 @@ extension VideosAPI { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     func shareURL(_ item: ContentItem) -> URL { | ||||
|     func shareURL(_ item: ContentItem) -> URL? { | ||||
|         guard let frontendHost = account.instance.frontendHost else { | ||||
|             return nil | ||||
|         } | ||||
|  | ||||
|         var urlComponents = account.instance.urlComponents | ||||
|         urlComponents.host = account.instance.frontendHost | ||||
|         urlComponents.host = frontendHost | ||||
|  | ||||
|         switch item.contentType { | ||||
|         case .video: | ||||
|   | ||||
| @@ -13,7 +13,8 @@ final class PlayerModel: ObservableObject { | ||||
|     let logger = Logger(label: "net.arekf.Pearvidious.ps") | ||||
|  | ||||
|     private(set) var player = AVPlayer() | ||||
|     var controller: PlayerViewController? | ||||
|     private(set) var playerView = Player() | ||||
|     var controller: PlayerViewController? { didSet { playerView.controller = controller } } | ||||
|     #if os(tvOS) | ||||
|         var avPlayerViewController: AVPlayerViewController? | ||||
|     #endif | ||||
| @@ -52,6 +53,8 @@ final class PlayerModel: ObservableObject { | ||||
|  | ||||
|     private var timeObserverThrottle = Throttle(interval: 2) | ||||
|  | ||||
|     var playingInPictureInPicture = false | ||||
|  | ||||
|     init(accounts: AccountsModel? = nil, instances: InstancesModel? = nil) { | ||||
|         self.accounts = accounts ?? AccountsModel() | ||||
|         self.instances = instances ?? InstancesModel() | ||||
|   | ||||
| @@ -96,6 +96,7 @@ | ||||
| 		373CFAEF2697A78B003CB2C6 /* AddToPlaylistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373CFAEE2697A78B003CB2C6 /* AddToPlaylistView.swift */; }; | ||||
| 		373CFAF02697A78B003CB2C6 /* AddToPlaylistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373CFAEE2697A78B003CB2C6 /* AddToPlaylistView.swift */; }; | ||||
| 		373CFAF12697A78B003CB2C6 /* AddToPlaylistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373CFAEE2697A78B003CB2C6 /* AddToPlaylistView.swift */; }; | ||||
| 		374108D1272B11B2006C5CC8 /* PictureInPictureDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */; }; | ||||
| 		3743B86927216D3600261544 /* ChannelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743B86727216D3600261544 /* ChannelCell.swift */; }; | ||||
| 		3743B86A27216D3600261544 /* ChannelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743B86727216D3600261544 /* ChannelCell.swift */; }; | ||||
| 		3743CA4E270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3743CA4D270EFE3400E4D32B /* PlayerQueueRow.swift */; }; | ||||
| @@ -518,6 +519,7 @@ | ||||
| 		373CFADA269663F1003CB2C6 /* Thumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Thumbnail.swift; sourceTree = "<group>"; }; | ||||
| 		373CFAEA26975CBF003CB2C6 /* PlaylistFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaylistFormView.swift; sourceTree = "<group>"; }; | ||||
| 		373CFAEE2697A78B003CB2C6 /* AddToPlaylistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddToPlaylistView.swift; sourceTree = "<group>"; }; | ||||
| 		374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PictureInPictureDelegate.swift; sourceTree = "<group>"; }; | ||||
| 		3743B86727216D3600261544 /* ChannelCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelCell.swift; sourceTree = "<group>"; }; | ||||
| 		3743CA4D270EFE3400E4D32B /* PlayerQueueRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerQueueRow.swift; sourceTree = "<group>"; }; | ||||
| 		3743CA51270F284F00E4D32B /* View+Borders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Borders.swift"; sourceTree = "<group>"; }; | ||||
| @@ -976,6 +978,7 @@ | ||||
| 			children = ( | ||||
| 				37FD43E1270472060073EE42 /* Settings */, | ||||
| 				374C0542272496E4009BDDBE /* AppDelegate.swift */, | ||||
| 				374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */, | ||||
| 				37BE0BDB26A2367F0092E2DB /* Player.swift */, | ||||
| 				37BE0BD926A214630092E2DB /* PlayerViewController.swift */, | ||||
| 				374C0544272496FD009BDDBE /* Info.plist */, | ||||
| @@ -1825,6 +1828,7 @@ | ||||
| 				3784B23E2728B85300B09468 /* ShareButton.swift in Sources */, | ||||
| 				37BE0BDA26A214630092E2DB /* PlayerViewController.swift in Sources */, | ||||
| 				37E64DD226D597EB00C71877 /* SubscriptionsModel.swift in Sources */, | ||||
| 				374108D1272B11B2006C5CC8 /* PictureInPictureDelegate.swift in Sources */, | ||||
| 				37C7A1D6267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */, | ||||
| 				37319F0627103F94004ECCD0 /* PlayerQueue.swift in Sources */, | ||||
| 				37B767DC2677C3CA0098BAA8 /* PlayerModel.swift in Sources */, | ||||
|   | ||||
| @@ -5,6 +5,10 @@ private struct InNavigationViewKey: EnvironmentKey { | ||||
|     static let defaultValue = false | ||||
| } | ||||
|  | ||||
| private struct InChannelViewKey: EnvironmentKey { | ||||
|     static let defaultValue = false | ||||
| } | ||||
|  | ||||
| private struct HorizontalCellsKey: EnvironmentKey { | ||||
|     static let defaultValue = false | ||||
| } | ||||
| @@ -27,6 +31,11 @@ extension EnvironmentValues { | ||||
|         set { self[InNavigationViewKey.self] = newValue } | ||||
|     } | ||||
|  | ||||
|     var inChannelView: Bool { | ||||
|         get { self[InChannelViewKey.self] } | ||||
|         set { self[InChannelViewKey.self] = newValue } | ||||
|     } | ||||
|  | ||||
|     var horizontalCells: Bool { | ||||
|         get { self[HorizontalCellsKey.self] } | ||||
|         set { self[HorizontalCellsKey.self] = newValue } | ||||
|   | ||||
| @@ -104,6 +104,7 @@ struct AppTabNavigation: View { | ||||
|             if let channel = recents.presentedChannel { | ||||
|                 NavigationView { | ||||
|                     ChannelVideosView(channel: channel) | ||||
|                         .environment(\.inChannelView, true) | ||||
|                         .environment(\.inNavigationView, true) | ||||
|                         .background(playerNavigationLink) | ||||
|                 } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import Defaults | ||||
| import SwiftUI | ||||
|  | ||||
| struct Player: UIViewControllerRepresentable { | ||||
|     @EnvironmentObject<NavigationModel> private var navigation | ||||
|     @EnvironmentObject<PlayerModel> private var player | ||||
|  | ||||
|     var controller: PlayerViewController? | ||||
| @@ -17,6 +18,7 @@ struct Player: UIViewControllerRepresentable { | ||||
|  | ||||
|         let controller = PlayerViewController() | ||||
|  | ||||
|         controller.navigationModel = navigation | ||||
|         controller.playerModel = player | ||||
|         player.controller = controller | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import SwiftUI | ||||
|  | ||||
| final class PlayerViewController: UIViewController { | ||||
|     var playerLoaded = false | ||||
|     var navigationModel: NavigationModel! | ||||
|     var playerModel: PlayerModel! | ||||
|     var playerViewController = AVPlayerViewController() | ||||
|  | ||||
| @@ -11,6 +12,12 @@ final class PlayerViewController: UIViewController { | ||||
|         super.viewWillAppear(animated) | ||||
|  | ||||
|         loadPlayer() | ||||
|  | ||||
|         #if os(tvOS) | ||||
|             if !playerViewController.isBeingPresented, !playerViewController.isBeingDismissed { | ||||
|                 present(playerViewController, animated: false) | ||||
|             } | ||||
|         #endif | ||||
|     } | ||||
|  | ||||
|     func loadPlayer() { | ||||
| @@ -26,12 +33,9 @@ final class PlayerViewController: UIViewController { | ||||
|         #if os(tvOS) | ||||
|             playerModel.avPlayerViewController = playerViewController | ||||
|             playerViewController.customInfoViewControllers = [playerQueueInfoViewController] | ||||
|             present(playerViewController, animated: false) | ||||
|         #else | ||||
|             embedViewController() | ||||
|         #endif | ||||
|  | ||||
|         playerLoaded = true | ||||
|     } | ||||
|  | ||||
|     #if os(tvOS) | ||||
| @@ -66,7 +70,7 @@ extension PlayerViewController: AVPlayerViewControllerDelegate { | ||||
|     } | ||||
|  | ||||
|     func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_: AVPlayerViewController) -> Bool { | ||||
|         false | ||||
|         true | ||||
|     } | ||||
|  | ||||
|     func playerViewControllerWillBeginDismissalTransition(_: AVPlayerViewController) {} | ||||
| @@ -95,7 +99,35 @@ extension PlayerViewController: AVPlayerViewControllerDelegate { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) {} | ||||
|     func playerViewController( | ||||
|         _ playerViewController: AVPlayerViewController, | ||||
|         restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void | ||||
|     ) { | ||||
|         DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { | ||||
|             if self.navigationModel.presentingChannel { | ||||
|                 self.playerModel.playerNavigationLinkActive = true | ||||
|             } else { | ||||
|                 self.playerModel.presentPlayer() | ||||
|             } | ||||
|  | ||||
|     func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) {} | ||||
|             #if os(tvOS) | ||||
|             if self.playerModel.playingInPictureInPicture { | ||||
|                     self.present(playerViewController, animated: false) { | ||||
|                         completionHandler(true) | ||||
|                     } | ||||
|                 } | ||||
|             #else | ||||
|                 completionHandler(true) | ||||
|             #endif | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     func playerViewControllerWillStartPictureInPicture(_: AVPlayerViewController) { | ||||
|         playerModel.playingInPictureInPicture = true | ||||
|         playerModel.playerNavigationLinkActive = false | ||||
|     } | ||||
|  | ||||
|     func playerViewControllerWillStopPictureInPicture(_: AVPlayerViewController) { | ||||
|         playerModel.playingInPictureInPicture = false | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -17,6 +17,7 @@ struct VideoDetails: View { | ||||
|     @State private var currentPage = Page.details | ||||
|  | ||||
|     @Environment(\.dismiss) private var dismiss | ||||
|     @Environment(\.inNavigationView) private var inNavigationView | ||||
|  | ||||
|     @EnvironmentObject<AccountsModel> private var accounts | ||||
|     @EnvironmentObject<PlayerModel> private var player | ||||
| @@ -89,6 +90,7 @@ struct VideoDetails: View { | ||||
|                     .edgesIgnoringSafeArea(.horizontal) | ||||
|             } | ||||
|         } | ||||
|         .padding(.top, inNavigationView && fullScreen ? 10 : 0) | ||||
|         .onAppear { | ||||
|             #if !os(macOS) | ||||
|                 if video.isNil { | ||||
| @@ -298,9 +300,9 @@ struct VideoDetails: View { | ||||
|         } | ||||
|         #if os(iOS) | ||||
|             .sheet(isPresented: $presentingShareSheet) { | ||||
|                 ShareSheet(activityItems: [ | ||||
|                     accounts.api.shareURL(contentItem) | ||||
|                 ]) | ||||
|                 if let url = accounts.api.shareURL(contentItem) { | ||||
|                     ShareSheet(activityItems: [url]) | ||||
|                 } | ||||
|             } | ||||
|         #endif | ||||
|     } | ||||
|   | ||||
| @@ -42,9 +42,9 @@ struct VideoPlayerView: View { | ||||
|  | ||||
|     var content: some View { | ||||
|         Group { | ||||
|             VStack(alignment: .leading, spacing: 0) { | ||||
|             Group { | ||||
|                 #if os(tvOS) | ||||
|                     player() | ||||
|                     player.playerView | ||||
|                 #else | ||||
|                     GeometryReader { geometry in | ||||
|                         VStack(spacing: 0) { | ||||
| @@ -59,7 +59,8 @@ struct VideoPlayerView: View { | ||||
|                             if player.currentItem.isNil { | ||||
|                                 playerPlaceholder(geometry: geometry) | ||||
|                             } else { | ||||
|                                 player(geometry: geometry) | ||||
|                                 player.playerView | ||||
|                                     .modifier(VideoPlayerSizeModifier(geometry: geometry)) | ||||
|                             } | ||||
|                         } | ||||
|                         #if os(iOS) | ||||
| @@ -131,13 +132,6 @@ struct VideoPlayerView: View { | ||||
|         .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 | ||||
|     } | ||||
|  | ||||
|     #if os(iOS) | ||||
|         var sidebarQueue: Bool { | ||||
|             horizontalSizeClass == .regular && playerSize.width > 750 | ||||
|   | ||||
| @@ -21,6 +21,10 @@ struct VideoCell: View { | ||||
|             Button(action: { | ||||
|                 player.playNow(video) | ||||
|  | ||||
|                 guard !player.playingInPictureInPicture else { | ||||
|                     return | ||||
|                 } | ||||
|  | ||||
|                 if inNavigationView { | ||||
|                     player.playerNavigationLinkActive = true | ||||
|                 } else { | ||||
|   | ||||
| @@ -48,9 +48,9 @@ struct ChannelPlaylistView: View { | ||||
|         } | ||||
|         #if os(iOS) | ||||
|             .sheet(isPresented: $presentingShareSheet) { | ||||
|                 ShareSheet(activityItems: [ | ||||
|                     accounts.api.shareURL(contentItem) | ||||
|                 ]) | ||||
|                 if let url = accounts.api.shareURL(contentItem) { | ||||
|                     ShareSheet(activityItems: [url]) | ||||
|                 } | ||||
|             } | ||||
|         #endif | ||||
|         .onAppear { | ||||
|   | ||||
| @@ -67,6 +67,7 @@ struct ChannelVideosView: View { | ||||
|                 .prefersDefaultFocus(in: focusNamespace) | ||||
|             #endif | ||||
|         } | ||||
|         .environment(\.inChannelView, true) | ||||
|         #if !os(iOS) | ||||
|             .focusScope(focusNamespace) | ||||
|         #endif | ||||
| @@ -102,9 +103,9 @@ struct ChannelVideosView: View { | ||||
|         #endif | ||||
|         #if os(iOS) | ||||
|             .sheet(isPresented: $presentingShareSheet) { | ||||
|                 ShareSheet(activityItems: [ | ||||
|                     accounts.api.shareURL(contentItem) | ||||
|                 ]) | ||||
|                 if let url = accounts.api.shareURL(contentItem) { | ||||
|                     ShareSheet(activityItems: [url]) | ||||
|                 } | ||||
|             } | ||||
|         #endif | ||||
|         .modifier(UnsubscribeAlertModifier()) | ||||
|   | ||||
| @@ -7,28 +7,34 @@ struct ShareButton: View { | ||||
|     @EnvironmentObject<AccountsModel> private var accounts | ||||
|  | ||||
|     var body: some View { | ||||
|         Button { | ||||
|             #if os(iOS) | ||||
|                 presentingShareSheet = true | ||||
|             #else | ||||
|                 NSPasteboard.general.clearContents() | ||||
|                 NSPasteboard.general.setString(shareURL, forType: .string) | ||||
|             #endif | ||||
|         } label: { | ||||
|             #if os(iOS) | ||||
|                 Label("Share", systemImage: "square.and.arrow.up") | ||||
|             #else | ||||
|         Group { | ||||
|             if let url = shareURL { | ||||
|                 Button { | ||||
|                     #if os(iOS) | ||||
|                         presentingShareSheet = true | ||||
|                     #else | ||||
|                         NSPasteboard.general.clearContents() | ||||
|                         NSPasteboard.general.setString(url, forType: .string) | ||||
|                     #endif | ||||
|                 } label: { | ||||
|                     #if os(iOS) | ||||
|                         Label("Share", systemImage: "square.and.arrow.up") | ||||
|                     #else | ||||
|                         EmptyView() | ||||
|                     #endif | ||||
|                 } | ||||
|                 .keyboardShortcut("c") | ||||
|                 .foregroundColor(.blue) | ||||
|                 .buttonStyle(.plain) | ||||
|                 .labelStyle(.iconOnly) | ||||
|             } else { | ||||
|                 EmptyView() | ||||
|             #endif | ||||
|             } | ||||
|         } | ||||
|         .keyboardShortcut("c") | ||||
|         .foregroundColor(.blue) | ||||
|         .buttonStyle(.plain) | ||||
|         .labelStyle(.iconOnly) | ||||
|     } | ||||
|  | ||||
|     private var shareURL: String { | ||||
|         accounts.api.shareURL(contentItem).absoluteString | ||||
|     private var shareURL: String? { | ||||
|         accounts.api.shareURL(contentItem)?.absoluteString | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ struct VideoContextMenuView: View { | ||||
|     @Binding var playerNavigationLinkActive: Bool | ||||
|  | ||||
|     @Environment(\.inNavigationView) private var inNavigationView | ||||
|     @Environment(\.inChannelView) private var inChannelView | ||||
|     @Environment(\.navigationStyle) private var navigationStyle | ||||
|     @Environment(\.currentPlaylistID) private var playlistID | ||||
|  | ||||
| @@ -27,11 +28,13 @@ struct VideoContextMenuView: View { | ||||
|             addToQueueButton | ||||
|         } | ||||
|  | ||||
|         Section { | ||||
|             openChannelButton | ||||
|         if !inChannelView { | ||||
|             Section { | ||||
|                 openChannelButton | ||||
|  | ||||
|             if accounts.app.supportsSubscriptions { | ||||
|                 subscriptionButton | ||||
|                 if accounts.app.supportsSubscriptions { | ||||
|                     subscriptionButton | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -54,6 +57,10 @@ struct VideoContextMenuView: View { | ||||
|         Button { | ||||
|             player.playNow(video) | ||||
|  | ||||
|             guard !player.playingInPictureInPicture else { | ||||
|                 return | ||||
|             } | ||||
|  | ||||
|             if inNavigationView { | ||||
|                 playerNavigationLinkActive = true | ||||
|             } else { | ||||
| @@ -72,6 +79,14 @@ struct VideoContextMenuView: View { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private var isShowingChannelButton: Bool { | ||||
|         if case .channel = navigation.tabSelection { | ||||
|             return false | ||||
|         } | ||||
|  | ||||
|         return !inChannelView | ||||
|     } | ||||
|  | ||||
|     private var addToQueueButton: some View { | ||||
|         Button { | ||||
|             player.enqueueVideo(video) | ||||
|   | ||||
							
								
								
									
										28
									
								
								macOS/PictureInPictureDelegate.swift
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								macOS/PictureInPictureDelegate.swift
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| import AVKit | ||||
| import Foundation | ||||
|  | ||||
| final class PictureInPictureDelegate: NSObject, AVPlayerViewPictureInPictureDelegate { | ||||
|     var playerModel: PlayerModel! | ||||
|  | ||||
|     func playerViewShouldAutomaticallyDismissAtPicture(inPictureStart _: AVPlayerView) -> Bool { | ||||
|         false | ||||
|     } | ||||
|  | ||||
|     func playerViewWillStartPicture(inPicture _: AVPlayerView) { | ||||
|         playerModel.playingInPictureInPicture = true | ||||
|         playerModel.presentingPlayer = false | ||||
|     } | ||||
|  | ||||
|     func playerViewWillStopPicture(inPicture _: AVPlayerView) { | ||||
|         playerModel.playingInPictureInPicture = false | ||||
|         playerModel.presentPlayer() | ||||
|     } | ||||
|  | ||||
|     func playerView( | ||||
|         _: AVPlayerView, | ||||
|         restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: (Bool) -> Void | ||||
|     ) { | ||||
|         playerModel.presentingPlayer = true | ||||
|         completionHandler(true) | ||||
|     } | ||||
| } | ||||
| @@ -4,18 +4,24 @@ import SwiftUI | ||||
| final class PlayerViewController: NSViewController { | ||||
|     var playerModel: PlayerModel! | ||||
|     var playerView = AVPlayerView() | ||||
|     var pictureInPictureDelegate = PictureInPictureDelegate() | ||||
|  | ||||
|     override func viewDidDisappear() { | ||||
|         playerModel.pause() | ||||
|         if !playerModel.playingInPictureInPicture { | ||||
|             playerModel.pause() | ||||
|         } | ||||
|         super.viewDidDisappear() | ||||
|     } | ||||
|  | ||||
|     override func loadView() { | ||||
|         playerView.player = playerModel.player | ||||
|         pictureInPictureDelegate.playerModel = playerModel | ||||
|  | ||||
|         playerView.allowsPictureInPicturePlayback = true | ||||
|         playerView.showsFullScreenToggleButton = true | ||||
|  | ||||
|         playerView.pictureInPictureDelegate = pictureInPictureDelegate | ||||
|  | ||||
|         view = playerView | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Arkadiusz Fal
					Arkadiusz Fal