Implement thread reload after publishing reply (IOS-176)
This commit is contained in:
parent
7fb8fcaca1
commit
31796f1680
|
@ -394,7 +394,6 @@
|
||||||
DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */; };
|
DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */; };
|
||||||
DB938EE62623F50700E5B6C1 /* ThreadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */; };
|
DB938EE62623F50700E5B6C1 /* ThreadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */; };
|
||||||
DB938EED2623F79B00E5B6C1 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */; };
|
DB938EED2623F79B00E5B6C1 /* ThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */; };
|
||||||
DB938F0326240EA300E5B6C1 /* CachedThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F0226240EA300E5B6C1 /* CachedThreadViewModel.swift */; };
|
|
||||||
DB938F0926240F3C00E5B6C1 /* RemoteThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */; };
|
DB938F0926240F3C00E5B6C1 /* RemoteThreadViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */; };
|
||||||
DB938F0F2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */; };
|
DB938F0F2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */; };
|
||||||
DB938F1F2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */; };
|
DB938F1F2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */; };
|
||||||
|
@ -1117,7 +1116,6 @@
|
||||||
DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerEmptyStateView.swift; sourceTree = "<group>"; };
|
DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerEmptyStateView.swift; sourceTree = "<group>"; };
|
||||||
DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewController.swift; sourceTree = "<group>"; };
|
DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewController.swift; sourceTree = "<group>"; };
|
||||||
DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewModel.swift; sourceTree = "<group>"; };
|
DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewModel.swift; sourceTree = "<group>"; };
|
||||||
DB938F0226240EA300E5B6C1 /* CachedThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachedThreadViewModel.swift; sourceTree = "<group>"; };
|
|
||||||
DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteThreadViewModel.swift; sourceTree = "<group>"; };
|
DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteThreadViewModel.swift; sourceTree = "<group>"; };
|
||||||
DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThreadViewModel+LoadThreadState.swift"; sourceTree = "<group>"; };
|
DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThreadViewModel+LoadThreadState.swift"; sourceTree = "<group>"; };
|
||||||
DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThreadViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThreadViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -2690,7 +2688,6 @@
|
||||||
DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */,
|
DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */,
|
||||||
DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */,
|
DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */,
|
||||||
DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */,
|
DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */,
|
||||||
DB938F0226240EA300E5B6C1 /* CachedThreadViewModel.swift */,
|
|
||||||
DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */,
|
DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */,
|
||||||
DB0FCB7F27968F70006C02E2 /* MastodonStatusThreadViewModel.swift */,
|
DB0FCB7F27968F70006C02E2 /* MastodonStatusThreadViewModel.swift */,
|
||||||
);
|
);
|
||||||
|
@ -3912,7 +3909,6 @@
|
||||||
2AB5011C299243FB00346092 /* WidgetExtension.intentdefinition in Sources */,
|
2AB5011C299243FB00346092 /* WidgetExtension.intentdefinition in Sources */,
|
||||||
DB9F58F126EF512300E7BBE9 /* AccountListTableViewCell.swift in Sources */,
|
DB9F58F126EF512300E7BBE9 /* AccountListTableViewCell.swift in Sources */,
|
||||||
2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */,
|
2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */,
|
||||||
DB938F0326240EA300E5B6C1 /* CachedThreadViewModel.swift in Sources */,
|
|
||||||
DBA5A53526F0A36A00CACBAA /* AddAccountTableViewCell.swift in Sources */,
|
DBA5A53526F0A36A00CACBAA /* AddAccountTableViewCell.swift in Sources */,
|
||||||
2D35237A26256D920031AF25 /* NotificationSection.swift in Sources */,
|
2D35237A26256D920031AF25 /* NotificationSection.swift in Sources */,
|
||||||
DB98EB6927B21A7C0082E365 /* ReportResultActionTableViewCell.swift in Sources */,
|
DB98EB6927B21A7C0082E365 /* ReportResultActionTableViewCell.swift in Sources */,
|
||||||
|
|
|
@ -19,12 +19,10 @@ extension DataSourceFacade {
|
||||||
status: MastodonStatus,
|
status: MastodonStatus,
|
||||||
meta: Meta
|
meta: Meta
|
||||||
) async throws {
|
) async throws {
|
||||||
let _redirectRecord = DataSourceFacade.status(
|
let redirectRecord = DataSourceFacade.status(
|
||||||
managedObjectContext: provider.context.managedObjectContext,
|
|
||||||
status: status,
|
status: status,
|
||||||
target: target
|
target: target
|
||||||
)
|
)
|
||||||
guard let redirectRecord = _redirectRecord else { return }
|
|
||||||
|
|
||||||
await responseToMetaTextAction(
|
await responseToMetaTextAction(
|
||||||
provider: provider,
|
provider: provider,
|
||||||
|
|
|
@ -13,10 +13,9 @@ import MastodonSDK
|
||||||
|
|
||||||
extension DataSourceFacade {
|
extension DataSourceFacade {
|
||||||
static func status(
|
static func status(
|
||||||
managedObjectContext: NSManagedObjectContext,
|
|
||||||
status: MastodonStatus,
|
status: MastodonStatus,
|
||||||
target: StatusTarget
|
target: StatusTarget
|
||||||
) -> MastodonStatus? {
|
) -> MastodonStatus {
|
||||||
switch target {
|
switch target {
|
||||||
case .status:
|
case .status:
|
||||||
return status.reblog ?? status
|
return status.reblog ?? status
|
||||||
|
|
|
@ -18,13 +18,11 @@ extension DataSourceFacade {
|
||||||
status: MastodonStatus
|
status: MastodonStatus
|
||||||
) async {
|
) async {
|
||||||
let _root: StatusItem.Thread? = {
|
let _root: StatusItem.Thread? = {
|
||||||
let _redirectRecord = DataSourceFacade.status(
|
let redirectRecord = DataSourceFacade.status(
|
||||||
managedObjectContext: provider.context.managedObjectContext,
|
|
||||||
status: status,
|
status: status,
|
||||||
target: target
|
target: target
|
||||||
)
|
)
|
||||||
guard let redirectRecord = _redirectRecord else { return nil }
|
|
||||||
|
|
||||||
let threadContext = StatusItem.Thread.Context(status: redirectRecord)
|
let threadContext = StatusItem.Thread.Context(status: redirectRecord)
|
||||||
return StatusItem.Thread.root(context: threadContext)
|
return StatusItem.Thread.root(context: threadContext)
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
//
|
|
||||||
// CachedThreadViewModel.swift
|
|
||||||
// Mastodon
|
|
||||||
//
|
|
||||||
// Created by MainasuK Cirno on 2021-4-12.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import MastodonSDK
|
|
||||||
import MastodonCore
|
|
||||||
|
|
||||||
final class CachedThreadViewModel: ThreadViewModel {
|
|
||||||
init(context: AppContext, authContext: AuthContext, status: MastodonStatus) {
|
|
||||||
let threadContext = StatusItem.Thread.Context(status: status)
|
|
||||||
super.init(
|
|
||||||
context: context,
|
|
||||||
authContext: authContext,
|
|
||||||
optionalRoot: .root(context: threadContext)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -87,7 +87,7 @@ extension MastodonStatusThreadViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = self.__ancestors + newItems
|
let items = self.__ancestors + newItems
|
||||||
self.__ancestors = items
|
self.__ancestors = items.removingDuplicates()
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendDescendant(
|
func appendDescendant(
|
||||||
|
@ -122,7 +122,7 @@ extension MastodonStatusThreadViewModel {
|
||||||
guard !items.contains(item) else { continue }
|
guard !items.contains(item) else { continue }
|
||||||
items.append(item)
|
items.append(item)
|
||||||
}
|
}
|
||||||
self.__descendants = items
|
self.__descendants = items.removingDuplicates()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,12 +55,13 @@ extension ThreadViewController: DataSourceProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handle(status: MastodonStatus) {
|
private func handle(status: MastodonStatus) {
|
||||||
viewModel.mastodonStatusThreadViewModel.ancestors.handle(status: status, for: viewModel)
|
viewModel.mastodonStatusThreadViewModel.ancestors.handleUpdate(status: status, for: viewModel)
|
||||||
viewModel.mastodonStatusThreadViewModel.descendants.handle(status: status, for: viewModel)
|
viewModel.mastodonStatusThreadViewModel.descendants.handleUpdate(status: status, for: viewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func delete(status: MastodonStatus) {
|
func delete(status: MastodonStatus) {
|
||||||
assertionFailure("Needs implementation")
|
viewModel.mastodonStatusThreadViewModel.ancestors.handleDelete(status: status, for: viewModel)
|
||||||
|
viewModel.mastodonStatusThreadViewModel.descendants.handleDelete(status: status, for: viewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
@ -70,7 +71,7 @@ extension ThreadViewController: DataSourceProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension [StatusItem] {
|
private extension [StatusItem] {
|
||||||
mutating func handle(status: MastodonStatus, for viewModel: ThreadViewModel) {
|
mutating func handleUpdate(status: MastodonStatus, for viewModel: ThreadViewModel) {
|
||||||
for (index, ancestor) in enumerated() {
|
for (index, ancestor) in enumerated() {
|
||||||
switch ancestor {
|
switch ancestor {
|
||||||
case let .feed(record):
|
case let .feed(record):
|
||||||
|
@ -105,4 +106,40 @@ private extension [StatusItem] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutating func handleDelete(status: MastodonStatus, for viewModel: ThreadViewModel) {
|
||||||
|
for (index, ancestor) in enumerated() {
|
||||||
|
switch ancestor {
|
||||||
|
case let .feed(record):
|
||||||
|
if record.status?.id == status.id {
|
||||||
|
self.remove(at: index)
|
||||||
|
}
|
||||||
|
case let.feedLoader(record):
|
||||||
|
if record.status?.id == status.id {
|
||||||
|
self.remove(at: index)
|
||||||
|
}
|
||||||
|
case let .status(record):
|
||||||
|
if record.id == status.id {
|
||||||
|
self.remove(at: index)
|
||||||
|
}
|
||||||
|
case let .thread(thread):
|
||||||
|
switch thread {
|
||||||
|
case let .root(context):
|
||||||
|
if context.status.id == status.id {
|
||||||
|
self.remove(at: index)
|
||||||
|
}
|
||||||
|
case let .reply(context):
|
||||||
|
if context.status.id == status.id {
|
||||||
|
self.remove(at: index)
|
||||||
|
}
|
||||||
|
case let .leaf(context):
|
||||||
|
if context.status.id == status.id {
|
||||||
|
self.remove(at: index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .bottomLoader, .topLoader:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,10 @@ extension ThreadViewModel.LoadThreadState {
|
||||||
|
|
||||||
class NoMore: ThreadViewModel.LoadThreadState {
|
class NoMore: ThreadViewModel.LoadThreadState {
|
||||||
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
|
||||||
return false
|
switch stateClass {
|
||||||
|
case is Loading.Type: return true
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,15 @@ class ThreadViewModel {
|
||||||
context.publisherService
|
context.publisherService
|
||||||
.statusPublishResult
|
.statusPublishResult
|
||||||
.sink { [weak self] value in
|
.sink { [weak self] value in
|
||||||
if case let Result.success(result) = value, case StatusPublishResult.edit = result {
|
if case let Result.success(result) = value {
|
||||||
self?.hasPendingStatusEditReload = true
|
switch result {
|
||||||
|
case .edit:
|
||||||
|
self?.hasPendingStatusEditReload = true
|
||||||
|
case .post:
|
||||||
|
guard let self else { return }
|
||||||
|
self.loadThreadStateMachine.enter(LoadThreadState.Loading.self)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
Loading…
Reference in New Issue