diff --git a/CHANGELOG.md b/CHANGELOG.md index c277e06..9df6482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Host-only analytics recording**: the keyboard extension no longer opens the analytics or keyboard-usage SQLite queues. The host app is the only process that records and uploads events, so hiding the keyboard cannot hold WAL locks and get killed as `0xdead10cc`. Keyboard-activated and per-keystroke usage events are no longer collected. / **仅主 App 记埋点**:键盘扩展不再打开统计与键盘用量 SQLite 队列;开库、记账与上传只在主 App 进行,收起键盘时不会因 WAL 锁被系统以 `0xdead10cc` 终止。不再采集「键盘激活」和逐次按键用量。 ### Fixed +- **Keyboard killed after hiding on pinyin**: hiding the keyboard while the pinyin/English typing surface was showing kept librime's user dictionary open, and its LevelDB `LOCK` file in the shared App Group got the suspended extension killed as `0xdead10cc` (about 30 kills in 3 days on one test device). The typing engine is now closed on every hide and reopened on the next show, which adds about 30–50 ms only when a still-running keyboard is reopened. / **拼音界面收起后键盘被系统终止**:在拼音/英文打字界面收起键盘时,librime 用户词库仍保持打开,其位于共享 App Group 的 LevelDB `LOCK` 文件导致挂起的扩展被系统以 `0xdead10cc` 终止(一台测试机 3 天约 30 次)。现在每次收起都会关闭打字引擎、下次弹出时重新打开,仅在复用仍存活的键盘进程时多约 30–50 毫秒。 - **Misleading edit hint after insertion**: stop showing “Hold to edit your last input” for 10 seconds after every insertion. Holding the microphone asks AI; editing the last input uses the pencil button beside it. / **插入后的误导性编辑提示**:每次插入后不再显示 10 秒的「长按编辑上一条」。长按麦克风是向 AI 提问,编辑上一条请使用旁边的铅笔按钮。 - **Saving invitation posters**: declare add-only Photos access in the built app and preflight the privacy description before calling PhotoKit, preventing Save Image from terminating the app when the generated project configuration is stale. / **保存邀请海报**:在 App 构建配置中声明“仅添加照片”权限,并在调用 PhotoKit 前检查权限说明,避免生成的工程配置过期时点击“保存图片”导致 App 被系统终止。 - **Invitation redemption retrying forever**: an invitation the server permanently rejected (unknown code, self-referral, already bound, or binding window expired) stayed stored and was retried on every sign-in. These rejections now show a specific message and drop the stored code; network failures still retry. / **邀请兑换无限重试**:服务器明确拒绝的邀请(邀请码无效、邀请自己、已绑定或超出绑定期限)会一直保留并在每次登录时重试。现在这些情况会给出具体提示并清除暂存的邀请码;网络失败仍会重试。 diff --git a/OSGKeyboardExt/KeyboardViewController.swift b/OSGKeyboardExt/KeyboardViewController.swift index 24cc549..29c3e53 100644 --- a/OSGKeyboardExt/KeyboardViewController.swift +++ b/OSGKeyboardExt/KeyboardViewController.swift @@ -269,9 +269,11 @@ public final class KeyboardViewController: UIInputViewController { if !preserve { prepareSurfaceForNextPresentation() } - if state.surface != .typing { - deactivateTypingSurface() - } + // Always finalize librime on hide, even on the typing surface: its + // LevelDB userdb holds `Rime/UserData/*.userdb/LOCK` in the App Group, + // and RunningBoard kills a suspended extension holding that lock + // (0xdead10cc). `viewWillAppear` re-prepares Rime (~30–50 ms). + deactivateTypingSurface() if preserve { return } diff --git a/OSGKeyboardShared/Typing/LibrimeEngine.swift b/OSGKeyboardShared/Typing/LibrimeEngine.swift index 329e43c..3474ad4 100644 --- a/OSGKeyboardShared/Typing/LibrimeEngine.swift +++ b/OSGKeyboardShared/Typing/LibrimeEngine.swift @@ -47,7 +47,9 @@ public final class LibrimeEngine: RimeEngineBridging { let configured = configurationProvider() schema = configured.schema guard runtime.selectSchema(schema.rawValue) else { - runtime.stopSession() + // `start()` already initialized the shared runtime; finalize it so + // no user dictionary stays open without an owning bridge. + runtime.finalizeRuntime() throw LibrimeEngineError.schemaUnavailable(schema.rawValue) } _ = runtime.setASCIIMode(language == .english)