Better loading and handling streams

This commit is contained in:
Arkadiusz Fal 2021-12-19 17:56:47 +01:00
parent 1fbb0cfa80
commit cef0b2594a
5 changed files with 48 additions and 52 deletions

View File

@ -6,6 +6,14 @@ final class InstancesModel: ObservableObject {
Defaults[.instances]
}
static var forPlayer: Instance? {
guard let id = Defaults[.playerInstanceID] else {
return nil
}
return InstancesModel.find(id)
}
var lastUsed: Instance? {
guard let id = Defaults[.lastInstanceID] else {
return nil

View File

@ -27,16 +27,14 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
self.account = account
signedIn = false
if account.anonymous {
validInstance = true
return
}
validInstance = false
validInstance = account.anonymous
configure()
if !account.anonymous {
validate()
}
}
func validate() {
validateInstance()

View File

@ -26,7 +26,7 @@ final class PlayerModel: ObservableObject {
@Published var stream: Stream?
@Published var currentRate: Float = 1.0 { didSet { player.rate = currentRate } }
@Published var availableStreams = [Stream]() { didSet { rebuildTVMenu() } }
@Published var availableStreams = [Stream]() { didSet { handleAvailableStreamsChange() }}
@Published var streamSelection: Stream? { didSet { rebuildTVMenu() } }
@Published var queue = [PlayerQueueItem]() { didSet { Defaults[.queue] = queue } }
@ -171,10 +171,24 @@ final class PlayerModel: ObservableObject {
}
}
private func pauseOnPlayerDismiss() {
if !playingInPictureInPicture, !presentingPlayer {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.pause()
private func handleAvailableStreamsChange() {
rebuildTVMenu()
guard stream.isNil else {
return
}
guard let stream = preferredStream(availableStreams) else {
return
}
streamSelection = stream
playStream(
stream,
of: currentVideo!,
preservingTime: !currentItem.playbackTime.isNil
)
}
}
}
}

View File

@ -54,21 +54,10 @@ extension PlayerModel {
preservedTime = currentItem.playbackTime
restoreLoadedChannel()
loadAvailableStreams(currentVideo!) { streams in
guard let stream = self.preferredStream(streams) else {
return
loadAvailableStreams(currentVideo!)
}
self.streamSelection = stream
self.playStream(
stream,
of: self.currentVideo!,
preservingTime: !self.currentItem.playbackTime.isNil
)
}
}
private func preferredStream(_ streams: [Stream]) -> Stream? {
func preferredStream(_ streams: [Stream]) -> Stream? {
let quality = Defaults[.quality]
var streams = streams

View File

@ -15,21 +15,20 @@ extension PlayerModel {
availableStreams.sorted(by: streamsSorter)
}
func loadAvailableStreams(
_ video: Video,
completionHandler: @escaping ([Stream]) -> Void = { _ in }
) {
func loadAvailableStreams(_ video: Video) {
availableStreams = []
var instancesWithLoadedStreams = [Instance]()
let playerInstance = InstancesModel.forPlayer ?? InstancesModel.all.first
InstancesModel.all.forEach { instance in
fetchStreams(instance.anonymous.video(video.videoID), instance: instance, video: video) { _ in
self.completeIfAllInstancesLoaded(
instance: instance,
streams: self.availableStreams,
instancesWithLoadedStreams: &instancesWithLoadedStreams,
completionHandler: completionHandler
)
guard !playerInstance.isNil else {
return
}
logger.info("loading streams from \(playerInstance!.description)")
fetchStreams(playerInstance!.anonymous.video(video.videoID), instance: playerInstance!, video: video) { _ in
InstancesModel.all.filter { $0 != playerInstance }.forEach { instance in
self.logger.info("loading streams from \(instance.description)")
self.fetchStreams(instance.anonymous.video(video.videoID), instance: instance, video: video)
}
}
}
@ -45,25 +44,13 @@ extension PlayerModel {
.onSuccess { response in
if let video: Video = response.typedContent() {
self.availableStreams += self.streamsWithInstance(instance: instance, streams: video.streams)
} else {
self.logger.critical("no streams available from \(instance.description)")
}
}
.onCompletion(onCompletion)
}
private func completeIfAllInstancesLoaded(
instance: Instance,
streams: [Stream],
instancesWithLoadedStreams: inout [Instance],
completionHandler: @escaping ([Stream]) -> Void
) {
instancesWithLoadedStreams.append(instance)
rebuildTVMenu()
if InstancesModel.all.count == instancesWithLoadedStreams.count {
completionHandler(streams.sorted { $0.kind < $1.kind })
}
}
func streamsWithInstance(instance: Instance, streams: [Stream]) -> [Stream] {
streams.map { stream in
stream.instance = instance