From e94bee4fc8790bc044383121c14b8874d68a7e67 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 13 Apr 2024 23:06:30 -0400 Subject: [PATCH] Fix a handful of strict concurrency warnings --- .../Sources/PushNotifications/PushSubscription.swift | 4 ++-- .../Sources/TuskerPreferences/Preferences.swift | 2 ++ .../TuskerPreferences/Supporting Types/PostVisibility.swift | 4 ++-- .../Sources/UserAccounts/UserAccountsManager.swift | 3 ++- Tusker/API/LogoutService.swift | 6 +++--- Tusker/Screens/Preferences/About/FlipView.swift | 2 +- Tusker/Screens/Preferences/AcknowledgementsView.swift | 2 +- Tusker/Screens/Preferences/Tip Jar/ConfettiView.swift | 2 +- Tusker/Screens/Preferences/Tip Jar/TipJarView.swift | 6 ++++-- 9 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift b/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift index b326363a..d7cf1b0c 100644 --- a/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift +++ b/Packages/PushNotifications/Sources/PushNotifications/PushSubscription.swift @@ -53,7 +53,7 @@ public struct PushSubscription { self.policy = policy } - public enum Policy: String, CaseIterable, Identifiable { + public enum Policy: String, CaseIterable, Identifiable, Sendable { case all, followed, followers public var id: some Hashable { @@ -61,7 +61,7 @@ public struct PushSubscription { } } - public struct Alerts: OptionSet, Hashable { + public struct Alerts: OptionSet, Hashable, Sendable { public static let mention = Alerts(rawValue: 1 << 0) public static let status = Alerts(rawValue: 1 << 1) public static let reblog = Alerts(rawValue: 1 << 2) diff --git a/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift b/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift index 1274f303..59d388b9 100644 --- a/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift +++ b/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift @@ -8,6 +8,7 @@ import Foundation public struct Preferences { + @MainActor public static let shared: PreferenceStore = load() private static var documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! @@ -18,6 +19,7 @@ public struct Preferences { private init() {} + @MainActor public static func save() { let encoder = PropertyListEncoder() let data = try? encoder.encode(PreferenceCoding(wrapped: shared)) diff --git a/Packages/TuskerPreferences/Sources/TuskerPreferences/Supporting Types/PostVisibility.swift b/Packages/TuskerPreferences/Sources/TuskerPreferences/Supporting Types/PostVisibility.swift index 00cdc97f..77ba01a6 100644 --- a/Packages/TuskerPreferences/Sources/TuskerPreferences/Supporting Types/PostVisibility.swift +++ b/Packages/TuskerPreferences/Sources/TuskerPreferences/Supporting Types/PostVisibility.swift @@ -12,7 +12,7 @@ public enum PostVisibility: Codable, Hashable, CaseIterable, Sendable { case serverDefault case visibility(Visibility) - public static var allCases: [PostVisibility] = [.serverDefault] + Visibility.allCases.map { .visibility($0) } + public private(set) static var allCases: [PostVisibility] = [.serverDefault] + Visibility.allCases.map { .visibility($0) } public func resolved(withServerDefault serverDefault: Visibility?) -> Visibility { switch self { @@ -57,7 +57,7 @@ public enum ReplyVisibility: Codable, Hashable, CaseIterable { case sameAsPost case visibility(Visibility) - public static var allCases: [ReplyVisibility] = [.sameAsPost] + Visibility.allCases.map { .visibility($0) } + public private(set) static var allCases: [ReplyVisibility] = [.sameAsPost] + Visibility.allCases.map { .visibility($0) } @MainActor public func resolved(withServerDefault serverDefault: Visibility?) -> Visibility { diff --git a/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift b/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift index e0d197fc..dd27dd73 100644 --- a/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift +++ b/Packages/UserAccounts/Sources/UserAccounts/UserAccountsManager.swift @@ -8,7 +8,8 @@ import Foundation import Combine -public class UserAccountsManager: ObservableObject { +// Sendability: UserDefaults is not marked Sendable, but is documented as being thread safe +public final class UserAccountsManager: ObservableObject, @unchecked Sendable { public static let shared = UserAccountsManager() diff --git a/Tusker/API/LogoutService.swift b/Tusker/API/LogoutService.swift index 870765c4..6e36c84b 100644 --- a/Tusker/API/LogoutService.swift +++ b/Tusker/API/LogoutService.swift @@ -23,10 +23,10 @@ class LogoutService { func run() { let accountInfo = self.accountInfo - Task.detached { - if await PushManager.shared.pushSubscription(account: accountInfo) != nil { + Task.detached { @MainActor in + if PushManager.shared.pushSubscription(account: accountInfo) != nil { _ = try? await self.mastodonController.run(Pachyderm.PushSubscription.delete()) - await PushManager.shared.removeSubscription(account: accountInfo) + PushManager.shared.removeSubscription(account: accountInfo) } try? await self.mastodonController.client.revokeAccessToken() } diff --git a/Tusker/Screens/Preferences/About/FlipView.swift b/Tusker/Screens/Preferences/About/FlipView.swift index d288ea2e..8da72327 100644 --- a/Tusker/Screens/Preferences/About/FlipView.swift +++ b/Tusker/Screens/Preferences/About/FlipView.swift @@ -107,7 +107,7 @@ struct FlipEffect: GeometryEffect { } private struct WidthPrefKey: PreferenceKey { - static var defaultValue: CGFloat = 0 + static let defaultValue: CGFloat = 0 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = nextValue() diff --git a/Tusker/Screens/Preferences/AcknowledgementsView.swift b/Tusker/Screens/Preferences/AcknowledgementsView.swift index 33c2db7b..548ca726 100644 --- a/Tusker/Screens/Preferences/AcknowledgementsView.swift +++ b/Tusker/Screens/Preferences/AcknowledgementsView.swift @@ -292,7 +292,7 @@ private extension AttributeScopes { private enum HeadingLevelAttributes: CodableAttributedStringKey, MarkdownDecodableAttributedStringKey { public typealias Value = Int - public static var name = "headingLevel" + public static let name = "headingLevel" } private extension AttributeDynamicLookup { diff --git a/Tusker/Screens/Preferences/Tip Jar/ConfettiView.swift b/Tusker/Screens/Preferences/Tip Jar/ConfettiView.swift index 7997a2a9..038aa06d 100644 --- a/Tusker/Screens/Preferences/Tip Jar/ConfettiView.swift +++ b/Tusker/Screens/Preferences/Tip Jar/ConfettiView.swift @@ -59,7 +59,7 @@ struct ConfettiView: View { } private struct SizeKey: PreferenceKey { - static var defaultValue: CGSize = .zero + static let defaultValue: CGSize = .zero static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() } diff --git a/Tusker/Screens/Preferences/Tip Jar/TipJarView.swift b/Tusker/Screens/Preferences/Tip Jar/TipJarView.swift index 2b72bc80..f7a0180d 100644 --- a/Tusker/Screens/Preferences/Tip Jar/TipJarView.swift +++ b/Tusker/Screens/Preferences/Tip Jar/TipJarView.swift @@ -44,7 +44,7 @@ struct TipJarView: View { Text(error.localizedDescription) }) .task { - updatesObserver = Task.detached { + updatesObserver = Task.detached { @MainActor in await observeTransactionUpdates() } do { @@ -95,6 +95,7 @@ struct TipJarView: View { } } + @MainActor private func observeTransactionUpdates() async { for await verificationResult in StoreKit.Transaction.updates { guard let index = products.firstIndex(where: { $0.0.id == verificationResult.unsafePayloadValue.productID }) else { @@ -175,6 +176,7 @@ private struct TipRow: View { } } + @MainActor private func purchase() async { isPurchasing = true let result: Product.PurchaseResult @@ -229,7 +231,7 @@ extension HorizontalAlignment { } private struct ButtonWidthKey: PreferenceKey { - static var defaultValue: CGFloat = 0 + static let defaultValue: CGFloat = 0 static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = max(value, nextValue()) }