mastodon-ios/Mastodon/Scene/Thread/ThreadViewModel.swift

120 lines
4.0 KiB
Swift
Raw Normal View History

2021-04-13 13:46:42 +02:00
//
// ThreadViewModel.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021-4-12.
//
import UIKit
import Combine
import CoreData
import CoreDataStack
import GameplayKit
import MastodonSDK
2021-07-23 13:10:27 +02:00
import MastodonMeta
import MastodonAsset
2022-10-08 07:43:06 +02:00
import MastodonCore
import MastodonLocalization
2021-04-13 13:46:42 +02:00
class ThreadViewModel {
var disposeBag = Set<AnyCancellable>()
var rootItemObserver: AnyCancellable?
2021-04-13 13:46:42 +02:00
// input
let context: AppContext
let authContext: AuthContext
let mastodonStatusThreadViewModel: MastodonStatusThreadViewModel
2021-04-13 13:46:42 +02:00
// output
var diffableDataSource: UITableViewDiffableDataSource<StatusSection, StatusItem>?
@Published var root: StatusItem.Thread?
@Published var threadContext: ThreadContext?
@Published var hasPendingStatusEditReload = false
let onDismiss = PassthroughSubject<MastodonStatus, Never>()
let onEdit = PassthroughSubject<MastodonStatus, Never>()
2021-04-13 13:46:42 +02:00
private(set) lazy var loadThreadStateMachine: GKStateMachine = {
let stateMachine = GKStateMachine(states: [
LoadThreadState.Initial(viewModel: self),
LoadThreadState.Loading(viewModel: self),
LoadThreadState.Fail(viewModel: self),
LoadThreadState.NoMore(viewModel: self),
])
stateMachine.enter(LoadThreadState.Initial.self)
return stateMachine
}()
@Published var navigationBarTitle: MastodonMetaContent?
2021-04-13 13:46:42 +02:00
init(
context: AppContext,
authContext: AuthContext,
optionalRoot: StatusItem.Thread?
) {
2021-04-13 13:46:42 +02:00
self.context = context
self.authContext = authContext
self.root = optionalRoot
self.mastodonStatusThreadViewModel = MastodonStatusThreadViewModel(context: context)
// end init
2023-11-22 12:32:04 +01:00
$root
2021-04-13 13:46:42 +02:00
.receive(on: DispatchQueue.main)
.sink { [weak self] root in
guard let self = self else { return }
guard case let .root(threadContext) = root else { return }
2023-11-22 12:32:04 +01:00
let status = threadContext.status
2021-04-13 13:46:42 +02:00
// bind threadContext
self.threadContext = .init(
2023-11-22 12:32:04 +01:00
domain: authContext.mastodonAuthenticationBox.domain, //status.domain,
statusID: status.id,
2023-11-22 12:32:04 +01:00
replyToID: status.entity.inReplyToID
)
2021-04-13 13:46:42 +02:00
// bind titleView
self.navigationBarTitle = {
2023-11-22 12:32:04 +01:00
let title = L10n.Scene.Thread.title(status.entity.account.displayNameWithFallback)
let content = MastodonContent(content: title, emojis: status.entity.account.emojis?.asDictionary ?? [:])
return try? MastodonMetaContent.convert(document: content)
}()
2021-04-13 13:46:42 +02:00
}
.store(in: &disposeBag)
context.publisherService
.statusPublishResult
.sink { [weak self] value in
guard let self else { return }
if case let Result.success(result) = value {
switch result {
case let .edit(content):
let status = content.value
let mastodonStatus = MastodonStatus.fromEntity(status)
self.hasPendingStatusEditReload = true
if status.id == root?.record.id {
self.root = .root(context: .init(status: mastodonStatus))
}
self.loadThreadStateMachine.enter(LoadThreadState.Loading.self)
self.onEdit.send(mastodonStatus)
case .post:
self.loadThreadStateMachine.enter(LoadThreadState.Loading.self)
}
}
}
.store(in: &disposeBag)
2021-04-13 13:46:42 +02:00
}
}
extension ThreadViewModel {
struct ThreadContext {
2021-04-13 13:46:42 +02:00
let domain: String
let statusID: Mastodon.Entity.Status.ID
let replyToID: Mastodon.Entity.Status.ID?
}
}