feat(account): add QR invitation poster and 8-character invitation codes

- Invite opens an appearance-matched poster with the app icon, inviter name,
  QR code, and short code; tap for a full-brightness QR view; save (add-only
  Photos access), share, or copy the link. Mac shows the poster in a popover
  and can save it as PNG.
- Accounts get look-alike-free 8-character codes. "I have a code" accepts a
  code, link, or pasted message during the server-defined binding window.
- Permanently rejected redemptions show a specific message and drop the
  stored code instead of retrying on every sign-in.
This commit is contained in:
2026-10-20 20:06:36 +02:00
parent eaacc35cf7
commit 03bfbbe08b
26 changed files with 2269 additions and 86 deletions
+6
View File
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- **QR invitation poster**: the Invite button now opens a minimal poster that automatically matches light or dark appearance, uses the current App Icon, names the inviter (falling back to “OSG User”), and shows the QR code plus the short invitation code in Chinese or English. Tap the poster to show the code full screen at full brightness for face-to-face scanning; your brightness returns when you close it. You can also save the poster to Photos (add-only access), share the image, or copy the link. On Mac, the account page shows the same poster in a popover and can save it as a PNG. / **二维码邀请海报**:「邀请」按钮会打开自动适配黑白外观的极简海报,使用当前 App Icon,显示邀请人用户名(未设置时为「OSG 用户」),并以中英文展示二维码与短邀请码;点海报可全屏显示二维码并自动调到最亮,方便当面扫码,关闭后恢复原亮度;也可保存到相册(仅申请添加权限)、分享图片或复制链接。Mac 账户页以弹出面板展示同款海报,并可存为 PNG。
- **8-character invitation codes**: every account now has a short code such as `K7M2-Q9XA`, printed on the poster, the Mac poster popover, and the invitation landing page. The code skips look-alike characters (0/O, 1/I/L), so it can be read aloud. Tap “I have a code” to type it, or paste an invitation link or a whole chat message instead; the clipboard is never read on its own. A friend who installed from the App Store therefore still gets credited. For the first 7 days after registering, and until an inviter is bound, the home card shows “Enter a code, or invite more friends for credits” with the “I have a code” button, and Invite moves to the bottom of that sheet; the window follows the server’s campaign deadline. The landing page copies the link and opens the App Store in one tap, and keeps the link-open paths that older app builds rely on. / **8 位邀请码**:每个账号都有一个形如 `K7M2-Q9XA` 的短邀请码,印在海报、Mac 海报面板与邀请落地页上;不含易混字符(0/O、1/I/L),念出来也不会输错。点「我有邀请码」即可输入,也可直接粘贴邀请链接或整段聊天消息;App 不会主动读取剪贴板。好友从 App Store 安装后仍能计入邀请。注册后 7 天内且尚未绑定邀请人时,首页卡片显示「输入邀请码,或邀请更多好友获取积分」与「我有邀请码」按钮,「邀请」入口移到弹窗底部;期限以服务器活动截止时间为准。落地页一键「复制邀请并下载」,并保留旧版本 App 依赖的链接打开方式。
### Changed
- **Dictation progress on the microphone**: while a dictation is being recognized and polished, the microphone capsule fills from left to right in the brand colour instead of showing a spinner. The fill steps forward when recognition finishes, slows as it nears the end, and completes only when the text is inserted; the polish estimate adapts to how long polishing usually takes on this device. / **麦克风上的听写进度**:听写识别与润色期间,麦克风胶囊改为从左到右填充品牌色,取代原来的转圈。识别完成时进度向前跳一段,越接近结束走得越慢,只有文字真正插入时才填满;润色耗时的预估会按这台设备的实际情况自动校准。
- **Messaging shift to AI voice keyboard / voice double / agentic skills**: README and the product page now lead with “Say it. It’s typed. Speaks like you. Acts for you.” — the personalization story (learned style, three-tone replies) moves ahead of typing, clipboard skills are framed as agentic actions, and typing becomes the fallback capability. / **宣传定位转向 AI 语音键盘 / 嘴替 / Agentic 技能**:README 与产品页改用「开口即文字。会说你的话,会办你的事。」定位;个人化卖点(专属风格、三语气回复)提前,剪贴板技能表述升级为 Agentic 行动,打字退为兜底能力。
@@ -15,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- **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. / **邀请兑换无限重试**:服务器明确拒绝的邀请(邀请码无效、邀请自己、已绑定或超出绑定期限)会一直保留并在每次登录时重试。现在这些情况会给出具体提示并清除暂存的邀请码;网络失败仍会重试。
- **Faster managed dictation feedback**: begin the managed Volcengine streaming connection while the microphone touch primes audio, reuse it when recording starts, and keep the live transcript automatically scrolled to the newest recognition text. The early connection is reused only while it is fresh (under 10 seconds) and still open; otherwise it is closed and a new one opens, so an unused early connection can no longer make the next dictation fail. / **托管听写反馈提速**:在麦克风触摸预热音频时同步建立托管火山流式连接,录音开始后直接复用,并让实时转写自动滚动到最新识别文字。提前建立的连接仅在新鲜(10 秒内)且仍可用时复用,否则关闭并重新建立,未被使用的提前连接不会再导致下一次听写失败。
- **Recording kept when live recognition fails**: a streaming recognition error while you were still speaking ended the dictation immediately and discarded the audio. Recording now continues, and when you finish, the recorded audio is retried with batch recognition before any error is shown. After a cancelled or failed dictation, that batch retry also stopped working for the rest of the session; it now works again from the next dictation. / **实时识别失败时保留录音**:说话过程中流式识别一旦出错,本次听写会立即结束并丢弃录音。现在会继续录音,说完后先用批量识别重试已录下的音频,仍失败才提示错误。此前一次听写被取消或失败后,本次会话内的批量重试也会失效;现在从下一次听写起恢复正常。
- **Stalled cloud ASR losing the recording**: when the streaming recognizer went quiet and the result wait expired, the utterance ended as "no speech" even though the audio was captured. A stalled recognizer now counts as a failure, so the batch ASR fallback retries the recorded audio before giving up. / **云端识别卡住时丢失录音**:流式识别无响应、等待结果超时后,即便录音已采集,本次语音也会直接报「未检测到语音」。现在识别卡住按失败处理,会先用批量识别重试已录下的音频再放弃。