chore: snapshot uncommitted local work before rebasing onto cloud-agent
Safety commit so the 94 uncommitted files in the working tree (in-flight Account/Mac/Tip work plus the feature-preview recording tooling) survive the move onto cursor/cloud-agent-1787824905651-vxuwc. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@@ -105,8 +105,8 @@ difference until the server request schema supports them.
|
||||
|
||||
## StoreKit credits
|
||||
|
||||
The existing `ByRockyACoffee` product remains a voluntary consumable and never
|
||||
grants credits. Configure `500tks` for 500 credits at USD 0.99, `1500tks` for
|
||||
The app ships three consumable credit packs and no other in-app purchase.
|
||||
Configure `500tks` for 500 credits at USD 0.99, `1500tks` for
|
||||
1,500 credits at USD 1.99 / CNY 18, and `3000tks` for 3,000 credits at
|
||||
USD 2.99 / CNY 28.
|
||||
|
||||
@@ -123,5 +123,4 @@ USD 2.99 / CNY 28.
|
||||
once.
|
||||
6. Sign in to another OSG account and verify the first account's transaction is
|
||||
rejected.
|
||||
7. Confirm there is no Restore Purchases action for credit packs and that the
|
||||
voluntary tip still changes only the local support count.
|
||||
7. Confirm there is no Restore Purchases action for credit packs.
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Price | Free |
|
||||
| In-App Purchases | Optional consumables: tip `ByRockyACoffee`; managed-credit packs `500tks`, `1500tks`, `3000tks` |
|
||||
| In-App Purchases | Optional consumables: managed-credit packs `500tks`, `1500tks`, `3000tks` |
|
||||
| Availability | All configured App Store territories |
|
||||
| Pre-order | No |
|
||||
|
||||
@@ -153,16 +153,14 @@ OSGKeyboard is a custom keyboard for iOS/iPadOS 26.
|
||||
transactions are finished.
|
||||
7. AI polish and AI mode can use either managed credits or a user-owned
|
||||
provider key. Without either, local dictation still inserts recognized text.
|
||||
8. Optional tip `ByRockyACoffee` remains a consumable support purchase and
|
||||
does not grant managed credits or unlock features.
|
||||
9. Clipboard history is off by default. To test it, open Settings →
|
||||
8. Clipboard history is off by default. To test it, open Settings →
|
||||
Clipboard, enable History, copy text on this device or through Universal
|
||||
Clipboard, then return to the keyboard. Secure fields hide the clipboard
|
||||
entry point. Turning History off preserves saved items; use the separate
|
||||
confirmed clear action to delete them.
|
||||
10. First-party Product Analytics is enabled by default under Settings →
|
||||
About → Privacy. Turning it off deletes queued events. It does not collect
|
||||
keyboard input, audio, transcripts, prompts, model output, or credentials.
|
||||
9. First-party Product Analytics is enabled by default under Settings →
|
||||
About → Privacy. Turning it off deletes queued events. It does not collect
|
||||
keyboard input, audio, transcripts, prompts, model output, or credentials.
|
||||
|
||||
Privacy policy:
|
||||
https://hkgood.github.io/OSGKeyboard/privacy/
|
||||
@@ -280,17 +278,50 @@ output, audio, or keyboard content.
|
||||
`Info.plist` declares `ITSAppUsesNonExemptEncryption = false`. Network calls use
|
||||
standard HTTPS. Re-evaluate this answer if non-exempt cryptography is added.
|
||||
|
||||
## Screenshots
|
||||
|
||||
OSGKeyboard ships for **iPhone and iPad** (`TARGETED_DEVICE_FAMILY: "1,2"`), so
|
||||
both device families need screenshots. Apple scales one uploaded set down to
|
||||
smaller devices, so only the largest size per family is required.
|
||||
|
||||
| Set | Capture device | Pixel size | Required |
|
||||
|---|---|---|---|
|
||||
| iPhone 6.9" | iPhone 17 Pro Max | 1320 × 2868 (or 1290 × 2796) | Yes |
|
||||
| iPad 13" | iPad Pro 13" (M4) | 2064 × 2752 (or 2048 × 2732) | Yes, because the app supports iPad |
|
||||
|
||||
Apple adjusts accepted sizes over time — confirm the current list in the
|
||||
App Store Connect media manager before capturing.
|
||||
|
||||
### Capture procedure
|
||||
|
||||
1. Run the **submitted build** on the simulators above (Xcode 26).
|
||||
2. Capture with `xcrun simctl io booted screenshot ~/Desktop/shot.png`.
|
||||
Simulator captures contain no device bezel, which Apple requires.
|
||||
3. Verify pixel dimensions; do not upscale a smaller capture.
|
||||
4. Upload per device family in App Store Connect. Screenshots are **not**
|
||||
stored in this repository; `docs/assets/screenshots/` holds the smaller,
|
||||
web-optimized images used by the GitHub Pages site only.
|
||||
|
||||
### Scenes, in order
|
||||
|
||||
1. **Keyboard at rest** — OSGKeyboard in a text field, not recording
|
||||
2. **Dictation in progress** — recording state with a partial transcript visible
|
||||
3. **Chinese / English typing** — candidate bar with pinyin candidates or the
|
||||
three-slot English QuickType bar
|
||||
4. **AI assistant** — a streamed answer inside the keyboard before insertion
|
||||
5. **Clipboard skills** — recommended actions after a copy
|
||||
6. **Home** — monthly usage calendar, metrics, and personal dictionary
|
||||
|
||||
## Submission checklist
|
||||
|
||||
- [ ] Confirm `project.yml` still reads version 2.0.3 / build 94
|
||||
- [ ] Open the existing Xcode project (do not regenerate unless needed)
|
||||
- [ ] Run the release build and test suites on macOS with Xcode 26
|
||||
- [ ] Replace screenshots with captures from the submitted build
|
||||
- [ ] Capture fresh iPhone 6.9" and iPad 13" screenshots from the submitted
|
||||
build (see Screenshots above)
|
||||
- [ ] Verify the privacy answers against the submitted provider features
|
||||
- [ ] In App Store Connect, add Device ID, Product Interaction, and Other
|
||||
Usage Data for Analytics; linked to the user, not used for tracking
|
||||
- [ ] Confirm `500tks`, `1500tks`, and `3000tks` are approved, consumable,
|
||||
and mapped to the server credit catalog
|
||||
- [ ] Confirm `ByRockyACoffee` remains an optional consumable tip and unlocks
|
||||
no feature
|
||||
- [ ] Upload, select build 94, add review notes, and submit
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# 功能预览片录制 / Feature preview recording
|
||||
|
||||
四段中文 App Store 预览片的录制与合成流程。成片位于
|
||||
`docs/assets/app-preview/zh/OSGKeyboard-<slug>-6.7-zh.mp4`。
|
||||
|
||||
| slug | 讲什么 | 素材来源 |
|
||||
|------|--------|----------|
|
||||
| `voice-polish` | 语音输入与自动润色,收在趣味润色风格 | `--edit-demo` + 润色风格页 |
|
||||
| `personal-style` | 从历史听写学习你的表达习惯,生成专属风格 | `--polish-styles-screenshot` |
|
||||
| `clipboard-agent` | 剪贴板 AI Agent,一键回复消息 | `--clipboard-demo` |
|
||||
| `ask-ai` | 轻点听写、长按问 AI | `--ai-demo` |
|
||||
|
||||
## 为什么不用键盘扩展录
|
||||
|
||||
`WhatsNewDemoDriver` 那条路(`--whats-new-host`)会让**真实键盘扩展**盖在
|
||||
Notes 宿主上,画面最真。但把第三方键盘设成**当前**输入法必须点一下地球键,
|
||||
`simctl` 没有对应命令,`.GlobalPreferences` 里的 `AppleKeyboards` 只决定
|
||||
"已启用"而不是"当前使用"。
|
||||
|
||||
所以这套流程改走 app 内的 DEBUG demo host:它们渲染的是**同一批真实键盘视图**
|
||||
(`AIKeyboardView`、`LastInputEditView`、`ClipboardHistoryPanelView`……,见
|
||||
`project.yml` 中 app target 的 `OSGKeyboardExt/Views/*` 源),由脚本化的
|
||||
`KeyboardState` 驱动,不走 ASR、不走 LLM、不联网,也就不需要任何点击。
|
||||
|
||||
`--preview-fullscreen` 会在键盘上方补一块 Notes / Messages 宿主文档
|
||||
(`FeaturePreviewHostDocument`),把原本留给 What's New 裁剪的空白填满,
|
||||
让整帧可以直接当全屏预览片用。不传这个 flag 时,各 demo view 的画面与
|
||||
What's New 工作流完全一致。
|
||||
|
||||
## 设备要求
|
||||
|
||||
- **iPhone 16 Plus**:原生 1290×2796,正好是 App Store Connect 6.9" 预览位
|
||||
接受的尺寸之一,零缩放。
|
||||
- **iOS 26.5 或更新**:app 用到的 `SwiftUI.View.glassEffect(_:in:)` 在 iOS 26.0
|
||||
运行时里不存在,装上去会在启动时 `Symbol not found` 崩溃。
|
||||
|
||||
Xcode 预置的 iPhone 16 Plus 挂在 iOS 26.0 下,需要自建一台:
|
||||
|
||||
```bash
|
||||
xcrun simctl create "OSG-Preview-16Plus" \
|
||||
com.apple.CoreSimulator.SimDeviceType.iPhone-16-Plus \
|
||||
com.apple.CoreSimulator.SimRuntime.iOS-26-5
|
||||
```
|
||||
|
||||
## 完整流程
|
||||
|
||||
```bash
|
||||
# 1) 编译(必须带签名,否则没有 entitlements → App Group 不可用 → 启动崩溃)
|
||||
xcodebuild -project OSGKeyboard.xcodeproj -scheme OSGKeyboard \
|
||||
-configuration Debug -destination "id=$UDID" \
|
||||
-onlyUsePackageVersionsFromResolvedFile CODE_SIGNING_ALLOWED=YES build
|
||||
|
||||
# 2) 干净安装。覆盖安装不会刷新 App Group 容器,
|
||||
# 容器缺失时 app 会渲染 AppGroupErrorView,录出来就是一屏报错。
|
||||
xcrun simctl uninstall "$UDID" com.osgkeyboard.ios
|
||||
xcrun simctl install "$UDID" \
|
||||
~/Library/Developer/Xcode/DerivedData/OSGKeyboard-*/Build/Products/Debug-iphonesimulator/OSGKeyboard.app
|
||||
|
||||
# 3) 录制(脚本会先校验 App Group 容器,缺失直接报错退出)
|
||||
Scripts/record_feature_previews.sh "$UDID" # 全部四段
|
||||
Scripts/record_feature_previews.sh "$UDID" ask-ai # 只录一段
|
||||
|
||||
# 4) 合成。需要 Pillow —— 这版 ffmpeg 没有 libfreetype / libass,
|
||||
# 所有文字都由 PIL 渲染成 RGBA PNG 再 overlay。
|
||||
python3 -m venv .venv && .venv/bin/pip install Pillow
|
||||
.venv/bin/python Scripts/compose_feature_previews.py
|
||||
```
|
||||
|
||||
## 已知的坑
|
||||
|
||||
**变帧率**。`simctl io recordVideo` 录的是 VFR,时间轴不按墙钟走:直接
|
||||
`-ss` 会定位到错误位置,`-t` 截出来的长度也不对(实测 24s 的窗口出来 27.4s,
|
||||
足以让成片超出 App Store 的 30 秒上限)。`compose_feature_previews.py` 会先把
|
||||
每段原始素材转成 30fps CFR 再裁,所以配置里的 `trim_start` / `trim_duration`
|
||||
是真实秒数。
|
||||
|
||||
**静态页面录不出长片**。VFR 只在画面变化时出帧,纯静态页面录 22 秒也只得到
|
||||
约 5 秒素材。`Source(freeze_at=…)` 会抽一帧定格,配合 `ken_burns` 用运镜提供
|
||||
动势 —— `personal-style` 就是这么做的。
|
||||
|
||||
**字幕 PNG 必须 `-loop 1`**。单帧输入的 pts 恒为 0,`fade` 的时间轴永远停在
|
||||
起点,alpha 被钉死,字幕完全不显示。
|
||||
|
||||
**色彩标签会丢**。原始素材是 `tv` range / bt709 / sRGB transfer,重编码不显式
|
||||
带上就变成 `unknown`,播放器猜错会明显发灰。合成脚本每一次编码都显式打标签。
|
||||
|
||||
**抽帧检查会骗你**。用 ffmpeg 抽出 PNG 再看,色彩管理与实际播放不同,画面会
|
||||
偏灰;判断压暗层强度请量像素值,不要看缩略图。
|
||||
|
||||
## App 内卡片版(无字幕短循环)
|
||||
|
||||
同一批原始素材还会产出第二种成品:给 app 内卡片用的短循环,位于
|
||||
`docs/assets/feature-cards/<slug>.mp4`,另附 `<slug>-poster.png` 作占位图。
|
||||
|
||||
```bash
|
||||
.venv/bin/python Scripts/compose_feature_cards.py
|
||||
```
|
||||
|
||||
与预览片的区别:**没有字幕、没有片头片尾、没有音轨**,并且裁到键盘区
|
||||
(`1290×944`),画面里只有真实键盘 chrome,不含任何为讲故事补的宿主界面。
|
||||
|
||||
窗口都选在首尾状态相近的位置,再叠一次 0.5 秒的尾接头淡入,所以可以无限循环
|
||||
播放而看不出接缝(实测首末帧平均像素差 0.19–0.57 / 255)。`personal-style` 是
|
||||
静态设置页,改用推近再拉回的对称运镜,天然闭合。
|
||||
|
||||
裁切区取 `y=1780` 起、高 944:剪贴板面板是键盘区里最高的元素(顶边 y=1779),
|
||||
屏幕最底部 72px 是键盘下方的空白内边距,一并去掉。
|
||||
|
||||
### 技能行必须由真实排序器产生
|
||||
|
||||
`AIKeyboardView` 的技能行读 `ClipboardHistoryStore.shared` 与
|
||||
`ClipboardSemanticRankingStore.shared` 两个**单例**,并交给
|
||||
`ClipboardSkillSemanticRanker.recommended(...)` 按剪贴板内容排序。demo view 早期
|
||||
用私有 store + `AIKeyboardView.debugPreviewSkills` 强塞了一排回复风格,结果录出
|
||||
一个真实 app 里**不可能出现**的键盘——排序器在通用「回复」之外最多只放
|
||||
`maximumReplyRecommendations = 2` 个专门回复技能。
|
||||
|
||||
现在 `ClipboardHistoryDemoView` 直接喂真实单例:把要回复的那条消息 ingest 成
|
||||
最新剪贴板项,调 `ranking.analyze(entry)` 并**等它出 snapshot**(分析在主 actor 外
|
||||
跑,抢跑会让行退化成孤零零一个「回复」),然后由排序器决定行内容。当前这条
|
||||
消息排出的是「译为英语 / 回复 / 澄清追问 / 日程」。
|
||||
|
||||
演示脚本只从排出来的行里挑技能点——先点通用「回复」,再点行内第一个
|
||||
`supportsReplyStyle` 的技能——所以画面里点的永远是屏幕上真实存在的 chip。
|
||||
|
||||
app 里**没有**「点一次回复,弹出多条候选」这种交互:点一个技能生成一条。
|
||||
多风格是靠技能行里并列的多个回复技能实现的,先选风格再生成。
|
||||
|
||||
一个容易踩的坑:`AISessionState` 的 `beginGenerating` / `receivePartialAnswer` /
|
||||
`receiveAnswer` 都用 `activeUtteranceID == utteranceID` 做守卫,而这个 ID 只由
|
||||
`beginPreparing` 设置。跳过 `beginPreparing` 直接 `beginGenerating`,整串调用会
|
||||
**静默变成空操作**,键盘区从头到尾不出现任何答案。每一轮都要
|
||||
`enter()` → `beginPreparing` → `beginGenerating`。
|
||||
|
||||
两个 ffmpeg 细节:`zoompan` 的 `d=1` 是按输入帧走的,而 `-loop 1` 读 PNG 默认
|
||||
**25fps**,不加 `-framerate 30` 出来的片长会短 25/30;另外推拉运镜不要用单条
|
||||
`zoompan` 表达式同时做进和出——它的实际出帧数对不上 `duration * FPS`,片子会
|
||||
停在半路,循环处肉眼可见地跳。现在的做法是只渲染推近的一半再 `reverse` 拼接。
|
||||
|
||||
## 改动了 demo 时间轴之后
|
||||
|
||||
`Scripts/feature_preview_clips.py` 里的裁切点和字幕时间是照着实际录像量出来的。
|
||||
只要改了 `EditDemoView` / `AIKeyboardDemoView` / `ClipboardHistoryDemoView` 的
|
||||
时间轴,就要重录并重新对时。合成脚本会校验成片是否落在 App Store 要求的
|
||||
15–30 秒、1290×2796、H.264 之内,不合规会在输出里标 `!!`。
|
||||
@@ -1,109 +0,0 @@
|
||||
# OSGKeyboard 1.8.0 更新说明
|
||||
|
||||
> 以下为 OSGKeyboard 从 1.6.6 升级至 1.8.0 的关键变化。
|
||||
|
||||
## 新功能
|
||||
|
||||
### AI Agent
|
||||
|
||||
- 语音听写与 AI 问答合并为全新的助手模式:轻点麦克风开始听写,长按麦克风可直接语音提问。
|
||||
- 新增热点与情境热词,麦克风区域会展示天气、节日、新闻、热搜等建议;点按即可向 AI 获取相关信息。
|
||||
- AI 回答会实时显示在键盘中,确认后可插入当前输入框;支持的服务商可联网搜索,并在失败时自动回退。
|
||||
- 仅当原输入框与光标上下文仍然匹配时自动插入 AI 回答;上下文变化时会保留回答,等待用户明确插入或丢弃。
|
||||
- 设置 → AI Agent 可调节回复篇幅:简短、中等或详细。
|
||||
|
||||
### 剪贴板与 AI 技能
|
||||
|
||||
- 新增剪贴板历史。在设置 → 剪贴板开启“历史记录”后,可在本机保存最近 15 条纯文本;该功能默认关闭。
|
||||
- 新增剪贴板建议条。可从键盘顶栏打开历史并点按插入;开启建议条后,最新复制内容会显示在键盘上方。
|
||||
- 复制文字后约 30 秒内,助手会显示回复、总结、翻译等快捷技能;技能支持分页浏览,并可在技能页调整顺序。
|
||||
- 新增技能页,最多可将 8 个技能放入键盘。内置技能可提取待办、添加日历日程、存入备忘录,或识别地址后打开高德、百度与 Apple 地图导航。
|
||||
- 新增自定义 AI 技能,可设置名称、图标和提示词,也可选择连接自己的 iCloud 快捷指令。
|
||||
|
||||
### 编辑上次输入
|
||||
|
||||
- 编辑入口移至键盘右下角。点按后可口述修改要求、对比原文与编辑结果,并选择替换原文或追加内容。
|
||||
- 编辑只使用最近一次由 OSGKeyboard 插入且仍可验证的文字,不会读取输入框中的无关内容。
|
||||
|
||||
## 全新 App 界面
|
||||
|
||||
- iPhone 底部导航重做为“首页 / 技能 / 风格 / 设置”四栏 Liquid Glass Dock,并以绿色胶囊标示当前页面。
|
||||
- 首页改为信息总览,将使用统计、听写历史和个性词库集中显示为资料卡。
|
||||
- 技能与润色风格采用统一的卡片式管理:点按选择、右上角编辑、右下角显示启用状态;技能支持长按拖动排序。
|
||||
- 设置入口重新整理,AI Agent、剪贴板、语音与文字输入等页面更容易找到,并直接显示当前设置摘要。
|
||||
- iPad 改为侧栏 + 内容区布局;键盘横竖屏均充分利用可用宽度,并加入系统地球键、撤销、重做、复制和剪切等操作。
|
||||
|
||||
## 中英文输入全面升级
|
||||
|
||||
- 中英文输入均可在本机学习用户的输入习惯、候选频率和选择偏好;设置中可单独清除打字习惯,不会删除个性词库。
|
||||
- 拼音优化混合简拼排序,并支持 `zh`、`ch`、`sh` 两键简拼。
|
||||
- 英文键盘新增类 QuickType 候选栏,同时显示原词、纠错和补全;约 4 万词离线词表会结合系统词库、通讯录名称与文本替换提供建议。
|
||||
- 英文邻键纠错更贴合真实键位,并减少对专名、短词和全大写词的误改;拒绝纠错后会学习保留原词。
|
||||
- 支持叠指连打、英文双空格句号,以及根据输入框显示前往、搜索、发送、完成、下一项等操作。
|
||||
|
||||
## 稳定性、隐私与重要变化
|
||||
|
||||
- 听写、AI 回答、编辑结果和剪贴板粘贴可通过统一的撤销操作回滚。
|
||||
- 修复切换键盘崩溃、中文输入初始化后无法恢复、通用剪贴板导致键盘卡住,以及 AI 会话结束后麦克风不可用等问题。
|
||||
- 全部内置与自定义润色风格都会保留问句原意,不再把用户的问题改写成回答。
|
||||
- 设备端语音识别仍为默认选项;AI 使用用户自己配置的服务商与 API Key,不再提供内置 DeepSeek 回退。
|
||||
- 剪贴板历史默认关闭,内容保存在本机,并仅在用户主动调用技能后发送给所配置的 AI 服务商。
|
||||
- 长按麦克风现用于向 AI 提问;编辑上次输入改用右下角编辑按钮。旧的长按剪贴板语音指令已由剪贴板历史和快捷技能取代。
|
||||
- 已安装旧中文名称“待办”或“日程”快捷指令的用户,需要从技能页重新安装 `OSGExtractTodos` 和 `OSGExtractEvents`。
|
||||
- 已移除空白区域滑动光标及其设置开关。
|
||||
|
||||
---
|
||||
|
||||
# OSGKeyboard 1.8.0 Release Notes
|
||||
|
||||
> Key changes when upgrading OSGKeyboard from 1.6.6 to 1.8.0.
|
||||
|
||||
## New Features
|
||||
|
||||
### AI Agent
|
||||
|
||||
- Voice dictation and AI questions now share one Assistant mode: tap the microphone to dictate, or hold it to ask a question by voice.
|
||||
- New trending and contextual hotwords surface suggestions for weather, holidays, news, trending topics, and more; tap one to ask AI about it.
|
||||
- AI answers stream directly into the keyboard for review and insertion. Supported providers can search the web and fall back automatically when needed.
|
||||
- AI answers insert automatically only while the original field and cursor context still match. If the context changes, the answer is retained for explicit insertion or discard.
|
||||
- Settings → AI Agent now offers Short, Medium, and Detailed response lengths.
|
||||
|
||||
### Clipboard and AI Skills
|
||||
|
||||
- New Clipboard History keeps the latest 15 plain-text copies on this device when enabled in Settings → Clipboard. It is off by default.
|
||||
- A new Clipboard suggestion strip lets you open history from the keyboard, insert an item, or keep the latest copy above the keyboard.
|
||||
- For about 30 seconds after copying text, Assistant shows quick Reply, Summarize, Translate, and other skills. Skills support paging and can be reordered from the Skills page.
|
||||
- The new Skills page lets you place up to eight skills on the keyboard. Built-in skills extract reminders, add calendar events, save to Notes, or open navigation in Amap, Baidu Maps, or Apple Maps.
|
||||
- Custom AI Skills support your own name, icon, and prompt, with an optional iCloud Shortcut connection.
|
||||
|
||||
### Edit Last Input
|
||||
|
||||
- Edit moves to the bottom-right keyboard button. Describe the change by voice, compare the original and edited text, then replace or append the result.
|
||||
- Editing uses only the latest verifiable text inserted by OSGKeyboard and does not read unrelated field content.
|
||||
|
||||
## A New App Interface
|
||||
|
||||
- The iPhone dock is rebuilt around four Liquid Glass destinations: Home, Skills, Styles, and Settings, with a green capsule marking the current page.
|
||||
- Home becomes an overview of usage statistics, dictation history, and Personal Dictionary cards.
|
||||
- Skills and polish styles share a card-based interaction: tap to select, edit from the top-right, see enabled status at the bottom-right, and long-press skills to reorder.
|
||||
- Settings navigation is reorganized so AI Agent, Clipboard, Speech, and Text Input are easier to find, with current summaries shown beside each row.
|
||||
- iPad adopts a sidebar + detail layout. The keyboard fills the available portrait and landscape width and adds the system globe key, undo, redo, copy, and cut.
|
||||
|
||||
## Chinese and English Typing, Rebuilt
|
||||
|
||||
- Chinese and English typing learn candidate frequency and selection preferences locally. Typing habits can be cleared without deleting Personal Dictionary entries.
|
||||
- Pinyin improves mixed abbreviations and supports two-key `zh`, `ch`, and `sh` abbreviations.
|
||||
- The English keyboard adds a QuickType-style bar for the typed word, correction, and completion. An offline list of about 40,000 words works with the system lexicon, contact names, and text replacements.
|
||||
- Neighbor-key correction follows the physical keyboard while avoiding unwanted changes to names, short words, and all-caps text. Rejecting a correction teaches the original.
|
||||
- Overlapping key presses, the English double-space period, and contextual Go, Search, Send, Done, and Next actions make typing feel closer to the system keyboard.
|
||||
|
||||
## Stability, Privacy, and Important Changes
|
||||
|
||||
- One Undo action now rolls back dictation, AI answers, edits, and clipboard pastes.
|
||||
- Fixes include keyboard-switch crashes, Chinese input recovery after setup, Universal Clipboard freezes, and a microphone that could remain unavailable after AI sessions.
|
||||
- Every built-in and custom polish style preserves questions instead of rewriting them as answers.
|
||||
- On-device speech recognition remains the default. AI uses your configured provider and API key; the built-in DeepSeek fallback has been removed.
|
||||
- Clipboard History stays off by default, keeps its contents on device, and sends text to the configured AI provider only after you invoke a skill.
|
||||
- Holding the microphone now asks AI, while Edit Last Input moves to the bottom-right Edit button. Clipboard History and quick skills replace the old hold-to-command clipboard flow.
|
||||
- If you installed the older Chinese-named Tasks or Events Shortcuts, reinstall `OSGExtractTodos` and `OSGExtractEvents` from the Skills page.
|
||||
- Blank-area cursor sliding and its Settings toggle have been removed.
|
||||
@@ -1,113 +1,132 @@
|
||||
# StoreKit — Voluntary Support Tip
|
||||
# StoreKit — managed credit packs
|
||||
|
||||
OSGKeyboard offers a single **Consumable** in-app purchase:
|
||||
OSGKeyboard ships **three Consumable** in-app purchases and no subscriptions.
|
||||
All three add credits to the optional OSG managed account. The authoritative
|
||||
local catalog is [`OSGKeyboard.storekit`](../OSGKeyboard.storekit); App Store
|
||||
Connect must match it exactly.
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| **Type** | Consumable |
|
||||
| **Product ID** | `ByRockyACoffee` |
|
||||
| **Reference name (Connect)** | 给老刘买杯咖啡 |
|
||||
| **Display name (en)** | Buy me a cup of coffee |
|
||||
| **Display name (zh-Hans)** | 给老刘买杯冰美式 |
|
||||
| **Price (China)** | ¥28 (nearest available App Store tier) |
|
||||
| **Price (US, suggested)** | $3.99 equivalent tier |
|
||||
| Product ID | Type | Reference name | Display name (en) | Price (CN) | Grants |
|
||||
|---|---|---|---|---|---|
|
||||
| `500tks` | Consumable | 500 OSG 积分 | 500 OSG Credits | ¥8 | 500 account credits |
|
||||
| `1500tks` | Consumable | 1,500 OSG 积分 | 1,500 OSG Credits | ¥18 | 1,500 account credits |
|
||||
| `3000tks` | Consumable | 3,000 OSG 积分 | 3,000 OSG Credits | ¥28 | 3,000 account credits |
|
||||
|
||||
**Important:** this tip does **not** unlock translation, dictionary limits,
|
||||
long Flow sessions, or any other capability. The app remains fully free.
|
||||
Rules that apply to all three:
|
||||
|
||||
Consumable purchases **cannot be restored** (Apple policy). Settings copy
|
||||
explains this to users.
|
||||
- Consumables **cannot be restored** (Apple policy). The UI states this.
|
||||
- Nothing here gates a feature. Local dictation, BYOK providers, typing,
|
||||
clipboard skills, and iCloud sync stay free with or without a purchase.
|
||||
- Credits only add balance to the optional OSG account. They are useless
|
||||
without Sign in with Apple, and the app never requires an account.
|
||||
- Credit packs are **iOS / iPadOS only**. The macOS build ships via Developer
|
||||
ID outside the Mac App Store, so it loads no StoreKit products at all.
|
||||
|
||||
## Where the packs appear
|
||||
|
||||
iOS Home → credit card → Account Center, and Settings → Account Center. Both
|
||||
require Sign in with Apple.
|
||||
|
||||
## Purchase flow (server-verified)
|
||||
|
||||
Credit packs are not client-trusted. `AccountCreditPurchaseManager`:
|
||||
|
||||
1. Buys with StoreKit 2, binding `appAccountToken` to the signed-in account ID.
|
||||
2. Rejects any transaction whose `appAccountToken` or product ID does not match
|
||||
the configured set.
|
||||
3. Submits the signed transaction to the account service
|
||||
(`submitCreditTransaction`) and checks the returned transaction and product
|
||||
IDs against the local ones.
|
||||
4. Calls `transaction.finish()` **only after** the server confirms and the
|
||||
ledger is updated.
|
||||
|
||||
A purchase that fails server verification stays unfinished and is retried from
|
||||
the transaction-updates stream, so a crashed or backgrounded app does not lose
|
||||
credits.
|
||||
|
||||
---
|
||||
|
||||
## App Store Connect setup
|
||||
|
||||
1. Open **App Store Connect → OSGKeyboard → In-App Purchases**.
|
||||
2. Create **Consumable** with Product ID `ByRockyACoffee`.
|
||||
3. Add localizations (en + zh-Hans) using the strings in
|
||||
`OSGKeyboardShared/*/Shared.strings` (`tip.*` keys) and
|
||||
`docs/APPSTORE_METADATA.md`.
|
||||
4. Set pricing: **China ¥28** (App Store only offers fixed tiers — ¥28 is
|
||||
the nearest to ¥30); pick equivalent tiers for other territories.
|
||||
5. Submit the IAP for review **with** the app version that includes the
|
||||
Settings → Support the Developer entry.
|
||||
2. Create each of the three products as **Consumable** with the exact Product
|
||||
IDs above. Do not rename an existing ID — Apple treats it as a new product.
|
||||
3. Add en + zh-Hans localizations. Copy comes from
|
||||
[`OSGKeyboard.storekit`](../OSGKeyboard.storekit) (`localizations`) and
|
||||
[`docs/APPSTORE_METADATA.md`](APPSTORE_METADATA.md).
|
||||
4. Set pricing to the nearest App Store tier for China (¥8 / ¥18 / ¥28) and let
|
||||
Apple map the equivalent tiers elsewhere.
|
||||
5. Submit the IAPs for review **together with** the app version that exposes
|
||||
them. A first IAP submitted without a build is rejected as incomplete.
|
||||
|
||||
### Review screenshot (required — fixes「元数据丢失」)
|
||||
### Review screenshot (required — otherwise「元数据丢失」)
|
||||
|
||||
App Store Connect → IAP **ByRockyACoffee** → **审核信息** → **截屏**:
|
||||
Each product needs a screenshot under **审核信息 → 截屏**: run the app signed
|
||||
in, open **Home → credit card → Account Center**, and capture the pack list
|
||||
showing localized prices.
|
||||
|
||||
1. Run the app (Simulator or device) with Settings open at the top
|
||||
**支持开发者** card showing the green **打赏 ¥28.00** button.
|
||||
2. Capture that screen (⌘S in Simulator, or device screenshot).
|
||||
3. Upload to **截屏 → 选取文件**.
|
||||
4. Optional **审核备注**:
|
||||
Optional **审核备注**:
|
||||
|
||||
```
|
||||
Optional voluntary tip only (Consumable IAP ByRockyACoffee).
|
||||
All features free before and after purchase. Settings tab → top of page.
|
||||
Consumable — cannot restore (stated in UI).
|
||||
Consumable credits for the optional OSG managed speech/AI service.
|
||||
Requires Sign in with Apple. Local dictation and user-supplied API keys
|
||||
remain free and never require credits. Consumable — cannot restore.
|
||||
```
|
||||
|
||||
Save — status should become **准备提交**.
|
||||
|
||||
---
|
||||
|
||||
## Local testing (StoreKit Test — no Connect / sandbox account)
|
||||
## Local testing (StoreKit Test — no Connect, no sandbox account)
|
||||
|
||||
Uses [`OSGKeyboard.storekit`](../OSGKeyboard.storekit). The **OSGKeyboard**
|
||||
scheme already references it in `project.yml` (`storeKitConfiguration`).
|
||||
The **OSGKeyboard** scheme already references `OSGKeyboard.storekit` in
|
||||
`project.yml` (`storeKitConfiguration`).
|
||||
|
||||
1. `xcodegen generate && open OSGKeyboard.xcodeproj`
|
||||
2. **Product → Scheme → Edit Scheme → Run → Options**
|
||||
- Confirm **StoreKit Configuration** = `OSGKeyboard.storekit`
|
||||
3. Run **OSGKeyboard** on Simulator (e.g. iPhone 17) or a plugged-in device
|
||||
4. Open **Settings** tab → top card **支持开发者**
|
||||
5. Tap **打赏 ¥28.00** → StoreKit Test purchase sheet appears
|
||||
6. **Buy** → thank-you alert; **Cancel** → no error
|
||||
7. Repeat buy once (Consumable allows multiple)
|
||||
1. `./Scripts/generate-xcodeproj.sh && open OSGKeyboard.xcodeproj`
|
||||
2. **Product → Scheme → Edit Scheme → Run → Options** — confirm
|
||||
**StoreKit Configuration** = `OSGKeyboard.storekit`
|
||||
3. Run **OSGKeyboard** on a simulator (e.g. iPhone 17) or a device.
|
||||
4. Sign in with Apple, then open **Home → credit card → Account Center**.
|
||||
5. Buy `500tks` → balance increases by 500 after the account service confirms;
|
||||
the purchase-history row appears.
|
||||
6. Cancel a purchase → returns to idle with no error spam.
|
||||
7. Repeat a purchase → allowed (Consumable).
|
||||
|
||||
**Debug menu (optional):** Xcode → **Debug → StoreKit → Manage Transactions**
|
||||
to view / delete test purchases.
|
||||
**Debug menu:** Xcode → **Debug → StoreKit → Manage Transactions** to inspect
|
||||
or delete test purchases.
|
||||
|
||||
Automated coverage: `AccountCreditPurchaseManagerTests` (in the hermetic
|
||||
manifest — see [TESTING.md](TESTING.md)) and `AccountCenterUITests`, which runs
|
||||
separately via `xcodebuild -scheme OSGKeyboardUITests` against the `IAPReview`
|
||||
stub harness — see
|
||||
[ACCOUNT_MANAGED_GATEWAY_TESTING.md](ACCOUNT_MANAGED_GATEWAY_TESTING.md).
|
||||
|
||||
---
|
||||
|
||||
## Sandbox testing (real App Store sandbox — after Connect IAP is 准备提交)
|
||||
## Sandbox testing (after Connect IAPs reach 准备提交)
|
||||
|
||||
1. App Store Connect → **用户和访问** → **沙盒** → create a **Sandbox Tester**
|
||||
2. On device: **设置 → App Store → 沙盒账户** → sign in (not your real Apple ID)
|
||||
3. Install via **TestFlight** or **Debug run without** `.storekit`:
|
||||
- To hit Connect products: Edit Scheme → Run → Options → set StoreKit
|
||||
Configuration to **None**, then run on device
|
||||
4. Settings → **支持开发者** → purchase with sandbox account
|
||||
5. Sandbox charges are free; receipt is real sandbox flow
|
||||
1. App Store Connect → **用户和访问 → 沙盒** → create a **Sandbox Tester**.
|
||||
2. On device: **设置 → App Store → 沙盒账户** → sign in (not your real Apple ID).
|
||||
3. Install via **TestFlight**, or Debug-run with **StoreKit Configuration =
|
||||
None** so the app hits Connect products.
|
||||
4. Buy each pack once and confirm the server-side ledger, not just the UI.
|
||||
5. Sandbox charges are free; the receipt path is the real one.
|
||||
|
||||
The full server-side matrix (replayed transactions, interrupted network,
|
||||
wrong-account rejection) lives in
|
||||
[ACCOUNT_MANAGED_GATEWAY_TESTING.md](ACCOUNT_MANAGED_GATEWAY_TESTING.md).
|
||||
|
||||
---
|
||||
|
||||
## Submit to App Review (after local + sandbox pass)
|
||||
## Release checklist
|
||||
|
||||
Yes — **wait until testing looks good**, then:
|
||||
|
||||
1. IAP **ByRockyACoffee** status = **准备提交** (pricing + screenshot + localizations)
|
||||
2. Bump app version in `project.yml` / `CHANGELOG.md` if needed
|
||||
3. **Archive** → upload build to App Store Connect
|
||||
4. Open the new **App Store version** page → **App 内购买项目** → **+** → select **ByRockyACoffee**
|
||||
5. Fill metadata, attach build, submit **version + IAP together** (first IAP rule)
|
||||
|
||||
### Sandbox checklist
|
||||
|
||||
- [ ] Product loads and shows localized price
|
||||
- [ ] Successful purchase shows thank-you alert
|
||||
- [ ] All three products load and show localized prices
|
||||
- [ ] Each pack adds the correct balance after server verification
|
||||
- [ ] Purchase history lists the new transaction without duplicates
|
||||
- [ ] A failed/interrupted verification is retried and not lost
|
||||
- [ ] User cancel returns to idle (no error spam)
|
||||
- [ ] Repeat purchase works (Consumable allows multiple)
|
||||
- [ ] No Restore button for this product (Consumable)
|
||||
- [ ] Translation, Flow, dictionary, BYOK unchanged after tipping
|
||||
|
||||
### macOS note
|
||||
|
||||
The menu-bar Mac build (`com.osgkeyboard.mac`) ships via Developer ID outside
|
||||
the Mac App Store today. StoreKit products load only for App Store builds.
|
||||
The Mac Settings UI is present for parity; tip IAP requires an App Store
|
||||
distribution if Mac tipping is enabled later.
|
||||
- [ ] No Restore button for any of these products
|
||||
- [ ] Local dictation, BYOK, typing, and clipboard skills unchanged after purchase
|
||||
|
||||
---
|
||||
|
||||
@@ -115,8 +134,7 @@ distribution if Mac tipping is enabled later.
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `OSGKeyboardShared/Services/Tip/TipProduct.swift` | Product ID constants |
|
||||
| `OSGKeyboardShared/Services/Tip/TipPurchaseManager.swift` | StoreKit 2 purchase flow |
|
||||
| `OSGKeyboardShared/DesignSystem/SupportDeveloperSection.swift` | iOS Settings UI |
|
||||
| `OSGKeyboardMac/MacSupportDeveloperTipRows.swift` | macOS Settings UI |
|
||||
| `OSGKeyboard/Views/Account/AccountCreditPurchaseManager.swift` | Purchase + server verification |
|
||||
| `OSGKeyboard/Views/Account/AccountCreditStore.swift` | StoreKit 2 product/purchase abstraction |
|
||||
| `OSGKeyboard/Views/Account/AccountCenterView.swift` | Credit pack UI, purchase history |
|
||||
| `OSGKeyboard.storekit` | Local StoreKit Test catalog |
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Typing Keyboard Baseline (Phase 0)
|
||||
|
||||
> **文档状态**:Phase 0 冻结基线(历史快照,2026-08-03)。它记录当时的选型依据,
|
||||
> 不随版本更新。**当前权威的依赖版本与许可以 `NOTICE-TYPING.md` 和
|
||||
> `OSGKeyboard/Resources/Typing/Rime/manifest.json` 为准**;实施进展见
|
||||
> `docs/keyboard-accuracy-plan.md`。
|
||||
|
||||
Frozen reference for NanoMouse × OSGKeyboard fusion.
|
||||
|
||||
## NanoMouse reference
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Archived documents
|
||||
|
||||
Point-in-time documents kept for traceability only. **They are not maintained
|
||||
and do not describe current behavior.** For current facts use `CHANGELOG.md`,
|
||||
`docs/APPSTORE_METADATA.md`, and the living docs directly under `docs/`.
|
||||
|
||||
| Document | What it was | Why it is archived |
|
||||
|---|---|---|
|
||||
| [ios-pip-voice-session-plan.md](ios-pip-voice-session-plan.md) | PiP voice-session keep-alive plan (2026-07-26) | Implemented in 1.6.5; its Live Activity assumption was removed in 1.6.6 |
|
||||
| [mac-parity-audit-2026-08-23.md](mac-parity-audit-2026-08-23.md) | iOS ↔ macOS parity audit at 2.0.1 (build 90) | One-off snapshot; superseded by later releases |
|
||||
@@ -1,8 +1,10 @@
|
||||
# iOS PiP 语音会话保活规划
|
||||
|
||||
> **文档状态**:产品与架构规划(待验证,未进入实现)
|
||||
> **适用范围**:iOS 主 App + 键盘扩展 + Live Activity
|
||||
> **目标版本**:待产品验证后确定
|
||||
> **文档状态**:**历史规划(已实现,部分结论已被取代)**——保留用于追溯设计取舍,不代表当前行为
|
||||
> **实际落地**:自动低感知 PiP 于 **1.6.5** 上线(`OSGKeyboard/Services/FlowPictureInPictureController.swift`)
|
||||
> **主要偏差**:本文假设 Live Activity 继续承担锁屏与灵动岛展示;**1.6.6 已删除 Live Activity 扩展与全部 ActivityKit 代码**,语音会话仅保留静默低感知 PiP,用户可见文案不出现「画中画」
|
||||
> **当前事实以何为准**:`CHANGELOG.md`、`docs/FLOW_BLUETOOTH_TESTING.md`、`docs/keyboard-memory-budget.md`
|
||||
> **适用范围**:iOS 主 App + 键盘扩展
|
||||
> **创建日期**:2026-07-26
|
||||
|
||||
---
|
||||
@@ -1,5 +1,6 @@
|
||||
# OSGKeyboard · iOS 完整检查 + macOS 差距与移植建议报告
|
||||
|
||||
> **文档状态**:**一次性审计快照(历史存档)**——仅代表 2026-08-23 当时的代码状态,其后 Mac 与 iOS 均有改动(如总览页已改为月度用量日历),不要作为现行文档使用
|
||||
> **报告日期**:2026-08-23
|
||||
> **当前版本**:2.0.1(build 90)— `project.yml:51-52`
|
||||
> **审查范围**:iOS Host (`OSGKeyboard/`, 88 .swift) + iOS HostSupport (`OSGKeyboardHostSupport/`, 29 .swift) + iOS Extension (`OSGKeyboardExt/`, 27 .swift) + Shared (`OSGKeyboardShared/`, 230 .swift) + macOS (`OSGKeyboardMac/`, 39 .swift) + macOS Tests (3 .swift)
|
||||
|
After Width: | Height: | Size: 119 KiB |
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 153 KiB |
|
After Width: | Height: | Size: 141 KiB |
@@ -1,11 +1,12 @@
|
||||
# 打字键盘输入准确率提升计划
|
||||
|
||||
> **文档状态**:产品与工程规划(**实现中**:Phase 1~4 已落地,待真机试打)
|
||||
> **文档状态**:**Phase 1~4 已随 1.6.1(2026-08-05)发布**;本文保留为设计依据与验收脚本,剩余工作见下方「剩余事项」
|
||||
> **适用范围**:iOS 键盘扩展打字面(`OSGKeyboardExt` 打字键网格)+ 共享布局度量(`OSGKeyboardShared`)
|
||||
> **关联基线**:`docs/TYPING_KEYBOARD_BASELINE.md`
|
||||
> **实现分支**:`feat/keyboard-touch-accuracy`
|
||||
> **已落地代码**:`OSGKeyboardShared/Typing/KeyHitTesting.swift`、`TypingKeyLayout.swift`、`PinyinNextKeyResolver.swift`、`OSGKeyboardExt/Typing/TypingKeyTouchPad.swift`(原分支 `feat/keyboard-touch-accuracy` 已合入 `main` 并删除)
|
||||
> **创建日期**:2026-08-03
|
||||
> **目标版本**:待 Phase 0 基线试打后确定发布节奏
|
||||
>
|
||||
> **剩余事项**:附录 A 的真机试打脚本尚未留下正式打分记录;Phase 5(气泡预览等加分项)未启动。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -76,6 +76,6 @@ operation-specific context. Filter Console by `OSGDiag/memory` and compare:
|
||||
## Structural split
|
||||
|
||||
- Extension links **OSGKeyboardShared** only (no Charts / StoreKit / Speech / HostSupport).
|
||||
- Host embeds **OSGKeyboardHostSupport** (ASR, CLM, CloudASR, tip/charts UI).
|
||||
- Host embeds **OSGKeyboardHostSupport** (ASR, CLM, CloudASR, charts UI).
|
||||
- Heavy assets (`osg_pinyin.dict.yaml`, CLM bin, licenses, local-asr catalog)
|
||||
ship in the **host app** bundle; extension reads Rime from App Group after deploy.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# OSGKeyboard 本地 ASR 技术架构
|
||||
|
||||
> **文档状态**:1.7.0 代码事实 + 后续评测方向
|
||||
> **文档状态**:Mac 本地 ASR 现行架构说明(结论已复核至 **2.0.3 / build 94**,2026-08-31)+ 后续评测方向
|
||||
> **适用范围**:macOS 15+ 本地听写;iOS 26+ 使用 Apple SpeechAnalyzer。
|
||||
> **当前结论**:Mac 默认安装目录模型为
|
||||
> `qwen3-mlx-0.6b-4bit`,通过 `mlx-audio-swift` 做 Qwen3 MLX 真流式识别;
|
||||
|
||||
@@ -178,6 +178,63 @@
|
||||
<p class="empty" id="empty-zh">暂无与当前版本匹配的更新说明。</p>
|
||||
<p class="empty" id="empty-en">No release notes match this app version.</p>
|
||||
|
||||
<!-- ========== 2.0.3 ========== -->
|
||||
<article class="version-block" data-version="2.0.3">
|
||||
<div class="version-chip">2.0.3</div>
|
||||
|
||||
<div class="lang-block" data-lang="zh">
|
||||
<section class="section">
|
||||
<h2>英文个性词推荐</h2>
|
||||
<ul>
|
||||
<li>除中文输入习惯外,键盘现在也会学习你反复使用的英文生词,并推荐加入个人词库</li>
|
||||
<li>中英文推荐词都需要你确认后才会加入,原有的中文学习记录不受影响</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>界面一致性优化</h2>
|
||||
<ul>
|
||||
<li>统一卡片间距、设置页字体和菜单对齐方式,账号与购买记录的排版更整齐</li>
|
||||
<li>一级页面与详情页之间的标签栏过渡更自然</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>问题修复</h2>
|
||||
<ul>
|
||||
<li>重装 App 或重新回到前台后,Apple 账号登录状态恢复更可靠,登录过程中的加载提示保持一致</li>
|
||||
<li>在不同 App 之间切换后,中英文候选词可靠恢复,且不会残留上一个输入框的内容</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="lang-block" data-lang="en">
|
||||
<section class="section">
|
||||
<h2>English Personal-Term Suggestions</h2>
|
||||
<ul>
|
||||
<li>Alongside Chinese typing habits, the keyboard now learns rare English words you use repeatedly and suggests adding them to your Personal Dictionary</li>
|
||||
<li>Suggestions in either language are added only after you confirm, and existing Chinese learning history is preserved</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Interface Consistency</h2>
|
||||
<ul>
|
||||
<li>Card spacing, settings typography, menu alignment, and the account and purchase-history rows are now consistent</li>
|
||||
<li>Tab-bar transitions between primary pages and detail pages feel smoother</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<h2>Fixes</h2>
|
||||
<ul>
|
||||
<li>Apple sign-in is restored more reliably after a reinstall or when returning to the foreground, with a consistent loading state</li>
|
||||
<li>Chinese and English candidates recover reliably after switching apps, without leaking state from the previous text field</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- ========== 2.0.2 ========== -->
|
||||
<article class="version-block" data-version="2.0.2">
|
||||
<div class="version-chip">2.0.2</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Personal Dictionary iCloud KVS — Manual Verification Checklist
|
||||
|
||||
Use this on **macOS with Xcode 16+** and at least two devices signed into the **same Apple ID** with iCloud Drive / iCloud enabled.
|
||||
Use this on **macOS with Xcode 26** (the repository build requirement) and at least two devices signed into the **same Apple ID** with iCloud Drive / iCloud enabled.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. In Apple Developer Portal, enable **iCloud** → **Key-value storage** for `com.osgkeyboard.ios`.
|
||||
2. Regenerate provisioning profiles after entitlements change.
|
||||
3. Run `xcodegen generate` and install a fresh build on each device.
|
||||
3. Run `./Scripts/generate-xcodeproj.sh` and install a fresh build on each device.
|
||||
|
||||
## Scenarios
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 84 KiB |
@@ -1,73 +0,0 @@
|
||||
# App Store Screenshots
|
||||
|
||||
> ⚠️ **PLACEHOLDERS.** The 10 PNGs in this directory are
|
||||
> automatically generated blanks produced by
|
||||
> `scripts/generate_screenshot_placeholders.py` and must be
|
||||
> **replaced with real Simulator screenshots** before App Store
|
||||
> submission. They use the correct dimensions (1290×2796 for
|
||||
> 6.7", 1179×2556 for 6.1") so the upload validator will accept
|
||||
> them, but they contain no real UI.
|
||||
|
||||
## Required dimensions (2026)
|
||||
|
||||
| Size | Devices | Dimensions | Apple requirement |
|
||||
|------|---------|-----------|---|
|
||||
| 6.7" | iPhone 17 Pro Max, 17, 16 Pro Max, 16 Plus, 15 Pro Max, 15 Plus | 1290 × 2796 px | **Required** (3-10 images) |
|
||||
| 6.1" | iPhone 17 Pro, 17, 16 Pro, 16, 15 Pro, 15, 14 Pro, 14 | 1179 × 2556 px | **Required** (3-10 images) |
|
||||
| 5.5" | iPhone 8 Plus (legacy) | 1242 × 2208 px | Optional since 2024 |
|
||||
|
||||
iPad screenshots are not required because OSGKeyboard is iPhone-only
|
||||
(`TARGETED_DEVICE_FAMILY = 1`).
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
docs/screenshots/
|
||||
├── 6.7/ ← 1290×2796 (iPhone 17 Pro Max / 17)
|
||||
│ ├── 01-keyboard-default.png
|
||||
│ ├── 02-flow-session.png
|
||||
│ ├── 03-on-device-asr.png
|
||||
│ ├── 04-llm-polish.png
|
||||
│ └── 05-providers.png
|
||||
└── 6.1/ ← 1179×2556 (iPhone 17 Pro / 17)
|
||||
├── 01-keyboard-default.png
|
||||
├── 02-flow-session.png
|
||||
├── 03-on-device-asr.png
|
||||
├── 04-llm-polish.png
|
||||
└── 05-providers.png
|
||||
```
|
||||
|
||||
## How to capture real screenshots
|
||||
|
||||
1. Open `OSGKeyboard.xcodeproj` in Xcode 26+
|
||||
2. Run on **iPhone 17 Pro** simulator (6.1" set) and **iPhone 17 Pro Max** simulator (6.7" set)
|
||||
3. For each scene:
|
||||
```bash
|
||||
# Take a screenshot of the simulator window
|
||||
xcrun simctl io booted screenshot ~/Desktop/shot.png
|
||||
```
|
||||
4. Process for App Store (Apple rejects frames containing the device bezel — full-screen content only):
|
||||
```bash
|
||||
# The simulator screenshot already has a thin device frame.
|
||||
# Open in Preview, crop to full screen (⌘+K with ⌥ for precision),
|
||||
# export as PNG at 1290×2796 or 1179×2556.
|
||||
sips -z 2796 1290 shot.png --out final-6.7.png
|
||||
sips -z 2556 1179 shot.png --out final-6.1.png
|
||||
```
|
||||
5. Replace the placeholders with the real captures, keeping the
|
||||
same filenames so the App Store Connect → Version → Uploads UI
|
||||
auto-pairs by file.
|
||||
|
||||
## Scenes to capture
|
||||
|
||||
The 5 placeholders are intentional scene placeholders. Capture these
|
||||
*exact* screens, in this order:
|
||||
|
||||
1. **Keyboard at rest** — the iOS keyboard, OSGKeyboard mode, no recording
|
||||
2. **Flow session active** — keyboard with the green/orange recording ring,
|
||||
partial transcript visible in the host text field
|
||||
3. **On-device ASR** — Settings view with the locale list, the on-device
|
||||
indicator (iPhone icon) visible next to ≥ 3 supported locales
|
||||
4. **LLM polish** — Settings view with the API provider card, a sample
|
||||
"polish" transformation shown in the inline preview
|
||||
5. **Providers** — API Settings card scrolled to show all 6 provider logos
|
||||