112 lines
2.8 KiB
Swift
112 lines
2.8 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 AVKit
|
|
import Factory
|
|
import JellyfinAPI
|
|
import Logging
|
|
import SwiftUI
|
|
|
|
// TODO: remove
|
|
|
|
struct NativeVideoPlayer: View {
|
|
|
|
@Environment(\.presentationCoordinator)
|
|
private var presentationCoordinator
|
|
|
|
@InjectedObject(\.mediaPlayerManager)
|
|
private var manager: MediaPlayerManager
|
|
|
|
@LazyState
|
|
private var proxy: AVMediaPlayerProxy
|
|
|
|
@Router
|
|
private var router
|
|
|
|
init() {
|
|
self._proxy = .init(wrappedValue: AVMediaPlayerProxy())
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
|
|
Color.black
|
|
|
|
switch manager.state {
|
|
case .playback:
|
|
NativeVideoPlayerView(proxy: proxy)
|
|
default:
|
|
ProgressView()
|
|
}
|
|
}
|
|
.onAppear {
|
|
manager.proxy = proxy
|
|
manager.start()
|
|
}
|
|
.preference(key: IsStatusBarHiddenKey.self, value: true)
|
|
.backport
|
|
.onChange(of: presentationCoordinator.isPresented) { _, isPresented in
|
|
Container.shared.mediaPlayerManager.reset()
|
|
guard !isPresented else { return }
|
|
manager.stop()
|
|
}
|
|
.alert(
|
|
L10n.error,
|
|
isPresented: .constant(manager.error != nil)
|
|
) {
|
|
Button(L10n.close, role: .cancel) {
|
|
Container.shared.mediaPlayerManager.reset()
|
|
router.dismiss()
|
|
}
|
|
} message: {
|
|
// TODO: localize
|
|
Text("Unable to load this item.")
|
|
}
|
|
}
|
|
}
|
|
|
|
extension NativeVideoPlayer {
|
|
|
|
private struct NativeVideoPlayerView: UIViewControllerRepresentable {
|
|
|
|
let proxy: AVMediaPlayerProxy
|
|
|
|
func makeUIViewController(context: Context) -> UINativeVideoPlayerViewController {
|
|
UINativeVideoPlayerViewController(proxy: proxy)
|
|
}
|
|
|
|
func updateUIViewController(_ uiViewController: UINativeVideoPlayerViewController, context: Context) {}
|
|
}
|
|
|
|
private class UINativeVideoPlayerViewController: AVPlayerViewController {
|
|
|
|
private let proxy: AVMediaPlayerProxy
|
|
|
|
init(proxy: AVMediaPlayerProxy) {
|
|
self.proxy = proxy
|
|
|
|
super.init(nibName: nil, bundle: nil)
|
|
|
|
player = proxy.player
|
|
|
|
player?.allowsExternalPlayback = true
|
|
player?.appliesMediaSelectionCriteriaAutomatically = false
|
|
allowsPictureInPicturePlayback = true
|
|
|
|
#if !os(tvOS)
|
|
updatesNowPlayingInfoCenter = false
|
|
#endif
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|
|
}
|