tokisaki galaxy
7b42d9b057
fix(installer): widen the dev certificate to 90 days and surface its expiry
2026-10-20 22:59:50 +08:00
tokisaki galaxy
c790740dd3
fix(installer): reuse the dev certificate only within the run that created it
2026-10-20 22:26:09 +08:00
tokisaki galaxy
d1e4282eb6
ci: add the dev-build workflow for toolchain-free contributor builds
...
A contributor who only wants to try a change should not have to install
vcpkg, Boost, Inno Setup and the Windows SDK. The Dev build workflow builds,
packages and signs on the runner, and the artifact is a full installer plus
its signing certificate.
Three ways in: a feature-branch push builds automatically; a pull_request
run gives reviewers and fork contributors an installer from the check page
(pull_request deliberately, not pull_request_target -- building PR code
executes scripts from that code, and pull_request_target would hand those
scripts a writable token); workflow_dispatch stays for picking a single
component or rebuilding without a push. develop, main and release-please
maintenance branches never trigger it.
The certificate is minted per run by installer/sign-dev-build.ps1 with the
fixed subject CN=Metasequoia IME Dev Build Code Signing; the private key
lives only in the runner's memory. installer/import-dev-trust.ps1 ships in
the artifact for the user side: remove the previous certificate by subject,
import the new one, so repeated builds do not grow the trust stores.
The workflow reuses ci.yml's vcpkg cache scopes and sccache, downloads the
locked dictionaries, embeds the uiAccess manifest and passes the dev version
through MSIME_PRODUCT_VERSION_OVERRIDE so the about page shows the full dev
string. Artifacts expire in 7 days. ci.yml remains the merge gate; nothing
here creates a release or touches the update manifest.
2026-10-19 16:01:26 +08:00
tokisaki galaxy
d376b93e03
installer: let the packaging carry a prerelease version string
...
Two independent obstacles surfaced the first time a version with a hyphen
reached the installer:
- Inno Setup's VersionInfoVersion only accepts digits and dots, so ISCC
aborted on 0.7.1-dev.20261019.<hash>. AppVersion, the output filename and
the versioned DLL directory are free text and keep the full string; only
VersionInfoVersion moves to a separate MyVersionInfo define that
Prepare-PackageFiles.ps1 fills with the part before the hyphen, failing
loudly if what remains is not numeric. Releases pass a bare semver, strip
nothing, and behave exactly as before.
- TsfRoot64 called ApplyPathRedirRulesForCurrentProcess, an Inno Setup 7
support function the windows-2025 runner's 6.7.1 does not have. #925 added
it five hours after the last hosted-compiler run, and every release since
then compiled on the self-hosted Inno 7, so the latent break never fired;
the dev-build's hosted package job is the first to execute that path. The
call was a no-op anyway: with
ArchitecturesInstallIn64BitMode=x64compatible the setup process is 64-bit
on every supported OS, so {sys} already expands to the real System32 and
no WOW64 redirection applies. Expand the constant directly, with the #434
warning in this README updated to name the function explicitly.
2026-10-19 16:01:05 +08:00
小莫
dd018f7985
fix(server): 修复关于页显示旧版本 ( #1084 )
...
* fix(server): 从产品版本文件显示关于页版本
* fix(server): 使用发布版本更新关于页
2026-10-19 13:27:46 +08:00
Lu Fan(SonnyCalcr)
c0a9d371f0
feat(server,windows,engine): 横排候选时左右方向键移动高亮 ( #1080 )
...
- 快捷键页「翻页方式」新增「左 / 右(横排时移动候选项)」,与「上 / 下」各自独立,默认关闭,
只在候选窗为横排时生效。配置项 general.candidate_horizontal_arrow_navigation 已写入出厂模板。
- 光标在拼音串尾时右键移动高亮(到页末翻页),左键往回移高亮,高亮回到第一个候选后再按才移动光标;
光标在串中间时右键先把光标移回串尾,再按才移动高亮。Ctrl+左/右与 UILess 宿主不变。
- 新增 worker 消息 HorizontalArrowSelectionChanged(39)和按键标记 FanyImePipeFlags::HorizontalArrowSelection:
开关生效时 TSF 把候选态下的左右键交给 Server 决定,移光标时 Server 用 CompositionRestored 回光标,
移高亮时回 MoveSelection*,TSF 不再自己预测光标。旧 DLL 忽略新消息,保持原行为。
Closes #779
Closes #895
2026-10-19 02:11:25 +08:00
Lu Fan(SonnyCalcr)
75d8c710a9
feat(server,windows,engine): 新增顿号自定义,翻页方式移到快捷键页 ( #1071 )
...
- 设置「输入」页在智能标点上方新增「顿号自定义」:\ 和 / 各一个勾,至少保留一个,
未勾选的键按原样输出。新装默认两个都开;升级用户的配置里没有 / 这一项,
模板合并时补成关,保持原来只有 \ 出顿号。
- 新增 worker 消息 EnumerationCommaKeysChanged(38),载荷见
engine/contracts/enumeration_comma.h;旧 DLL 忽略它,保持只用 \。
- 选候选时按 / 改为按配置上屏「候选 + 、」;未作顿号的 \ 或 / 跟在候选后原样上屏。
小键盘 / 与小键盘 . 一样始终输出原字符。
- 「翻页方式」从「输入」页移到「快捷键」页。
- AtLeastOneChecks 从辅助码页移到公共绑定,两页共用。
2026-10-18 23:49:41 +08:00
Lu Fan(SonnyCalcr)
5de73de7a6
feat(engine,server,windows): 双拼末尾辅助码支持间接触发,句中辅助码单独成区 ( #1068 )
...
双拼辅助码新增「直接辅助码」开关(默认开,行为不变)。关掉后末尾辅助码改由引导键触发:
反引号、分号、大写字母可多选,触发键后接一到两个辅码(如 ulpb;xy、ulpbXy),一码重排、
两码筛选,只在输入末尾生效。触发键在 TSF 缓冲与 Server raw 里统一记成 |,与句中辅助码的
反引号段区分。
两组触发键互斥:一边勾上某个键会取消另一边的同一个键;手改配置两边都勾时归句中辅助码。
新增 Worker 消息 EndHelpcodeTriggersChanged(37),旧 DLL 忽略。
设置页把句中辅助码单独成区(仅双拼),其中间接(引导键)与直接(万象式)两种方式互斥。
新配置项同时写进出厂模板与开发配置。
2026-10-18 22:54:17 +08:00
Lu Fan(SonnyCalcr)
e701cebbe4
feat(server,ui,installer): 内置皮肤改由皮肤清单定义,新增微信绿(卷轴)内置皮肤 ( #1061 )
...
* feat(ui): CandidateList 支持等宽网格列与关闭选中态
- Appearance::gridColumns:横排时按可用宽度均分成等宽列(列数不超过 gridColumns,每列不窄于
minItemWidth),放不下一列的项占多列。
- Appearance::selectable:为 false 时不画任何选中态,首项也能正常显示悬停与按下效果。
* feat(server,installer): 内置皮肤改由皮肤清单定义,新增微信绿(卷轴)内置皮肤
内置皮肤数据化:
- skins/default/<id>/skin.toml 从只放开关改为完整的出厂清单(配色、圆角、版式、工具栏、名称与说明),
并新增 canvas 基底的清单。候选窗、悬浮工具栏、光标状态徽标不再在代码里写死任何内置皮肤的参数。
- 出厂清单在构建时编进程序;数据目录里的清单写了的键覆盖出厂值,缺失或写错时退回出厂外观。
安装包改为每次整份覆盖 skins\default。
- 皮肤清单新增版式键(padding、item_gap、number_inset 等,长度可写 DIP 或 "0.3em"),以及
[candidate_window.horizontal] / [candidate_window.vertical] 分排列覆盖、page_arrow_divider、
toolbar.icon_corner_radius_dip。
- test_candidate_skin_tokens 保留改动前的内置分支作参照,逐个皮肤、主题、排列与字号比对清单解析结果。
共用候选窗场景:
- 候选框的场景搭建与套皮肤抽成 CandidateSkinScene,候选窗与设置页的皮肤预览共用;设置页预览改用
真实的候选窗控件绘制,删除原先移植自网页样式的预览绘制与各皮肤硬编码。
卷轴展开(expand_panel)与微信绿(卷轴):
- 皮肤开关 expand_panel / expand_rows:横排候选行右端的展开按钮,展开后首行与后续候选网格一起滚动,
右侧细滚动条;展开与收起只认按钮,展开时滚轮上下滚动、不翻页。
- 网格点选按绝对下标上屏并在工作线程核对显示文字;滚到底部时自动再展开一批候选。
- 新增内置皮肤 wechat_scroll「微信绿(卷轴)」。
2026-10-18 20:42:06 +08:00
Lu Fan(SonnyCalcr)
6784eb8ff8
feat(server): 外观新增横向候选强制单行开关 ( #1056 )
...
新增 appearance.candidate_window_single_line(默认关闭)。横向排列时开启后,候选窗宽度上限由半屏放开到
当前屏幕宽度,超出屏幕才换行;竖向排列不受影响。出厂模板、开发配置与设置页读写映射同步加入,候选窗
显示中切换时立即按新宽度重排。
Refs #805
2026-10-18 13:24:07 +08:00
Lu Fan(SonnyCalcr)
23bfdd4d51
feat(engine,server): 符号混输放开拼音读音,emoji 混输改为整串精确匹配 ( #1050 )
...
- 符号混输不再挡读得成拼音的编码:混输本来就只认整串精确匹配,xi → ξ 也照样混入;单字母编码仍不混。
- 构建器读取 msime-dictionary 新增的 custom/symbols.txt(拼音<TAB>符号),把 dian → · 、、
shuminghao → 《》 〈〉 等标点读音写进 symbol_code,书名号、引号、括号成对给出。
- emoji 混输改用新的 query_mixed_emoji,只认整串精确等于关键词,不再按前缀带出 emoji;双拼下只查
展开后的全拼,并和符号一样只在光标位于末尾时查询。Shift+E 的 emoji 模式仍按前缀查。
- 同步更新设置页说明、出厂与开发配置注释和 README。
2026-10-18 11:23:26 +08:00
Lu Fan(SonnyCalcr)
2c7795ef4e
feat(server): 候选词翻译新增只显示单条释义开关 ( #1048 )
...
* feat(server): 候选词翻译新增只显示单条释义开关
新增 general.candidate_translation_single_sense(默认关闭)。开启后候选窗译文只显示第一条释义,
仅影响显示,Ctrl+Enter 仍按原始译文列出全部释义。出厂模板、开发配置与设置页读写映射同步加入,
切换后立即刷新当前候选页。
* fix(server): 单条释义同时按逗号截取词库同义词
english.db 的中译英释义在同一词性内用 ", " 分隔同义词("v. teach, instruct"),只按分号截断时
仍会显示多个词。译文缓存记录来源,单条释义模式下仅对词库译文在括号外的首个逗号处截断;
在线翻译是整句,逗号属于标点,保持原样。
2026-10-18 08:15:12 +08:00
Lu Fan(SonnyCalcr)
3cd429b19d
feat(server): 加入 S 模式符号输入与符号混输 ( #1047 )
...
符号数据改用 rime-wanxiang 的符号表与 typst/codex 符号名,源数据放在
msime-dictionary 的 sources/symbols/,替换原来的 piliapp 符号表。
- 建库:新增 symbols_db.py,生成表情面板用的 symbol_catalog(中文分类)和
S 模式、符号混输用的 symbol_code;剔除 wanxiang-unrenderable.txt 列出的
Windows 自带字体显示不了的符号,以及与 ① ❶ 看不出区别的 Dingbats 带圈数字
- 新增 scripts/check-symbol-rendering.py,用 Windows 字体生成上面的剔除清单
- Shift+S 进入符号模式,按万象分组码(xl、sx、szq)、数字读音(yi → 一 ① ⑴)
或符号名(alpha、infinity)检索
- 符号混输:整串精确等于编码时混入,首个紧跟首选;读得成拼音的编码只混数字
序号写法;双拼先按方案换算成全拼再查(小鹤 sj → san → ③)
- 表情面板符号页:中文分类,搜索把整词命中的符号列在「最佳匹配」
- 配置:utility.symbol_mode(默认开)、general.symbol_mixed_input(默认关)
Refs #795
2026-10-18 02:08:39 +08:00
Lu Fan(SonnyCalcr)
e9825a521f
feat(server): 优化设置窗口滚动手感并加入启动画面 ( #1045 )
...
* feat(ui): 滚轮平滑滚动贴近浏览器手感
- 每次滚轮的平滑滚动改为 cubic ease-out,接续当前速度,不再有指数逼近的长尾
- 滚动距离跟随系统「一次滚动的行数」,「一次滚动一屏」时按整页滚动
- 合成交换链的帧时间对齐到 DWM 的刷新网格,消除绘制开始时刻抖动带来的位移抖动
* fix(server): 设置页滚动到 Niya Demo 皮肤时不再卡顿
Niya Demo 的 background.png 实际是 1280x720 的 WebP,预览第一次滚入视野时在界面线程同步解码,首次加载 WebP 解码器要 100-200ms。皮肤预览的静态图改为打开页面时就在后台线程解码,界面线程只创建位图。
设置页与词库表格的滚轮步长同时调到 100(与 Chrome 一致),平滑时长 260ms。
* feat(server): 设置窗口加入启动画面与开关
打开设置时先在窗口中央显示齿轮图标(Win11 用 Segoe Fluent Icons U+E713,Win10 回退 Segoe MDL2 Assets),等首个 configSnapshot 填好控件后再淡入主界面,避免输入方案先显示全拼再跳到双拼。齿轮至少停留 200ms,淡出 140ms。
「关于」页新增「启动动画」开关(appearance.settings_launch_animation,默认开启),关闭后只短暂显示纯色背景。新键已写入出厂模板和开发配置,并补了默认值与读写往返测试。
2026-10-18 00:27:50 +08:00
Ten-Shine and fanlusky
4eed9c8442
fix(installer): 升级不再删除 custom_translations.txt ( #1035 )
...
* fix(installer): 升级不再删除 custom_translations.txt
custom_translations.txt 是用户手工放在数据目录根下的中英翻译覆盖表,
安装包不携带、引擎只读不写。覆盖安装时 CleanAppDataExceptUserFiles 会
清掉根下所有不在 IsPreservedAppDataItem 名单里的条目,换数据目录时
MigrateUserDataDir 的 robocopy 清单也不含它,于是升级会把它删掉,或留在
旧目录随 RemoveDataDir 一起消失。它没有 config.toml 那样的出厂副本可
回退,删掉即内容彻底丢失。
新增 IsUserTranslationFile 并接入 IsPreservedAppDataItem,覆盖安装时与
其他用户数据同等保留;MigrateUserDataDir 的 robocopy 文件清单补上它,
换数据目录时一并搬走。preserve-user-data.ps1 的 $required 同步更新。
同步 installer/README.md 的迁移清单与 PRIVACY.md 的升级保留说明,并订正
新增函数注释里引用的 README 章节名。
* fix(installer): 迁移 custom_translations.txt 时不覆盖、不静默丢失
换数据目录时 robocopy /MOVE 会用旧目录那份直接盖掉目标目录里已有的
custom_translations.txt,而冲突检查只管 config.toml。现在 ConfigMigrationProblem
对它做同样的检查:两份内容不同就拒绝这个目录,相同就删掉旧目录的残留再搬。
这也避免了 RemoveDataDir 在非独占目录里按名字删掉没搬走的那一份。
迁移失败时原先只有用户词库和 config.toml 会中止安装,custom_translations.txt
被当成皮肤一样可重建的东西只记日志。它没有出厂副本,新增
TranslationMigrationFailure,没搬成同样中止。
同步 PRIVACY.md 与 installer/README.md 的保留/迁移清单,补上此前就漏掉的
stats.db、helpcodes\custom、shuangpin、models。
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-17 21:46:48 +08:00
Mista and fanlusky
a0da400ae0
feat(server): 支持 Jev 基础候选接入 ( #1030 )
...
* feat(server): 支持 Jev 本地候选推荐
接入 TypeSafe Choice API,并在 AI 辅助设置中提供独立凭据和模型配置。
从本地候选中选择推荐项,保留候选元数据和前两项位置,丢弃取消或过期结果。
补充离线回归测试与数据发送说明。
* fix(server): 修正 Jev 候选重排与配置默认值
- Promote 只在未固定的词库候选槽位之间重排,不再挪动同文字的快捷短语、
云候选、英文和日期等异步行,也不因列表里有任何固定候选就跳过却仍打标记
- 选择无法应用时清除 Jev 选择,〔Jev〕标记只给词库候选
- 少于两个候选时不发 Jev 请求
- 出厂模板和工作配置里 endpoint_jev / model_jev 留空,跟随代码默认值
- 设置页 Jev 的接口地址固定为官方地址,默认值改用 Jev::kEndpoint / kModel
- 查询模型不再列出未经验证的 jev-latest / jev-preview
- 免费函数 Jev::Fetch 直接委托 Client::Fetch,不重复检查
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-17 21:33:35 +08:00
Lu Fan(SonnyCalcr)
1b875267db
refactor: 移除 WebView2,界面只保留 Direct2D ( #1013 )
...
* refactor(engine): 语音独立工具改用原生托盘菜单,移除 WebView2
托盘菜单改用 Win32 弹出菜单,设置项改为用关联编辑器打开 config.toml,关于页改为消息框。删除 window_webview2 与两份 HTML 资源,windows-app 特性不再依赖 webview2 端口。
* refactor(server): 移除 WebView2,候选窗、工具栏、托盘菜单与设置窗口只保留 Direct2D
删除 src/webview2 与 webview_utils,小窗口的置顶、皮肤重载和工具栏状态缓存移到 window/small_windows,presenter 成为唯一路径,D2D 下的置顶时序与 cloak 行为保持不变。设置进程去掉 WebView2 宿主、鼠标转发与启动图,只构建原生窗口;旧快捷方式传入的 --d2d / --webview2 被忽略。删除 appearance.ui_backend 与 appearance.settings_ui_backend(读取、写入、设置页下拉框与两份配置模板),升级时由模板合并丢弃旧值。设置窗口的图片资源移到 server/assets/settings,安装到数据目录的 assets\settings。不再链接 WebView2Loader,vcpkg 去掉 webview2 端口。
* build(installer): 打包与 CI 不再处理 WebView2 页面和运行时
Prepare-PackageFiles 去掉 -UiHtmlDirectory 与 html 暂存,改为暂存 server/assets/settings;安装器不再检查 WebView2 Runtime、不再创建 ProgramData 下的 WebView2 用户数据目录,升级和卸载时清理旧版留下的 webview2 / webview2-settings 与数据目录里的 html。CI 删除设置页构建、契约同步检查和候选窗 DOM 测试,release 的打包任务不再依赖网页产物;dependabot 去掉 npm。第三方声明去掉 WebView2Loader。
* refactor(ui-html): 删除 WebView2 页面与设置页前端工程
候选窗、工具栏、托盘菜单、设置页、主题和契约副本都已没有使用者;设置窗口用到的图片资源已移到 server/assets/settings。sync-contracts.py 与 pnpm/Vite/TypeScript 工程一并删除,契约仍以 engine/contracts/webview 为唯一来源。
* docs(server): 文档改为只描述 Direct2D 界面
仓库地图去掉 ui-html,组件边界、uiAccess 与置顶时序、设置窗口和配置读写的说明改写为 Direct2D 唯一界面;安装说明去掉 WebView2 Runtime 检查,打包命令去掉 -UiHtmlDirectory;engine/contracts/webview 的说明改为设置窗口是唯一使用者,名字是历史遗留。
* docs(skins): 皮肤说明不再区分 WebView2 与 D2D 渲染器
v2 字段去掉「仅 WebView2」,改为说明由 Direct2D 原生渲染、部分字段仍在补全;颜色必须带 # 改为清单格式约定。随包的 skins/niya-demo/skin.toml 不改,免得用户机器上的同名皮肤在升级时被当成已修改而改名备份。
* docs(ui): demo 说明文字不再提 WebView2
2026-10-17 02:48:02 +08:00
Lu Fan(SonnyCalcr) and li shiyan
c67814caf8
feat(server): 改进中文模式下英文补全词形和首页候选 ( #1010 )
...
* feat(server): expand mixed English completion choices
* fix(server): count fixed English in the first-page English budget
- Fixed-position English never takes the slot, regardless of
first_page_count; fixed English on the first page counts toward the
budget and the page room, and the first-page emoji is placed so that
re-inserting fixed words returns it to the last slot.
- SlottedEnglishIndex returns the first unfixed English, so slot
learning keeps working when the top-ranked English is fixed.
- Drop the protected-prefix lower bound on the completion target: it
pushed the single default completion off the first page.
- Protect cloud/AI (and AI following English) from the extra English
even with a learned slot.
- Keep the legacy five-row prefix query for the default single English
candidate; only first_page_count > 1 uses the mixed distinct-word query.
- Let SetConfiguredEnglishMixedInputFirstPageCount own the range check.
---------
Co-authored-by: li shiyan <150001555+lsy9966303@users.noreply.github.com >
2026-10-16 23:00:06 +08:00
26e6896c5f
fix(voice): dismissible overlay, silent no-speech handling, reasoning strip + provider registry with mainstream presets ( #996 )
...
* fix(server): keep vendor chat fields off foreign endpoints and strip reasoning from responses
* fix(engine): strip inline reasoning from polished text and assistant responses
* fix(server): never block the voice control loop with modal dialogs
* feat(server): provider registry for AI assistant with mainstream provider presets
* feat(ui-html): settings pages for the provider registry, model fetch everywhere and new ASR providers
* test(server): vendor detection, reasoning strip, provider store and expanded provider defaults
* fix(server): keep the voice overlay dismissible at all times
* fix(server,ui-html,installer): 服务商注册表与语音收尾的评审修正
- 加载配置时先读 ai_providers.json 再校验当前服务商,用户添加的服务商不再被重置为 deepseek
- Token 不再明文写进 ai_providers.json,统一存为 config.toml 的 token_<id>(DPAPI 加密、升级时按凭证保留);旧文件里的明文 token 读取时清掉
- 配置重载同时检查 ai_providers.json 的修改时间,只改注册表也能同步到 Server
- 删除当前服务商时按切换服务商的流程更新 token、地址和模型
- 内置服务商列表收敛到 ProviderStore::BuiltinProviderIds 一处,新增的六个预置服务商同样以 config.toml 为准;去掉未使用的 MakeProviderId,前端生成 id 时避开内置 id
- 出厂模板和开发配置补上六个新预置服务商的 token_/endpoint_/model_ 键
- 录音回调失败时走完整的取消收尾,恢复系统静音并关闭豆包连接;删除不可达的第二段 Esc 处理
- 语音转写地址查询模型时正确推出 /models
- 设置页补上语音识别和润色的 Custom 选项、新预置服务商的显示名,修正添加服务商的地址提示
---------
Co-authored-by: alayahbridge319-boop <246594988+alayahbridge319-boop@users.noreply.github.com >
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-16 21:46:41 +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
luo jiyin and fanlusky
acc25f40e6
fix(installer): 在最终数据目录保存云候选选择 ( #972 )
...
* fix(installer): 在最终数据目录保存云候选选择
安装器在数据目录确定后检查已有配置。升级迁移遇到配置冲突时停止,避免覆盖目标配置。
首次安装以 UTF-8 写入云候选选择,并在写入失败时报告错误。
增加安装时序检查和 Windows 安装测试矩阵。
Refs #931
* test(installer): 用 Inno 探针验证云候选配置写回
主安装器与探针共用云候选配置函数。
Windows CI 执行五个隔离的首次安装和升级场景。
Refs #931
* test(installer): 接受 Inno 配置文件的 CRLF 行尾
测试按完整的 cloud_candidates 行检查结果。失败时打印实际字段值。
Refs #931
* fix(installer): check config migration conflict before stopping IME
* test(installer): clear expected conflict exit code
* test(installer): narrow source check to migration order
* fix(installer): 云候选写回失败不再中断安装,迁移可重试
- 写回「不启用云候选」失败时只记日志并提示,挪到必需的安装后步骤之后
- 两处 config.toml 内容相同时视为上次迁移的残留,允许重试
- config.toml 没搬过去时中止安装,避免新目录装上出厂配置
- 数据目录页就检查配置冲突
- ShouldSkipPage 不再写全局状态
- 探针复用生产的迁移判断与顺序,补齐改目录首次安装、重试和迁移失败场景
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-15 23:00:34 +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
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)
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
時崎 ギャラクシー 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
Jia Sui
d495ea2ad0
fix(engine,server,installer): octagram 加成收敛为单一注入,校正量纲与参数,修复〔万象〕同音乱码
2026-10-12 13:12:21 +08:00
fanlusky
371d651a40
fix(windows,installer): 输入法语言配置图标改用固定路径,升级后任务栏不再显示「简体」
...
TSF DLL 每次升级都装进新的 msime_v* 版本目录,语言配置注册的图标指向 DLL 自身,
注册表里的图标路径随之每次变化。任务栏恰好在换目录时取不到图标,就改显示「简体」文字,
并一直沿用到资源管理器重启。
- 安装器把 windows/image/msime.ico 装成 Program Files 与 Program Files (x86) 下
metasequoiaime\MetasequoiaImeTip.ico,排在 TSF DLL 的 regserver 条目之前
- RegisterProfiles 发现 DLL 上一级目录有这个文件就注册它(索引 0),否则退回 DLL
内嵌的 IDIS_METASEQUOIAIME,开发时从 build 目录注册不受影响
- 打包脚本收集并断言该图标;打包测试检查两份都装、且先于 DLL 安装
2026-10-12 04:20:17 +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)
19543ead61
fix(server,installer): 升级不再改掉老用户设置和效果档模型,SimplySign 打包前构建词库 ( #852 )
...
* fix(server): 升级不再把只给新装用户的出厂默认值推给老用户
* fix(installer): 升级时把 0.9.x 随包的效果档模型挪到 models\neural-desktop,不再删掉
* fix(installer): SimplySign 完整包打包前从同级 msime-dictionary 构建词库并备好模型
2026-10-12 00:27:59 +08:00
fanlusky
39cc1c39ca
feat(installer): 新用户默认 fluent 横排皮肤并关闭辅助码
2026-10-11 22:22:27 +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)
7825e93038
feat(installer): 翻译默认使用小牛翻译 ( #836 )
...
出厂模板和开发配置都改为默认启用小牛翻译(niutrans.enabled = true),
开发配置同时关掉腾讯云,与出厂模板保持一致。设置页的翻译供应商按
niutrans.enabled 推导,新装用户打开即是小牛翻译;升级用户保留原选择。
2026-10-11 17:32:22 +08:00
Lu Fan(SonnyCalcr)
9495b8b60d
feat(installer): 自动安装首次运行所需的依赖 ( #823 )
...
* feat(installer): 自动安装首次运行所需的依赖
- pnpm install: 构建 ui-html 时自动安装 node_modules,首次运行不再因缺失 tsc 而失败
- pypinyin: 词库构建自动安装 Python 依赖,无需手动提前装
- 新增 scripts/download-neural-model.ps1: 从 chinese-ime-lm Release 下载神经整句模型
* 幂等设计,摘要验证正确时直接跳过,首次运行下载 ~30 MB
* Invoke-LocalTest.ps1 在词库构建后自动调用
优化完整包构建流程(test.ps1),首次运行时自动处理所有依赖安装和下载。
* fix: build-failures 测试允许 pnpm install 成功
mock pnpm 函数现在只让 'pnpm run build' 失败,允许 'pnpm install' 成功。
这样测试可以验证脚本在 build 失败时正确地中止,同时支持首次依赖安装。
2026-10-11 15:33:31 +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)
5aed0fcbf0
fix: 修复部分用户打不开设置页,WebView2 缺失时仍可正常打字 ( #801 )
...
* fix(installer): VC++ 运行库要求提到 14.40 并给出直接下载链接
服务端程序用 MSVC 14.40+ 编译并导入 msvcp140.dll,配上更旧的运行库,
std::mutex 首次加锁即访问冲突、进程无声闪退,设置页因此打不开;原先
14.20 的门槛放过了装着 2019 / 早期 2022 运行库的机器。
- 缺失与「已装但过旧」分开提示,并显示当前版本
- 「是」直接下载 VC++ x64 运行库与 WebView2 Evergreen Bootstrapper
- 更正 WebView2 缺失的影响:只有设置页需要它,默认 D2D 候选窗照常打字
* fix(server): WebView2 不可用时设置页给出提示,候选窗退回 D2D
- 设置进程不再忽略 WebView2 environment / controller 创建失败(运行时缺失
时同步失败、回调不来,界面会一直停在启动画面),改为弹框说明原因、错误码
与下载直链后退出
- ui_backend = webview2 而检测不到运行时时,本次进程改用 D2D 渲染,保证能
正常打字;不改配置,装好运行时后下次启动自动恢复
- WebView2 下载地址统一为 Evergreen Bootstrapper 直链
2026-10-11 02:21:40 +08:00
fanlusky
90e812fe4e
fix(installer): start fresh installs in Chinese and ship opt-in features off
...
- input.default_ime_mode defaults to chinese, matching the Server and TSF fallbacks
- utility.emoji_mode / kaomoji_mode default off so Shift+E / Shift+M no longer swallow
English words that start with a capital letter
- voice_input, ai_assistant and tencent_tmt default off; without a token they only pop a
prompt (voice on Right Alt, which is also AltGr) or do nothing
- doubao_enable_ddc defaults off, matching its comment and the code fallback
- drop general.enable_emoji, which nothing reads
cloud_candidates stays on: the installer's network page asks the user and only writes
false when unchecked. Code fallbacks in ime_config are aligned with the template.
2026-10-10 23:02:15 +08:00
Lu Fan(SonnyCalcr)
5e03628a7e
feat(installer): build cn-en translations into the local dictionary ( #784 )
...
* fix(server): drop part-of-speech labels from Ctrl+Enter translation senses
The machine-translated Chinese-to-English glosses prefix each sense with a
label ("n. silver medal", "proper n. Wanshan District"). The candidate
window keeps showing the whole gloss, but splitting it for Ctrl+Enter now
strips the label so it never reaches the committed text.
* feat(installer): build cn-en translations into the local dictionary
build-dictionary.py gains a cn-en-translations stage that loads
sources/cn-en/machine-translations.txt from msime-dictionary into
zh_en_glosses verbatim, keeping every sense instead of the two the ECDICT
derivation keeps. It runs after english-glosses and before
custom-translations, so it overrides ECDICT and custom/translations.txt
still overrides it.
Local full test packages now always build the dictionary from the sibling
msime-dictionary checkout instead of downloading the product-lock release:
Invoke-LocalTest.ps1 and prepare-package-inputs.ps1 call
build-dictionary.py --if-stale, which skips only when out/ was built from
the current clean source commit by the current builder. CI and releases
still take the dictionary from product-lock.json.
2026-10-10 21:17:03 +08:00
xiaozhu1337 and fanlusky
9c0f6da9be
feat(windows): add opt-in per-app Vim Escape mode ( #737 )
...
* feat(windows): add opt-in per-app Vim Escape mode
* fix(windows): 改用 config.toml 的 vim_mode_apps 并移除 yaml-cpp
TSF DLL 会注入所有宿主进程,约定保持 /Zc:threadSafeInit- 且不加全局构造器;
yaml-cpp 带命名空间级 std::string 数组和线程安全局部静态,违背这一约定。
配置改为 [input] vim_mode_apps = [...],由 DLL 内的小型解析器读取,
沿用 config.toml 的时间戳缓存;键写入出厂模板与工作配置,升级合并保留用户值。
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-09 16:59:05 +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
小莫 and fanlusky
ad78409e3c
ci(release): run the SignPath path on GitHub-hosted runners ( #709 )
...
* ci(release): run the SignPath path on GitHub-hosted runners
SignPath's open-source plan accepts a signing request only when every job leading up to it ran on a GitHub-hosted runner, and tsf, server and package all ran on the self-hosted release machine. With WINDOWS_SIGNING_PROVIDER=signpath they now run on windows-2025, restoring vcpkg binaries and (for the Server) sccache the way ci.yml does; the certificate path keeps the self-hosted runner unchanged.
The org secret holding the SignPath API token is SIGNPATH_TOKEN, so the workflow and detect-release-signing.ps1 read that name instead of SIGNPATH_API_TOKEN.
AGENTS.md lists what SignPath needs configured, and the code signing policy records the accepted application and the hosted-runner rule.
* fix(ci): let the SignPath action read the run's artifacts
* fix(installer): drop authenticode-sign attributes SignPath Foundation rejects
* fix(ci): fail the hosted SignPath release before signatures are spent
- Probe ISCC with WizardStyle=modern dynamic and run that probe at the start of the hosted package job, so an image ISCC older than 6.6 fails before the payload signing request instead of after it.
- Verify the TSF vcpkg root before installing into it or saving its archives under the -complete key.
- Check the Server job's C:\vcpkg override against the vcpkg the hosted image puts on PATH.
- Code signing policy: drop the stale "once approved" wording and state that the hosted-runner rule applies to SignPath-signed releases.
* docs: list only the configured SignPath approver
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-08 23:16:34 +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
6489d4be17
feat(server): 调整 Emoji 混输候选项位置至候选列表末尾
2026-10-08 22:10:13 +08:00