mirror of
https://github.com/yattee/yattee.git
synced 2025-08-06 10:44:06 +00:00
Unwatched videos in subscriptions
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import Cache
|
||||
import CoreData
|
||||
import Foundation
|
||||
import Siesta
|
||||
import SwiftyJSON
|
||||
@@ -9,11 +10,15 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
@Published var isLoading = false
|
||||
@Published var videos = [Video]()
|
||||
@Published private var page = 1
|
||||
@Published var unwatched = [Account: Int]()
|
||||
|
||||
private var cacheModel = FeedCacheModel.shared
|
||||
private var accounts = AccountsModel.shared
|
||||
|
||||
var storage: Storage<String, JSON>?
|
||||
|
||||
private var backgroundContext = PersistenceController.shared.container.newBackgroundContext()
|
||||
|
||||
var feed: Resource? {
|
||||
accounts.api.feed(page)
|
||||
}
|
||||
@@ -78,7 +83,8 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
self.videos.append(contentsOf: videos)
|
||||
} else {
|
||||
self.videos = videos
|
||||
FeedCacheModel.shared.storeFeed(account: account, videos: self.videos)
|
||||
self.cacheModel.storeFeed(account: account, videos: self.videos)
|
||||
self.calculateUnwatchedFeed()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,9 +105,87 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
loadFeed(force: true, paginating: true)
|
||||
}
|
||||
|
||||
func calculateUnwatchedFeed() {
|
||||
guard let account = accounts.current else { return }
|
||||
let feed = cacheModel.retrieveFeed(account: account)
|
||||
guard !feed.isEmpty else { return }
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
let watched = self.watchFetchRequestResult(feed, context: self.backgroundContext).filter { $0.finished }.count
|
||||
let unwatched = feed.count - watched
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self else { return }
|
||||
if unwatched != self.unwatched[account] {
|
||||
self.unwatched[account] = unwatched
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func markAllFeedAsWatched() {
|
||||
guard let account = accounts.current else { return }
|
||||
guard !videos.isEmpty else { return }
|
||||
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self else { return }
|
||||
self.videos.forEach { Watch.markAsWatched(videoID: $0.videoID, account: account, duration: $0.length, context: self.backgroundContext) }
|
||||
|
||||
self.calculateUnwatchedFeed()
|
||||
}
|
||||
}
|
||||
|
||||
func markAllFeedAsUnwatched() {
|
||||
guard accounts.current != nil,
|
||||
!videos.isEmpty else { return }
|
||||
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
let watches = self.watchFetchRequestResult(self.videos, context: self.backgroundContext)
|
||||
watches.forEach { self.backgroundContext.delete($0) }
|
||||
|
||||
try? self.backgroundContext.save()
|
||||
|
||||
self.calculateUnwatchedFeed()
|
||||
}
|
||||
}
|
||||
|
||||
func watchFetchRequestResult(_ videos: [Video], context: NSManagedObjectContext) -> [Watch] {
|
||||
let watchFetchRequest = Watch.fetchRequest()
|
||||
watchFetchRequest.predicate = NSPredicate(format: "videoID IN %@", videos.map(\.videoID) as [String])
|
||||
return (try? context.fetch(watchFetchRequest)) ?? []
|
||||
}
|
||||
|
||||
func playUnwatchedFeed() {
|
||||
guard let account = accounts.current else { return }
|
||||
let videos = cacheModel.retrieveFeed(account: account)
|
||||
guard !videos.isEmpty else { return }
|
||||
|
||||
let watches = watchFetchRequestResult(videos, context: backgroundContext)
|
||||
let watchesIDs = watches.map(\.videoID)
|
||||
let unwatched = videos.filter { video in
|
||||
if !watchesIDs.contains(video.videoID) {
|
||||
return true
|
||||
}
|
||||
|
||||
if let watch = watches.first(where: { $0.videoID == video.videoID }),
|
||||
watch.finished
|
||||
{
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
guard !unwatched.isEmpty else { return }
|
||||
PlayerModel.shared.play(unwatched)
|
||||
}
|
||||
|
||||
var feedTime: Date? {
|
||||
if let account = accounts.current {
|
||||
return FeedCacheModel.shared.getFeedTime(account: account)
|
||||
return cacheModel.getFeedTime(account: account)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -113,7 +197,7 @@ final class FeedModel: ObservableObject, CacheModel {
|
||||
|
||||
private func loadCachedFeed() {
|
||||
guard let account = accounts.current else { return }
|
||||
let cache = FeedCacheModel.shared.retrieveFeed(account: account)
|
||||
let cache = cacheModel.retrieveFeed(account: account)
|
||||
if !cache.isEmpty {
|
||||
DispatchQueue.main.async(qos: .userInteractive) { [weak self] in
|
||||
self?.videos = cache
|
||||
|
Reference in New Issue
Block a user