Kurdtvs-Live-Kurdish-TV-Kur.../Mastodon/Scene/PublicTimeline/PublicTimelineViewModel.swift

96 lines
3.1 KiB
Swift

//
// PublicTimelineViewModel.swift
// Mastodon
//
// Created by sxiaojian on 2021/1/27.
//
import os.log
import UIKit
import GameplayKit
import Combine
import CoreData
import CoreDataStack
import MastodonSDK
import AlamofireImage
class PublicTimelineViewModel: NSObject {
var disposeBag = Set<AnyCancellable>()
// input
let context: AppContext
let fetchedResultsController: NSFetchedResultsController<Toot>
weak var tableView: UITableView?
// output
var diffableDataSource: UITableViewDiffableDataSource<TimelineSection, Item>?
let tootIDs = CurrentValueSubject<[String], Never>([])
let items = CurrentValueSubject<[Item], Never>([])
var cellFrameCache = NSCache<NSNumber, NSValue>()
init(context: AppContext) {
self.context = context
self.fetchedResultsController = {
let fetchRequest = Toot.sortedFetchRequest
fetchRequest.predicate = Toot.predicate(idStrs: [])
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.fetchBatchSize = 20
let controller = NSFetchedResultsController(
fetchRequest: fetchRequest,
managedObjectContext: context.managedObjectContext,
sectionNameKeyPath: nil,
cacheName: nil
)
return controller
}()
super.init()
self.fetchedResultsController.delegate = self
items
.receive(on: DispatchQueue.main)
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
.sink { [weak self] items in
guard let self = self else { return }
guard let diffableDataSource = self.diffableDataSource else { return }
os_log("%{public}s[%{public}ld], %{public}s: items did change", ((#file as NSString).lastPathComponent), #line, #function)
var snapshot = NSDiffableDataSourceSnapshot<TimelineSection, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items)
diffableDataSource.apply(snapshot, animatingDifferences: !items.isEmpty)
}
.store(in: &disposeBag)
tootIDs
.receive(on: DispatchQueue.main)
.sink { [weak self] ids in
guard let self = self else { return }
self.fetchedResultsController.fetchRequest.predicate = Toot.predicate(idStrs: ids)
do {
try self.fetchedResultsController.performFetch()
} catch {
assertionFailure(error.localizedDescription)
}
}
.store(in: &disposeBag)
}
deinit {
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
}
}
extension PublicTimelineViewModel {
func fetchLatest() -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Toot]>, Error> {
return context.apiService.publicTimeline(count: 20, domain: "mstdn.jp")
}
}