fix: keyboard stability, host-only analytics, and auto-reply dedupe
- record analytics/usage only in the host app; the extension no longer opens the SQLite queues, so hiding the keyboard cannot hold WAL locks (0xdead10cc) - sync clipboard history writes across processes so deletes made on one side are not reverted by the other - guard memory-relief reentrancy on controller and telemetry sides to break the recursive crash loop - resolve credentials off the main thread and migrate legacy keys once per install, so Keychain reads cannot be caught in the suspend window - gate Volcengine ASR ping completion to once (SIGTRAP on double resume) - treat same-text captures as the same logical copy and dedupe auto actions by content fingerprint within 30s, stopping Universal Clipboard storms - realign version line to 2.1.0 (build 110)
This commit is contained in:
@@ -312,6 +312,9 @@ public struct AnalyticsRuntime: Sendable {
|
||||
|
||||
/// Main-app runtime. A bearer provider may be supplied by host-only account
|
||||
/// code without making the shared framework depend on that code.
|
||||
/// Production keyboard-extension processes must not construct this runtime
|
||||
/// (or any other SQLite-backed analytics client): an open WAL connection is
|
||||
/// killed as RunningBoard `0xdead10cc` when the keyboard hides.
|
||||
public static func mainApp(
|
||||
environment: AnalyticsEnvironment,
|
||||
repositoryConfiguration: AnalyticsRepositoryConfiguration = .appGroupDefault(),
|
||||
@@ -341,36 +344,6 @@ public struct AnalyticsRuntime: Sendable {
|
||||
)
|
||||
}
|
||||
|
||||
/// Keyboard-extension runtime. This factory intentionally has no bearer
|
||||
/// parameter, so extension uploads are anonymous by construction.
|
||||
public static func keyboardExtension(
|
||||
environment: AnalyticsEnvironment,
|
||||
repositoryConfiguration: AnalyticsRepositoryConfiguration = .appGroupDefault(),
|
||||
uploadConfiguration: AnalyticsUploadConfiguration,
|
||||
network: any AnalyticsNetworking = URLSessionAnalyticsNetwork(),
|
||||
wallClock: any AnalyticsWallClock = SystemAnalyticsWallClock(),
|
||||
monotonicClock: any AnalyticsMonotonicClock = SystemAnalyticsMonotonicClock(),
|
||||
uuidGenerator: any AnalyticsUUIDGenerating = SystemAnalyticsUUIDGenerator(),
|
||||
random: any AnalyticsRandomGenerating = SystemAnalyticsRandomGenerator(),
|
||||
trigger: any AnalyticsUploadTriggering = NoopAnalyticsUploadTrigger(),
|
||||
logger: any AnalyticsLogging = NoopAnalyticsLogger()
|
||||
) -> Self {
|
||||
Self(
|
||||
surface: .keyboard,
|
||||
environment: environment,
|
||||
repositoryConfiguration: repositoryConfiguration,
|
||||
uploadConfiguration: uploadConfiguration,
|
||||
network: network,
|
||||
bearerProvider: nil,
|
||||
wallClock: wallClock,
|
||||
monotonicClock: monotonicClock,
|
||||
uuidGenerator: uuidGenerator,
|
||||
random: random,
|
||||
trigger: trigger,
|
||||
logger: logger
|
||||
)
|
||||
}
|
||||
|
||||
public func setEnabled(_ enabled: Bool) async {
|
||||
await repository.setEnabled(enabled)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user