Wait for authentications to be available before trying to use them.

The prior fix for memory corruption problems in authentications had caused the app to launch to the new user screen every time.
This commit is contained in:
shannon 2024-10-30 14:38:21 -04:00
parent 20f7d761bd
commit fdca50179e
5 changed files with 76 additions and 73 deletions

View File

@ -10,6 +10,7 @@ import MastodonCore
class IntentHandler: INExtension {
@MainActor
override func handler(for intent: INIntent) -> Any {
AuthenticationServiceProvider.shared.prepareForUse()

View File

@ -83,21 +83,21 @@ public extension AuthenticationServiceProvider {
return authentications.sorted(by: { $0.activedAt > $1.activedAt })
}
@MainActor
func prepareForUse() {
if authentications.isEmpty {
restoreFromKeychain()
}
}
@MainActor
private func restoreFromKeychain() {
DispatchQueue.main.async {
self.authentications = Self.keychain.allKeys().compactMap {
guard
let encoded = Self.keychain[$0],
let data = Data(base64Encoded: encoded)
else { return nil }
return try? JSONDecoder().decode(MastodonAuthentication.self, from: data)
}
self.authentications = Self.keychain.allKeys().compactMap {
guard
let encoded = Self.keychain[$0],
let data = Data(base64Encoded: encoded)
else { return nil }
return try? JSONDecoder().decode(MastodonAuthentication.self, from: data)
}
}

View File

@ -73,7 +73,7 @@ private extension FollowersCountWidgetProvider {
func loadCurrentEntry(for configuration: FollowersCountIntent, in context: Context, completion: @escaping (FollowersCountEntry) -> Void) {
Task {
AuthenticationServiceProvider.shared.prepareForUse()
await AuthenticationServiceProvider.shared.prepareForUse()
guard
let authBox = WidgetExtension.appContext

View File

@ -24,75 +24,77 @@ struct HashtagWidgetProvider: IntentTimelineProvider {
extension HashtagWidgetProvider {
func loadMostRecentHashtag(for configuration: HashtagIntent, in context: Context, completion: @escaping (HashtagWidgetTimelineEntry) -> Void ) {
AuthenticationServiceProvider.shared.prepareForUse()
guard
let authBox = WidgetExtension.appContext
.authenticationService
.mastodonAuthenticationBoxes
.first
else {
if context.isPreview {
return completion(.placeholder)
} else {
return completion(.unconfigured)
}
}
let desiredHashtag: String
if let hashtag = configuration.hashtag {
desiredHashtag = hashtag.replacingOccurrences(of: "#", with: "")
} else {
return completion(.notFound("hashtag"))
}
Task {
do {
let mostRecentStatuses = try await WidgetExtension.appContext
.apiService
.hashtagTimeline(limit: 40, hashtag: desiredHashtag, authenticationBox: authBox)
.value
let filteredStatuses: [Mastodon.Entity.Status]
if configuration.ignoreContentWarnings?.boolValue == true {
filteredStatuses = mostRecentStatuses
} else {
filteredStatuses = mostRecentStatuses.filter { $0.sensitive == false }
await MainActor.run {
AuthenticationServiceProvider.shared.prepareForUse()
guard
let authBox = WidgetExtension.appContext
.authenticationService
.mastodonAuthenticationBoxes
.first
else {
if context.isPreview {
return completion(.placeholder)
} else {
return completion(.unconfigured)
}
}
if let mostRecentStatus = filteredStatuses.first {
let hashtagEntry = HashtagEntry(
accountName: mostRecentStatus.account.displayNameWithFallback,
account: mostRecentStatus.account.acct,
content: mostRecentStatus.content ?? "-",
reblogCount: mostRecentStatus.reblogsCount,
favoriteCount: mostRecentStatus.favouritesCount,
hashtag: "#\(desiredHashtag)",
timestamp: mostRecentStatus.createdAt
)
let hashtagTimelineEntry = HashtagWidgetTimelineEntry(
date: mostRecentStatus.createdAt,
hashtag: hashtagEntry
)
completion(hashtagTimelineEntry)
let desiredHashtag: String
if let hashtag = configuration.hashtag {
desiredHashtag = hashtag.replacingOccurrences(of: "#", with: "")
} else {
let noStatusFound = HashtagWidgetTimelineEntry.notFound(desiredHashtag)
completion(noStatusFound)
return completion(.notFound("hashtag"))
}
Task {
do {
let mostRecentStatuses = try await WidgetExtension.appContext
.apiService
.hashtagTimeline(limit: 40, hashtag: desiredHashtag, authenticationBox: authBox)
.value
let filteredStatuses: [Mastodon.Entity.Status]
if configuration.ignoreContentWarnings?.boolValue == true {
filteredStatuses = mostRecentStatuses
} else {
filteredStatuses = mostRecentStatuses.filter { $0.sensitive == false }
}
if let mostRecentStatus = filteredStatuses.first {
let hashtagEntry = HashtagEntry(
accountName: mostRecentStatus.account.displayNameWithFallback,
account: mostRecentStatus.account.acct,
content: mostRecentStatus.content ?? "-",
reblogCount: mostRecentStatus.reblogsCount,
favoriteCount: mostRecentStatus.favouritesCount,
hashtag: "#\(desiredHashtag)",
timestamp: mostRecentStatus.createdAt
)
let hashtagTimelineEntry = HashtagWidgetTimelineEntry(
date: mostRecentStatus.createdAt,
hashtag: hashtagEntry
)
completion(hashtagTimelineEntry)
} else {
let noStatusFound = HashtagWidgetTimelineEntry.notFound(desiredHashtag)
completion(noStatusFound)
}
} catch {
completion(.notFound(desiredHashtag))
}
}
} catch {
completion(.notFound(desiredHashtag))
}
}
}
}

View File

@ -73,7 +73,7 @@ private extension MultiFollowersCountWidgetProvider {
func loadCurrentEntry(for configuration: MultiFollowersCountIntent, in context: Context, completion: @escaping (MultiFollowersCountEntry) -> Void) {
Task {
AuthenticationServiceProvider.shared.prepareForUse()
await AuthenticationServiceProvider.shared.prepareForUse()
guard
let authBox = WidgetExtension.appContext