Cache account relationships in CoreData
This commit is contained in:
parent
2cfc0cf28a
commit
1a4517c43a
|
@ -18,6 +18,7 @@ public class Relationship: Decodable {
|
||||||
public let followRequested: Bool
|
public let followRequested: Bool
|
||||||
public let domainBlocking: Bool
|
public let domainBlocking: Bool
|
||||||
public let showingReblogs: Bool
|
public let showingReblogs: Bool
|
||||||
|
public let endorsed: Bool?
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case id
|
case id
|
||||||
|
@ -29,5 +30,6 @@ public class Relationship: Decodable {
|
||||||
case followRequested = "requested"
|
case followRequested = "requested"
|
||||||
case domainBlocking = "domain_blocking"
|
case domainBlocking = "domain_blocking"
|
||||||
case showingReblogs = "showing_reblogs"
|
case showingReblogs = "showing_reblogs"
|
||||||
|
case endorsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,6 +260,7 @@
|
||||||
D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */; };
|
D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */; };
|
||||||
D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */; };
|
D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */; };
|
||||||
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */; };
|
D6DD353F22F502EC00A9563A /* Preferences+Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */; };
|
||||||
|
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */; };
|
||||||
D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; };
|
D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; };
|
||||||
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */; };
|
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */; };
|
||||||
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
||||||
|
@ -594,6 +595,7 @@
|
||||||
D6D4DDF1212518A200E1C4BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
D6D4DDF1212518A200E1C4BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWarningCopyMode.swift; sourceTree = "<group>"; };
|
D6DD353C22F28CD000A9563A /* ContentWarningCopyMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentWarningCopyMode.swift; sourceTree = "<group>"; };
|
||||||
D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preferences+Notification.swift"; sourceTree = "<group>"; };
|
D6DD353E22F502EC00A9563A /* Preferences+Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Preferences+Notification.swift"; sourceTree = "<group>"; };
|
||||||
|
D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelationshipMO.swift; sourceTree = "<group>"; };
|
||||||
D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = "<group>"; };
|
D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||||
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakArray.swift; sourceTree = "<group>"; };
|
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakArray.swift; sourceTree = "<group>"; };
|
||||||
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
||||||
|
@ -893,6 +895,7 @@
|
||||||
D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */,
|
D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */,
|
||||||
D60E2F232442372B005F8713 /* StatusMO.swift */,
|
D60E2F232442372B005F8713 /* StatusMO.swift */,
|
||||||
D60E2F252442372B005F8713 /* AccountMO.swift */,
|
D60E2F252442372B005F8713 /* AccountMO.swift */,
|
||||||
|
D6DF95C02533F5DE0027A9B6 /* RelationshipMO.swift */,
|
||||||
D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */,
|
D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */,
|
||||||
);
|
);
|
||||||
path = CoreData;
|
path = CoreData;
|
||||||
|
@ -1837,6 +1840,7 @@
|
||||||
D677284C24ECBE9100C732D3 /* ComposeAvatarImageView.swift in Sources */,
|
D677284C24ECBE9100C732D3 /* ComposeAvatarImageView.swift in Sources */,
|
||||||
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */,
|
D6BC9DDA232D8BE5002CA326 /* SearchResultsViewController.swift in Sources */,
|
||||||
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */,
|
D627FF7F217E95E000CC0648 /* DraftTableViewCell.swift in Sources */,
|
||||||
|
D6DF95C12533F5DE0027A9B6 /* RelationshipMO.swift in Sources */,
|
||||||
D6AEBB4A23216F0400E5038B /* UnfollowAccountActivity.swift in Sources */,
|
D6AEBB4A23216F0400E5038B /* UnfollowAccountActivity.swift in Sources */,
|
||||||
D663626421360D2300C9CBA2 /* AvatarStyle.swift in Sources */,
|
D663626421360D2300C9CBA2 /* AvatarStyle.swift in Sources */,
|
||||||
D6D3FDE024F41B8400FF50A5 /* ComposeContainerView.swift in Sources */,
|
D6D3FDE024F41B8400FF50A5 /* ComposeContainerView.swift in Sources */,
|
||||||
|
|
|
@ -29,10 +29,13 @@ class FollowAccountActivity: AccountActivity {
|
||||||
|
|
||||||
let request = Account.follow(account.id)
|
let request = Account.follow(account.id)
|
||||||
mastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case .failure(_) = response {
|
switch response {
|
||||||
|
case .failure(_):
|
||||||
// todo: display error message
|
// todo: display error message
|
||||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||||
fatalError()
|
fatalError()
|
||||||
|
case let .success(relationship, _):
|
||||||
|
self.mastodonController.persistentContainer.addOrUpdate(relationship: relationship)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,13 @@ class UnfollowAccountActivity: AccountActivity {
|
||||||
|
|
||||||
let request = Account.unfollow(account.id)
|
let request = Account.unfollow(account.id)
|
||||||
mastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
if case .failure(_) = response {
|
switch response {
|
||||||
|
case .failure(_):
|
||||||
// todo: display error message
|
// todo: display error message
|
||||||
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
UINotificationFeedbackGenerator().notificationOccurred(.error)
|
||||||
fatalError()
|
fatalError()
|
||||||
|
case let .success(relationship, _):
|
||||||
|
self.mastodonController.persistentContainer.addOrUpdate(relationship: relationship)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
|
|
||||||
let statusSubject = PassthroughSubject<String, Never>()
|
let statusSubject = PassthroughSubject<String, Never>()
|
||||||
let accountSubject = PassthroughSubject<String, Never>()
|
let accountSubject = PassthroughSubject<String, Never>()
|
||||||
|
let relationshipSubject = PassthroughSubject<String, Never>()
|
||||||
|
|
||||||
init(for accountInfo: LocalData.UserAccountInfo?, transient: Bool = false) {
|
init(for accountInfo: LocalData.UserAccountInfo?, transient: Bool = false) {
|
||||||
if transient {
|
if transient {
|
||||||
|
@ -136,6 +137,40 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func relationship(forAccount id: String, in context: NSManagedObjectContext? = nil) -> RelationshipMO? {
|
||||||
|
let context = context ?? viewContext
|
||||||
|
let request: NSFetchRequest<RelationshipMO> = RelationshipMO.fetchRequest()
|
||||||
|
request.predicate = NSPredicate(format: "accountID = %@", id)
|
||||||
|
request.fetchLimit = 1
|
||||||
|
if let result = try? context.fetch(request), let relationship = result.first {
|
||||||
|
return relationship
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
private func upsert(relationship: Relationship) -> RelationshipMO {
|
||||||
|
if let relationshipMO = self.relationship(forAccount: relationship.id, in: self.backgroundContext) {
|
||||||
|
relationshipMO.updateFrom(apiRelationship: relationship, container: self)
|
||||||
|
return relationshipMO
|
||||||
|
} else {
|
||||||
|
let relationshipMO = RelationshipMO(apiRelationship: relationship, container: self, context: self.backgroundContext)
|
||||||
|
return relationshipMO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addOrUpdate(relationship: Relationship, completion: ((RelationshipMO) -> Void)? = nil) {
|
||||||
|
backgroundContext.perform {
|
||||||
|
let relationshipMO = self.upsert(relationship: relationship)
|
||||||
|
if self.backgroundContext.hasChanges {
|
||||||
|
try! self.backgroundContext.save()
|
||||||
|
}
|
||||||
|
completion?(relationshipMO)
|
||||||
|
self.relationshipSubject.send(relationship.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func addAll(accounts: [Account], completion: (() -> Void)? = nil) {
|
func addAll(accounts: [Account], completion: (() -> Void)? = nil) {
|
||||||
backgroundContext.perform {
|
backgroundContext.perform {
|
||||||
accounts.forEach { self.upsert(account: $0, incrementReferenceCount: true) }
|
accounts.forEach { self.upsert(account: $0, incrementReferenceCount: true) }
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
//
|
||||||
|
// RelationshipMO.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 10/11/20.
|
||||||
|
// Copyright © 2020 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
import Pachyderm
|
||||||
|
|
||||||
|
@objc(RelationshipMO)
|
||||||
|
public final class RelationshipMO: NSManagedObject {
|
||||||
|
|
||||||
|
@nonobjc public class func fetchRequest() -> NSFetchRequest<RelationshipMO> {
|
||||||
|
return NSFetchRequest<RelationshipMO>(entityName: "Relationship")
|
||||||
|
}
|
||||||
|
|
||||||
|
@NSManaged public var accountID: String
|
||||||
|
@NSManaged public var blocking: Bool
|
||||||
|
@NSManaged public var domainBlocking: Bool
|
||||||
|
@NSManaged public var endorsed: Bool
|
||||||
|
@NSManaged public var followedBy: Bool
|
||||||
|
@NSManaged public var following: Bool
|
||||||
|
@NSManaged public var muting: Bool
|
||||||
|
@NSManaged public var mutingNotifications: Bool
|
||||||
|
@NSManaged public var requested: Bool
|
||||||
|
@NSManaged public var showingReblogs: Bool
|
||||||
|
@NSManaged public var account: AccountMO?
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension RelationshipMO {
|
||||||
|
convenience init(apiRelationship relationship: Relationship, container: MastodonCachePersistentStore, context: NSManagedObjectContext) {
|
||||||
|
self.init(context: context)
|
||||||
|
self.updateFrom(apiRelationship: relationship, container: container)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateFrom(apiRelationship relationship: Relationship, container: MastodonCachePersistentStore) {
|
||||||
|
guard let context = managedObjectContext else {
|
||||||
|
// we have been deleted, don't bother updating
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.accountID = relationship.id
|
||||||
|
self.blocking = relationship.blocking
|
||||||
|
self.domainBlocking = relationship.domainBlocking
|
||||||
|
self.endorsed = relationship.endorsed ?? false
|
||||||
|
self.followedBy = relationship.followedBy
|
||||||
|
self.following = relationship.following
|
||||||
|
self.muting = relationship.muting
|
||||||
|
self.mutingNotifications = relationship.mutingNotifications
|
||||||
|
self.requested = relationship.followRequested
|
||||||
|
self.showingReblogs = relationship.showingReblogs
|
||||||
|
|
||||||
|
self.account = container.account(for: relationship.id, in: context)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="16119" systemVersion="19D76" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17507" systemVersion="19G2021" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||||
<entity name="Account" representedClassName="AccountMO" syncable="YES">
|
<entity name="Account" representedClassName="AccountMO" syncable="YES">
|
||||||
<attribute name="acct" attributeType="String"/>
|
<attribute name="acct" attributeType="String"/>
|
||||||
<attribute name="avatar" attributeType="URI"/>
|
<attribute name="avatar" attributeType="URI"/>
|
||||||
|
@ -20,12 +20,26 @@
|
||||||
<attribute name="url" attributeType="URI"/>
|
<attribute name="url" attributeType="URI"/>
|
||||||
<attribute name="username" attributeType="String"/>
|
<attribute name="username" attributeType="String"/>
|
||||||
<relationship name="movedTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account"/>
|
<relationship name="movedTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account"/>
|
||||||
|
<relationship name="relationship" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Relationship" inverseName="account" inverseEntity="Relationship"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
<uniquenessConstraint>
|
<uniquenessConstraint>
|
||||||
<constraint value="id"/>
|
<constraint value="id"/>
|
||||||
</uniquenessConstraint>
|
</uniquenessConstraint>
|
||||||
</uniquenessConstraints>
|
</uniquenessConstraints>
|
||||||
</entity>
|
</entity>
|
||||||
|
<entity name="Relationship" representedClassName="RelationshipMO" syncable="YES">
|
||||||
|
<attribute name="accountID" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="blocking" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="domainBlocking" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="endorsed" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="followedBy" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="following" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="muting" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="mutingNotifications" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="requested" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<attribute name="showingReblogs" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
|
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="relationship" inverseEntity="Account"/>
|
||||||
|
</entity>
|
||||||
<entity name="Status" representedClassName="StatusMO" syncable="YES">
|
<entity name="Status" representedClassName="StatusMO" syncable="YES">
|
||||||
<attribute name="applicationName" optional="YES" attributeType="String"/>
|
<attribute name="applicationName" optional="YES" attributeType="String"/>
|
||||||
<attribute name="attachmentsData" attributeType="Binary"/>
|
<attribute name="attachmentsData" attributeType="Binary"/>
|
||||||
|
@ -59,7 +73,8 @@
|
||||||
</uniquenessConstraints>
|
</uniquenessConstraints>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="Account" positionX="169.21875" positionY="78.9609375" width="128" height="328"/>
|
<element name="Account" positionX="169.21875" positionY="78.9609375" width="128" height="343"/>
|
||||||
<element name="Status" positionX="-63" positionY="-18" width="128" height="418"/>
|
<element name="Status" positionX="-63" positionY="-18" width="128" height="418"/>
|
||||||
|
<element name="Relationship" positionX="63" positionY="135" width="128" height="208"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
|
@ -71,7 +71,13 @@ extension MenuPreviewProvider {
|
||||||
elementHandler([
|
elementHandler([
|
||||||
self.createAction(identifier: "follow", title: following ? "Unfollow" : "Follow", systemImageName: following ? "person.badge.minus" : "person.badge.plus", handler: { (_) in
|
self.createAction(identifier: "follow", title: following ? "Unfollow" : "Follow", systemImageName: following ? "person.badge.minus" : "person.badge.plus", handler: { (_) in
|
||||||
let request = (following ? Account.unfollow : Account.follow)(accountID)
|
let request = (following ? Account.unfollow : Account.follow)(accountID)
|
||||||
mastodonController.run(request) { (_) in
|
mastodonController.run(request) { (response) in
|
||||||
|
switch response {
|
||||||
|
case .failure(_):
|
||||||
|
fatalError()
|
||||||
|
case let .success(relationship, _):
|
||||||
|
mastodonController.persistentContainer.addOrUpdate(relationship: relationship)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
|
|
|
@ -23,7 +23,11 @@ class ProfileHeaderView: UIView {
|
||||||
return nib.instantiate(withOwner: nil, options: nil).first as! ProfileHeaderView
|
return nib.instantiate(withOwner: nil, options: nil).first as! ProfileHeaderView
|
||||||
}
|
}
|
||||||
|
|
||||||
weak var delegate: ProfileHeaderViewDelegate?
|
weak var delegate: ProfileHeaderViewDelegate? {
|
||||||
|
didSet {
|
||||||
|
createObservers()
|
||||||
|
}
|
||||||
|
}
|
||||||
var mastodonController: MastodonController! { delegate?.apiController }
|
var mastodonController: MastodonController! { delegate?.apiController }
|
||||||
|
|
||||||
@IBOutlet weak var headerImageView: UIImageView!
|
@IBOutlet weak var headerImageView: UIImageView!
|
||||||
|
@ -41,10 +45,10 @@ class ProfileHeaderView: UIView {
|
||||||
|
|
||||||
var accountID: String!
|
var accountID: String!
|
||||||
|
|
||||||
var avatarRequest: ImageCache.Request?
|
private var avatarRequest: ImageCache.Request?
|
||||||
var headerRequest: ImageCache.Request?
|
private var headerRequest: ImageCache.Request?
|
||||||
|
|
||||||
private var accountUpdater: Cancellable?
|
private var cancellables = [AnyCancellable]()
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
avatarRequest?.cancel()
|
avatarRequest?.cancel()
|
||||||
|
@ -74,6 +78,22 @@ class ProfileHeaderView: UIView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func createObservers() {
|
||||||
|
cancellables = []
|
||||||
|
|
||||||
|
mastodonController.persistentContainer.accountSubject
|
||||||
|
.filter { [weak self] in $0 == self?.accountID }
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] in self?.updateUI(for: $0) }
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
|
mastodonController.persistentContainer.relationshipSubject
|
||||||
|
.filter { [weak self] in $0 == self?.accountID }
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] (_) in self?.updateRelationship() }
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
func updateUI(for accountID: String) {
|
func updateUI(for accountID: String) {
|
||||||
self.accountID = accountID
|
self.accountID = accountID
|
||||||
|
|
||||||
|
@ -111,6 +131,9 @@ class ProfileHeaderView: UIView {
|
||||||
|
|
||||||
// don't show relationship label for the user's own account
|
// don't show relationship label for the user's own account
|
||||||
if accountID != mastodonController.account?.id {
|
if accountID != mastodonController.account?.id {
|
||||||
|
// while fetching the most up-to-date, show the current data (if any)
|
||||||
|
updateRelationship()
|
||||||
|
|
||||||
let request = Client.getRelationships(accounts: [accountID])
|
let request = Client.getRelationships(accounts: [accountID])
|
||||||
mastodonController.run(request) { [weak self] (response) in
|
mastodonController.run(request) { [weak self] (response) in
|
||||||
guard let self = self,
|
guard let self = self,
|
||||||
|
@ -118,9 +141,7 @@ class ProfileHeaderView: UIView {
|
||||||
let relationship = results.first else {
|
let relationship = results.first else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
DispatchQueue.main.async {
|
self.mastodonController.persistentContainer.addOrUpdate(relationship: relationship)
|
||||||
self.followsYouLabel.isHidden = !relationship.followedBy
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +173,14 @@ class ProfileHeaderView: UIView {
|
||||||
|
|
||||||
nameLabel.heightAnchor.constraint(equalTo: valueTextView.heightAnchor).isActive = true
|
nameLabel.heightAnchor.constraint(equalTo: valueTextView.heightAnchor).isActive = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if accountUpdater == nil {
|
private func updateRelationship() {
|
||||||
accountUpdater = mastodonController.persistentContainer.accountSubject
|
guard let relationship = mastodonController.persistentContainer.relationship(forAccount: accountID) else {
|
||||||
.filter { [weak self] in $0 == self?.accountID }
|
return
|
||||||
.receive(on: DispatchQueue.main)
|
|
||||||
.sink { [weak self] in self?.updateUI(for: $0) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
followsYouLabel.isHidden = !relationship.followedBy
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func updateUIForPreferences() {
|
@objc private func updateUIForPreferences() {
|
||||||
|
|
Loading…
Reference in New Issue