refactor(concurrency): isolate ProviderConfig to the main actor and drop unneeded @unchecked Sendable
- ProviderConfig is now @MainActor instead of @unchecked Sendable; AppL10n reads the persisted UI language key directly so off-main string lookups stay valid. - EnglishLearningStore serializes its read-modify-write with a type-wide lock (several instances share one defaults key). - URLSession-only transports, GatewayGrantKeychainStore and Keychain conform to Sendable without @unchecked. UserDefaults/DeviceCheck wrappers keep @unchecked because those SDK types are not Sendable.
This commit is contained in:
@@ -12,7 +12,7 @@ protocol PublicContentHTTPTransport: Sendable {
|
||||
|
||||
final class URLSessionPublicContentHTTPTransport:
|
||||
PublicContentHTTPTransport,
|
||||
@unchecked Sendable {
|
||||
Sendable {
|
||||
private let session: URLSession
|
||||
|
||||
init(session: URLSession = .shared) {
|
||||
|
||||
@@ -30,9 +30,16 @@ enum AppL10n {
|
||||
/// screen that exists so a provisioning mistake does *not* become a crash
|
||||
/// loop. `.auto` follows the system language, which is the right answer
|
||||
/// when no stored preference is reachable anyway.
|
||||
///
|
||||
/// Reads the persisted key directly rather than `ProviderConfig.shared`
|
||||
/// (main-actor isolated) because localized strings are also resolved off
|
||||
/// the main actor. `ProviderConfig` writes this key synchronously in its
|
||||
/// `uiLanguage` didSet, so both paths observe the same value.
|
||||
private static var resolvedUILanguage: AppUILanguage {
|
||||
guard AppGroup.isAvailable else { return .auto }
|
||||
return ProviderConfig.shared.uiLanguage
|
||||
guard let defaults = AppGroup.defaultsIfAvailable else { return .auto }
|
||||
return AppUILanguage.fromStored(
|
||||
defaults.string(forKey: AppGroupConfiguration.Keys.uiLanguage)
|
||||
)
|
||||
}
|
||||
|
||||
static func format(
|
||||
|
||||
@@ -91,6 +91,7 @@ struct SettingsVersionRow: View {
|
||||
|
||||
// MARK: - Config entry summaries (shown on Settings home)
|
||||
|
||||
@MainActor
|
||||
enum SettingsConfigSummary {
|
||||
static func speechRecognition(config: ProviderConfig) -> String {
|
||||
if config.engineMode == "local" {
|
||||
|
||||
Reference in New Issue
Block a user