Lu Fan(SonnyCalcr)
ef28cf690d
fix(server,ui,ui-html): 打磨 Direct2D 设置窗口:图标、检查更新、热力图、滚动与冷启动 ( #1001 )
...
* fix(ui): SVG 按整像素栅格化、滚动改为跟手的指数滑动,并可预热 D3D 设备
- GetSvgBitmap 按四舍五入的像素尺寸建位图,避免 D2D 向上取整后被挤压采样
- ScrollViewer 平滑滚动改为按帧时间逼近目标:连续滚轮不再每格从零速重起,
内容按整设备像素排布,滑动中文字不再抖动
- 新增 DeviceResources::PrewarmComposition,在后台线程提前创建 D3D11 设备,
首帧复用,省去约 200ms 的驱动初始化
* fix(server): 修复 Direct2D 设置窗口的图标、检查更新与热力图交互,加快冷启动
- 侧栏等 SVG 图标对齐设备像素绘制,不再发糊
- 关于页「检查更新」:页面持有状态,点击不再无反应;按钮加悬停描边与按下位移;
后台任务结果改为投递消息回窗口,窗口被遮挡时不再因 WM_TIMER 被压制而卡在「正在检查…」
- 弹窗按显式宽度测量内容,换行文字不再与下一行重叠
- 以 --about 打开时侧栏指示条落在「关于」
- 日历热力图可横向滚动(拖动滑块、点击轨道、Shift+滚轮),滚动条与竖向一致:
8px、无箭头、2px 圆角;悬停格子 500ms 后显示日期与字数
- 滚轮每格 60px;暗色主题首帧前不再闪白(按主题色擦底并在首帧前隐藏窗口)
- 启动时预热 D3D 设备,首帧从约 300ms 降到约 140ms
* fix(ui-html): 热力图滚动条与页面竖向滚动条一致,检查更新按钮加悬停与按下反馈
与 Direct2D 设置窗口的同步改动保持一致。
2026-10-16 18:51:21 +08:00
Lu Fan(SonnyCalcr)
53649d9d12
feat(server,ui,ui-html): 新增实验性的 Direct2D 设置窗口 ( #999 )
...
* feat(ui): 动画时钟、渲染剔除与文本框扩展,并优化 msimeui 性能
- 新增 Animation.h:cubic-bezier 缓动、Tween、颜色插值,Window 提供
RequestAnimationFrame / GetFrameTime,动画帧随显示刷新率推进
- Window 可选 DirectComposition 渲染(含不透明模式以支持 ClearType)、
双击按下、捕获丢失时结束按压、悬停刷新、可关闭销毁时退出消息循环
- Scene 把滚轮交给光标下最内层可滚动元素并逐级冒泡
- DeviceResources:裁剪栈驱动的离屏剔除、按帧回收的笔刷缓存、SVG 栅格缓存
- ScrollViewer 可配置外观与平滑滚动;Popup 支持阴影通道与出现动画;
卡片阴影缓存抽成可复用的 ShadowCache
- TextBox 支持 SetText、密码掩码、多行滚动、字重/字间距/行高与外观设置
- 调试日志默认关闭(MSIMEUI_DEBUG_LOG=1 才写文件),不再在每次点击和
TSF GetTextExt 时打开文件
- 字体回退在 CJK/emoji 映射之后保留系统回退,缺字不再显示方框
- 新增动画与剔除单元测试
* feat(server): 新增实验性的 Direct2D 设置窗口
设置窗口可通过 appearance.settings_ui_backend 选择渲染方式:默认 webview2,
d2d 为实验性的 msimeui 原生实现(server/src/settings/native/),1:1 复刻
网页设置页,包括侧栏切换时竖向高亮条的滑动动画。
- 两个前端共用同一套 webview 契约消息与 HandleClientMessage,配置读写
映射仍只在 settings_app.cpp
- 切换渲染方式后设置进程自动以新方式重新打开;--d2d / --webview2 可临时指定
- 新配置项写入出厂模板与开发配置,UiBackendPolicy 与测试同步更新
- METASEQUOIA_IME_SETTINGS_INSTANCE 允许开发版与已安装的设置窗口并存
- 更新 ui-backends 文档与 server/AGENTS.md
* feat(ui-html): 外观页新增设置窗口渲染方式选项
2026-10-16 16:13:13 +08:00
chr331 and fanlusky
1c3bd7cb83
feat(server,ui-html,windows): 支持自定义“输入状态切换”中的快捷键 ( #985 )
...
* fix(windows): 支持标点切换快捷键改绑与取消绑定
* fix(shortcut): 对齐虚拟键并处理语音与窗口快捷键冲突
* fix(ui-html): 绑定标点快捷键前提示应用快捷键占用
* fix(ui-html): 仅对已知快捷键冲突提示确认
* feat(shortcuts): 支持自定义输入状态切换快捷键
* fix: keep shortcut editor buttons on one row
* fix(shortcuts): 限定输入状态快捷键为 Ctrl 组合
* fix: clarify shortcut override and punctuation lock behavior
* perf(server,windows): 提前筛选输入状态快捷键
* fix(windows,server,ui-html): 修正输入状态快捷键的兼容与保存问题
- windows: 未协商 InputStateShortcuts 时回退到旧的 Ctrl+Shift+E KeyEvent,
新 DLL 配旧 Server 时英文候选快捷键不再失效
- windows: 全角快捷键与标点快捷键一样可在待处理按键后排队,不再漏给应用
- windows: Server 不可用时排队的英文候选切换按 FUNCTION_CANCEL 离线回放,
不再丢弃其后的按键
- server: 非字符串配置值不再以 "!invalid" 作为 binding 发给设置页
- server: 仅三个输入状态快捷键路径强制回传配置快照;去掉 worker 中与
reader 重复的协商检查;抽出 InputStateShortcutViews 去除重复转换
- ui-html: 保存后 5 秒未收到快照则恢复编辑器并提示重试
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-16 03:31:19 +08:00
Jia Sui and fanlusky
d414268b5f
[Feat] U 模式重构为部件拆字反查 ( #973 )
...
* feat(engine,server,windows,ui-html,installer): U 模式重构为部件拆字反查 (#971 )
把 U 模式从 Unicode 十六进制码位输入改成部件拆字反查:Shift+U 后输入各
组成部分的拼音连写(晶 = ririri)即可出字,候选上反显注音。
- 引擎:新增 local_modes/radical_query(前缀匹配、字频降序),数据表
engine/radical/decomposition.txt 与生成脚本;LocalInputMode::Unicode
改为 Radical;删除 unicode_query。
- Server:g_radical_mode_triggered + IsRadicalCompositionActive + 候选分发,
用 cpp-pinyin 反显注音;删除 Unicode 码位路径。
- 前端 TSF:删除 U 模式的十六进制/数字特例与影子预判,按普通组合处理。
- 配置:utility.unicode_mode 改为 utility.radical_mode。
- 部署:assets 登记 radical_decomposition,安装器与 CI 拷表。
数据来源 mirtlecn/rime-radical-pinyin (GPL-3.0),授权见 engine/radical/NOTICE.md。
* feat(server): U 模式反显拼音改为带调风格(jīng)
* fix(server,installer): 修复 U 模式 CI(拆字表打包夹具与 clang-format)
* fix(engine,server): 修正 U 模式按键错位、重复候选与配置迁移
- Server 在 U 模式不再吞掉撇号、分号、斜杠、大写字母等键:TSF 已把它们记进按键缓冲,
吞掉又不重同步会让两侧串和光标错位。照常插入,含非 a-z 的码查不出候选
- 拆字查询全码命中排在仅前缀命中之前,同一个字的几种拆法只出一次
- 升级合并把旧键 utility.unicode_mode 的值带到 utility.radical_mode,读取时也兜底旧键
- 生成脚本只收汉字,重建拆字表去掉 abc 码下的 51 行数字、字母与符号
- 开着 U 模式时在后台预热拆字表与 cpp-pinyin 词典,避开首个按键的冷加载
- Server 按会话的 RuntimePaths 查拆字表,删掉走全局数据目录的便捷重载
- cpp-pinyin 初始化合并到 utils/hanzi_pinyin,设置页导入注音共用;U 模式与快捷短语的收键分支合并
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-16 01:01:18 +08:00
Jia Sui and fanlusky
2f7335be3e
统计增加首词命中率 ( #963 )
...
* feat(engine): webview 契约给统计概览增加首词命中率字段并支持 null 分支
* feat(server,ui-html): 统计新增首词命中率(决策点记录、stats v2 迁移与设置页展示)
* fix(server): 首词命中计数补日语标点排除与并发迁移复查
* fix(ui-html): 统计卡片改用自适应列宽,避免长数字被省略号截断
* fix(server,installer): 修复首词命中率随附测试在 CI 的失败
三条 server 用例是首词命中率改动新加、但从未跑绿:RawDb 在迁移用例里对尚不存在的库开只读写连接,补上 SQLITE_OPEN_CREATE;09-19 写了一次次选,按契约它是一次真实测量(0%),断言却要求 nullopt,改为断言 0.0,并把 nullopt 覆盖移到迁移用例(total==0 的那天)。安装器 preserve-user-data 从 stats_pipe.cpp 取库名,而 EnsureStatsStoreOpen 连同 stats.db 字面量已挪到 stats_candidate_capture.cpp,改到新位置。
* fix(server,ui-html): 首词命中率写库移出按键路径,修正迁移与统计口径
- 选词计数改由后台 SerialTaskRunner 写库,标点收尾与选词路径不再同步等 SQLite 锁
- 迁移以表结构为准,不再被版本号挡住;缺列时在 IMMEDIATE 事务里逐列补齐
- 标点在日期入口上收尾时按实际上屏的首条候选计数
- 五笔四码唯一自动上屏不计入;多段造词任一段非首位即不算命中
- 只有选词计数的日线不算打字日,不影响天数、日均与连续天数
- 卡片复用 formatFirstWordRatio 并展示累计命中率,概览复用 DailyRow::FirstWordRatio
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-15 22:09:50 +08:00
e56bfabdf2
feat(server,ui-html): AI 联想候选徽标支持切换 🤖 / 🐳 ( #948 )
...
* feat(server,ui-html): AI 联想候选徽标支持切换 🤖 / 🐳
AI 联想候选的来源角标此前硬编码为 🤖 ,用户无法更改。按固定排位徽标
(#463)的既有做法把它做成可配置项 appearance.candidate_ai_badge_style,
取值 "robot"(🤖 ,出厂默认)或 "whale"(🐳 )。
- 默认值保持 🤖 不变,升级不改变默认观感
- 与固定排位徽标一致,配置里存枚举名而不是字面 emoji,TOML/日志/diff
里不出现图形字符;新增样式只改白名单与展示层映射
- 非法取值一律回退到出厂 🤖 ,手改 TOML 写错不会让 AI 候选失去来源标识
- 展示层新增纯函数 AiSuggestionBadge(style),沿用既有 badge 字段通道,
D2D 与 WebView2 两个后端同时生效,不新增渲染路径
- 配置改动经既有 ConfigChanged → WM_APPLY_IME_CONFIG 链路即时生效,
无需重启输入法进程
- 出厂模板 config.default.toml 与开发配置 config.toml 同步补齐,
避免升级时用户选择被 MergeConfigIntoTemplate 静默丢弃
验证:
- server/tests/portable(Linux,g++,无 vcpkg):57 test(s), 0 failure(s)
- ui-html settings:vitest 167 passed,tsc --noEmit 通过,vite build 通过
- clang-format 18.1.8 --dry-run --Werror --style=file:改动文件全部通过
- scripts/ci/check-developer-paths.sh 通过;sync-contracts.py --check 通过
* fix(server): 补齐 IsValidCandidateAiBadgeStyle 的跨编译单元声明
ime_config_appearance.cpp 是独立编译单元,无法看到定义在 ime_config.cpp
里的 IsValidCandidateAiBadgeStyle,MSVC 报 C3861。补上 ime_config_internal.h
里的声明——IsValidCandidateFixedBadgeStyle 等同类校验函数都声明在那里。
* refactor(server,ui-html): AI 徽标样式改为单一映射表并精简测试
- AiSuggestionBadgeGlyph 作为样式到字形的唯一映射,配置层白名单
IsValidCandidateAiBadgeStyle 直接查它,新增样式不会两边漂移
- 测试去掉与首条断言重复的一行和恒真的 cloud 断言,改为检查映射表
对已知/未知样式的判定
- 设置页描述写明两种样式对应的 emoji
---------
Co-authored-by: Caiyi Liao <216114941+cxk1993@users.noreply.github.com >
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-15 02:44:27 +08:00
Jia Sui and fanlusky
456b23ed94
feat(engine,server): 五笔支持 T 模式与 V 模式 ( #942 )
...
* feat(engine,server): 五笔支持 T 模式与 V 模式
五笔方案此前被排除在 Shift+T 日期时间模式与 V 模式之外。根因是方案层就把
raw 归一成小写 a–y、丢弃数字与运算符,Server 的形状判定读不到大写 T/V 前缀。
- 引擎 WubiScheme 新增 raw_input_with_cases_:保留大小写与 T/V 模式的非字母键
(数字、运算符、: /),但按码字域丢掉越域字母(默认配置下 z)。查询码仍由
normalize_wubi_code 派生,普通码下两者长度相等——Server 用原样串长度数四码。
- Server:T 触发新增独立谓词 date_time_scheme(chinese_scheme || Wubi),不并入
chinese_scheme 本身;FormatVModeWorkerPayload 对五笔返回 UppercaseOnly。
- 自动上屏 / 顶字两个谓词新增 special_mode_active 前置:T 模式关键词归一后可能与
合法四码重合(Tdate → tdat),不挡会在第四个字母上结束模式。
- 引擎与 Server 测试、README 与两份配置模板文案同步。
* fix(engine,server,ui-html): 五笔 T/V 模式由宿主标注字面输入
原实现让五笔原样串不再裁到码长,普通码下原样串可以比码长(混输关、z 通配时 wqazb 对 wqaz),
Server 读回后光标、退格和上屏都会错位;守卫也只认 T 模式的全小写主体,TdatE 仍会顶出 tdat。
- 引擎:InputSession::set_wubi_literal_input 随 pending 序列一起下发,只作用于同一次设置。
普通码的原样串就是带大小写的码,与查询码逐位对应、一起截断;字面输入原样保留,
不查码表与拼音,也不算完整四码。退格从原样串重新派生码,字母键两份视图取同一个字母。
- Server:ApplyCompositionEditKey 按 IsWubiLiteralComposition(T 模式触发标记或 V 模式形状)
标注字面输入;两个五笔上屏策略恢复原签名,不再需要 special_mode_active。
- 设置页 T/V 模式说明补上五笔。
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-15 02:08:36 +08:00
Ten-Shine
4d697c9a55
fixup! feat(server,ui-html,windows): 添加任务栏语言栏按钮显隐配置
...
*修复缺失的`languageBarDisabledHint`文字
2026-10-14 15:49:32 +08:00
Ten-Shine
850ad772a1
feat(server,ui-html,windows): 添加任务栏语言栏按钮显隐配置
...
任务栏语言栏(输入法指示器旁)此前固定注册中/英模式、全/半角、中文标点三个按钮,
用户无法隐藏。新增 [language_bar] 配置节:enabled 是总开关,关闭时不再向
ITfLangBarItemMgr 注册任何按钮;show_ime_mode / show_double_single_byte /
show_punctuation 分别控制单个按钮。键缺失或共享配置不存在时默认全部显示,
旧配置与全新安装的行为不变。
- 出厂模板 config.default.toml 与工作配置 config.toml 新增 [language_bar] 节,
四个键默认 true;升级时 MergeConfigIntoTemplate 以出厂模板为骨架重建用户配置
- Server:LoadImeConfig 读取四个开关,ime_config_general 提供成对读写入口;
设置进程 BuildConfigMessage(configSnapshot)与 ApplyConfigUpdate(path 分发)
- 设置页「工具」分区新增语言栏卡片:总开关 + 三个子开关。总开关关闭时子开关
置灰禁用但保留勾选展示,交互与候选混输一致;快照回填与点击上报均有测试覆盖
- TSF DLL:SetupLanguageBar 在注册时机读取共享配置,不注册的按钮不会出现在
语言栏。按钮对象仍创建以保持析构对称;模式与标点切换走 compartment,
隐藏按钮不影响输入
- 改动需重启生效(按钮在 TSF 激活时注册),设置页已注明
2026-10-14 13:54:11 +08:00
Lu Fan(SonnyCalcr)
e1f9e26767
fix(server,ui-html): 收紧微软皮肤的候选尺寸、选中条与翻页箭头 ( #934 )
...
- 候选行上下内边距 0.235em → 0.12em(行高约 1.82em → 1.59em),左右内边距 0.76em/0.9em → 0.4em/0.3em
- 横排每项最小宽 4.35em → 3.5em,项间距与换行行距 0.28em → 0.15em
- 选中条 max(3px, 0.24em) × 1.1em → 3px × 0.9em
- 翻页三角 0.47em × 0.56em → 0.44em × 0.52em,圆角由高度的 1/4 加到 3/8,两三角间距减半
- 候选窗 CSS、设置页预览与 D2D 端同步修改
2026-10-14 02:20:39 +08:00
Lu Fan(SonnyCalcr)
e46294308d
fix: CS2 / Dota 2 / 三角洲行动等游戏里的输入法兼容(加载、候选、翻页、独占全屏、启动崩溃) ( #925 )
...
* fix(installer): TSF DLL 改装到系统目录,CS2 等 Trusted Mode 游戏里可以切出输入法
CS2 的 Trusted Mode 只放行位于系统目录且有代码签名的第三方 in-proc DLL,
装在 Program Files 下的 DLL 会被拒绝加载,游戏里切不出输入法。
x64 DLL 改装到 System32\IME\MetasequoiaIME\msime_v*,x86 装到 SysWOW64 下同名目录,
语言配置图标随之放到两处根目录;升级时清掉旧版留在 Program Files 的版本目录。
* fix(windows): CS2、Dota 2 不理会 UI-less 声明,照常显示候选窗
起源 2 引擎的 Valve 游戏以 UI-less 激活 TSF,但只替白名单里的输入法绘制候选。
我们据声明收起了自己的候选窗,游戏又不画,结果只剩左上角的系统默认 IME 小框,只能盲打。
对 cs2.exe、dota2.exe 忽略 UI-less,照常由 Server 绘制候选窗。
* fix(server): 前台为 D3D 独占全屏时不弹候选窗与光标状态提示
独占全屏下别的进程的窗口画不上去,弹出去反而可能把游戏踢出独占模式(闪黑、切分辨率、卡死)。
在 UI 线程真正显示前用 SHQueryUserNotificationState 判一次(300ms 缓存),独占全屏就收起候选窗,
并清掉已渲染可见标记,数字键与空格选词不再等待不会到来的绘制。
* fix(engine,server,windows): 游戏自绘候选时后台改动的候选列表实时同步给宿主
英雄联盟等 UI-less 宿主自己画候选。云候选、AI 候选、模型重排、英文混排在按键回复之后才改
候选列表,却从不通知 DLL,游戏还画着上一键读到的旧列表,数字键和空格却按新列表上屏,
于是「选的和上屏的不一样」。
- 契约新增 Worker opcode 35 UiLessCandidatesChanged,载荷与 UiLessComposition 同形,
由 uiless_page.h 统一格式化与解析,并附候选页代号;旧 DLL 读选中位时在第三个制表符处停下,兼容。
- Server 在上述后台改动之后把新页推给候选归属的客户端。
- DLL 收到后回到 TSF 线程核对焦点与组合纪元,更新候选 UI 元素并通知宿主重读。推送与按键回复
走不同管道,按代号只接受不旧于当前的页,避免旧页盖掉新页。
- 从共享内存重读到不同的页时高亮回到第一项,与 Server 每次重建都选中首项一致,
不再保留旧高亮造成「高亮这个、空格上屏那个」。
* feat(windows,server,ui-html,installer): 游戏兼容开关,CS2 / Dota 2 独占全屏打字不再黑屏
CS2、Dota 2 只替内置白名单(按输入法登记名称全等比对)里的输入法处理输入法消息。不在名单里时
组合落到 Windows 默认组合窗 CiceroUIWndFrame,左上角弹出编码小框;独占全屏下这个窗口一出现
游戏就被踢出全屏,表现为一打字就黑屏。清风输入法未开兼容时同样如此。
- 设置页帮助页新增「游戏兼容(CS2 / Dota 2)」:开启后把水杉在系统里登记的名称换成白名单里的
名字(默认「拼音输入法」),游戏会自己画候选。需要管理员权限:设置进程以
--apply-game-compat-name 提权重启自身,写 HKLM 记录值并改语言配置的 Description。
- TSF DLL 注册时以记录值为准,安装/升级重新注册不再把用户选的名称冲掉;卸载时删除记录值。
- 开启时不再对 cs2.exe / dota2.exe 忽略「宿主自己画候选」的声明,避免两个候选框。
- Server 的独占全屏判断覆盖进出独占模式时的 QUNS_BUSY 间隙,不在切换途中弹候选窗。
- TSF 诊断日志在组合开始/结束与 BeginUIElement 时记录宿主窗口状态(只有窗口与标志,没有文本)。
* fix(windows): 后台刷新回调持有加载器引用,宿主卸载 TSF DLL 后不再崩溃
当前输入法是水杉时,CS2 启动途中会加载再卸载 TSF DLL。诊断日志的线程池回调
FlushTsfDiagnosticLogs 正在 Sleep(250),只靠 DllAddRef 撑着:那只回答 DllCanUnloadNow,
挡不住宿主直接卸载。DLL 卸载后 SDL3 映射进同一段地址,回调醒来跑进 SDL3 的代码,
游戏崩溃(0xc0000005,崩溃转储里卸载模块的地址范围与崩溃地址吻合)。
- 诊断日志与统计上报的线程池回调改为用 GetModuleHandleEx 取加载器引用,
回调里 FreeLibraryWhenCallbackReturns,函数完全返回后才放手。
- 析构函数把 DllRelease 挪到最后,不在等待 IPC 线程退出之前就让 DLL 可卸载。
* fix(windows): 游戏自绘候选时不再把 Server 的 HTML 候选页当成候选交给游戏
CS2 开了游戏兼容后打一个码,游戏里的候选只有一项且是乱码。宿主要等 BeginUIElement 才说
自己画候选,而那时组合首键已经不带 UI-less 标记发给了 Server;Server 往共享内存写的是给
自己候选窗用的 HTML 页(辅助码、译文 span),DLL 的候选元素从共享内存回读后整串交给了游戏。
- 开了游戏兼容名称的 cs2.exe / dota2.exe 在 ActivateEx 就认定由游戏画候选,每个按键都带标记。
- 候选会话里收到过 Server 的 UI-less 页之后才从共享内存回读,之前一律不读。
* fix(windows): 游戏自绘候选时翻页能刷新,部分上屏后不再出现乱码候选
三角洲行动(虚幻引擎,以 TF_TMF_UIELEMENTENABLEDONLY 激活)里按 = / - / PageUp / PageDown
翻页,Server 已翻到第 N 页,游戏却还画着第一页;接着按空格上屏的是第 N 页的首项(多为单字),
剩下的拼音继续组合时候选框里出现乱码。
- 翻页、移高亮等键走异步的 WM_AsyncServerCandidateKey,以前把回复当作「只是确认」丢掉;
UI-less 下这份回复就是新的候选页,现在应用并通知宿主重读。
- UI-less 的 _SetText 拿不到 Server 的候选页时不再退回本地引擎的占位列表——那不是候选,
宿主会画成一条乱码。部分上屏后从共享内存回读 Server 写好的新页;_ClearList 同时清掉上次
的页记录,页文本相同也会重新载入。
2026-10-13 21:58:15 +08:00
Hao Qu
e39ea0b11c
feat(server): 添加候选译文词性显示开关 ( #915 )
2026-10-13 21:57:46 +08:00
Lu Fan(SonnyCalcr)
242f8b2bc8
fix(ui-html): 词库、删除确认框与凭据测试的异步问题跟进修复 ( #904 )
...
* fix(ui-html): 词库删除和保存在发起时锁定目标词库,跨标签结果注明词库
删除确认和编辑弹窗期间切换标签不再改变操作目标;切换标签时清空上次查询,
导入成功后的刷新不再重读搜索框或误报「请输入查询内容」;结果属于其他词库时
提示前缀词库名。两个导入入口合并为 bindImportInput。
* fix(ui-html): 删除确认框 Enter 只认焦点所在按钮,忽略自动重复与组词
Tab 限制在两个按钮之间;焦点不在按钮上时 Enter 不再默认删除;打开弹窗那次
Enter 的自动重复和输入法组词中的 Enter 不再被当成确认。
* fix(ui-html): 凭据测试覆盖 AI 翻译的过时判断,显式构造请求并加超时
候选词翻译走 AI 服务时请求不带凭据,改按 AI 辅助页当前配置判断结果是否过时;
发送的消息只含 requestId/service/config,不再直接发内部状态;Server 30 秒
无回复时恢复按钮并提示超时。
2026-10-12 22:46:06 +08:00
Rio Yu
7788913967
fix(ui-html): 测试中修改配置后不再显示旧的测试结果 ( #899 )
2026-10-12 21:29:50 +08:00
Rio Yu
f56c51c42d
fix(ui-html): 删除确认框焦点在取消时 Enter 不再删除 ( #898 )
2026-10-12 21:29:19 +08:00
Rio Yu
d52c7989a0
fix(ui-html): 导入词库期间切换标签不再改变导入目标 ( #897 )
2026-10-12 21:28:54 +08:00
時崎 ギャラクシー and fanlusky
add122fcc6
feat: 候选词翻译新增 AI 辅助提供方,收敛为单一 translation.provider ( #876 )
...
* feat(engine): 翻译凭据测试新增 translation.ai 服务类型
* feat(server): 候选词翻译新增 AI 辅助提供方,收敛为单一 translation.provider
* feat(ui-html): 候选词翻译新增 AI 辅助提供方并跟随单一 provider
* fix(server): 将 ai_translation 加入编译目标与测试套件
* fix(server): 在 AiTranslation 命名空间导出 ParseTranslations 供测试调用
* fix(server): 解析模型返回时剥除 Markdown 代码块标记
* fix(server): AI 候选词翻译校验占位 Token、收紧解析,翻译配置改读快照
- AI 翻译的 Token 改用 IsUsableSecret 校验,出厂模板的占位符不再被当成可用凭据
- 解析模型回复时,合法 JSON 但键不对、数组长度不符或残缺 JSON 一律作废,不再把原文当译文显示和写进释义库
- 从旧布尔推导出腾讯云时保留 tencent_tmt.enabled 门禁;在设置页明确选择时才打开,升级不会替用户向腾讯云发送候选词
- 候选词翻译读取的 provider 与各服务配置合成一份加锁快照,配置重载时整份替换,候选线程和翻译 worker 不再直接读会被改写的全局字符串;每个任务只解析当前服务的配置
- provider 与三个旧布尔一次原子写入;旧的 niutrans/custom enabled 开关改为切换 provider
- AI 联想与 AI 翻译共用 ChatCompletions 传输层,翻译超时与 AI 联想一致改为 8 秒
- 设置页凭据测试与运行时共用 AiTranslation::FromConfiguredTranslation,provider 白名单只保留 IsValidTranslationProvider 一处
* fix(ui-html): 候选词翻译的 AI 配置提示随 AI 辅助页实时更新
AI 辅助页改服务商、地址、Token 或模型后,翻译区的提示和摘要立刻刷新,不用重开设置窗口;可用性判断与服务端一致,占位 Token 不算已配置。
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-12 16:47:04 +08:00
fanlusky
1fd6bebbe2
fix(server): 设为默认改为把水杉排到中文第一位
...
原实现只写「替代默认输入法」(InputMethodOverride),水杉在中文(简体)的键盘列表里
仍排在末尾,系统设置里看不到它是默认,Win + Space 切到中文时也不是水杉。
- SetAsDefault 不在列表时先 InstallLayoutOrTip 加入,再 SetDefaultLayoutOrTip
挪到第一位并复核;不改语言列表顺序,也就不动界面语言
- 不再写替代默认输入法,旧版写下且仍指向水杉的在设置成功后清掉
- QueryStatus 改为判断水杉是否在所在语言排第一
- 加入失败时区分「输入法未注册」与「未添加中文(简体)语言」
- 「系统设置」按钮改开「语言和区域」
- 卸载时清理仍指向水杉的替代默认输入法
2026-10-12 03:56:28 +08:00
fanlusky
797c0f5652
feat(server,ui,ui-html): 候选窗可严格按文字宽度收紧
...
皮肤新增 [candidate_window] fit_content,设置页「外观」新增「候选窗口按文字收紧宽度」
(appearance.candidate_window_fit_content),两者取或。打开后:
- D2D 不再垫 160 DIP 卡片最小宽度和列表 80 DIP 下限,行尾不再多留 6 DIP,
右侧留白与序号左侧留白相同;
- WebView2 去掉 .container 的 7em 下限;
- 同一输入里宽度不再只增不减,高度仍保持。
皮肤的 min_width_dip 与装饰图宽度照常生效;内置皮肤清单出厂为 false。
2026-10-12 02:03:59 +08:00
fanlusky
c821e5addc
fix(installer,server): 新用户默认关闭候选词翻译
2026-10-12 01:04:52 +08:00
Lu Fan(SonnyCalcr)
0d7ae4ca79
feat(server): 翻译里的词性与分隔符单独配色 ( #848 )
...
候选翻译(如 "adj. spreading; n. sound of laughter")由 Server 切成单词、词性、
分隔符三段:WebView2 端包成 .cand-pos / .cand-sep,D2D 端经
CandidateList::Item::translationRuns 用分段画刷绘制,两端同一切法。
新增皮肤键 translation_pos / translation_separator 及选中行的
selected_translation_pos / selected_translation_separator,留空时与翻译同色。
内置皮肤的翻译改用 Notion 调色板:词性取相邻的另一个色相并降到 50% 不透明度,
分隔符为单词色 45%;铺实色高亮的选中行另配一组。仓库内的外部皮肤同步补上词性与
分隔符配色。
2026-10-11 23:28:30 +08:00
Lu Fan(SonnyCalcr)
2c19958396
fix(ui-html): AI 设置的模型改为可输入下拉框,思考强度仅 DeepSeek 显示 ( #841 )
...
模型框改用和字体选择框相同的组合框外观,右侧加下拉箭头,仍可直接
输入模型名。列表为空时点箭头等同点「查询模型」,结果返回后自动展开;
点进输入框不会发请求。
思考强度只有 DeepSeek 会发给服务商(reasoning_effort 取 low/high/max),
其他服务商下隐藏该项,已保存的档位保持不动。
2026-10-11 18:52:20 +08:00
Lu Fan(SonnyCalcr)
649747f8cd
feat(server): 神经网络整句效果优先模型改为按需下载 ( #838 )
...
效果优先模型(sentence-model-desktop.safetensors,约 25 MB)不再随安装包分发,
改为和八股文模型一样在设置页下载后才能使用。
- engine:SentenceAssociationOptions 新增 neural_desktop_model 路径,留空即模型缺席、
静默不重排;词典不再从资源目录固定加载效果档。load_file 按 UTF-8 打开路径,
数据目录在非 ASCII 用户目录下也能读到模型
- server:新增 settings/neural_model,下载到 <数据目录>\models\neural-desktop\,
下载与导入都按 neural-model/lock.json 的字节数和 SHA256 校验后原子落位;
会话层只在开关打开时解析模型路径
- ui-html:设置页增加下载 / 导入 / 删除 / 浏览器下载,模型未就绪时开关置灰
- installer:不再打包效果档模型;旧版装进数据目录根下的那份在覆盖安装与卸载时清掉
原有配置项 sentence_neural_desktop 保持不变,用户的开关状态升级后保留。
2026-10-11 18:08:33 +08:00
Lu Fan(SonnyCalcr)
ce12355612
fix(ui-html): AI 设置的模型列表恢复点外部关闭与键盘选择,左右控件等高 ( #837 )
...
#829 把模型下拉从 setupDropdownMenu 换成了手写的 focus/blur 处理,
丢掉了点外部关闭和上下键选择,选中一次还会写两次配置。改回
setupDropdownMenu,只去掉那个空列表时无用的下拉箭头,模型框外观与
普通输入框一致。
服务提供商、思考强度的下拉按钮比输入框矮 10px 左右,网格内统一为
40px,左右两列对齐。模型列表按单行算高度,长模型名改为省略号截断。
2026-10-11 17:54:40 +08:00
fanlusky
5160721f39
ui-html: AI 辅助设置 UI 改进
...
- 将「获取模型」按钮改名为「查询模型」,更清晰地表达功能
- 移除模型输入框的下拉箭头:输入框支持自由输入,不仅限于选择
- 简化模型菜单交互:菜单改为浮动层,在输入框获焦时显示
- 添加 placeholder 提示用户可以手动输入或使用查询功能
- 改进模型菜单项的点击处理,确保选中后自动更新输入框
Fixes: 模型输入框 UI 交互不清晰的问题
2026-10-11 16:04:52 +08:00
Lu Fan(SonnyCalcr)
f273dccd18
feat(server): AI 联想与语音润色支持设置 DeepSeek 思考强度 ( #821 ) ( #824 )
...
新增 [ai_assistant] thinking 与 [voice_input] polish_thinking,可选 disabled / low / high / max,
默认 disabled 保持原行为。非 disabled 时向 DeepSeek 发送 thinking: enabled 与 reasoning_effort,
其他提供商不受影响。开启思考时 AI 联想超时放宽到 30 秒、max_tokens 提到 8192,润色超时放宽到 30 秒;
AI 联想缓存键纳入思考强度。设置页 AI 辅助与文本润色 API 各加「思考强度」下拉框。
Closes #821
2026-10-11 15:23:46 +08:00
Lu Fan(SonnyCalcr)
42c2666a4d
feat(server): 悬浮工具栏改用候选窗的柔和阴影,开着阴影也能贴边,并可在设置中关闭阴影 ( #809 )
...
* feat(server): 悬浮工具栏改用候选窗的柔和阴影,并可在设置中关闭阴影
- D2D 工具栏改用与候选窗相同的两层阴影(light α .18/.10,dark α .34/.22),
透明边距与候选窗一致(16/14/32/34 DIP)
- 新增配置 general.floating_toolbar_shadow(默认开启),设置页「悬浮工具栏」
加「工具栏阴影」开关;关闭后去掉阴影边距,工具栏可贴住屏幕边缘
- 关闭阴影时保留 1 DIP 边距,避免居中描边的外半边被窗口边缘裁掉
- WebView2 工具栏:开关同样生效;默认页阴影改为候选窗的近接层(宿主只留 8px)
* feat(server): 悬浮工具栏开着阴影也能贴住屏幕边缘
- 阴影边距允许伸出屏幕:拖动结束、改尺寸和默认位置都只要求工具栏本体
(含描边)留在工作区内;伸出工作区的部分用窗口区域裁掉,不绘制、
不挡任务栏点击,拖动时实时更新
- 伸出量按宿主实际像素尺寸和卡片位置计算,消除向上取整留下的 1-3 px
缝隙;关掉阴影时同样贴边
- 切换阴影时保持工具栏本体位置不动,并按工作区重新判定边界,
避免工具栏一部分跑到任务栏下面
- 设置页「工具栏阴影」说明改为「在工具栏周围显示与候选窗一致的柔和阴影」
2026-10-11 13:07:27 +08:00
Lu Fan(SonnyCalcr)
b4479974b8
fix(server): 改用 SetInputMethodOverride 设置默认输入法 ( #807 )
...
input.dll 的 SetDefaultLayoutOrTip 在 Windows 11 上返回成功,但只改了语言内排序、
Preload 和 CTF 的语言默认项,不写 InputMethodOverride,默认输入法实际不变,复核
因此报「系统没有应用这项设置」。改为调用 bcp47langs.dll 的 SetInputMethodOverride,
与系统设置「替代默认输入法」及 Set-WinDefaultInputMethodOverride 写同一项;仅在缺少
该导出的旧系统上回退到 SetDefaultLayoutOrTip。
同时给两个按钮单独的样式:原先复用的 restart-server-button 在浅色主题下悬停前后
背景几乎相同,看不出是按钮。「设为默认」改为强调色主按钮,两者都有悬停、按下和
键盘焦点反馈。
2026-10-11 02:53:36 +08:00
Lu Fan(SonnyCalcr)
85edddc988
feat(server): 设置页支持把水杉设为默认输入法 ( #802 )
...
帮助页新增「默认输入法」卡片:显示当前是否为默认,提供「设为默认」和
「系统设置」两个按钮。设置走 input.dll 的 InstallLayoutOrTip /
SetDefaultLayoutOrTip,完成后按 HKCU International\User Profile 复核;
EnumEnabledLayoutOrTip 在 Windows 10/11 上对 TSF 输入法返回空列表,
因此状态直接读注册表。只在用户点击时执行,不在启动或升级时改写。
新增 defaultImeRequest / defaultImeResponse WebView 契约并同步 ui-html。
同时在帮助页加入 Wiki 与 FAQ 链接,在关于页加入官网 msime.app。
2026-10-11 02:22:01 +08:00
fanlusky
4973434c8f
docs(ui-html): 快捷键页补全未列出的快捷键
...
补上 Ctrl+Shift+E 英文候选模式、Ctrl+Shift+Space 全半角、Ctrl+. 标点、
Ctrl+Enter 上屏译文、Shift+Enter 提交拼音、以词定字、Ctrl+Backspace /
Ctrl+方向键按音节编辑、Delete、手动分词和 Ctrl+Shift+Win+K 屏幕键盘。
2026-10-10 23:03:09 +08:00
Lu Fan(SonnyCalcr)
0d07b93268
fix(ui-html): 直接辅助码说明改为三码字优先、四码词优先,去掉万象式字样 ( #753 )
...
* fix(ui-html): 直接辅助码说明改为三码字优先、四码词优先,去掉万象式字样
* fix(ui-html): 直接辅助码说明改为常驻描述文字
2026-10-09 23:40:30 +08:00
Lu Fan(SonnyCalcr)
32d7656471
fix(ui-html): 非豆包服务商时隐藏豆包鉴权方式 ( #746 )
2026-10-09 19:26:52 +08:00
AkaneIwasa and fanlusky
568d07f513
feat(windows): 添加中日英三语轮换 ( #717 )
...
* feat(windows): 添加中日英三语轮换
* fix(windows): 三语轮换改为快捷键开关并修复两端状态不同步
- 开关移到「快捷键 → 中英文切换」下的「允许中日英循环切换」,配置键改为
[keybindings] trilingual_cycle;输入模式恢复为中文/日文,二者互不影响
- 循环请求带显式标记位和请求方自身的中英/日文状态,Server 据此计算目标语言;
普通 VK_SHIFT 仍是中英切换,不再被误当成循环
- Server 开关在请求途中被关闭时仍回复,按中英切换处理,TSF 只丢弃后续排队按键,
不再超时重连
- 已发出的循环回复未被应用(含 Superseded)时走完整重连,避免日文状态两端不一致
- 循环切换补上光标处状态提示和标点同步
- 切换语言时复用暂存的另一语言会话,不在按键路径上重建引擎和打开 msime.db
- 配置读取的语言与开关改为原子量;TrilingualCycleChanged 的能力过滤移到发送方
- 中日切换不再重发 TrilingualCycleChanged;结束组合被拒绝时不计入统计
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-09 15:44:41 +08:00
時崎 ギャラクシー
aa5c632ea9
Merge pull request #711 from Tokisaki-Galaxy/feat/llm-model-fetch
...
feat: AI 辅助新增获取模型、测试连接与 Custom 提供商
2026-10-08 23:13:01 +08:00
normaltank
c2bd59d448
fix(server): 翻页扩展时保留混输候选并同步 Emoji 末尾排序
2026-10-08 22:10:13 +08:00
Evan Hu
702f90105b
feat(ui-html): offer the dl.msime.app mirror in the update dialog
...
When update.json names the installer, the dialog adds a 国内镜像下载 button that opens https://dl.msime.app/gh/ plus that installer's GitHub download URL, derived from releaseUrl and the validated installerName, so the SHA256 shown beside it applies unchanged. update.json keeps its shape; older clients are unaffected.
2026-10-08 22:37:57 +09:00
MSIME(MetaSequoia IME)
ddf22c890a
Merge pull request #696 from Tokisaki-Galaxy/fix/stats-heatmap-label
...
fix(ui-html): 优化日历热力图默认右对齐与月份标签防重叠
2026-10-08 20:08:30 +08:00
fanlusky
e0e3f5e0b1
fix(ui-html): 热力图首列月份标签与窄窗口贴右
...
首列含某月 1 日时按该月标注;不含时离第一个边界不足 3 列就留空,
不再用残月挤掉真正的月份标签。列数和格子到下限后继续缩窗也贴齐今天,
滚回最右侧时恢复自动贴右。
2026-10-08 19:33:57 +08:00
tokisaki galaxy
f0a15e3285
fix(ui-html): 优化日历热力图默认右对齐与月份标签防重叠
2026-10-08 18:00:11 +08:00
fanlusky
799d6361e5
feat(server): 候选翻译目标语种新增泰语、越南语和意大利语
2026-10-08 17:20:58 +08:00
Lu Fan(SonnyCalcr)
92b456512b
Merge pull request #648 from ouchihao/codex/fix-641-doubao-resource-id
...
fix(ui-html): expose Doubao ASR resource ID
2026-10-08 14:32:49 +08:00
fanlusky
827662980f
fix(ui-html): fall back to the default Doubao Resource ID when it is empty
...
Clearing the field used to save asr_resource_id = "", which makes
DoubaoAsrClient::Start fail silently. Empty input now restores and saves
the default, the credential test sends the default, and a reload without
the key resets the field instead of keeping a stale value. The default is
defined once in voice.ts, and the hint lists the 1.0 bigasr resource IDs.
2026-10-08 14:25:21 +08:00
fanlusky
06fb8f87ba
fix(server): 关闭顶字且混输关闭时第五码仍走顶字,避免丢字与两端分叉
...
混输关闭时码表答得出的完整四码保留四码上限,关掉顶字后第五个字母会被 Server
裁掉,而 raw 预编辑样式的 TSF 已经显示了它,两边缓冲就此分叉。顶字开关改为只在
混输开启时生效(字母并入混输串),混输关闭时仍按顶字上屏首选。
同时修正第四键注释(两个开关作用在不同按键上)、设置页与配置模板的说明文字,
以及 settings_app.cpp 新增行的缩进。
2026-10-08 14:10:36 +08:00
Jia Sui
3d31a40a74
feat(server): 五笔四码自动上屏与顶字各加一个设置开关
...
「四码唯一时自动上屏」和「第五码将首选上屏」此前都是无条件行为,用户遇到
误上屏没有任何出口。四家主流五笔(搜狗/QQ/百度/微软)都提供这两个开关且
默认开启,这里补上并保持默认开,升级用户零行为变化。
- input.wubi_four_code_auto_commit(默认 true)门控四码唯一自动上屏
- input.wubi_fifth_code_top_commit(默认 true)门控真顶字
- 开关只落在 Server 判定层,引擎完全不知道:WubiInputOptions 不加字段,
避免测试里大量聚合初始化静默取默认值
- 顶字关闭后第五个字母落回引擎既有四码上限(混输关=裁掉,混输开=并入混输
串),与搜狗 PC 一致,不补新分支
- 顺带修正 input_key_policy.h 与 event_listener_keys.cpp 中把不存在的开关
当既成事实引用的注释,以及两个把「无条件」写进名字的用例
2026-10-08 13:24:25 +08:00
Ouchihao
f98b568034
fix(ui-html): expose Doubao ASR resource ID
2026-10-07 14:41:43 +08:00
Lu Fan(SonnyCalcr)
5d6eaa5bd1
feat(server): 全拼纠错候选的 * 标记可在设置中关闭 ( #631 )
...
新增 quanpin.autocorrect_marker 开关,默认开启(显示 *),关闭后纠错得到的候选
不再在末尾附加 * 标记。只影响候选窗显示,不影响上屏文字和词频。
同步出厂模板、工作配置、两个设置宿主的读写映射和设置页「输入」分区的开关,
并在配置持久化测试里覆盖默认值、落盘重读和缺键回退。
2026-10-05 22:04:06 +08:00
Lu Fan(SonnyCalcr)
53ee180ec3
feat(engine): 直接辅助码句中四码可用第二位辅码大写结束 ( #630 )
...
直接辅助码的四码在句中原来只能补 / 结束(uiab/),现在也可以把第二位辅码敲成大写(uiaB)。
设置页「直接辅助码句中四码标记」两个勾选框可多选、至少留一个,默认只勾 /。
- 引擎:拼写图新增 Aux2Upper(非缩写)。开着大写标记时大写字母只能当第二位辅码,
走不通再退回不分大小写的旧规则,第一位辅码敲大写(uiAuiQ)照常可用。/ 的收键受勾选控制。
- 协议:DirectHelpcodeChanged 载荷改为 "0"/"1"/"2"(2 = 开着但 / 不是编码键),
TSF 据此决定吃不吃 /。
- 配置:新增 helpcode.shuangpin_direct_helpcode_slash / _uppercase,同步写入出厂模板、
工作配置和两个设置宿主的读写映射。
2026-10-05 20:43:02 +08:00
Lu Fan(SonnyCalcr)
3c79876205
Merge pull request #629 from fanlusky/feat/v-mode
...
feat: 新增 V 模式,数字转中文与算式计算
2026-10-05 17:51:21 +08:00
Lu Fan(SonnyCalcr)
ae353d142c
feat(server): 语言栏右键菜单新增输入方案二级菜单 ( #625 )
...
在托盘语言栏菜单第二项加入「输入方案」,悬停展开全拼/双拼/五笔二级菜单,
当前方案打勾,点击即切换(与设置页走同一条 SetConfiguredInputScheme 路径)。
- D2D:TrayMenuPresenter 用 Popup 实现子菜单,展开时宿主窗口向有空间的一侧加宽,收起时还原
- WebView2:页面通过 inputSchemeSubmenu 请求宿主加宽窗口,再由 PlaceInputSchemeSubmenu 摆放;
changeInputScheme 切换方案
- 契约:messages.json 新增 changeInputScheme / inputSchemeSubmenu,并重新生成 ui-html/webview2/shared
2026-10-05 02:44:59 +08:00
Lu Fan(SonnyCalcr)
1b74617eed
feat(server): make direct and mid-sentence helpcode mutually exclusive ( #621 )
...
Turning either one on now turns the other off, in the config setters both
settings hosts go through, so the snapshot pushed back to the settings page
shows the change; the page also flips the other toggle immediately. Turning
one off leaves the other alone. Configs saved before this with both on load
with mid-sentence helpcode treated as off in memory, matching the behaviour
direct helpcode already had, without rewriting the user's file.
2026-10-04 22:04:32 +08:00