Commit Graph
801 Commits
Author SHA1 Message Date
TRIP 1ab0807ada Merge pull request #434 from Open-Less/fix/qwen-asr-long-audio-loss
fix(local-asr): Qwen3-ASR 长语音末段丢内容 + 长录音超时
2026-05-13 23:08:48 +08:00
TRIP 61325e3e03 Merge pull request #433 from Open-Less/feat/wayland-callout-three-commands
feat(wayland): callout 补全 --toggle-qa / --cancel-dictation
2026-05-13 23:08:21 +08:00
baiqing 41d2d9aa86 fix(local-asr): 修复 Qwen3-ASR 长语音末段丢内容 + 长录音超时
两个独立缺陷一并修:

缺陷 1(主要,丢内容):transcribe_stream 内部按 2s chunk 切片;
用户说完最后一个字立刻松键时录音缓冲没有任何静默尾巴,末 chunk
< 2s 拿不到静默帧 → C 引擎不收尾 → 该 chunk 转写结果被丢弃。等
5-10 秒静默再松键时由于尾部静默被录进缓冲反而正常。

修复:local_provider.rs transcribe() 把 PCM 转 f32 后追加 0.5 秒
(8000 个 f32 零值 @ 16kHz)静默,给 C 引擎收尾信号。duration_ms
仍按原始缓冲长度计算,padding 不计入。

缺陷 2(次要,长录音超时):COORDINATOR_GLOBAL_TIMEOUT_SECS = 15s
固定值;用户 RTF ≈ 0.3、慢机可达 0.5,60s 录音需 ~18s 转写就直接
超时。

修复:新增 local_qwen_transcribe_timeout(audio_secs) -> Duration,
公式 max(15, ceil(audio_s × 0.6) + 10);只在 Local Qwen 路径用
(Volcengine / Whisper / Bailian / Foundry / QA 路径不动)。配套
LocalQwenAsr::buffer_duration_ms() 不消费缓冲地读取音频时长。

加 4 条单测覆盖公式:短录音兜底 15s、长录音线性放大、ceil 部分秒、
0 秒边界。39 条 coordinator 测试全过。
2026-05-13 22:42:42 +08:00
baiqing 15c2ce560e feat(wayland): callout 补全 --toggle-qa / --cancel-dictation 命令
#420 评论里 aeoform 反馈 1.3.1-19 在 Wayland 下 callout 只展示 --toggle-dictation
一条,没有提及 QA 触发用 --toggle-qa、取消用 --cancel-dictation。

把单条命令展示改为三条命令并列,每条独立"复制"按钮 + 用途短标签
(开始/停止录音、打开/关闭 QA 面板、取消当前录音)。GNOME / KDE 步骤
改为"重复添加 1-3 组";Hyprland / sway 步骤给出三行示例 + 帮助区
启用 pre-line 渲染多行配置片段。

5 份 i18n 文件(zh-CN 源、en / zh-TW / ja / ko 同步翻译)同步新增三条
label key 并更新步骤文案。后端 CLI 三条命令早已实现(cli.rs:41-43),
本次只补前端提示。
2026-05-13 22:38:30 +08:00
baiqing 38f202a010 chore(release): v1.3.1-19 — SelectLite zoom 偏移 + 闪动修复(PR #428)
bump 1.3.1-18 → 1.3.1-19,6 处版本号手动同步(bump-version.sh regex 不收
Beta 版本号):package.json / package-lock.json (root+nested) / tauri.conf.json
/ Cargo.toml / Cargo.lock(openless)。

[变更]
- SelectLite 下拉位置在 html.zoom != 1 下不再右偏(fontScale 的 large 档影响
  最大);CSS zoom 在 WKWebView 下让 getBoundingClientRect 返回 post-zoom
  坐标但 position:fixed 用 pre-zoom 坐标,positionPopover 现在补偿 zoom 转回。
- 下拉打开瞬间的位置闪动消除(popoverMounted state 触发 useLayoutEffect 同步
  二次定位,替代 requestAnimationFrame 的 post-paint 校正)。
- 移除 macOS 走原生 <select> 的旁路分支,三平台统一自定义 popover。
2026-05-13 14:27:34 +08:00
TRIP 1f2b259909 Merge pull request #428 from Open-Less/fix/selectlite-zoom-offset
fix(SelectLite): zoom 补偿修位置偏移 + 同步二次定位消除闪动 + 三平台统一
2026-05-13 14:25:15 +08:00
baiqing 424d9738d9 fix(SelectLite): zoom 补偿修位置偏移 + 同步二次定位消除闪动 + 三平台统一
[zoom 偏移 — 真凶]
fontScale.ts 通过 html.style.zoom 整体缩放页面(small=.9 / medium=1 / large=1.1)。
WKWebView 在 zoom 下双标:getBoundingClientRect 返回 post-zoom(视觉)坐标,
而 position:fixed 的 left/top/width 被当 pre-zoom(布局)坐标处理。直接
`left = rect.left` 让 popover 视觉位置 = rect.left × zoom,右偏
rect.left × (zoom-1) 像素。trigger 越靠右、zoom 越大,偏移越大。

修法:positionPopover 拿到 rect 后,把视觉坐标除以 zoom 转回布局坐标再
setAnchor,浏览器渲染时 ×zoom 后回到正确视觉位置。这是 v1.3.1-17 注释里
那句"WKWebView 里 portal+position:fixed 的自定义 popover 位置漂移反复修
不干净"的真正根因——前几位修过的人没意识到 zoom 是分母。

[闪动]
之前 setPopoverRef 用 requestAnimationFrame 在 popover mount 后再校正一次
位置,但 RAF 在 paint 之后触发,导致「兜底位置 paint → 校正位置 paint」
两帧闪动。短选项尤其明显(fallback popoverHeight=280 vs 真实 60~100px 让
flipUp 决策反转)。改用 popoverMounted state 翻 useLayoutEffect 的依赖,
两阶段定位都同步在 paint 前完成,用户只看到一帧最终位置。

[移除 mac native 分支]
v1.3.1-17 因为上述偏移修不干净,把 macOS 改走原生 <select>(NSPopUpButton)。
zoom 补偿到位后自定义 popover 在 mac 上对齐 trigger,删掉 mac 原生分支
(含 detectOS import),三平台统一走自定义实现,视觉/键盘交互一致。
2026-05-13 14:10:04 +08:00
baiqing 1d0f01a4b5 chore(release): 补齐 package-lock.json 到 1.3.1-18
上一次 bump 漏改了 package-lock.json 的 root + nested version,
导致 beta push CI 的 'Verify version sync across all 5 files' 步骤红。
release-tauri.yml 已基于 v1.3.1-18-beta-tauri 出包成功,本 patch 只
为修复 CI 元数据对齐,不影响已发布产物。
2026-05-13 13:55:00 +08:00
baiqing b4aa4972dd chore(release): v1.3.1-18 — Wayland CLI 触发修复 #420 2026-05-13 12:47:03 +08:00
TRIP b699384762 Merge pull request #427 from Open-Less/fix/issue-420-wayland-cli
fix(hotkey): Wayland 下用 CLI 触发录音,修复 #420
2026-05-13 12:45:58 +08:00
baiqing effa12e5f1 fix(hotkey): Wayland 下用 CLI 触发录音,修复 #420
Wayland 协议禁止应用监听非聚焦窗口键盘事件,原 rdev 路径必然失效。
保留 X11 rdev 不动;Wayland 下走 stub HotkeyAdapter(不监听键盘),
通过 tauri-plugin-single-instance 把 `openless --toggle-dictation`
等 CLI 命令的 argv 转给主实例 coordinator,由桌面环境快捷键设置
绑定该命令实现全局触发。Settings → 录音 mount 时 invoke
is_wayland_cli_mode 拉状态,显示绑命令引导 callout
(GNOME / KDE / Hyprland / sway 四段步骤)。

新增:
- src-tauri/src/cli.rs — CLI intent 解析 + 10 个单测
- docs/issue-420-wayland-hotkey-research.md — 方案调研文档

改动:
- hotkey.rs Linux 分支:Wayland 检测命中走 WaylandCliAdapter stub
  (不再硬拒绝 wayland_unsupported)
- lib.rs:single-instance 回调路由 argv → dispatch_cli_intent
- commands.rs:新增 is_wayland_cli_mode IPC command
- coordinator.rs:dictation_phase_for_cli + cli_toggle_qa_panel
  暴露 CLI 入口,复用现有状态机
- Settings.tsx:WaylandHotkeyCallout 组件 + invoke pull 模型
- i18n × 5 locale:settings.recording.wayland.* 共 14 个键

macOS CGEventTap 和 Windows RegisterHotKey 路径零触碰。
2026-05-13 12:34:52 +08:00
baiqing c5bdb02595 chore(release): v1.3.1-17 — Mac native select + 胶囊白底升 0.85 + ASR 行清理
[SelectLite]
- macOS 走原生 <select>(NSPopUpButton),不再用自定义 portal popover——
  WKWebView 里 portal+position:fixed 的位置漂移问题反复修不干净
- Win/Linux 仍用自定义 popover:popover 锁到 trigger 宽(width 不再用 minWidth),
  避免内容撑大跑出 trigger 范围
- positionPopover 横向 maxLeft 用 rect.width,两帧 left 一致

[Capsule]
- pill 白底 alpha 0.62 → 0.85(用户:"让白色更白一些")
- cancel/confirm 按钮保持 1.3.0 stable 取值;thinking 字号 17/weight 600/cap-shine
  动画保留
- 此前 v1.3.1-9 ~ v1.3.1-15 多轮 alpha 微调 / NSVisualEffectView 实验全部回退

[Settings ASR 行]
- 下拉只保留云端 provider,删 disabled 的本地引擎条目
- 本地引擎激活时下拉锁住 + 显示一行"ASR 提供商已被接管"提示
- i18n 五语言加 settings.providers.asrProviderTakenOver

[版本]
1.3.1-8 → 1.3.1-17,四处版本号同步
2026-05-12 21:58:51 +08:00
baiqing 40c39e11d3 chore(release): v1.3.1-8 hotfix — SelectLite 死锁 + 玻璃统一
[CRITICAL fix: SelectLite 所有下拉打不开]
v1.3.1-7 (PR #426) 我引入了 deadlock:
- anchor 初始 null + portal 条件 `open && anchor && createPortal(...)`
- 我删了 useLayoutEffect 在 open=true 时调 positionPopover
- 改成 popoverRef callback ref(只在 DOM mount 时 fire)
- 但 popover DOM 挂载条件依赖 anchor 非 null → anchor 永 null → 死锁

用户报"所有竖向切换横幅的界面全都打不开了"——LLM 供应商 / ASR 提供商 /
paste shortcut / mirror / language / polish mode 等 SelectLite 下拉全部
点击无反应。这是我的 review 失误,深表歉意。

修:加回 useLayoutEffect 在 open=true 时调 positionPopover 一次(用 trigger
宽 fallback 立即设 anchor),保留 callback ref RAF 在 popover mount 后用
真实宽精确重定位。两步合并:anchor 立即不为 null → portal 渲染 → callback
ref 触发 → 重新精确定位。

[玻璃统一处理]
用户:"现在完全没有磨砂玻璃的效果,应该把底下的细控组件、边栏以及盖栏
等设置的边栏采用同一种方式处理"。

之前 main content (`<main>`) 用 `var(--ol-surface)` 完全不透明白底,跟透明
sidebar 视觉割裂。改成 `rgba(255,255,255,0.62)` + `backdrop-filter blur(18px)
saturate(170%)`,跟 sidebar 一起坐在 WindowChrome 磨砂底板上,全应用一块
连续玻璃。

[版本]
1.3.1-7 → 1.3.1-8,6 处版本号同步。
2026-05-12 19:38:29 +08:00
baiqing 5aafc29ee5 chore(release): bump version to 1.3.1-7 (Beta) + Capsule 磨砂玻璃 + thinking 黑底
[bump] v1.3.1-6 → v1.3.1-7。本版本含 PR #426 merged(SelectLite 位置/动画/
滚外关)+ 本 commit 的两件用户实机 surface:

[Capsule 磨砂玻璃 Windows 路径打开]
之前 Capsule.tsx Windows 路径 useBackdrop = os !== 'win' 强制关掉 backdrop-filter,
让 Windows 胶囊看上去就是白色 pill 没玻璃感。WebView2 现在支持 backdrop-filter,
打开让 Windows 玻璃感对齐 macOS:
- Pill: backdrop-filter blur(28px) saturate(180%)
- CircleButton (cancel): blur(12px) saturate(160%)

[Thinking 字体重做]
- 字号 17 保持,字重 700 → 600 稍细
- 底字浅亮黄 #FCD34D → var(--ol-ink) 黑(用户:"亮黄太显眼,黑底更稳")
- 中段扫光 var(--ol-blue) 深蓝不变(继续作为高对比"滑动"标志)
2026-05-12 19:16:24 +08:00
TRIP db86a14169 Merge pull request #426 from Open-Less/fix/v1.3.1-7
fix(SelectLite): 下拉位置错位 + 关闭动画 + 滚外部自动收缩 (v1.3.1-7)
2026-05-12 19:14:51 +08:00
baiqing 167ceb297b fix(SelectLite): 位置错位 + 加关闭动画 + 滚外部自动收缩
用户在 macOS 上反馈 LLM provider 下拉 3 个问题:
1. 位置完全错位(popover 跟 trigger 不对齐)
2. 没有关闭动画
3. 在 popover 外滚动应自动收缩,但当前会跟着 trigger 重定位

[位置错位根因]
positionPopover useCallback deps [],useLayoutEffect 在 open=true 时 fire
一次 —— 此时 popoverRef.current 还没挂载,popoverWidth 用 trigger.width 兜底。
Popover mount 后真实宽度 ≠ trigger 宽(长选项撑大),但 effect 不再重算。

修法:popoverRef 改用 callback ref,每次 popover DOM mount 时 RAF 推到下一帧
重算 anchor,拿到真实 popover 宽。同时 positionPopover 用 max(trigger 宽,
popoverRect 宽) 保证 popoverWidth 不低估。

[滚动外部 → 关闭]
之前 useLayoutEffect 监听 scroll 事件做 reposition。改成监听 'scroll' + 'wheel'
capture phase,target 在 popover 内(popoverRef.contains)保留打开(长列表
内部 scroll 不关),target 在外部 → closeMenu。同时 window resize 也强制关闭。

[关闭动画]
加 leaving state 让 popover 在 unmount 前播 ol-select-pop-out 反向 keyframe
(opacity 1→0 + translateY 0→-4 + scale 1→.98,跟入场对偶)。140ms 后真正
unmount + 清 anchor / highlight。
2026-05-12 19:02:43 +08:00
baiqing ca5cb5277a chore(release): bump version to 1.3.1-6 (Beta)
PR #425 合并后 bump。本版本相对 v1.3.1-5-beta 累积:

[胶囊动画]
- 入场 .26s → .38s,cubic-bezier(.16,.86,.32,1.18) 更强 spring overshoot
- 出场 .24s → .36s(EXIT_ANIM_MS 同步加到 360),cubic-bezier(.55,.06,.68,.19)
  慢启动加速收尾的平滑曲线,让用户能看清"左右收缩 + 下移 + 淡出"
- thinking 字号 14 → 17,字重 500 → 700,浅亮黄底字 + 深蓝扫光

[LocalAsr Windows Qwen3]
- 删除顶部"白底显眼"提示 banner(已 inert + 灰显,banner 多余)
- Windows 列表为空时不再画 placeholder Card,简化为空白占位
- 千问3 ASR 标题加 amber 小 badge "实验性"
- 5 个 locale 新加 i18n key qwenExperimentalBadge

[polish prompt 反 AI 自述]
- OUTPUT_BLOCK 新加"# 反 AI 自述式表达(强约束)":禁词列表 +
  保持原句人称视角 + 直陈原意不扩写
- Light task 加"工程化直陈"段
- Formal task 加"工程化正式"段(不展开为商务铺垫)
- Structured task 加"判断事项的标准"4 种独立事项形态,事项 ≥3 强制双层
  即使输入听起来像顺着说下来的口播
2026-05-12 18:44:42 +08:00
TRIP 545c3312c3 Merge pull request #425 from Open-Less/fix/v1.3.1-6
fix(capsule): 入场出场动画加慢加曲线 + thinking 字号/颜色重做 (v1.3.1-6)
2026-05-12 18:44:04 +08:00
baiqing 960889da7c fix(polish): Structured prompt 加强"判断事项标准",提升结构化稳定性
用户报 Structured 模式不稳定 —— 同样输入有时双层 list 有时连贯段落。
失败示例:用户口述 4 个独立反馈(千问3 提示样式 + 让它消失 + 改实验性 +
其他没问题)输出成连贯段落,没归类成双层 list。

LLM 判断"事项数"时可能要求用户明说"第一""第二""另外"等连接词,
口语化输入没这些就误判为"一段连贯陈述"。

加强:Structured task block 顶部新加"默认行为:双层 list。判断事项的标准":
列出 4 种独立事项的形态(可独立成句的陈述、独立请求/建议、状态判断/结论、
针对模块的描述/要求),明确"事项数 ≥3 强制双层化,即使输入听起来像顺着
说下来的口播"。

跟前面 commit 35d53b8b 的"不可降级到轻度润色 + 多个组合需求处理规则"
形成三重 sticky:
- 规则 1:不可降级到轻度润色(事项 ≥3 必须双层)
- 规则 2:多组合需求按大类按口述顺序排
- 规则 3(本 commit):明确"事项"的判断标准,不依赖用户的连接词
2026-05-12 18:32:01 +08:00
baiqing cb5b544c0f fix: LocalAsr 灰显去 banner + 千问3 加实验性标签 + polish 反 AI 自述
[LocalAsr Windows 灰显简化(用户:"白底太显眼")]
- 删除顶部 qwenUnavailableOnWindows banner Card(白底浅橙 noise)
- 列表为空时的 placeholder Card 改成纯空 <div minHeight:60>,不再二次重复 banner 文案
- 灰显 + inert + opacity 已自我解释,不需要 banner 引导

[千问3 标记为「实验性」(用户拍板)]
- LocalAsr.tsx 在 qwenTitle 前加 amber-300 小 badge "实验性"
- 5 个 locale 新加 i18n key `qwenExperimentalBadge`:
  - zh-CN: 实验性
  - en: Experimental
  - ja: 実験的
  - ko: 실험적
  - zh-TW: 實驗性

[polish 反 AI 自述(用户:"直抒胸臆,不加多余话;不要 AI 输出式语言")]
- OUTPUT_BLOCK 新加 "# 反 AI 自述式表达(强约束)" 子段:
  - 禁词列表:"我们看了一下""我们发现""经过分析""综合来看""总体而言"
    "整体来说""依我所见""根据情况""从结果来看"等代入第三方/自述视角的语句
  - 保持原句的人称视角,原句没有"我们"就不引入
  - 直陈原意,不扩写
  - 不加修饰副词或铺垫句("值得一提的是""值得注意""值得考虑"等)

- Light task block 加 "**工程化直陈**" 段:
  - 开发协作 / 任务清单 / 技术沟通 / 工作汇报场景按主谓宾陈述
  - 不加修饰副词、铺垫句、AI 自述
  - 输出长度尽量贴近原句字数 ± 20%
  - 新增示例:用户原话"嗯我们目前看了一下没什么大问题就是缓存策略可能要改一下"
    → 输出"目前没什么大问题,缓存策略需要调整"(不引入"我们看了一下")

- Formal task block 加 "**工程化正式**" 段:
  - 正式 ≠ 扩张;不展开为商务铺垫
  - 不加"经过分析""综合来看""值得注意的是"等代入第三方视角的语句
  - 输出长度 ± 30% 以内,不让正式化扩张到两倍长度
  - 新增示例:用户原话"嗯这次发版前我们看了一下其实问题不大但还是建议把缓存改一改"
    → 输出"本次发版整体问题不大,建议调整缓存策略"(不写"我们看了一下""经过评估")
2026-05-12 18:27:33 +08:00
baiqing 80e840341b fix(capsule): 入场出场动画加慢加曲线 + thinking 字号/颜色重做
用户在 v1.3.1-5 装机后反馈:
1. 胶囊入场效果不错但希望"再慢一点 + 曲线感"
2. 出场动画"看不到" —— 240ms 太快感知不到
3. thinking 字体"不明显",希望字大 / 色亮 / 滑动清楚

改动:
- @keyframes capsule-in: .26s → .38s,cubic-bezier(.16,.86,.32,1.18)
  spring overshoot 更强,"从中心冒出向左右生长"更弹更曲线
- @keyframes capsule-out: .24s → .36s,cubic-bezier(.55,.06,.68,.19)
  慢启动 + 加速收尾的平滑曲线,让用户能看清"左右收缩 + 下移 + 淡出"
- EXIT_ANIM_MS: 240 → 360 同步加长,避免定时器先于动画结束 unmount

thinking 配色(用户拍板,参考 d 项):
- fontSize 14 → 17(更大)
- fontWeight 500 → 700(更粗)
- 两侧底字:浅亮黄 #FCD34D (amber-300)
- 中段扫光:深蓝 var(--ol-blue) (≈ #2563EB)
- 浅黄暖底 + 深蓝扫光对比强烈但不刺眼,扫光滑过感清晰
2026-05-12 18:18:05 +08:00
baiqing 1a810c1c67 chore(release): bump version to 1.3.1-5 (Beta)
PR #423 合并后 bump。本版本相对 v1.3.1-4-beta 累积:

[3 个 dev task] (worktree-isolated dev agents + 3 个 reviewer)
- 胶囊动画:进入从中心冒出向左右生长,退出左右收缩 + 淡化 + 下移
- Windows 千问3 ASR 灰显 disabled + 不可激活提示 banner
- 5 个 SVG 重画:translate / vocab / history / overview / selectionAsk

[review feedback fix]
- Capsule EXIT_ANIM_MS / INITIAL_VISIBLE_STATE 抽 const
- Qwen3 disabled 区加 inert 让键盘 Tab 跳过
- overview icon 加 sparkline 数据线区分 layout icon
- selectionAsk 气泡尾巴拉到 y=23 防 viewBox 24 底裁切

[用户实机 surface]
- Vocab 词条大椭圆真根因:父 flex minHeight 拉伸子 item,加
  alignSelf:flex-start 阻止
- Windows 原生顶栏 vs 玻璃色差:caption color 0xFFFFFF → 0x00F7F5F5
  跟 glass 起始色一致;glass alpha 0.78 → 0.92 压色差

[polish prompt 反降级]
- Structured task block 加"不可降级到轻度润色"和"多个组合需求归类规则"
2026-05-12 17:46:25 +08:00
TRIP 784f947cf3 Merge pull request #423 from Open-Less/fix/v1.3.1-5
fix(v1.3.1-5): 胶囊动画 + Qwen3 灰显 + 5 SVG 重画 + 6 项 Windows 视觉修复 + polish 反降级
2026-05-12 17:45:27 +08:00
baiqing 76e0723613 fix(polish): Structured prompt 加强反"降级到轻度润色" + 组合需求归类规则
用户报 DeepSeek V4 Flash 走 Structured 模式时仍只做轻度润色(标点 + 断句
+ 去口癖然后输出一段连贯段落),没有按双层 list 结构化输出。模型能力较
弱时容易把"清晰结构"理解成"清楚地表达"而非"双层归类"。

加两条新规则到 Structured task block:
1. **不可降级到轻度润色** —— 明确禁止只补标点然后输出连贯段落,最低
   输出形态是双层 list。即使原文听起来连贯,事项 ≥3 都必须双层化。
2. **多个组合需求处理规则** —— 用户原话:"当用户提出多个组合需求时,
   要分别归入不同大类,并且按照顺序把这些组合需求做结构化整理"。
   写进规则:按语义/领域分大类,按口述顺序排,每个大类用 (a)(b)(c)
   子项,不允许合并丢失或重排到错误大类。

加在原有 # 任务(清晰结构) 标题之后、"**重要前提**"之前。前后顺序与
其他段落兼容,不动 ROLE_BLOCK / COMMON_RULES / OUTPUT / 示例。
2026-05-12 17:32:54 +08:00
baiqing 35d53b8be2 polish: 集成 review 反馈 + 用户新 surface 的 Windows 视觉修复
review 阶段标的 4 个 High 全部处理,加上用户在 v1.3.1-4 装机后新报的 2 个
Windows 视觉问题,本 commit 一次性收:

[review-capsule High]
- Capsule.tsx 抽 EXIT_ANIM_MS / INITIAL_VISIBLE_STATE 两个 const,去掉
  `240` magic number + `isTauri ? 'idle' : 'recording'` 字面量重复
- 修正退出动画调度的 race 描述注释(cleanup clearTimeout 阻止 fire,
  不是"定时器仍会触发")

[review-qwen3 High]
- LocalAsr.tsx Windows Qwen3 disabled wrapper 加 `inert` HTML5 属性,
  让键盘 Tab 也跳过 disabled 区域(仅靠 pointerEvents:none 不挡键盘 +
  aria-disabled 不传给后代)。两个 wrapper 都加。@ts-expect-error
  注释解释为何这里需要绕过 TS lib.dom 旧版未收录 inert 属性。

[review-icons 2 High]
- Icon.tsx `overview`: 在三个 dashboard tile 顶部加 sparkline 数据线
  区分 layout icon(之前几乎一样,14px nav 视觉无法分辨)
- Icon.tsx `selectionAsk`: 气泡尾巴 y=24 → y≈23,避免 strokeLinecap
  round + strokeWidth 1.5 出 viewBox 底边被裁

[用户新 surface — Vocab 词条大椭圆]
- Vocab.tsx VocabChip 加 `alignSelf: 'flex-start'`。真根因(之前 PR
  #422 误判为 button user-agent appearance):父 flex 容器 minHeight: 80
  让 flex item 默认 align-self: stretch 把单个 chip 拉伸到 80px 高,
  borderRadius:999 渲染成超大椭圆。alignSelf:flex-start 阻止拉伸。

[用户新 surface — 顶栏 vs 玻璃色差]
- lib.rs DWMWA_CAPTION_COLOR 从纯白 0xFFFFFF → 0x00F7F5F5
  (rgb 245,245,247) 跟 WindowChrome glass linear-gradient 起始色一致
- WindowChrome.tsx glass alpha 0.78 → 0.92(PR #422 为加强玻璃感降的,
  现在为压缩色差升回去,玻璃感由 backdrop-filter blur+saturate 提供)

后续:用户希望调研"完全取消 Windows 原生顶栏(像微信那样自绘)"——
属于 v1.3.1-6 级别 large rewrite,单独追。
2026-05-12 17:31:41 +08:00
baiqing f44eb5958c feat(icons): redraw translation / vocab / history / selectionAsk SVGs 2026-05-12 17:26:52 +08:00
baiqing a981815b8b feat(localasr): Windows 端千问3 ASR 改为灰显 disabled + 提示 2026-05-12 17:26:52 +08:00
baiqing ad6cd93b10 feat(capsule): center-grow entry + contract-fade exit animation 2026-05-12 17:26:52 +08:00
baiqing a7a9284db6 chore(release): bump version to 1.3.1-4 (Beta)
PR #422 合并后 bump。本版本相对 v1.3.1-3-beta 累积修复:
- Windows 默认字号 'large'(fontScale.ts UA 检测)
- Windows 原生标题栏底色刷成白色,与 sidebar 视觉统一(DWM CAPTION_COLOR)
- 全平台玻璃统一:WindowChrome 撤销 PR #419 留下的"Windows 100% opaque +
  无 backdropFilter"分支,两平台用同一半透明 background + blur saturate(190%),
  alpha 0.92 → 0.78 让玻璃感更明显但不过透
- Vocab 词条大圈再次根治:global.css button reset 补加 outline:none /
  min-width:0 / min-height:0 / box-sizing:border-box
- polish ROLE_BLOCK 撤销 b2325a27 回滚,恢复 7e60bdb5 8-条规则状态
- polish ROLE_BLOCK 「意图难判」规则改为强制结构化(用户拍板的新版)
2026-05-12 17:00:05 +08:00
TRIP ec55d9e509 Merge pull request #422 from Open-Less/fix/v1.3.1-4-multi-tweaks
fix: v1.3.1-4 Windows 字号/顶栏色/玻璃 + Vocab 大圈 + polish 回滚
2026-05-12 16:59:24 +08:00
baiqing 76a4a4131f fix(polish): ROLE_BLOCK"意图难判"规则改为强制结构化
旧版(7e60bdb5 引入):"意图难以判断 → 只做句子层面整理(标点、断句、
口癖去除)"——这条 safety net 在 Structured 模式下会让 LLM 退回 Light/Raw
行为,导致"清晰结构"模式对意图不明的输入不输出双层 list。

新版(用户拍板):意图难判时**强制结构化整理**,输出必须与当前 mode 的
结构要求一致,同时贴近原意不扩写。这样:
- Structured 模式:意图模糊也强制归类成双层 list
- Light / Raw 模式:仍按各自 task block 走(不会强制结构化,因为它们的
  task block 明确写了"保留原句顺序"等约束)

ROLE_BLOCK 其他 7 条规则不动。
2026-05-12 16:48:53 +08:00
baiqing 9e62dfe271 fix: v1.3.1-4 multi-tweaks(字号 / 顶栏色 / 玻璃 / 词条 / polish 回滚)
5 个用户反馈一次性收:

1. Windows 默认字号放大
   fontScale.ts readFontScale() 检测 navigator UA 含 Windows 时新装默认
   返回 'large'(1.1x zoom),已存 localStorage 偏好的用户不受影响。

2. Windows 顶栏白色,与左侧 sidebar 视觉统一
   lib.rs 重新引入 apply_windows_caption_color,用 DWM API DwmSetWindowAttribute
   DWMWA_CAPTION_COLOR=35 (Win11 22H2+) 把原生标题栏底色刷成 0x00FFFFFF。
   pre-22H2 Win 静默失败仅 warn。

3. 全平台玻璃效果统一 & 略浊
   WindowChrome.tsx 撤销 PR #419 留下的"Windows 100% opaque background +
   去 backdropFilter"分支(那是 Win sidebar 完全无玻璃感的根因)。两个
   平台改用同一份半透明 background(alpha 从 0.92 降到 0.78)+ blur
   var(--ol-glass-blur-strong) saturate(190%),让 sidebar 透过磨砂底板。
   Windows 配合 apply_mica + tauri.conf transparent:true 透出 Mica。

4. Vocab 词条大圈再次尝试根治
   global.css button reset 在 appearance:none 基础上再加 outline:none /
   min-width:0 / min-height:0 / box-sizing:border-box。Windows Chromium
   user-agent style 包含上述四项默认值,单一个 appearance:none 不够覆盖
   全部。键盘焦点指示走 .ol-focus-ring + :focus-visible box-shadow,
   不被 outline:0 影响。

5. polish.rs ROLE_BLOCK 撤回 b2325a27 回滚
   用户确认 13:08 之前最近的 polish.rs commit(20756f7e,含 7e60bdb5
   refine)表现正常。我之前 b2325a27 误以为 7e60bdb5 是问题源把 ROLE_BLOCK
   改回 v1.2.24-9-beta 状态,反而离用户认可的版本更远。改回 7e60bdb5
   8-条 ROLE_BLOCK 状态。
2026-05-12 16:39:03 +08:00
baiqing b227b69a03 chore(release): bump version to 1.3.1-3 (Beta)
PR #421 hotfix 合并后 bump。本版本相对 v1.3.1-1-beta-tauri 累积修复:
- Windows 主窗口交还原生 Win11 chrome(修 PR #419 删自定义标题栏后无法
  拖/关/最小化的卡死状态)
- Vocab 词条 Windows 大圈(global.css button appearance:none)
- polish "清晰结构"模式输出退化成单段(ROLE_BLOCK 回滚到 v1.2.24-9-beta)

v1.3.1-2 tag + release 已删除(含 Windows 主窗口无 chrome 阻塞 bug)。
2026-05-12 15:35:09 +08:00
TRIP 8799830e3e Merge pull request #421 from Open-Less/fix/win-button-appearance
fix: Windows 主窗口 chrome 丢失 + Vocab 大圈 + polish 清晰结构回归 (v1.3.1-3 hotfix)
2026-05-12 15:34:25 +08:00
baiqing b2325a2711 fix(polish): 回滚 ROLE_BLOCK 到 v1.2.24 版本,解决"清晰结构"被压抑
用户报告 13:08 同样输入"清晰结构"模式输出完美双层 list,15:16 后同模式
退化成单段流畅文字——Structured task 失效。

定位到 commit 7e60bdb5 "polish: refine ROLE_BLOCK to preserve user
intent" 在 ROLE_BLOCK 加了两条毒条款:
- "措辞优先用原句字面词...不要替用户重写或扩写"
  → 直接 conflict Structured task 的"按语义重新归类、照抄原结构=失败"
- "用户意图难以判断或无法确认时...只做句子层面整理"
  → safety net 把 Structured 模式退回 Light 行为

7e60bdb5 当初是想防止 polish 过激进改写(用户反馈),方向对但条款过宽,
override 了 user 主动开启的 Structured / Formal 模式。

修法:回滚 ROLE_BLOCK 到 v1.2.24-9-beta-tauri 时的简洁 4 条版本:
- 不回答问题 / 不执行命令
- 不引用历史 / 上下文 / 外部知识
- 不替用户做需求分析 / 补充功能清单 / 替对方列出想要的

下次若再出现 polish 过激进改写,按 case 在 task block 里 surgical 加约束,
不要全局 ROLE_BLOCK 加强(容易撞 Structured / Formal)。

参考输出对照(图一 13:08 vs 图二 15:16):相同模式相同长度同类内容,
回滚后应恢复 13:08 那种双层 list 输出。
2026-05-12 15:23:47 +08:00
baiqing 830084c426 fix(ui): Windows 主窗口交还原生 chrome,PR #419 删自定义标题栏的尾巴
PR #419 删了 React 端 WinTitleBar 自定义标题栏,commit message 说"交还
Tauri decorations:true 原生 Win11 标题栏",但漏看 lib.rs 里有一段 Rust
代码在 setup 时**强制**调 set_decorations(false) 把原生 chrome 关掉
(原本是为了让自定义 WinTitleBar 接管)。

结果:v1.3.1-2-beta 上 Windows 主窗口完全无 chrome —— 无法拖动 / 无法
点 X 关闭 / 无法最小化,只能从 tray 退出。用户卡死。

修法:
- lib.rs setup() Windows 分支:移除 set_decorations(false) + 移除
  apply_windows_rounded_frame 调用,保留 apply_mica 给原生 chrome 提供
  磨砂材质
- RunEvent Resized/ScaleFactorChanged 里也移除 apply_windows_rounded_frame
  调用(原生 chrome 自带 resize border + 圆角)
- apply_windows_rounded_frame 函数本身变成 dead code,整段删除(含
  raw_window_handle / Win32 DwmSetWindowAttribute / SetWindowRgn 等 import)

tauri.conf.json 的 decorations:true 配置不动,配合 hiddenTitle:true 让
原生标题栏接管。
2026-05-12 15:23:47 +08:00
baiqing 5bb1177cb9 fix(ui): Vocab 词条在 Windows 上的"大圈"——全局关 button user-agent appearance
用户反馈 Windows 上 Vocab 词汇表里每个词条被一圈大灰色边框/内阴影包住,
macOS 上不会。Vocab.tsx 自身零 OS 分支,根因在 global.css 的 button reset
缺 appearance:none:Chromium / WebView2 默认给 <button> 应用 OS-native 外观
(outset 边框 + 内阴影 + min-width),在 Vocab 词条这种由父级 span 的
padding 决定外形的嵌套 button 上整圈就露出来;macOS WKWebView 对
appearance:auto 处理较弱所以看不出来。

修法是 global.css button reset 加 appearance:none + -webkit-appearance:none,
一行修整仓。所有现有 button 都自己 inline 重写了背景/边框/圆角,关掉
user-agent appearance 不会改变它们的视觉。
2026-05-12 15:13:03 +08:00
baiqing a2a944ea31 chore(release): bump version to 1.3.1-2 (Beta)
PR #419 已合并到 beta,UI 完整版(Windows 原生 chrome / 胶囊缩小 /
自定义下拉 / a11y 焦点指示 + 键盘 scrollIntoView + 视口 clamp)相比
上一轮 1.3.1-1 commit (90b35057) 累积了实质改动,bump patch-build
号到 1.3.1-2 区分。

6 处版本号同步:package.json / package-lock.json (root + nested) /
tauri.conf.json / Cargo.toml / Cargo.lock。
2026-05-12 14:58:08 +08:00
TRIP 993bb90dd3 Merge pull request #419 from Open-Less/fix/windows-ui-417-418
fix(ui): Windows 原生 chrome / 胶囊缩小 / 自定义下拉 (#417 #418)
2026-05-12 14:54:37 +08:00
baiqing 6c7598a858 fix(a11y): SelectLite 键盘高亮自动滚动 + popover 横向 viewport clamp
pr-agent #419 第二轮 review 指出的两个 focus areas:

1. Keyboard scroll:长 dropdown 超过 280px 时 ArrowUp/Down 切换 highlight
   不会把高亮项 scroll into view,键盘用户看不到当前选中。新增 useEffect
   监听 highlight 改变,找到 data-option-index 对应 DOM 元素后
   scrollIntoView({ block: 'nearest' }),已可见的项不会被强行滚动。

2. Viewport clipping:popover 用 trigger.left 作 anchor,没有横向边界
   clamp。窗口右边的 select 弹出后可能溢出屏幕。positionPopover 改成测
   真实 popover 宽度(首次开打用 trigger 宽度估),然后把 left clamp 到
   [8, viewport - width - 8] 区间。

不动 keyboard 导航 / disabled 处理 / vertical flip 等已 verified 行为。
2026-05-12 14:28:19 +08:00
baiqing 70917cb027 fix(a11y): SelectLite / SwitchLite 加键盘焦点指示
pr-agent #419 review 指出两个 button 都用 outline:none 关掉了浏览器默认
焦点 ring 却没替代——键盘 Tab 时用户看不到当前焦点在哪。和 _atoms.tsx
Collapsible 的 pr-agent #407 是同一类问题。

修法:新增 .ol-focus-ring class,:focus-visible 时上 2px 半透明蓝
box-shadow(不是 outline,因为 inline style 的 outline:none 会盖掉
class 里的 outline,但盖不掉 box-shadow)。:focus-visible 只在键盘
focus 时生效,鼠标点击保持干净。
2026-05-12 14:02:48 +08:00
baiqing 8a6ac8b308 fix(ci): 补齐 package-lock.json 的 version 字段对齐
90b35057 bump 到 1.3.1-1 时漏改了 package-lock.json 的 root 与
nested version 字段(都还是 1.3.0),CI "Verify version sync
across 5 files" 卡死所有平台,本 PR 的 build / check 步骤根本
没机会执行。

手动同步到 1.3.1-1,与 package.json / tauri.conf.json /
Cargo.toml / Cargo.lock 对齐。本地复跑 CI 第一步的 node -p 校验
全部一致。
2026-05-12 13:48:44 +08:00
baiqing 5bf6350fd2 fix(ui): Windows 原生 chrome / 胶囊缩小 / 自定义下拉 (#417 #418)
- WindowChrome: 移除 Windows 端自定义标题栏和 resize handles,
  交还 Tauri decorations:true 原生 Win11 标题栏,修复 X 按钮重叠
  与圆角处的黑边/白线
- Capsule (#417): Windows pill 196×52→180×44,textWidth 104→88,
  视觉密度与 macOS 对齐
- SelectLite (#418): 重写为受控下拉组件(portal popover, 键盘导航
  Arrow/Enter/Esc, 视口翻转, a11y combobox/listbox),替换 11 处
  native <select> 以避开 Win32 ComboBox 直角丑框
- SettingsModal: 删除"个性化"中重复的"界面语言"入口,功能保留在
  "设置 → 语言"分区;5 个 locale 同步清理 modal.personalize.language
- SwitchLite: 加 outline:none 解决 Windows 上点击后的黑色焦点框
- global.css: 移入 ol-select-pop 关键帧;不再用全局 outline:none,
  以保留 _atoms.tsx Collapsible 的键盘 outline (pr-agent #407)
2026-05-12 13:34:08 +08:00
baiqing 90b3505794 chore(release): bump version to 1.3.1-1 (Beta)
First beta after Stable 1.3.0. Carries the Settings modularization refactor
(PR #416). Tagged as v1.3.1-1-beta-tauri to trigger the release-tauri.yml
Beta-channel build (prerelease=true, manifest filenames carry -beta suffix
so the Stable in-app updater endpoint cannot pick this up).
2026-05-12 12:50:16 +08:00
TRIPandbaiqing 6baca19e05 refactor(settings): split Settings.tsx into per-section modules + simplify Advanced labels (#416)
Settings.tsx (2835 → ~2150 lines) split by logical responsibility: each tab
now lives in src/pages/settings/. Pure mechanical extraction — no behavior change.

- settings/shared.tsx     — SettingRow, Toggle, inputStyle, AsrPresetId
- settings/AdvancedSection.tsx
- settings/ShortcutsSection.tsx
- settings/PermissionsSection.tsx (incl. PermissionPill / HotkeyStatusPill / WindowsImeStatusPill)
- settings/LanguageSection.tsx
- settings/AboutUpdateControl.tsx
- Settings.tsx keeps RecordingSection + ProvidersSection (their helper tangle
  is large; follow-up PR), re-exports Toggle / AboutUpdateControl so
  SettingsModal's existing imports keep working.

Advanced settings labels: shortened verbose copy across zh-CN / zh-TW / en /
ja / ko. "启用流式输入" → "流式输入", "同步写入剪贴板" → "同步到剪贴板",
desc / hint blocks trimmed; the toggle already conveys enable/disable so the
verb prefix was redundant.

Verified: tsc clean, vite build green, cargo check green, cargo test --lib
222/222 passing.

Co-authored-by: baiqing <lbx12309@icloud.com>
2026-05-12 12:48:31 +08:00
TRIP 71f2792f09 Merge pull request #415 from H-Chris233/fix/issue-413-streaming-sse-edges
修复流式 SSE UTF-8 切分与部分输入丢失
2026-05-12 10:58:47 +08:00
H-Chris233 20756f7e93 Keep streamed output consistent across SSE edge cases
Streaming LLM output can split UTF-8 codepoints across HTTP chunks, and unicode typing can fail after a prefix has already reached the focused app. The stream path now decodes SSE bytes incrementally and records only confirmed typed prefixes so history and clipboard match what appeared on screen.

Constraint: Issue #413 requires fixing both streaming polish and QA SSE paths plus partial-delta typing loss.

Rejected: Decode each response chunk independently | valid UTF-8 can be split by HTTP frame boundaries.

Rejected: Keep full delta on typing error | it records text that may never have reached the target app.

Confidence: high

Scope-risk: moderate

Directive: Do not re-enable mutating final postprocess for already_streamed text without proving screen/history/clipboard consistency.

Tested: cargo test --manifest-path src-tauri/Cargo.toml --lib

Tested: cargo check --manifest-path src-tauri/Cargo.toml

Tested: git diff --check
2026-05-12 10:32:57 +08:00
baiqing 8ea4e8932f chore(release): bump version to 1.3.0 (Stable) 2026-05-12 10:28:07 +08:00
baiqing e90fe9f7b1 chore(release): correct beta version to 1.3.0-1 (MSI requires numeric pre-release)
上一条 1.3.0-BETA 在 Windows MSI 打包阶段被 Tauri 拒绝:MSI ProductVersion
只接受 \"MAJOR.MINOR.BUILD\" + 数字 pre-release(≤ 65535)。BETA 字面被
canonicalize 时报错 \"optional pre-release identifier in app version must be
numeric-only\"。

按仓库历史 (1.2.24-7/8/9) 同体例改为 1.3.0-1,表示 1.3.0 的第 1 个 Beta。
2026-05-12 09:56:20 +08:00
baiqing 7136cf55cc chore(release): bump version to 1.3.0-BETA 2026-05-12 02:04:32 +08:00