mirror of
https://github.com/yattee/yattee.git
synced 2025-08-06 10:44:06 +00:00
Use cache for loading player queue and history
This commit is contained in:
@@ -96,11 +96,6 @@ final class PlayerModel: ObservableObject {
|
||||
@Published var currentItem: PlayerQueueItem! { didSet { handleCurrentItemChange() } }
|
||||
@Published var videoBeingOpened: Video? { didSet { seek.reset() } }
|
||||
@Published var historyVideos = [Video]()
|
||||
@Published var queueItemBeingLoaded: PlayerQueueItem?
|
||||
@Published var queueItemsToLoad = [PlayerQueueItem]()
|
||||
@Published var historyItemBeingLoaded: Video.ID?
|
||||
@Published var historyItemsToLoad = [Watch]()
|
||||
|
||||
@Published var preservedTime: CMTime?
|
||||
|
||||
@Published var sponsorBlock = SponsorBlockAPI()
|
||||
|
@@ -165,7 +165,8 @@ extension PlayerModel {
|
||||
currentItem.playbackTime = time
|
||||
|
||||
let playTime = currentItem.shouldRestartPlaying ? CMTime.zero : time
|
||||
playerAPI(newItem.video).loadDetails(currentItem, failureHandler: { self.videoLoadFailureHandler($0, video: self.currentItem.video) }) { newItem in
|
||||
guard let video = newItem.video else { return }
|
||||
playerAPI(video).loadDetails(currentItem, failureHandler: { self.videoLoadFailureHandler($0, video: self.currentItem.video) }) { newItem in
|
||||
self.playItem(newItem, at: playTime)
|
||||
}
|
||||
}
|
||||
@@ -276,42 +277,40 @@ extension PlayerModel {
|
||||
|
||||
restoredQueue.append(contentsOf: Defaults[.queue])
|
||||
queue = restoredQueue.compactMap { $0 }
|
||||
queue.forEach { loadQueueVideoDetails($0) }
|
||||
}
|
||||
|
||||
func loadQueueVideoDetails(_ item: PlayerQueueItem) {
|
||||
guard !accounts.current.isNil, !item.hasDetailsLoaded, let video = item.video else { return }
|
||||
guard !accounts.current.isNil, !item.hasDetailsLoaded else { return }
|
||||
|
||||
let videoID = item.video?.videoID ?? item.videoID
|
||||
|
||||
if queueItemBeingLoaded == nil {
|
||||
logger.info("loading queue details: \(videoID)")
|
||||
queueItemBeingLoaded = item
|
||||
} else {
|
||||
logger.info("POSTPONING details load: \(videoID)")
|
||||
queueItemsToLoad.append(item)
|
||||
return
|
||||
}
|
||||
let video = item.video ?? Video(app: item.app ?? .local, instanceURL: item.instanceURL, videoID: videoID)
|
||||
|
||||
playerAPI(video)?.loadDetails(item, completionHandler: { [weak self] newItem in
|
||||
guard let self else { return }
|
||||
|
||||
self.queue.filter { $0.videoID == item.videoID }.forEach { item in
|
||||
let replaceQueueItem: (PlayerQueueItem) -> Void = { newItem in
|
||||
self.queue.filter { $0.videoID == videoID }.forEach { item in
|
||||
if let index = self.queue.firstIndex(of: item) {
|
||||
self.queue[index] = newItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.logger.info("LOADED queue details: \(videoID)")
|
||||
if let video = VideosCacheModel.shared.retrieveVideo(video.cacheKey) {
|
||||
var item = item
|
||||
item.id = UUID()
|
||||
item.video = video
|
||||
replaceQueueItem(item)
|
||||
return
|
||||
}
|
||||
|
||||
if self.queueItemBeingLoaded == item {
|
||||
self.logger.info("setting nothing loaded")
|
||||
self.queueItemBeingLoaded = nil
|
||||
}
|
||||
playerAPI(video)?
|
||||
.loadDetails(item, completionHandler: { [weak self] newItem in
|
||||
guard let self else { return }
|
||||
|
||||
if let item = self.queueItemsToLoad.popLast() {
|
||||
self.loadQueueVideoDetails(item)
|
||||
}
|
||||
})
|
||||
replaceQueueItem(newItem)
|
||||
|
||||
self.logger.info("LOADED queue details: \(videoID)")
|
||||
})
|
||||
}
|
||||
|
||||
private func videoLoadFailureHandler(_ error: RequestError, video: Video? = nil) {
|
||||
|
@@ -8,6 +8,8 @@ struct PlayerQueueItem: Hashable, Identifiable, Defaults.Serializable {
|
||||
var id = UUID()
|
||||
var video: Video!
|
||||
var videoID: Video.ID
|
||||
var app: VideosApp?
|
||||
var instanceURL: URL?
|
||||
var playbackTime: CMTime?
|
||||
var videoDuration: TimeInterval?
|
||||
|
||||
@@ -15,14 +17,25 @@ struct PlayerQueueItem: Hashable, Identifiable, Defaults.Serializable {
|
||||
.init(
|
||||
video,
|
||||
videoID: watch.videoID,
|
||||
app: watch.app,
|
||||
instanceURL: watch.instanceURL,
|
||||
playbackTime: CMTime.secondsInDefaultTimescale(watch.stoppedAt),
|
||||
videoDuration: watch.videoDuration
|
||||
)
|
||||
}
|
||||
|
||||
init(_ video: Video? = nil, videoID: Video.ID? = nil, playbackTime: CMTime? = nil, videoDuration: TimeInterval? = nil) {
|
||||
init(
|
||||
_ video: Video? = nil,
|
||||
videoID: Video.ID? = nil,
|
||||
app: VideosApp? = nil,
|
||||
instanceURL: URL? = nil,
|
||||
playbackTime: CMTime? = nil,
|
||||
videoDuration: TimeInterval? = nil
|
||||
) {
|
||||
self.video = video
|
||||
self.videoID = videoID ?? video!.videoID
|
||||
self.app = app
|
||||
self.instanceURL = instanceURL
|
||||
self.playbackTime = playbackTime
|
||||
self.videoDuration = videoDuration
|
||||
}
|
||||
|
@@ -33,6 +33,8 @@ struct PlayerQueueItemBridge: Defaults.Bridge {
|
||||
return [
|
||||
"localURL": localURL,
|
||||
"videoID": value.videoID,
|
||||
"app": (value.app ?? value.video.app)?.rawValue ?? "",
|
||||
"instanceURL": (value.instanceURL ?? value.video.instanceURL)?.absoluteString ?? "",
|
||||
"playbackTime": playbackTime,
|
||||
"videoDuration": videoDuration
|
||||
]
|
||||
@@ -41,6 +43,8 @@ struct PlayerQueueItemBridge: Defaults.Bridge {
|
||||
func deserialize(_ object: Serializable?) -> Value? {
|
||||
guard let object else { return nil }
|
||||
|
||||
var app: VideosApp?
|
||||
var instanceURL: URL?
|
||||
var playbackTime: CMTime?
|
||||
var videoDuration: TimeInterval?
|
||||
|
||||
@@ -57,6 +61,16 @@ struct PlayerQueueItemBridge: Defaults.Bridge {
|
||||
videoDuration = TimeInterval(duration)
|
||||
}
|
||||
|
||||
if let appString = object["app"],
|
||||
!appString.isEmpty
|
||||
{
|
||||
app = VideosApp(rawValue: appString)
|
||||
}
|
||||
|
||||
if let url = object["instanceURL"]?.url {
|
||||
instanceURL = url
|
||||
}
|
||||
|
||||
if let localUrlString = object["localURL"],
|
||||
!localUrlString.isEmpty,
|
||||
let localURL = URL(string: localUrlString)
|
||||
@@ -71,7 +85,10 @@ struct PlayerQueueItemBridge: Defaults.Bridge {
|
||||
guard let videoID = object["videoID"] else { return nil }
|
||||
|
||||
return PlayerQueueItem(
|
||||
.init(app: app ?? .local, instanceURL: instanceURL, videoID: videoID),
|
||||
videoID: videoID,
|
||||
app: app,
|
||||
instanceURL: instanceURL,
|
||||
playbackTime: playbackTime,
|
||||
videoDuration: videoDuration
|
||||
)
|
||||
|
Reference in New Issue
Block a user