diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 733f91e66..e08f34198 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -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 = ""; }; DB938EE52623F50700E5B6C1 /* ThreadViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewController.swift; sourceTree = ""; }; DB938EEC2623F79B00E5B6C1 /* ThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadViewModel.swift; sourceTree = ""; }; - DB938F0226240EA300E5B6C1 /* CachedThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachedThreadViewModel.swift; sourceTree = ""; }; DB938F0826240F3C00E5B6C1 /* RemoteThreadViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteThreadViewModel.swift; sourceTree = ""; }; DB938F0E2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThreadViewModel+LoadThreadState.swift"; sourceTree = ""; }; DB938F1E2624382F00E5B6C1 /* ThreadViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ThreadViewModel+Diffable.swift"; sourceTree = ""; }; @@ -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 */, diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Meta.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Meta.swift index 3cb21fb0f..5140639fd 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Meta.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Meta.swift @@ -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, diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Model.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Model.swift index 42e44d832..d5deef32d 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Model.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Model.swift @@ -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 diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Thread.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Thread.swift index 61075d436..169acc073 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Thread.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Thread.swift @@ -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) }() diff --git a/Mastodon/Scene/Thread/CachedThreadViewModel.swift b/Mastodon/Scene/Thread/CachedThreadViewModel.swift deleted file mode 100644 index 9301d1876..000000000 --- a/Mastodon/Scene/Thread/CachedThreadViewModel.swift +++ /dev/null @@ -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) - ) - } -} diff --git a/Mastodon/Scene/Thread/MastodonStatusThreadViewModel.swift b/Mastodon/Scene/Thread/MastodonStatusThreadViewModel.swift index 08e1c7c0f..9e6018ccd 100644 --- a/Mastodon/Scene/Thread/MastodonStatusThreadViewModel.swift +++ b/Mastodon/Scene/Thread/MastodonStatusThreadViewModel.swift @@ -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() } } diff --git a/Mastodon/Scene/Thread/ThreadViewController+DataSourceProvider.swift b/Mastodon/Scene/Thread/ThreadViewController+DataSourceProvider.swift index 14b5f18a2..a2f83a1dd 100644 --- a/Mastodon/Scene/Thread/ThreadViewController+DataSourceProvider.swift +++ b/Mastodon/Scene/Thread/ThreadViewController+DataSourceProvider.swift @@ -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 + } + } + } } diff --git a/Mastodon/Scene/Thread/ThreadViewModel+LoadThreadState.swift b/Mastodon/Scene/Thread/ThreadViewModel+LoadThreadState.swift index dff7dc047..7c9998746 100644 --- a/Mastodon/Scene/Thread/ThreadViewModel+LoadThreadState.swift +++ b/Mastodon/Scene/Thread/ThreadViewModel+LoadThreadState.swift @@ -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 + } } } - } diff --git a/Mastodon/Scene/Thread/ThreadViewModel.swift b/Mastodon/Scene/Thread/ThreadViewModel.swift index b4bf03d93..c12360215 100644 --- a/Mastodon/Scene/Thread/ThreadViewModel.swift +++ b/Mastodon/Scene/Thread/ThreadViewModel.swift @@ -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)