diff --git a/Pachyderm/Model/Status.swift b/Pachyderm/Model/Status.swift index e039ddf2..7b89739d 100644 --- a/Pachyderm/Model/Status.swift +++ b/Pachyderm/Model/Status.swift @@ -38,8 +38,8 @@ public class Status: Decodable { public let bookmarked: Bool? public let card: Card? - public static func getContext(_ status: Status) -> Request { - return Request(method: .get, path: "/api/v1/statuses/\(status.id)/context") + public static func getContext(_ statusID: String) -> Request { + return Request(method: .get, path: "/api/v1/statuses/\(statusID)/context") } public static func getCard(_ status: Status) -> Request { diff --git a/Tusker/Screens/Conversation/ConversationTableViewController.swift b/Tusker/Screens/Conversation/ConversationTableViewController.swift index fb5c99cc..8fdb1db4 100644 --- a/Tusker/Screens/Conversation/ConversationTableViewController.swift +++ b/Tusker/Screens/Conversation/ConversationTableViewController.swift @@ -42,6 +42,13 @@ class ConversationTableViewController: EnhancedTableViewController { fatalError("init(coder:) has not been implemented") } + deinit { + mastodonController.persistentContainer.status(for: mainStatusID)?.decrementReferenceCount() + for (id, _) in statuses { + mastodonController.persistentContainer.status(for: id)?.decrementReferenceCount() + } + } + override func viewDidLoad() { super.viewDidLoad() @@ -58,32 +65,42 @@ class ConversationTableViewController: EnhancedTableViewController { statuses = [(mainStatusID, mainStatusState)] - guard let mainStatus = mastodonController.cache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") } - - let request = Status.getContext(mainStatus) + guard let mainStatus = self.mastodonController.persistentContainer.status(for: self.mainStatusID) else { + fatalError("Missing cached status \(self.mainStatusID)") + } + let mainStatusInReplyToID = mainStatus.inReplyToID + mainStatus.incrementReferenceCount() + + let request = Status.getContext(mainStatusID) mastodonController.run(request) { response in guard case let .success(context, _) = response else { fatalError() } - let parents = self.getDirectParents(of: mainStatus, from: context.ancestors) - self.mastodonController.cache.addAll(statuses: parents) - self.mastodonController.cache.addAll(statuses: context.descendants) - self.statuses = parents.map { ($0.id, .unknown) } + self.statuses + context.descendants.map { ($0.id, .unknown) } - let indexPath = IndexPath(row: parents.count, section: 0) - DispatchQueue.main.async { - self.tableView.scrollToRow(at: indexPath, at: .middle, animated: false) + + let parents = self.getDirectParents(inReplyTo: mainStatusInReplyToID, from: context.ancestors) + let parentStatuses = context.ancestors.filter { parents.contains($0.id) } + self.mastodonController.persistentContainer.addAll(statuses: parentStatuses) { + self.mastodonController.persistentContainer.addAll(statuses: context.descendants) { + self.statuses = parents.map { ($0, .unknown) } + self.statuses + context.descendants.map { ($0.id, .unknown) } + let indexPath = IndexPath(row: parents.count, section: 0) + DispatchQueue.main.async { + self.tableView.scrollToRow(at: indexPath, at: .middle, animated: false) + } + } } } } - func getDirectParents(of status: Status, from statuses: [Status]) -> [Status] { + func getDirectParents(inReplyTo inReplyToID: String?, from statuses: [Status]) -> [String] { var statuses = statuses - var parents: [Status] = [] - var currentStatus: Status? = status - while currentStatus != nil { - guard let index = statuses.firstIndex(where: { $0.id == currentStatus!.inReplyToID }) else { break } - let parent = statuses.remove(at: index) - parents.insert(parent, at: 0) - currentStatus = parent + var parents = [String]() + + var parentID: String? = inReplyToID + + while parentID != nil, let parentIndex = statuses.firstIndex(where: { $0.id == parentID }) { + let parentStatus = statuses.remove(at: parentIndex) + parents.insert(parentStatus.id, at: 0) + parentID = parentStatus.inReplyToID } + return parents } @@ -169,7 +186,7 @@ extension ConversationTableViewController: StatusTableViewCellDelegate { extension ConversationTableViewController: UITableViewDataSourcePrefetching { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { for indexPath in indexPaths { - guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { continue } + guard let status = mastodonController.persistentContainer.status(for: statuses[indexPath.row].id) else { continue } _ = ImageCache.avatars.get(status.account.avatar, completion: nil) for attachment in status.attachments { _ = ImageCache.attachments.get(attachment.url, completion: nil) @@ -179,7 +196,7 @@ extension ConversationTableViewController: UITableViewDataSourcePrefetching { func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { for indexPath in indexPaths { - guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { continue } + guard let status = mastodonController.persistentContainer.status(for: statuses[indexPath.row].id) else { continue } ImageCache.avatars.cancelWithoutCallback(status.account.avatar) for attachment in status.attachments { ImageCache.attachments.cancelWithoutCallback(attachment.url) diff --git a/Tusker/Views/Status/ConversationMainStatusTableViewCell.swift b/Tusker/Views/Status/ConversationMainStatusTableViewCell.swift index e6dcec75..bf7ec6ac 100644 --- a/Tusker/Views/Status/ConversationMainStatusTableViewCell.swift +++ b/Tusker/Views/Status/ConversationMainStatusTableViewCell.swift @@ -40,11 +40,11 @@ class ConversationMainStatusTableViewCell: BaseStatusTableViewCell { override func updateUI(statusID: String, state: StatusState) { super.updateUI(statusID: statusID, state: state) - guard let status = mastodonController.cache.status(for: statusID) else { fatalError() } + guard let status = mastodonController.persistentContainer.status(for: statusID) else { fatalError() } var timestampAndClientText = ConversationMainStatusTableViewCell.dateFormatter.string(from: status.createdAt) if let application = status.application { - timestampAndClientText += " • \(application.name)" + timestampAndClientText += " • \(application)" } timestampAndClientLabel.text = timestampAndClientText }