2021-01-28 09:10:30 +01:00
|
|
|
//
|
|
|
|
// 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>?
|
|
|
|
|
2021-02-01 11:06:29 +01:00
|
|
|
let tootIDs = CurrentValueSubject<[String], Never>([])
|
2021-01-28 09:10:30 +01:00
|
|
|
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)
|
|
|
|
|
2021-02-01 11:06:29 +01:00
|
|
|
tootIDs
|
2021-01-28 09:10:30 +01:00
|
|
|
.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")
|
|
|
|
}
|
|
|
|
}
|