Workaround for follow menu item never resolving on macOS

See #198
This commit is contained in:
Shadowfacts 2022-10-30 18:54:14 -04:00
parent c5921bc4cb
commit cc33cf18f2
2 changed files with 41 additions and 19 deletions

View File

@ -179,20 +179,21 @@ class MastodonCachePersistentStore: NSPersistentContainer {
}
@discardableResult
private func upsert(relationship: Relationship) -> RelationshipMO {
if let relationshipMO = self.relationship(forAccount: relationship.id, in: self.backgroundContext) {
private func upsert(relationship: Relationship, in context: NSManagedObjectContext) -> RelationshipMO {
if let relationshipMO = self.relationship(forAccount: relationship.id, in: context) {
relationshipMO.updateFrom(apiRelationship: relationship, container: self)
return relationshipMO
} else {
let relationshipMO = RelationshipMO(apiRelationship: relationship, container: self, context: self.backgroundContext)
let relationshipMO = RelationshipMO(apiRelationship: relationship, container: self, context: context)
return relationshipMO
}
}
func addOrUpdate(relationship: Relationship, completion: ((RelationshipMO) -> Void)? = nil) {
backgroundContext.perform {
let relationshipMO = self.upsert(relationship: relationship)
self.save(context: self.backgroundContext)
func addOrUpdate(relationship: Relationship, in context: NSManagedObjectContext? = nil, completion: ((RelationshipMO) -> Void)? = nil) {
let context = context ?? backgroundContext
context.perform {
let relationshipMO = self.upsert(relationship: relationship, in: context)
self.save(context: context)
completion?(relationshipMO)
self.relationshipSubject.send(relationship.id)
}

View File

@ -60,12 +60,23 @@ extension MenuActionProvider {
draft.visibility = .direct
self.navigationDelegate?.compose(editing: draft)
}),
UIDeferredMenuElement.uncached({ (elementHandler) in
Task { @MainActor in
if let action = await self.followAction(for: accountID, mastodonController: mastodonController) {
elementHandler([action])
} else {
elementHandler([])
UIDeferredMenuElement.uncached({ @MainActor elementHandler in
let relationship = Task {
await self.fetchRelationship(accountID: accountID, mastodonController: mastodonController)
}
// workaround for #198, may result in showing outdated relationship, so only do so where necessary
if ProcessInfo.processInfo.isiOSAppOnMac,
let mo = mastodonController.persistentContainer.relationship(forAccount: accountID),
let action = self.followAction(for: mo, mastodonController: mastodonController) {
elementHandler([action])
} else {
Task { @MainActor in
if let relationship = await relationship.value,
let action = self.followAction(for: relationship, mastodonController: mastodonController) {
elementHandler([action])
} else {
elementHandler([])
}
}
}
})
@ -381,16 +392,26 @@ extension MenuActionProvider {
})
}
private func followAction(for accountID: String, mastodonController: MastodonController) async -> UIMenuElement? {
guard let ownAccount = try? await mastodonController.getOwnAccount(),
accountID != ownAccount.id else {
private func fetchRelationship(accountID: String, mastodonController: MastodonController) async -> RelationshipMO? {
let req = Client.getRelationships(accounts: [accountID])
guard let (relationships, _) = try? await mastodonController.run(req),
let r = relationships.first else {
return nil
}
let request = Client.getRelationships(accounts: [accountID])
guard let (relationships, _) = try? await mastodonController.run(request),
let relationship = relationships.first else {
return await withCheckedContinuation { continuation in
mastodonController.persistentContainer.addOrUpdate(relationship: r, in: mastodonController.persistentContainer.viewContext) { mo in
continuation.resume(returning: mo)
}
}
}
@MainActor
private func followAction(for relationship: RelationshipMO, mastodonController: MastodonController) -> UIMenuElement? {
guard let ownAccount = mastodonController.account,
relationship.accountID != ownAccount.id else {
return nil
}
let accountID = relationship.accountID
let following = relationship.following
return createAction(identifier: "follow", title: following ? "Unfollow" : "Follow", systemImageName: following ? "person.badge.minus" : "person.badge.plus") { _ in
let request = (following ? Account.unfollow : Account.follow)(accountID)