Fix crash when providing account actions before own account is loaded

This commit is contained in:
Shadowfacts 2022-03-29 12:52:14 -04:00
parent 6e3089f025
commit 727615a818
2 changed files with 46 additions and 38 deletions

View File

@ -67,6 +67,19 @@ class MastodonController: ObservableObject {
return client.run(request, completion: completion) return client.run(request, completion: completion)
} }
func run<Result>(_ request: Request<Result>) async throws -> (Result, Pagination?) {
return try await withCheckedThrowingContinuation({ continuation in
client.run(request) { response in
switch response {
case .failure(let error):
continuation.resume(throwing: error)
case .success(let result, let pagination):
continuation.resume(returning: (result, pagination))
}
}
})
}
/// - Returns: A tuple of client ID and client secret. /// - Returns: A tuple of client ID and client secret.
func registerApp() async throws -> (String, String) { func registerApp() async throws -> (String, String) {
if let clientID = client.clientID, if let clientID = client.clientID,

View File

@ -48,50 +48,21 @@ extension MenuPreviewProvider {
] ]
} }
var actionsSection: [UIMenuElement] = [ let actionsSection: [UIMenuElement] = [
createAction(identifier: "sendmessage", title: "Send Message", systemImageName: "envelope", handler: { [weak self] (_) in createAction(identifier: "sendmessage", title: "Send Message", systemImageName: "envelope", handler: { [weak self] (_) in
guard let self = self else { return } guard let self = self else { return }
self.navigationDelegate?.compose(mentioningAcct: account.acct) self.navigationDelegate?.compose(mentioningAcct: account.acct)
}), }),
] UIDeferredMenuElement({ (elementHandler) in
Task { @MainActor in
if accountID != mastodonController.account.id { if let action = await self.followAction(for: accountID, mastodonController: mastodonController) {
actionsSection.append(UIDeferredMenuElement({ (elementHandler) in elementHandler([action])
guard let mastodonController = self.mastodonController else { } else {
elementHandler([]) elementHandler([])
return
}
let request = Client.getRelationships(accounts: [account.id])
// talk about callback hell :/
mastodonController.run(request) { [weak self] (response) in
guard let self = self,
case let .success(results, _) = response,
let relationship = results.first else {
DispatchQueue.main.async {
elementHandler([])
}
return
}
let following = relationship.following
DispatchQueue.main.async {
let action = 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)
mastodonController.run(request) { (response) in
switch response {
case .failure(_):
fatalError()
case let .success(relationship, _):
mastodonController.persistentContainer.addOrUpdate(relationship: relationship)
} }
} }
}) })
elementHandler([ ]
action
])
}
}
}))
}
var shareSection = [ var shareSection = [
openInSafariAction(url: account.url), openInSafariAction(url: account.url),
@ -267,6 +238,30 @@ extension MenuPreviewProvider {
} }
} }
private func followAction(for accountID: String, mastodonController: MastodonController) async -> UIMenuElement? {
guard let ownAccount = try? await mastodonController.getOwnAccount(),
accountID != ownAccount.id else {
return nil
}
let request = Client.getRelationships(accounts: [accountID])
guard let (relationships, _) = try? await mastodonController.run(request),
let relationship = relationships.first else {
return nil
}
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)
mastodonController.run(request) { response in
switch response {
case .failure(_):
fatalError()
case .success(let relationship, _):
mastodonController.persistentContainer.addOrUpdate(relationship: relationship)
}
}
}
}
} }
extension LargeImageViewController: CustomPreviewPresenting { extension LargeImageViewController: CustomPreviewPresenting {