mirror of
https://github.com/yattee/yattee.git
synced 2024-12-24 22:43:41 +00:00
Add PiP for iOS
This commit is contained in:
parent
0c7f963378
commit
0d6f481470
@ -36,8 +36,9 @@ final class AVPlayerBackend: PlayerBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private(set) var avPlayer = AVPlayer()
|
private(set) var avPlayer = AVPlayer()
|
||||||
|
|
||||||
var controller: AppleAVPlayerViewController?
|
var controller: AppleAVPlayerViewController?
|
||||||
|
var enterPiPOnPlay = false
|
||||||
|
var switchToMPVOnPipClose = false
|
||||||
|
|
||||||
private var asset: AVURLAsset?
|
private var asset: AVURLAsset?
|
||||||
private var composition = AVMutableComposition()
|
private var composition = AVMutableComposition()
|
||||||
@ -535,14 +536,27 @@ final class AVPlayerBackend: PlayerBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if player.timeControlStatus != .waitingToPlayAtSpecifiedRate {
|
if player.timeControlStatus != .waitingToPlayAtSpecifiedRate {
|
||||||
|
if let controller = self.model.pipController {
|
||||||
|
if controller.isPictureInPicturePossible {
|
||||||
|
if self.enterPiPOnPlay {
|
||||||
|
self.enterPiPOnPlay = false
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.model.pipController?.startPictureInPicture()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
self?.model.objectWillChange.send()
|
self?.model.objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if player.timeControlStatus == .playing, player.rate != self.model.currentRate {
|
if player.timeControlStatus == .playing {
|
||||||
|
if player.rate != self.model.currentRate {
|
||||||
player.rate = self.model.currentRate
|
player.rate = self.model.currentRate
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
if player.timeControlStatus == .playing {
|
if player.timeControlStatus == .playing {
|
||||||
|
@ -41,7 +41,9 @@ final class MPVBackend: PlayerBackend {
|
|||||||
updateControlsIsPlaying()
|
updateControlsIsPlaying()
|
||||||
|
|
||||||
#if !os(macOS)
|
#if !os(macOS)
|
||||||
UIApplication.shared.isIdleTimerDisabled = model.presentingPlayer && isPlaying
|
DispatchQueue.main.async {
|
||||||
|
UIApplication.shared.isIdleTimerDisabled = self.model.presentingPlayer && self.isPlaying
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}}
|
}}
|
||||||
var playerItemDuration: CMTime?
|
var playerItemDuration: CMTime?
|
||||||
|
35
Model/Player/PiPDelegate.swift
Normal file
35
Model/Player/PiPDelegate.swift
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import AVKit
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
final class PiPDelegate: NSObject, AVPictureInPictureControllerDelegate {
|
||||||
|
var player: PlayerModel!
|
||||||
|
|
||||||
|
func pictureInPictureController(
|
||||||
|
_: AVPictureInPictureController,
|
||||||
|
failedToStartPictureInPictureWithError error: Error
|
||||||
|
) {
|
||||||
|
print(error.localizedDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pictureInPictureControllerWillStartPictureInPicture(_: AVPictureInPictureController) {}
|
||||||
|
|
||||||
|
func pictureInPictureControllerDidStartPictureInPicture(_: AVPictureInPictureController) {}
|
||||||
|
|
||||||
|
func pictureInPictureControllerDidStopPictureInPicture(_: AVPictureInPictureController) {
|
||||||
|
if player?.avPlayerBackend.switchToMPVOnPipClose ?? false {
|
||||||
|
DispatchQueue.main.async { [weak player] in
|
||||||
|
player?.avPlayerBackend.switchToMPVOnPipClose = false
|
||||||
|
player?.saveTime { [weak player] in
|
||||||
|
player?.changeActiveBackend(from: .appleAVPlayer, to: .mpv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pictureInPictureControllerWillStopPictureInPicture(_: AVPictureInPictureController) {}
|
||||||
|
|
||||||
|
func pictureInPictureController(
|
||||||
|
_: AVPictureInPictureController,
|
||||||
|
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler _: @escaping (Bool) -> Void
|
||||||
|
) {}
|
||||||
|
}
|
@ -83,6 +83,8 @@ final class PlayerModel: ObservableObject {
|
|||||||
var context: NSManagedObjectContext = PersistenceController.shared.container.viewContext
|
var context: NSManagedObjectContext = PersistenceController.shared.container.viewContext
|
||||||
|
|
||||||
@Published var playingInPictureInPicture = false
|
@Published var playingInPictureInPicture = false
|
||||||
|
var pipController: AVPictureInPictureController?
|
||||||
|
var pipDelegate = PiPDelegate()
|
||||||
|
|
||||||
@Published var presentingErrorDetails = false
|
@Published var presentingErrorDetails = false
|
||||||
var playerError: Error? { didSet {
|
var playerError: Error? { didSet {
|
||||||
@ -102,6 +104,9 @@ final class PlayerModel: ObservableObject {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private var currentArtwork: MPMediaItemArtwork?
|
private var currentArtwork: MPMediaItemArtwork?
|
||||||
|
#if !os(macOS)
|
||||||
|
var playerLayerView: PlayerLayerView!
|
||||||
|
#endif
|
||||||
|
|
||||||
init(accounts: AccountsModel? = nil, comments: CommentsModel? = nil, controls: PlayerControlsModel? = nil) {
|
init(accounts: AccountsModel? = nil, comments: CommentsModel? = nil, controls: PlayerControlsModel? = nil) {
|
||||||
self.accounts = accounts ?? AccountsModel()
|
self.accounts = accounts ?? AccountsModel()
|
||||||
|
@ -1,25 +1,14 @@
|
|||||||
|
import AVKit
|
||||||
import Defaults
|
import Defaults
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AppleAVPlayerView: UIViewControllerRepresentable {
|
struct AppleAVPlayerView: UIViewRepresentable {
|
||||||
@EnvironmentObject<CommentsModel> private var comments
|
|
||||||
@EnvironmentObject<NavigationModel> private var navigation
|
|
||||||
@EnvironmentObject<PlayerModel> private var player
|
@EnvironmentObject<PlayerModel> private var player
|
||||||
@EnvironmentObject<SubscriptionsModel> private var subscriptions
|
|
||||||
|
|
||||||
func makeUIViewController(context _: Context) -> UIViewController {
|
func makeUIView(context _: Context) -> some UIView {
|
||||||
let controller = AppleAVPlayerViewController()
|
player.playerLayerView = PlayerLayerView(frame: .zero)
|
||||||
|
return player.playerLayerView
|
||||||
controller.commentsModel = comments
|
|
||||||
controller.navigationModel = navigation
|
|
||||||
controller.playerModel = player
|
|
||||||
controller.subscriptionsModel = subscriptions
|
|
||||||
player.avPlayerBackend.controller = controller
|
|
||||||
|
|
||||||
return controller
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUIViewController(_: UIViewController, context _: Context) {
|
func updateUIView(_: UIViewType, context _: Context) {}
|
||||||
player.rebuildTVMenu()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -173,6 +173,9 @@ struct PlayerControls: View {
|
|||||||
HStack {
|
HStack {
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
fullscreenButton
|
fullscreenButton
|
||||||
|
#if os(iOS)
|
||||||
|
pipButton
|
||||||
|
#endif
|
||||||
rateButton
|
rateButton
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -235,6 +238,26 @@ struct PlayerControls: View {
|
|||||||
.init(get: { player.currentRate }, set: { rate in player.currentRate = rate })
|
.init(get: { player.currentRate }, set: { rate in player.currentRate = rate })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var pipButton: some View {
|
||||||
|
button("PiP", systemImage: "pip") {
|
||||||
|
if player.activeBackend == .mpv {
|
||||||
|
player.avPlayerBackend.switchToMPVOnPipClose = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if player.activeBackend != PlayerBackendType.appleAVPlayer {
|
||||||
|
player.saveTime {
|
||||||
|
player.changeActiveBackend(from: .mpv, to: .appleAVPlayer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||||
|
print(player.pipController?.isPictureInPicturePossible ?? false ? "possible" : "NOT possible")
|
||||||
|
player.avPlayerBackend.enterPiPOnPlay = true
|
||||||
|
player.pipController?.startPictureInPicture()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var mediumButtonsBar: some View {
|
var mediumButtonsBar: some View {
|
||||||
HStack {
|
HStack {
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
|
23
Shared/Player/PlayerLayerView.swift
Normal file
23
Shared/Player/PlayerLayerView.swift
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import AVFoundation
|
||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
final class PlayerLayerView: UIView {
|
||||||
|
var playerLayer = AVPlayerLayer()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
layer.addSublayer(playerLayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, unavailable)
|
||||||
|
required init?(coder _: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
playerLayer.frame = bounds
|
||||||
|
}
|
||||||
|
}
|
@ -226,6 +226,17 @@ struct VideoPlayerView: View {
|
|||||||
})
|
})
|
||||||
case .appleAVPlayer:
|
case .appleAVPlayer:
|
||||||
player.avPlayerView
|
player.avPlayerView
|
||||||
|
#if os(iOS)
|
||||||
|
.onAppear {
|
||||||
|
player.pipController = .init(playerLayer: player.playerLayerView.playerLayer)
|
||||||
|
let pipDelegate = PiPDelegate()
|
||||||
|
pipDelegate.player = player
|
||||||
|
|
||||||
|
player.pipDelegate = pipDelegate
|
||||||
|
player.pipController!.delegate = pipDelegate
|
||||||
|
player.playerLayerView.playerLayer.player = player.avPlayerBackend.avPlayer
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
|
@ -190,6 +190,11 @@
|
|||||||
372915E62687E3B900F5A35B /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
372915E62687E3B900F5A35B /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
||||||
372915E72687E3B900F5A35B /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
372915E72687E3B900F5A35B /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
||||||
372915E82687E3B900F5A35B /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
372915E82687E3B900F5A35B /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
|
||||||
|
372D85DE283841B800FF3C7D /* PiPDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373031F428383A89000CFD59 /* PiPDelegate.swift */; };
|
||||||
|
372D85DF283842EC00FF3C7D /* PiPDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373031F428383A89000CFD59 /* PiPDelegate.swift */; };
|
||||||
|
372D85E0283842EE00FF3C7D /* PlayerLayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373031F22838388A000CFD59 /* PlayerLayerView.swift */; };
|
||||||
|
373031F32838388A000CFD59 /* PlayerLayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373031F22838388A000CFD59 /* PlayerLayerView.swift */; };
|
||||||
|
373031F528383A89000CFD59 /* PiPDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373031F428383A89000CFD59 /* PiPDelegate.swift */; };
|
||||||
3730D8A02712E2B70020ED53 /* NowPlayingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3730D89F2712E2B70020ED53 /* NowPlayingView.swift */; };
|
3730D8A02712E2B70020ED53 /* NowPlayingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3730D89F2712E2B70020ED53 /* NowPlayingView.swift */; };
|
||||||
3730F75A2733481E00F385FC /* RelatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373197D82732015300EF734F /* RelatedView.swift */; };
|
3730F75A2733481E00F385FC /* RelatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373197D82732015300EF734F /* RelatedView.swift */; };
|
||||||
373197D92732015300EF734F /* RelatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373197D82732015300EF734F /* RelatedView.swift */; };
|
373197D92732015300EF734F /* RelatedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373197D82732015300EF734F /* RelatedView.swift */; };
|
||||||
@ -864,6 +869,8 @@
|
|||||||
3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisualEffectBlur-iOS.swift"; sourceTree = "<group>"; };
|
3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisualEffectBlur-iOS.swift"; sourceTree = "<group>"; };
|
||||||
3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = "<group>"; };
|
3729037D2739E47400EA99F6 /* MenuCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuCommands.swift; sourceTree = "<group>"; };
|
||||||
372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; };
|
372915E52687E3B900F5A35B /* Defaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Defaults.swift; sourceTree = "<group>"; };
|
||||||
|
373031F22838388A000CFD59 /* PlayerLayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerLayerView.swift; sourceTree = "<group>"; };
|
||||||
|
373031F428383A89000CFD59 /* PiPDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PiPDelegate.swift; sourceTree = "<group>"; };
|
||||||
3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = "<group>"; };
|
3730D89F2712E2B70020ED53 /* NowPlayingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingView.swift; sourceTree = "<group>"; };
|
||||||
373197D82732015300EF734F /* RelatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedView.swift; sourceTree = "<group>"; };
|
373197D82732015300EF734F /* RelatedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelatedView.swift; sourceTree = "<group>"; };
|
||||||
37319F0427103F94004ECCD0 /* PlayerQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerQueue.swift; sourceTree = "<group>"; };
|
37319F0427103F94004ECCD0 /* PlayerQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerQueue.swift; sourceTree = "<group>"; };
|
||||||
@ -1351,6 +1358,7 @@
|
|||||||
37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */,
|
37BE0BCE26A0E2D50092E2DB /* VideoPlayerView.swift */,
|
||||||
37E8B0EB27B326C00024006F /* TimelineView.swift */,
|
37E8B0EB27B326C00024006F /* TimelineView.swift */,
|
||||||
37F9619A27BD89E000058149 /* TapRecognizerViewModifier.swift */,
|
37F9619A27BD89E000058149 /* TapRecognizerViewModifier.swift */,
|
||||||
|
373031F22838388A000CFD59 /* PlayerLayerView.swift */,
|
||||||
);
|
);
|
||||||
path = Player;
|
path = Player;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1439,6 +1447,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
37EBD8C227AF0D7C00F1C24B /* Backends */,
|
37EBD8C227AF0D7C00F1C24B /* Backends */,
|
||||||
|
373031F428383A89000CFD59 /* PiPDelegate.swift */,
|
||||||
37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */,
|
37B767DA2677C3CA0098BAA8 /* PlayerModel.swift */,
|
||||||
37319F0427103F94004ECCD0 /* PlayerQueue.swift */,
|
37319F0427103F94004ECCD0 /* PlayerQueue.swift */,
|
||||||
37CC3F44270CE30600608308 /* PlayerQueueItem.swift */,
|
37CC3F44270CE30600608308 /* PlayerQueueItem.swift */,
|
||||||
@ -2548,6 +2557,7 @@
|
|||||||
37EF9A76275BEB8E0043B585 /* CommentView.swift in Sources */,
|
37EF9A76275BEB8E0043B585 /* CommentView.swift in Sources */,
|
||||||
373C8FE4275B955100CB5936 /* CommentsPage.swift in Sources */,
|
373C8FE4275B955100CB5936 /* CommentsPage.swift in Sources */,
|
||||||
3700155B271B0D4D0049C794 /* PipedAPI.swift in Sources */,
|
3700155B271B0D4D0049C794 /* PipedAPI.swift in Sources */,
|
||||||
|
373031F32838388A000CFD59 /* PlayerLayerView.swift in Sources */,
|
||||||
37B044B726F7AB9000E1419D /* SettingsView.swift in Sources */,
|
37B044B726F7AB9000E1419D /* SettingsView.swift in Sources */,
|
||||||
377FC7E3267A084A00A6BBAF /* VideoCell.swift in Sources */,
|
377FC7E3267A084A00A6BBAF /* VideoCell.swift in Sources */,
|
||||||
37C3A251272366440087A57A /* ChannelPlaylistView.swift in Sources */,
|
37C3A251272366440087A57A /* ChannelPlaylistView.swift in Sources */,
|
||||||
@ -2600,6 +2610,7 @@
|
|||||||
3788AC2726F6840700F6BAA9 /* FavoriteItemView.swift in Sources */,
|
3788AC2726F6840700F6BAA9 /* FavoriteItemView.swift in Sources */,
|
||||||
375DFB5826F9DA010013F468 /* InstancesModel.swift in Sources */,
|
375DFB5826F9DA010013F468 /* InstancesModel.swift in Sources */,
|
||||||
3751BA8327E6914F007B1A60 /* ReturnYouTubeDislikeAPI.swift in Sources */,
|
3751BA8327E6914F007B1A60 /* ReturnYouTubeDislikeAPI.swift in Sources */,
|
||||||
|
373031F528383A89000CFD59 /* PiPDelegate.swift in Sources */,
|
||||||
37DD9DC62785D63A00539416 /* UIResponder+Extensions.swift in Sources */,
|
37DD9DC62785D63A00539416 /* UIResponder+Extensions.swift in Sources */,
|
||||||
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
37C3A24927235FAA0087A57A /* ChannelPlaylistCell.swift in Sources */,
|
||||||
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
373CFACB26966264003CB2C6 /* SearchQuery.swift in Sources */,
|
||||||
@ -2758,6 +2769,7 @@
|
|||||||
37A9965F26D6F9B9006E3224 /* FavoritesView.swift in Sources */,
|
37A9965F26D6F9B9006E3224 /* FavoritesView.swift in Sources */,
|
||||||
37F4AE7326828F0900BD60EA /* VerticalCells.swift in Sources */,
|
37F4AE7326828F0900BD60EA /* VerticalCells.swift in Sources */,
|
||||||
37001560271B12DD0049C794 /* SiestaConfiguration.swift in Sources */,
|
37001560271B12DD0049C794 /* SiestaConfiguration.swift in Sources */,
|
||||||
|
372D85DE283841B800FF3C7D /* PiPDelegate.swift in Sources */,
|
||||||
37B81AFD26D2C9C900675966 /* VideoDetailsPaddingModifier.swift in Sources */,
|
37B81AFD26D2C9C900675966 /* VideoDetailsPaddingModifier.swift in Sources */,
|
||||||
37C0697F2725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
37C0697F2725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
|
||||||
37A9965B26D6F8CA006E3224 /* HorizontalCells.swift in Sources */,
|
37A9965B26D6F8CA006E3224 /* HorizontalCells.swift in Sources */,
|
||||||
@ -3000,6 +3012,8 @@
|
|||||||
37B17DA0268A1F89006AEE9B /* VideoContextMenuView.swift in Sources */,
|
37B17DA0268A1F89006AEE9B /* VideoContextMenuView.swift in Sources */,
|
||||||
37BE0BD726A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */,
|
37BE0BD726A1D4A90092E2DB /* AppleAVPlayerViewController.swift in Sources */,
|
||||||
37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */,
|
37484C3326FCB8F900287258 /* AccountValidator.swift in Sources */,
|
||||||
|
372D85DF283842EC00FF3C7D /* PiPDelegate.swift in Sources */,
|
||||||
|
372D85E0283842EE00FF3C7D /* PlayerLayerView.swift in Sources */,
|
||||||
37CEE4C32677B697005A1EFE /* Stream.swift in Sources */,
|
37CEE4C32677B697005A1EFE /* Stream.swift in Sources */,
|
||||||
37F64FE626FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
37F64FE626FE70A60081B69E /* RedrawOnModifier.swift in Sources */,
|
||||||
37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
37B2631C2735EAAB00FE0D40 /* FavoriteResourceObserver.swift in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user