Implement thread reload after publishing reply (IOS-176)

This commit is contained in:
Marcus Kida 2023-12-13 15:09:37 +01:00
parent 7fb8fcaca1
commit 31796f1680
No known key found for this signature in database
GPG Key ID: 19FF64E08013CA40
9 changed files with 60 additions and 44 deletions

View File

@ -394,7 +394,6 @@
DB9282B225F3222800823B15 /* PickServerEmptyStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9282B125F3222800823B15 /* PickServerEmptyStateView.swift */; };
DB938EE62623F50700E5B6C1 /* ThreadViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB938EE52623F50700E5B6C1 /* ThreadViewController.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 */; };
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 */; };
@ -1117,7 +1116,6 @@
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>"; };
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>"; };
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>"; };
@ -2690,7 +2688,6 @@
DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */,
DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */,
DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */,
DB938F0226240EA300E5B6C1 /* CachedThreadViewModel.swift */,
DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */,
DB0FCB7F27968F70006C02E2 /* MastodonStatusThreadViewModel.swift */,
);
@ -3912,7 +3909,6 @@
2AB5011C299243FB00346092 /* WidgetExtension.intentdefinition in Sources */,
DB9F58F126EF512300E7BBE9 /* AccountListTableViewCell.swift in Sources */,
2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */,
DB938F0326240EA300E5B6C1 /* CachedThreadViewModel.swift in Sources */,
DBA5A53526F0A36A00CACBAA /* AddAccountTableViewCell.swift in Sources */,
2D35237A26256D920031AF25 /* NotificationSection.swift in Sources */,
DB98EB6927B21A7C0082E365 /* ReportResultActionTableViewCell.swift in Sources */,

View File

@ -19,12 +19,10 @@ extension DataSourceFacade {
status: MastodonStatus,
meta: Meta
) async throws {
let _redirectRecord = DataSourceFacade.status(
managedObjectContext: provider.context.managedObjectContext,
let redirectRecord = DataSourceFacade.status(
status: status,
target: target
)
guard let redirectRecord = _redirectRecord else { return }
await responseToMetaTextAction(
provider: provider,

View File

@ -13,10 +13,9 @@ import MastodonSDK
extension DataSourceFacade {
static func status(
managedObjectContext: NSManagedObjectContext,
status: MastodonStatus,
target: StatusTarget
) -> MastodonStatus? {
) -> MastodonStatus {
switch target {
case .status:
return status.reblog ?? status

View File

@ -18,13 +18,11 @@ extension DataSourceFacade {
status: MastodonStatus
) async {
let _root: StatusItem.Thread? = {
let _redirectRecord = DataSourceFacade.status(
managedObjectContext: provider.context.managedObjectContext,
let redirectRecord = DataSourceFacade.status(
status: status,
target: target
)
guard let redirectRecord = _redirectRecord else { return nil }
let threadContext = StatusItem.Thread.Context(status: redirectRecord)
return StatusItem.Thread.root(context: threadContext)
}()

View File

@ -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)
)
}
}

View File

@ -87,7 +87,7 @@ extension MastodonStatusThreadViewModel {
}
let items = self.__ancestors + newItems
self.__ancestors = items
self.__ancestors = items.removingDuplicates()
}
func appendDescendant(
@ -122,7 +122,7 @@ extension MastodonStatusThreadViewModel {
guard !items.contains(item) else { continue }
items.append(item)
}
self.__descendants = items
self.__descendants = items.removingDuplicates()
}
}

View File

@ -55,12 +55,13 @@ extension ThreadViewController: DataSourceProvider {
}
private func handle(status: MastodonStatus) {
viewModel.mastodonStatusThreadViewModel.ancestors.handle(status: status, for: viewModel)
viewModel.mastodonStatusThreadViewModel.descendants.handle(status: status, for: viewModel)
viewModel.mastodonStatusThreadViewModel.ancestors.handleUpdate(status: status, for: viewModel)
viewModel.mastodonStatusThreadViewModel.descendants.handleUpdate(status: status, for: viewModel)
}
func delete(status: MastodonStatus) {
assertionFailure("Needs implementation")
viewModel.mastodonStatusThreadViewModel.ancestors.handleDelete(status: status, for: viewModel)
viewModel.mastodonStatusThreadViewModel.descendants.handleDelete(status: status, for: viewModel)
}
@MainActor
@ -70,7 +71,7 @@ extension ThreadViewController: DataSourceProvider {
}
private extension [StatusItem] {
mutating func handle(status: MastodonStatus, for viewModel: ThreadViewModel) {
mutating func handleUpdate(status: MastodonStatus, for viewModel: ThreadViewModel) {
for (index, ancestor) in enumerated() {
switch ancestor {
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
}
}
}
}

View File

@ -115,8 +115,10 @@ extension ThreadViewModel.LoadThreadState {
class NoMore: ThreadViewModel.LoadThreadState {
override func isValidNextState(_ stateClass: AnyClass) -> Bool {
return false
switch stateClass {
case is Loading.Type: return true
default: return false
}
}
}
}

View File

@ -82,8 +82,15 @@ class ThreadViewModel {
context.publisherService
.statusPublishResult
.sink { [weak self] value in
if case let Result.success(result) = value, case StatusPublishResult.edit = result {
self?.hasPendingStatusEditReload = true
if case let Result.success(result) = value {
switch result {
case .edit:
self?.hasPendingStatusEditReload = true
case .post:
guard let self else { return }
self.loadThreadStateMachine.enter(LoadThreadState.Loading.self)
}
}
}
.store(in: &disposeBag)