diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 26978680..cce6ba02 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -20,7 +20,6 @@ 04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */; }; 04DACE8E212CC7CC009840C4 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DACE8D212CC7CC009840C4 /* ImageCache.swift */; }; 04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04ED00B021481ED800567C53 /* SteppedProgressView.swift */; }; - D6028B9B2150811100F223B9 /* MastodonCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6028B9A2150811100F223B9 /* MastodonCache.swift */; }; D60309B52419D4F100A465FF /* ComposeAttachmentsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */; }; D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */; }; D60E2F272442372B005F8713 /* StatusMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F232442372B005F8713 /* StatusMO.swift */; }; @@ -133,6 +132,7 @@ D64BC19223C271D9000D0238 /* MastodonActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64BC19123C271D9000D0238 /* MastodonActivity.swift */; }; D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; }; D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; }; + D64D8CA92463B494006B0BAA /* CachedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D8CA82463B494006B0BAA /* CachedDictionary.swift */; }; D64F80E2215875CC00BEF393 /* XCBActionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64F80E1215875CC00BEF393 /* XCBActionType.swift */; }; D6538945214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */; }; D65A37F321472F300087646E /* SwiftSoup.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6BED16E212663DA00F02DA0 /* SwiftSoup.framework */; }; @@ -310,7 +310,6 @@ 04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarViewController.swift; sourceTree = ""; }; 04DACE8D212CC7CC009840C4 /* ImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCache.swift; sourceTree = ""; }; 04ED00B021481ED800567C53 /* SteppedProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SteppedProgressView.swift; sourceTree = ""; }; - D6028B9A2150811100F223B9 /* MastodonCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonCache.swift; sourceTree = ""; }; D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentsViewController.swift; sourceTree = ""; }; D60A4FFB238B726A008AC647 /* StatusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusState.swift; sourceTree = ""; }; D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseStatusTableViewCell.swift; sourceTree = ""; }; @@ -424,6 +423,7 @@ D64BC19123C271D9000D0238 /* MastodonActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonActivity.swift; sourceTree = ""; }; D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = ""; }; D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = ""; }; + D64D8CA82463B494006B0BAA /* CachedDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CachedDictionary.swift; sourceTree = ""; }; D64F80E1215875CC00BEF393 /* XCBActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCBActionType.swift; sourceTree = ""; }; D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSwipeActionProvider.swift; sourceTree = ""; }; D65F612D23AE990C00F3CFD3 /* Embassy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Embassy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1248,9 +1248,9 @@ D64D0AAC2128D88B005A6F37 /* LocalData.swift */, D627FF75217E923E00CC0648 /* DraftsManager.swift */, D6945C2E23AC47C3005C403C /* SavedDataManager.swift */, - D6028B9A2150811100F223B9 /* MastodonCache.swift */, D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */, D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */, + D64D8CA82463B494006B0BAA /* CachedDictionary.swift */, D60E2F2B24423EAD005F8713 /* LazilyDecoding.swift */, D6F1F84E2193B9BE00F5FE67 /* Caching */, D6757A7A2157E00100721E32 /* XCallbackURL */, @@ -1674,7 +1674,6 @@ D6BC9DD7232D7811002CA326 /* TimelinesPageViewController.swift in Sources */, D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */, D620483623D38075008A63EF /* ContentTextView.swift in Sources */, - D6028B9B2150811100F223B9 /* MastodonCache.swift in Sources */, D6A3BC802321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift in Sources */, D627944D23A9A03D00D38C68 /* ListTimelineViewController.swift in Sources */, D6945C3823AC739F005C403C /* InstanceTimelineViewController.swift in Sources */, @@ -1767,6 +1766,7 @@ 04D14BB022B34A2800642648 /* GalleryViewController.swift in Sources */, D641C773213CAA25004B4513 /* NotificationsTableViewController.swift in Sources */, D64BC18A23C16487000D0238 /* UnpinStatusActivity.swift in Sources */, + D64D8CA92463B494006B0BAA /* CachedDictionary.swift in Sources */, D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */, D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */, 0427037C22B316B9000D31B6 /* SilentActionPrefs.swift in Sources */, diff --git a/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift b/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift index 493923d7..bac7c884 100644 --- a/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift +++ b/Tusker/Activities/Account Activities/UnfollowAccountActivity.swift @@ -29,9 +29,7 @@ class UnfollowAccountActivity: AccountActivity { let request = Account.unfollow(account.id) mastodonController.run(request) { (response) in - if case let .success(relationship, _) = response { - self.mastodonController.cache.add(relationship: relationship) - } else { + if case .failure(_) = response { // todo: display error message UINotificationFeedbackGenerator().notificationOccurred(.error) fatalError() diff --git a/Tusker/CachedDictionary.swift b/Tusker/CachedDictionary.swift new file mode 100644 index 00000000..3760faaa --- /dev/null +++ b/Tusker/CachedDictionary.swift @@ -0,0 +1,35 @@ +// +// CachedDictionary.swift +// Tusker +// +// Created by Shadowfacts on 5/6/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import Foundation + +class CachedDictionary { + private let name: String + private var dict = [String: Value]() + private let queue: DispatchQueue + + init(name: String) { + self.name = name + self.queue = DispatchQueue(label: "CachedDictionary (\(name)) Coordinator", attributes: .concurrent) + } + + subscript(key: String) -> Value? { + get { + var result: Value? = nil + queue.sync { + result = dict[key] + } + return result + } + set(value) { + queue.async(flags: .barrier) { + self.dict[key] = value + } + } + } +} diff --git a/Tusker/Controllers/MastodonController.swift b/Tusker/Controllers/MastodonController.swift index 97063c18..d4c64152 100644 --- a/Tusker/Controllers/MastodonController.swift +++ b/Tusker/Controllers/MastodonController.swift @@ -30,8 +30,6 @@ class MastodonController { } } - private(set) lazy var cache = MastodonCache(mastodonController: self) - private(set) lazy var persistentContainer = MastodonCachePersistentStore(for: self) let instanceURL: URL diff --git a/Tusker/MastodonCache.swift b/Tusker/MastodonCache.swift deleted file mode 100644 index 9aec17c6..00000000 --- a/Tusker/MastodonCache.swift +++ /dev/null @@ -1,177 +0,0 @@ -// -// StatusCache.swift -// Tusker -// -// Created by Shadowfacts on 9/17/18. -// Copyright © 2018 Shadowfacts. All rights reserved. -// - -import Foundation -import Combine -import Pachyderm - -class MastodonCache { - - private var statuses = CachedDictionary(name: "Statuses") - private var accounts = CachedDictionary(name: "Accounts") - private var relationships = CachedDictionary(name: "Relationships") - private var notifications = CachedDictionary(name: "Notifications") - - let statusSubject = PassthroughSubject() - let accountSubject = PassthroughSubject() - - weak var mastodonController: MastodonController? - - init(mastodonController: MastodonController) { - self.mastodonController = mastodonController - } - - // MARK: - Statuses - func status(for id: String) -> Status? { - return statuses[id] - } - - func set(status: Status, for id: String) { - statuses[id] = status - add(account: status.account) - if let reblog = status.reblog { - add(status: reblog) - add(account: reblog.account) - } - - statusSubject.send(status) - } - - func status(for id: String, completion: @escaping (Status?) -> Void) { - guard let mastodonController = mastodonController else { - fatalError("The MastodonController for this cache has been deinitialized, so this cache should no longer exist. Are you storing a strong reference to it?") - } - let request = Client.getStatus(id: id) - mastodonController.run(request) { response in - guard case let .success(status, _) = response else { - completion(nil) - return - } - self.set(status: status, for: id) - completion(status) - } - } - - func add(status: Status) { - set(status: status, for: status.id) - } - - func addAll(statuses: [Status]) { - statuses.forEach(add) - } - - // MARK: - Accounts - func account(for id: String) -> Account? { - return accounts[id] - } - - func set(account: Account, for id: String) { - accounts[id] = account - accountSubject.send(account) - } - - func account(for id: String, completion: @escaping (Account?) -> Void) { - guard let mastodonController = mastodonController else { - fatalError("The MastodonController for this cache has been deinitialized, so this cache should no longer exist. Are you storing a strong reference to it?") - } - let request = Client.getAccount(id: id) - mastodonController.run(request) { response in - guard case let .success(account, _) = response else { - completion(nil) - return - } - self.set(account: account, for: account.id) - completion(account) - } - } - - func add(account: Account) { - set(account: account, for: account.id) - } - - func addAll(accounts: [Account]) { - accounts.forEach(add) - } - - // MARK: - Relationships - func relationship(for id: String) -> Relationship? { - return relationships[id] - } - - func set(relationship: Relationship, id: String) { - relationships[id] = relationship - } - - func relationship(for id: String, completion: @escaping (Relationship?) -> Void) { - guard let mastodonController = mastodonController else { - fatalError("The MastodonController for this cache has been deinitialized, so this cache should no longer exist. Are you storing a strong reference to it?") - } - let request = Client.getRelationships(accounts: [id]) - mastodonController.run(request) { response in - guard case let .success(relationships, _) = response, - let relationship = relationships.first else { - completion(nil) - return - } - self.set(relationship: relationship, id: relationship.id) - completion(relationship) - } - } - - func add(relationship: Relationship) { - set(relationship: relationship, id: relationship.id) - } - - func addAll(relationships: [Relationship]) { - relationships.forEach(add) - } - - // MARK: - Notifications - func notification(for id: String) -> Pachyderm.Notification? { - return notifications[id] - } - - func set(notification: Pachyderm.Notification, id: String) { - notifications[id] = notification - } - - func add(notification: Pachyderm.Notification) { - set(notification: notification, id: notification.id) - } - - func addAll(notifications: [Pachyderm.Notification]) { - notifications.forEach(add) - } - -} - -class CachedDictionary { - private let name: String - private var dict = [String: Value]() - private let queue: DispatchQueue - - init(name: String) { - self.name = name - self.queue = DispatchQueue(label: "CachedDictionary (\(name)) Coordinator", attributes: .concurrent) - } - - subscript(key: String) -> Value? { - get { - var result: Value? = nil - queue.sync { - result = dict[key] - } - return result - } - set(value) { - queue.async(flags: .barrier) { - self.dict[key] = value - } - } - } -} diff --git a/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift b/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift index ba6a509f..e25597d6 100644 --- a/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift +++ b/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.swift @@ -109,8 +109,7 @@ class FollowRequestNotificationTableViewCell: UITableViewCell { @IBAction func rejectButtonPressed() { let request = Account.rejectFollowRequest(account) mastodonController.run(request) { (response) in - guard case let .success(relationship, _) = response else { fatalError() } - self.mastodonController.cache.add(relationship: relationship) + guard case .success(_, _) = response else { fatalError() } DispatchQueue.main.async { UINotificationFeedbackGenerator().notificationOccurred(.success) self.actionButtonsStackView.isHidden = true @@ -126,8 +125,7 @@ class FollowRequestNotificationTableViewCell: UITableViewCell { @IBAction func acceptButtonPressed() { let request = Account.authorizeFollowRequest(account) mastodonController.run(request) { (response) in - guard case let .success(relationship, _) = response else { fatalError() } - self.mastodonController.cache.add(relationship: relationship) + guard case .success(_, _) = response else { fatalError() } DispatchQueue.main.async { UINotificationFeedbackGenerator().notificationOccurred(.success) self.actionButtonsStackView.isHidden = true diff --git a/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift b/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift index 9634fc4f..bd4e5af3 100644 --- a/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift +++ b/Tusker/Views/Profile Header/ProfileHeaderTableViewCell.swift @@ -122,12 +122,12 @@ class ProfileHeaderTableViewCell: UITableViewCell { fieldValuesStack.addArrangedSubview(valueTextView) } -// if accountUpdater == nil { -// accountUpdater = mastodonController.cache.accountSubject -// .filter { [unowned self] in $0.id == self.accountID } -// .receive(on: DispatchQueue.main) -// .sink { [unowned self] in self.updateUI(for: $0.id) } -// } + if accountUpdater == nil { + accountUpdater = mastodonController.persistentContainer.accountSubject + .filter { [unowned self] in $0 == self.accountID } + .receive(on: DispatchQueue.main) + .sink { [unowned self] in self.updateUI(for: $0) } + } } @objc func updateUIForPreferences() {