From cd78287a87724239f7c604d69a5feea96c0b4175 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 11 May 2020 17:57:50 -0400 Subject: [PATCH] Fix crash when viewing instance public timelines Use a CoreData in-memory store for public timelines. --- Pachyderm/Model/Status.swift | 6 +++--- Tusker/Controllers/MastodonController.swift | 6 ++++-- .../CoreData/MastodonCachePersistentStore.swift | 15 ++++++++++++--- Tusker/CoreData/StatusMO.swift | 4 ++-- .../Timeline/InstanceTimelineViewController.swift | 2 +- Tusker/Views/Status/BaseStatusTableViewCell.swift | 4 ++-- 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Pachyderm/Model/Status.swift b/Pachyderm/Model/Status.swift index e7e62884..734e8ad1 100644 --- a/Pachyderm/Model/Status.swift +++ b/Pachyderm/Model/Status.swift @@ -8,7 +8,7 @@ import Foundation -public final class Status: StatusProtocol, Decodable { +public final class Status: /*StatusProtocol,*/ Decodable { public let id: String public let uri: String public let url: URL? @@ -23,8 +23,8 @@ public final class Status: StatusProtocol, Decodable { // public let repliesCount: Int public let reblogsCount: Int public let favouritesCount: Int - public let reblogged: Bool - public let favourited: Bool + public let reblogged: Bool? + public let favourited: Bool? public let muted: Bool? public let sensitive: Bool public let spoilerText: String diff --git a/Tusker/Controllers/MastodonController.swift b/Tusker/Controllers/MastodonController.swift index d4c64152..c3dcaaf9 100644 --- a/Tusker/Controllers/MastodonController.swift +++ b/Tusker/Controllers/MastodonController.swift @@ -30,7 +30,8 @@ class MastodonController { } } - private(set) lazy var persistentContainer = MastodonCachePersistentStore(for: self) + private let transient: Bool + private(set) lazy var persistentContainer = MastodonCachePersistentStore(for: accountInfo, transient: transient) let instanceURL: URL var accountInfo: LocalData.UserAccountInfo? @@ -40,10 +41,11 @@ class MastodonController { var account: Account! var instance: Instance! - init(instanceURL: URL) { + init(instanceURL: URL, transient: Bool = false) { self.instanceURL = instanceURL self.accountInfo = nil self.client = Client(baseURL: instanceURL) + self.transient = transient } func run(_ request: Request, completion: @escaping Client.Callback) { diff --git a/Tusker/CoreData/MastodonCachePersistentStore.swift b/Tusker/CoreData/MastodonCachePersistentStore.swift index fc6b80e9..30651066 100644 --- a/Tusker/CoreData/MastodonCachePersistentStore.swift +++ b/Tusker/CoreData/MastodonCachePersistentStore.swift @@ -22,9 +22,18 @@ class MastodonCachePersistentStore: NSPersistentContainer { let statusSubject = PassthroughSubject() let accountSubject = PassthroughSubject() - - init(for controller: MastodonController) { - super.init(name: "\(controller.accountInfo!.id)_cache", managedObjectModel: MastodonCachePersistentStore.managedObjectModel) + + init(for accountInfo: LocalData.UserAccountInfo?, transient: Bool = false) { + if transient { + super.init(name: "transient_cache", managedObjectModel: MastodonCachePersistentStore.managedObjectModel) + + let storeDescription = NSPersistentStoreDescription() + storeDescription.type = NSInMemoryStoreType + persistentStoreDescriptions = [storeDescription] + } else { + super.init(name: "\(accountInfo!.id)_cache", managedObjectModel: MastodonCachePersistentStore.managedObjectModel) + } + loadPersistentStores { (description, error) in if let error = error { fatalError("Unable to load persistent store: \(error)") diff --git a/Tusker/CoreData/StatusMO.swift b/Tusker/CoreData/StatusMO.swift index aa54b71e..82c0728e 100644 --- a/Tusker/CoreData/StatusMO.swift +++ b/Tusker/CoreData/StatusMO.swift @@ -106,7 +106,7 @@ extension StatusMO { self.content = status.content self.createdAt = status.createdAt self.emojis = status.emojis - self.favourited = status.favourited + self.favourited = status.favourited ?? false self.favouritesCount = status.favouritesCount self.hashtags = status.hashtags self.inReplyToAccountID = status.inReplyToAccountID @@ -115,7 +115,7 @@ extension StatusMO { self.mentions = status.mentions self.muted = status.muted ?? false self.pinnedInternal = status.pinned ?? false - self.reblogged = status.reblogged + self.reblogged = status.reblogged ?? false self.reblogsCount = status.reblogsCount self.sensitive = status.sensitive self.spoilerText = status.spoilerText diff --git a/Tusker/Screens/Timeline/InstanceTimelineViewController.swift b/Tusker/Screens/Timeline/InstanceTimelineViewController.swift index 83b45411..5852d1a6 100644 --- a/Tusker/Screens/Timeline/InstanceTimelineViewController.swift +++ b/Tusker/Screens/Timeline/InstanceTimelineViewController.swift @@ -37,7 +37,7 @@ class InstanceTimelineViewController: TimelineTableViewController { self.instanceURL = url // the timeline VC only stores a weak reference to it, so we need to store a strong reference to make sure it's not released immediately - instanceMastodonController = MastodonController(instanceURL: url) + instanceMastodonController = MastodonController(instanceURL: url, transient: true) super.init(for: .public(local: true), mastodonController: instanceMastodonController) diff --git a/Tusker/Views/Status/BaseStatusTableViewCell.swift b/Tusker/Views/Status/BaseStatusTableViewCell.swift index e68ba80f..159e6db8 100644 --- a/Tusker/Views/Status/BaseStatusTableViewCell.swift +++ b/Tusker/Views/Status/BaseStatusTableViewCell.swift @@ -261,7 +261,7 @@ class BaseStatusTableViewCell: UITableViewCell { mastodonController.run(request) { response in DispatchQueue.main.async { if case let .success(newStatus, _) = response { - self.favorited = newStatus.favourited + self.favorited = newStatus.favourited ?? false self.mastodonController.persistentContainer.addOrUpdate(status: newStatus, incrementReferenceCount: false) UIImpactFeedbackGenerator(style: .light).impactOccurred() } else { @@ -286,7 +286,7 @@ class BaseStatusTableViewCell: UITableViewCell { mastodonController.run(request) { response in DispatchQueue.main.async { if case let .success(newStatus, _) = response { - self.reblogged = newStatus.reblogged + self.reblogged = newStatus.reblogged ?? false self.mastodonController.persistentContainer.addOrUpdate(status: newStatus, incrementReferenceCount: false) UIImpactFeedbackGenerator(style: .light).impactOccurred() } else {