Cooper-X-Oak
ed504c1a9f
fix(windows): polish capsule and custom titlebar shell
2026-05-01 00:46:31 +08:00
TRIP
884455a99a
Merge pull request #94 from appergb/codex/windows-recording-fixes
...
fix: stabilize Windows recording startup
2026-04-30 21:38:36 +08:00
baiqing
f937f586ee
chore: bump version to 1.2.6
2026-04-30 21:33:28 +08:00
Chris233
9d92500252
Merge pull request #93 from H-Chris233/main
...
fix(ui): 清理卸载后的延迟状态更新
2026-04-30 21:27:46 +08:00
baiqing
2002890a39
fix: stabilize Windows recording startup
2026-04-30 21:23:52 +08:00
H-Chris233
0d949a3cda
Clear frontend timeout callbacks on unmount
...
Store the remaining transient UI timeout handles in refs so Settings About copy feedback and Onboarding delayed permission refresh do not call setState after their components unmount.
Constraint: Issue #64 asks for minimal setTimeout handle cleanup without changing UI behavior
Confidence: high
Scope-risk: narrow
Tested: npm run build
Tested: git diff --check
2026-04-30 21:21:29 +08:00
Chris233
cf702d9d99
Merge pull request #92 from H-Chris233/main
...
fix(insertion): 修正 macOS 无权限时插入状态
2026-04-30 20:54:07 +08:00
H-Chris233
3282e1e5d9
Avoid false inserted history without macOS accessibility
...
Before posting Cmd+V on macOS, check the current Accessibility trust state. If permission has been revoked, keep the transcript on the clipboard and reuse the existing CopiedFallback path instead of recording a successful insertion.
Constraint: Keep issue #62 fix minimal and avoid adding unreliable target-control paste verification
Rejected: AX focused-value readback with timeout | broader and brittle across apps/web editors
Confidence: medium
Scope-risk: narrow
Tested: cargo check --manifest-path openless-all/app/src-tauri/Cargo.toml
Tested: git diff --check
Not-tested: Live macOS Accessibility revoke flow on this host
2026-04-30 20:42:24 +08:00
baiqing
9b2f65fe71
fix: harden Windows hotkey release handling
2026-04-30 19:26:31 +08:00
baiqing
6801f29e05
fix: start recorder before ASR handshake
...
Closes #91
2026-04-30 19:18:21 +08:00
baiqing
f456516f69
chore: release 1.2.5
2026-04-30 18:58:35 +08:00
baiqing
42dc4fe989
merge: integrate PR 90 windows foreground hotkey
...
# Conflicts:
# openless-all/app/src-tauri/src/coordinator.rs
# openless-all/app/src/App.tsx
2026-04-30 18:57:08 +08:00
baiqing
e86edd13c2
merge: integrate PR 86 windows foreground hotkey
2026-04-30 18:52:01 +08:00
baiqing
e6ec4935e0
feat: add dense request polish example
2026-04-30 18:44:39 +08:00
baiqing
d1ae8479ba
fix: let macOS position traffic lights
2026-04-30 18:41:44 +08:00
Chris233
9654cde893
Merge branch 'appergb:main' into main
2026-04-30 18:38:12 +08:00
baiqing
a853b592a1
chore: release 1.2.4 mac titlebar polish
2026-04-30 18:27:35 +08:00
H-Chris233
67bb14ec40
Restore foreground Windows hotkey edges
...
Windows can deliver modifier-only key events to the focused WebView without the low-level hook seeing the same edge, so the main window now forwards only hotkey-relevant DOM key events to the coordinator. Both native hook and window-forwarded events share the same coordinator edge gate so a working hook does not double-trigger toggle sessions.
Constraint: Issue #85 requires OpenLess foreground Right Control to reuse existing pressed/released/cancel semantics without changing global hook behavior
Rejected: Start dictation directly in the frontend | would duplicate coordinator state-machine semantics
Rejected: Keep a separate window-held flag | review found it can double-trigger toggle mode when both DOM and low-level hook report the same physical press
Confidence: medium
Scope-risk: moderate
Tested: cargo check --manifest-path openless-all/app/src-tauri/Cargo.toml
Tested: cargo test --manifest-path openless-all/app/src-tauri/Cargo.toml window_key_matcher_mirrors_windows_trigger_aliases
Tested: npm run build
Tested: git diff --check
Not-tested: Physical Windows foreground Right Control on this Linux host
2026-04-30 18:16:59 +08:00
baiqing
0378dd15ce
fix: restore team updater signing key
2026-04-30 18:09:37 +08:00
baiqing
ef9db9645d
fix: polish 失败有感知 + 词汇启停失败回滚 ( closes #57 #60 )
...
#57 : polish 失败静默回退原文 → 用户感知'风格设置没生效'
- polish_or_passthrough 返回类型 String → (String, Option<String>)
失败时第二个返回值是 reason,let _ = drop 用不到
- end_session: polish_error.is_some() 时 done_message='润色失败,已插入原文'
+ history.error_code='polishFailed'。文本仍插入(保留'用户的话不丢'语义)
#60 : 词汇启停乐观更新无回滚
- Vocab.tsx::onToggle try { await setVocabEnabled } catch { setEntries 回滚 + 显示错误 }
避免 UI 显示已禁用但 ASR/polish 仍注入
2026-04-30 17:55:23 +08:00
baiqing
1683224403
docs(readme): 更新到 v1.2 — 双语 / auto-update / single-instance;清理 Swift 遗留
...
- Status (v1.1) → (v1.2);加 i18n / 自动更新 / 单实例锁 / push-to-talk / vocab hits 累计
- Whisper 已上线,从 roadmap 移到当前状态
- 移除 Swift legacy build / 发版指引(Swift 整套已在 commit 34d2823 删除)
- Architecture 段从'Sparkle for legacy users'改为'Tauri updater 签名 artifact'
- Roadmap 加上 #43(翻译模式)+ #46(风格记忆);都是当前 open feature issue
- 维护者发版检查加 TAURI_SIGNING_PRIVATE_KEY secret 提示
中英 README 同步改。
2026-04-30 17:53:11 +08:00
Cooper-X-Oak
85fc5b8d5a
fix(windows): 修复前台主窗口热键失效
2026-04-30 17:43:27 +08:00
baiqing
1efc20b2b2
chore(release): bump 1.2.2 -> 1.2.3 + 自有 updater pubkey + 重启前 strip xattr
...
修复 Codex audit 对 main HEAD a9c81e6 的 2 条 HIGH + 把 macOS auto-update 的
"重启后 Gatekeeper 拦截"问题封死。
## HIGH #2 : 版本号不一致
PR #84 没顺手 bump 版本,main 仍自报 1.2.2,下次直接打 v1.2.3-tauri 会让 updater
manifest 自报 1.2.2,已安装的 1.2.2 客户端永远拿不到 "有新版本"。
修:package.json + tauri.conf.json + Cargo.toml 全部改 1.2.3。
## HIGH #1 : updater pubkey 所有权
PR #84 使用的 pubkey 是外部贡献者本地生成的,appergb 不掌握对应 private key。
任何持有那把私钥的人都能签发更新 -> 客户端 OTA 装上恶意版本。
修:
- 用 npx @tauri-apps/cli signer generate --ci 生成 appergb 自己的 keypair
- 新 pubkey: F0FCDE68E08E6D4E (写入 tauri.conf.json plugins.updater.pubkey)
- 私钥已通过 gh secret set TAURI_SIGNING_PRIVATE_KEY 配到 GitHub repo secret
- 私钥本地副本只在 /tmp,不进 git,commit 后会清除
## macOS auto-update 后 strip xattr
restart_app 在 app.restart() 前对 .app bundle 跑 /usr/bin/xattr -cr。这是
Tauri auto-updater + 未公证应用的组合下唯一让"自动更新对用户零摩擦"的解法 —
否则 Gatekeeper 在重启时会拦说"OpenLess 已损坏",用户必须开终端 xattr 才能
继续用,违反 auto-update 的本意。
未来发版逻辑必须保留这一步。release-tauri.yml 上一次 PR (#83 ) 已经在 CI 侧
strip 过一次,本次在 client 侧重启时再 strip 一次,双保险覆盖
"下载 -> 解压 -> 安装 -> 重启"全链路。
2026-04-30 17:41:50 +08:00
baiqing
a9c81e6e0e
feat(updater): 增加应用自动更新入口 ( #84 )
...
H-Chris233: closes #33。
实现 Tauri 内置 updater 集成:
- Cargo: tauri-plugin-updater v2
- tauri.conf.json: 加 updater 配置(pubkey + endpoint 指向 GitHub Releases latest)
- capabilities/default.json: 授予 updater:default 能力
- lib.rs: 注册 updater 插件 + restart_app 命令
- src/pages/Settings.tsx + i18n: 关于区域加'检查'按钮、检查/下载/安装/重启对话框流
- 新脚本 scripts/write-updater-manifest.mjs: release 侧从 build artifact 拉签名生成 manifest
- workflow: TAURI_SIGNING_PRIVATE_KEY env + 各平台 build 时 createUpdaterArtifacts true
注意:下次 v*-tauri tag 必须配 TAURI_SIGNING_PRIVATE_KEY secret,否则 CI 硬失败。
2026-04-30 17:20:32 +08:00
baiqing
786bc574a7
chore(release): bump 1.2.1 → 1.2.2 — 含 PR #82 凭据加载竞态修复
2026-04-30 15:00:00 +08:00
Chris233
df8846913a
fix(settings): 避免凭据加载前被空值覆盖 ( #82 )
...
* Prevent untouched credential fields from clearing secrets
Settings credential inputs can mount empty while readCredential is still pending. The field now waits for a successful read before enabling saves, tracks whether the user actually edited the value, and surfaces read failures without writing an empty credential back to storage.
Constraint: Issue #34 requires preserving existing credentials when the settings page is opened or blurred without edits.
Constraint: Keep secrets out of logs and UI.
Rejected: Add full E2E coverage now | larger test harness work than needed for the minimal bug fix.
Confidence: high
Scope-risk: narrow
Tested: npm install
Tested: npm run build
Tested: cargo check
Tested: git diff --check
* Keep credential fields recoverable after read errors
Review feedback identified that read failures left fields disabled while the temporary status disappeared. Read errors now leave the field interactive with a persistent readError status, and the credential-field status union is named explicitly for safer helper signatures.
Constraint: Preserve the issue #34 guard that only dirty loaded fields save credentials.
Rejected: Broader state-machine rewrite | unnecessary for this targeted review fix.
Confidence: high
Scope-risk: narrow
Tested: npm run build
Tested: cargo check
Tested: git diff --check
2026-04-30 14:58:53 +08:00
TRIP and baiqing
e3f91e849c
ci(release): 显式 strip macOS bundle xattr 作为 defense-in-depth ( #83 )
...
GitHub Actions 输出本来就不带 com.apple.quarantine (actions/upload-artifact
不跨机器持久化 xattr, softprops/action-gh-release 上传 binary stream 也不带),
但加这一步让 "云端 artifact 一定干净" 变成可验证的承诺, 未来 release 不会因
runner 环境变化退化.
用户下载到本地后浏览器/LaunchServices 仍会加 quarantine, 依赖 release notes
里的 xattr -cr 指引或一行安装命令处理.
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 14:56:22 +08:00
TRIP
90141e2731
Merge pull request #81 from appergb/develop
...
release(v1.2.1): 累积外部 PR + 终审 HIGH 修复
2026-04-30 14:31:30 +08:00
baiqing
ca31264b44
chore(release): bump v1.2.0 → v1.2.1
...
包含本轮所有合并:
- Codex 终审两条 HIGH (cancel race) 修复 (PR #79 )
- 6 个 Cooper-X-Oak/Codex bot PRs 自动合并 (#44 #49 #53 #68 #72 #73 )
- 2 个有冲突 PR 本地 rebase 后合并 (#66 cancel + 空转写并存 / #67 Windows docs)
- README 破图修复 (PR #80 )
- workflow-scope 受限的 #48 + #75 由用户在 GitHub UI 直接合并
3 处版本字段同步:package.json + tauri.conf.json + Cargo.toml
2026-04-30 14:31:05 +08:00
TRIP and baiqing
7a3a51a1ed
fix(readme): 修复 README 中破损的图片引用 ( #80 )
...
Resources/AppIcon.png 已在 commit 170283e(清理 Swift 残留)中删除,但 README.md
和 README.zh.md 顶部的 hero 图片仍然指向它,GitHub 上显示破图。
改为指向 Tauri 自身的图标:openless-all/app/src-tauri/icons/128x128@2x.png
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 14:27:46 +08:00
Cooper Oak and Cooper-X-Oak
7797d1479a
docs(windows): 补齐上游交付与测试工作流 ( #67 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:25:51 +08:00
Cooper Oak and Cooper-X-Oak
848cfc35c8
fix(windows): 收口录音会话失败态 ( #66 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:25:43 +08:00
Cooper Oak and Cooper-X-Oak
61177eafc3
ci(release): 补齐 macOS Tauri 产物发布 ( #75 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:21:54 +08:00
Cooper Oak and Cooper-X-Oak
ff694c07c1
fix(windows): 收敛启动和开发产物路径 ( #48 )
...
* fix(windows): 收敛启动和开发产物路径
* ci(windows): 校验运行时 smoke 脚本
---------
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:21:35 +08:00
Cooper Oak and Cooper-X-Oak
96ff66eb80
test(windows): 增加真机回归 smoke 矩阵 ( #73 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:19:29 +08:00
Cooper Oak and Cooper-X-Oak
b8988c3330
fix(windows): 缺失托盘图标时继续启动 ( #72 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:18:54 +08:00
Cooper Oak and Cooper-X-Oak
8de575d8de
fix(ui): 本会话内延后提供商配置提示 ( #68 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:18:18 +08:00
Cooper Oak and Cooper-X-Oak
ce0f00fd54
fix(windows): 校准麦克风权限探测 ( #53 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:17:42 +08:00
Cooper Oak and Cooper-X-Oak
bb7300ee85
fix(settings): 防止凭据字段清空已有密钥 ( #49 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:16:58 +08:00
Cooper Oak and Cooper-X-Oak
3d6870822f
test(windows): 增加低层热键钩子回归 ( #44 )
...
Co-authored-by: Cooper-X-Oak <Cooper-X-Oak@users.noreply.github.com >
2026-04-30 14:16:03 +08:00
TRIP
94c8507b5e
Merge pull request #78 from appergb/develop
...
release(v1.2.0): i18n + ASR 数据不丢失 + 状态机修复 + 单实例 + UI 动画补齐
2026-04-30 14:05:24 +08:00
TRIP and baiqing
bcd4d815c8
fix(coordinator): 关闭 cancel race 两处窗口期 — Codex audit HIGH #1 + HIGH #2 ( #79 )
...
closes Codex audit blockers on PR #78
## HIGH #1 — begin_session 内 await 期间 cancel 被覆盖
背景:volcengine open_session().await + Recorder::start 都是异步,期间用户按
Esc 调用 cancel_session 把 phase 改回 Idle 并 cancelled=true。但原代码后续无
条件 `state.phase = SessionPhase::Listening`,把 Idle 又翻回 Listening →
用户的 cancel 被吞掉,session 仍然继续。
修:
- 新增 `cancel_raced_during_starting(inner)` helper:持锁查 cancelled or phase
!= Starting
- ASR open_session().await 后调用:如已 race,asr.cancel() + 回 Idle
- Recorder::start Ok 分支用 BeginOutcome { Started / PendingStop / CancelRaced }
原子在同一 lock 内决定,CancelRaced 时清理 recorder + asr 资源不进 Listening
## HIGH #2 — cancelled check 与 inserter.insert 之间的窗口
背景:end_session 检查 cancelled 后到调用 inserter.insert 之间释放了 lock,
此时 Esc 触发 cancel_session 设 cancelled=true 已经晚了 — Cmd+V 即将发出,
撤销不掉。但 cancel_session 仍然 emit "已取消" → UI 与实际行为相反(已插入但
显示已取消)。
修:
- 新增 SessionPhase::Inserting:表示「已过最后一次 cancel 检查、即将/正在
调用 inserter.insert」的窗口
- end_session:把 polish 后的 cancel check + phase 转换 atomic 在同一 lock
内:cancelled → Idle + return;否则 → phase=Inserting 后 release lock 走 insert
- cancel_session:phase==Inserting → 直接 return(不设 cancelled、不 emit 取
消)。理由:物理上无法撤销 Cmd+V,硬装"已取消"只会让 UI 撒谎
cargo check 通过,13 个 warnings 全部是 pre-existing。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 14:05:04 +08:00
baiqing
d0d2da27a5
chore: merge origin/main into develop — 拉回 PR #45 的 polish 推理清理
2026-04-30 13:49:14 +08:00
TRIP and baiqing
e99fe6cfbd
fix(capsule): 终止态后 2 秒自动隐藏 — 覆盖 Done / Cancelled / Error 全部路径 ( #77 )
...
之前只有 Done 路径有 700ms 自动隐藏,cancel / 各种 error 都让胶囊一直挂着。
用户反馈:不论点 ✕ / ✓ / 中途出错 / 按 Esc,2 秒后底部胶囊都应自动消失。
修改:
- 新增 CAPSULE_AUTO_HIDE_DELAY_MS = 2000 + schedule_capsule_idle(inner, ms) helper
延迟后再次检查 phase==Idle 才 emit Idle,避免覆盖期间用户重新触发的 Recording
- Done 路径:原 700ms inline schedule 替换为 helper 调用 (2s)
- Cancelled 路径:cancel_session 末尾追加 schedule_capsule_idle
- Error 路径 5 处:mic 权限失败 / ASR 连接失败 / 录音启动失败 /
await_final 失败 / Whisper transcribe 失败,全部追加 schedule_capsule_idle
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:45:34 +08:00
TRIP and baiqing
1e101a3147
fix(coordinator): 会话状态机修复 — Starting 阶段补偿热键边沿 + Esc 取消支持 Processing ( #76 )
...
closes #51 , #52
## #51 — Starting 阶段忽略热键边沿
握手 ASR 期间(phase=Starting)的"停止"边沿(toggle 第二次按 / hold 松开)
之前被直接 _ => {} 掉,会话锁死直到用户再按一次或重启 app。
修:
- SessionState 加 pending_stop: bool
- handle_pressed Toggle/Starting → pending_stop = true
- handle_released Hold/Starting → pending_stop = true
- begin_session 转 phase=Listening 时 mem::replace 取出 pending_stop,
若为 true 立即 await end_session
## #52 — Esc 取消在 Processing 阶段无效
用户按 Esc 时若 end_session 已进入 Processing(润色 / 插入进行中),cancel
信号被忽略,文本仍插入到光标位置 → 数据无意写入用户当前 app。
修:
- SessionState 加 cancelled: bool
- cancel_session 设 cancelled=true(不再仅 Idle 之外 = 转 Idle)
Processing 阶段保持 phase=Processing 让 end_session 自己走完检查 + 收尾
- end_session 在 ASR 完成后、polish 之前 + polish 完成后、insert 之前
各检查一次 cancelled,命中即跳过 insert/history.append
新会话 begin_session 入口清两个 flag,避免遗留触发奇怪行为。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:36:39 +08:00
TRIP and baiqing
fea402dd15
fix(asr): 保证用户的话不丢 — partial 缓存 + 末帧排队 + Whisper 失败保留 buffer ( #74 )
...
closes #54 , #55 , #56
三件事,同一目标:用户的口述内容不能因为网络抖动 / 服务端关连接 / 凭证错误
而消失。
## #54 partial cache (volcengine.rs)
- SyncState 加 last_partial_text;每次非 final result 缓存当前累积文本
- 服务端 close(无 final 帧)和 receive loop Err(网络中断)路径不再直接 NoFinalResult
- 新增 fallback_to_partial_or_error:有 partial 就 signal_success(RawTranscript),
没有才 signal_error;外层 await_final_result 拿到的是已识别那段文字而非空
- 实测命中:网络抖动断线,用户至少拿到断线前那段已识别的话
## #55 audio finalize race (volcengine.rs)
- 新增 pending_sends: AtomicUsize + send_done: Notify
- consume_pcm_chunk 每个 spawn fetch_add(1),spawn 内发送完毕 fetch_sub(1) + notify
- send_last_frame 进函数先 await pending_sends == 0(800ms 上限避网络极端场景)
再发 leftover + NegativeSequence 末帧
- 防止:fire-and-forget 的 chunk-send 与末帧并发,末帧先到服务端 → 后续 chunk
被当成"流已结束"后多余帧丢弃 → 尾句吞掉
## #56 Whisper buffer 保留 (whisper.rs)
- 之前 transcribe 一进函数就 mem::take 把 buffer 清空,凭证错 / 网络挂 / 解析失败
都让 PCM 直接消失,无法重试也无法 fallback
- 改为先 clone (~960 KB / 30s 音频) → transcribe_inner → 成功才 clear buffer
- 失败时 buffer 保持,给上层"再试一次"或"留失败历史记录"留余地
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:33:54 +08:00
TRIP and baiqing
0d5bfa9b11
fix(infra): 接入 tauri-plugin-single-instance — 防止两份 OpenLess 共存导致重复粘贴 ( #71 )
...
closes #50
现象:/Applications/OpenLess.app 与 dev build 同时存在时,两个进程各自注册
macOS CGEventTap 监听全局热键。用户按 Right Option 一次:
- A 实例捕获 → ASR session 1 → polish → Cmd+V
- B 实例同时捕获 → ASR session 2 → polish → Cmd+V
结果:用户口述被插入两份。
修复:
- Cargo.toml: 加入 tauri-plugin-single-instance v2
- lib.rs: builder 第一个 plugin 即注册它;第二个进程启动时回调聚焦已有主窗口
激活信号通过 plugin 内部 socket 传递,无需额外 IPC 设计。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:28:50 +08:00
TRIP and baiqing
707eaa639b
fix(settings): 移除 SiliconFlow ASR 选项 — 后端未实现,选了必然失败 ( #70 )
...
closes #58
后端 coordinator.rs 只把 active_asr=='whisper' 路由到 WhisperBatchASR,其他全部
走 VolcengineStreamingASR + 火山凭证。设置页之前暴露 SiliconFlow 选项,用户选后
ASR 必然失败。
修复:从 ASR_PRESETS 删除 siliconflow 条目 + 删除 asrProvider==='siliconflow' 的
凭证字段分支。重新启用方案:在后端实现真正的 SiliconFlow ASR provider 后再加回。
Co-authored-by: baiqing <lbx12309@icloud.com >
2026-04-30 13:27:12 +08:00
baiqing
3640924c23
feat(animations): 全局补齐过渡反馈 — 22 处 transition + 页面切换淡入 + ProviderPrompt 弹窗动画
...
按 Codex agent A 的前端审计 fix-now 列表批量补齐:
**hover/active/focus 反馈(一行 transition 即可)**
- WindowChrome winBtnStyle: bg + color
- _atoms Btn: bg + color + border + shadow + transform
- FloatingShell sidebar nav / FooterIcon / 检查更新 / ProviderPrompt 两按钮
- History filter chip / 列表行
- Vocab input / chip
- Style 卡片 / 单卡 toggle / 整体 toggle
- Settings 分区 nav / 录音方式 segmented / Toggle / inputStyle / iconBtnStyle
- Capsule cancel/confirm(opacity + bg + transform)
- Onboarding 授权按钮
- Overview WeekChart bars(height + opacity)
**新增入场动画**
- 页面 tab 切换 ol-page-fade 0.18s(每次 setCurrentTab 重 mount key 触发淡入 + 上滑 4px)
- ProviderSetupPrompt ol-prompt-fade(背景)+ ol-prompt-pop(卡片)
- Vocab chip ol-chip-in(添加新词条时缩放淡入)
**保持不变**
- Capsule 自身的 audio bars 动画(上一轮已优化)
- SettingsModal 的 ol-modal-fade / ol-modal-pop(已有)
零功能变化、零 bug 风险。仅 CSS / inline style 添加。
2026-04-30 13:22:54 +08:00
Chris233
af9b2b62c0
Merge pull request #45 from H-Chris233/main
...
fix(polish): 过滤模型深度思考输出
2026-04-30 13:17:23 +08:00