feat(typing): wire PersonalDictionary into Chinese Pinyin via Rime sidecar

Redeploy an osg_personal import table on dictionary add/delete/sync so
Chinese, English typing, and ASR share one curated lexicon (next keyboard open).
This commit is contained in:
Rocky
2026-08-05 22:12:30 +08:00
parent 31f5937a7f
commit 717902716a
11 changed files with 665 additions and 14 deletions
@@ -1,9 +1,10 @@
// PersonalDictionary.swift
// OSGKeyboard · Shared
//
// User-curated list of terms the LLM must never rewrite. Persisted
// in the App Group (JSON-encoded) so both the main app's Settings
// UI and the keyboard extension's LLM call read the same data.
// User-curated list of terms shared across polish, ASR bias, English
// typing hotwords, and (via host Rime redeploy) Chinese Pinyin candidates.
// Persisted in the App Group (JSON-encoded) so the main app, keyboard
// extension, and host deploy pipeline read the same data.
//
// Sources (mutually exclusive per entry):
// - `.manual` user typed it in by hand
@@ -78,6 +78,7 @@ public final class TypingInputConfiguration: ObservableObject {
static let rememberLastSurface = "typing.input.rememberLastSurface"
static let lastSurface = "typing.input.lastSurface"
static let resourceVersion = "typing.rime.resourceVersion"
static let personalDictionaryFingerprint = "typing.rime.personalDictionaryFingerprint"
}
private let defaults: UserDefaults
@@ -187,6 +188,21 @@ public final class TypingInputConfiguration: ObservableObject {
(defaults ?? AppGroup.defaultsIfAvailable)?.set(value, forKey: Key.resourceVersion)
}
nonisolated public static func installedPersonalDictionaryFingerprint(
defaults: UserDefaults? = nil
) -> String? {
(defaults ?? AppGroup.defaultsIfAvailable)?
.string(forKey: Key.personalDictionaryFingerprint)
}
nonisolated public static func setInstalledPersonalDictionaryFingerprint(
_ value: String,
defaults: UserDefaults? = nil
) {
(defaults ?? AppGroup.defaultsIfAvailable)?
.set(value, forKey: Key.personalDictionaryFingerprint)
}
private func persistIfReady() {
guard !isHydrating else { return }
defaults.set(schema.rawValue, forKey: Key.schema)