Kurdtvs-Live-Kurdish-TV-Kur.../Mastodon/Scene/Notification/NotificationViewModel.swift

124 lines
4.9 KiB
Swift
Raw Normal View History

2021-04-12 10:31:53 +02:00
//
// NotificationViewModel.swift
// Mastodon
//
// Created by sxiaojian on 2021/4/12.
//
import Combine
import CoreData
import CoreDataStack
2021-04-15 04:16:30 +02:00
import Foundation
2021-04-12 10:31:53 +02:00
import GameplayKit
2021-04-13 15:31:49 +02:00
import MastodonSDK
2021-04-15 04:16:30 +02:00
import UIKit
2021-04-12 10:31:53 +02:00
2021-04-15 04:16:30 +02:00
final class NotificationViewModel: NSObject {
2021-04-12 10:31:53 +02:00
var disposeBag = Set<AnyCancellable>()
// input
let context: AppContext
2021-04-13 15:31:49 +02:00
weak var tableView: UITableView?
2021-04-12 10:31:53 +02:00
weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate?
2021-04-13 15:31:49 +02:00
let viewDidLoad = PassthroughSubject<Void, Never>()
2021-04-15 04:16:30 +02:00
let selectedIndex = CurrentValueSubject<Int, Never>(0)
let noMoreNotification = CurrentValueSubject<Bool, Never>(false)
2021-04-12 10:31:53 +02:00
let activeMastodonAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
let fetchedResultsController: NSFetchedResultsController<MastodonNotification>!
let notificationPredicate = CurrentValueSubject<NSPredicate?, Never>(nil)
let cellFrameCache = NSCache<NSNumber, NSValue>()
let isFetchingLatestNotification = CurrentValueSubject<Bool, Never>(false)
2021-04-15 04:16:30 +02:00
// output
2021-04-12 10:31:53 +02:00
var diffableDataSource: UITableViewDiffableDataSource<NotificationSection, NotificationItem>!
// top loader
private(set) lazy var loadLatestStateMachine: GKStateMachine = {
// exclude timeline middle fetcher state
let stateMachine = GKStateMachine(states: [
LoadLatestState.Initial(viewModel: self),
LoadLatestState.Loading(viewModel: self),
LoadLatestState.Fail(viewModel: self),
LoadLatestState.Idle(viewModel: self),
])
stateMachine.enter(LoadLatestState.Initial.self)
return stateMachine
}()
lazy var loadLatestStateMachinePublisher = CurrentValueSubject<LoadLatestState?, Never>(nil)
2021-04-14 13:04:11 +02:00
// bottom loader
private(set) lazy var loadoldestStateMachine: GKStateMachine = {
// exclude timeline middle fetcher state
let stateMachine = GKStateMachine(states: [
LoadOldestState.Initial(viewModel: self),
LoadOldestState.Loading(viewModel: self),
LoadOldestState.Fail(viewModel: self),
LoadOldestState.Idle(viewModel: self),
LoadOldestState.NoMore(viewModel: self),
])
stateMachine.enter(LoadOldestState.Initial.self)
return stateMachine
}()
2021-04-15 04:16:30 +02:00
2021-04-14 13:04:11 +02:00
lazy var loadOldestStateMachinePublisher = CurrentValueSubject<LoadOldestState?, Never>(nil)
init(context: AppContext) {
2021-04-12 10:31:53 +02:00
self.context = context
self.activeMastodonAuthenticationBox = CurrentValueSubject(context.authenticationService.activeMastodonAuthenticationBox.value)
self.fetchedResultsController = {
let fetchRequest = MastodonNotification.sortedFetchRequest
fetchRequest.returnsObjectsAsFaults = false
2021-04-15 04:16:30 +02:00
fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(MastodonNotification.status), #keyPath(MastodonNotification.account)]
2021-04-12 10:31:53 +02:00
let controller = NSFetchedResultsController(
fetchRequest: fetchRequest,
managedObjectContext: context.managedObjectContext,
sectionNameKeyPath: nil,
cacheName: nil
)
return controller
}()
super.init()
2021-04-15 04:16:30 +02:00
fetchedResultsController.delegate = self
2021-04-12 10:31:53 +02:00
context.authenticationService.activeMastodonAuthenticationBox
2021-04-13 15:31:49 +02:00
.sink(receiveValue: { [weak self] box in
guard let self = self else { return }
self.activeMastodonAuthenticationBox.value = box
if let domain = box?.domain {
self.notificationPredicate.value = MastodonNotification.predicate(domain: domain)
}
})
2021-04-12 10:31:53 +02:00
.store(in: &disposeBag)
notificationPredicate
2021-04-15 04:16:30 +02:00
.compactMap { $0 }
2021-04-12 10:31:53 +02:00
.sink { [weak self] predicate in
guard let self = self else { return }
self.fetchedResultsController.fetchRequest.predicate = predicate
do {
2021-04-14 09:00:48 +02:00
self.diffableDataSource?.defaultRowAnimation = .fade
2021-04-12 10:31:53 +02:00
try self.fetchedResultsController.performFetch()
2021-04-14 09:00:48 +02:00
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
guard let self = self else { return }
self.diffableDataSource?.defaultRowAnimation = .automatic
}
2021-04-12 10:31:53 +02:00
} catch {
assertionFailure(error.localizedDescription)
}
}
.store(in: &disposeBag)
2021-04-13 15:31:49 +02:00
2021-04-15 04:16:30 +02:00
viewDidLoad
2021-04-13 15:31:49 +02:00
.sink { [weak self] in
guard let domain = self?.activeMastodonAuthenticationBox.value?.domain else { return }
self?.notificationPredicate.value = MastodonNotification.predicate(domain: domain)
}
.store(in: &disposeBag)
2021-04-12 10:31:53 +02:00
}
}