feat: iCloud settings sync and cold-start return redesign

- Add iCloud key-value settings sync (engine/language/polish/Flow prefs);
  API keys stay on-device. New "Sync settings via iCloud" toggle.
- Redesign cold-start handoff: bottom-bar left-to-right swipe guidance,
  auto-dismiss on app switch, tap-anywhere to close, retained return link.
- Harden keyboard->app handoff with host-disconnected hint.
- Include prior Unreleased ASR fixes (route-change crash, fallback warning,
  multi-utterance recognition, local ASR diagnostics).

Release 0.5.0 (build 18).
This commit is contained in:
Rocky
2026-07-07 17:56:01 +08:00
parent bf844caa7f
commit 128aab1b02
42 changed files with 1818 additions and 337 deletions
@@ -8,23 +8,7 @@ import XCTest
// MARK: - Fake KVS
private final class FakeUbiquitousKeyValueStore: UbiquitousKeyValueStoreing, @unchecked Sendable {
private var storage: [String: Data] = [:]
func data(forKey key: String) -> Data? {
storage[key]
}
func set(_ value: Data?, forKey key: String) {
if let value {
storage[key] = value
} else {
storage.removeValue(forKey: key)
}
}
func synchronize() -> Bool { true }
}
// See FakeUbiquitousKeyValueStore.swift
// MARK: - Tests
@@ -170,6 +154,7 @@ final class PersonalDictionaryCloudSyncTests: XCTestCase {
try await sync.enableSync()
XCTAssertTrue(store.personalDictionaryICloudSyncEnabled)
XCTAssertEqual(kvs.object(forKey: ICloudSyncPreferences.dictionaryEnabledKey) as? Bool, true)
XCTAssertEqual(Set(store.personalDictionary.entries.map(\.term)), Set(["LocalTerm", "RemoteTerm"]))
XCTAssertNotNil(sync.loadRemote())
}