Skip to content

新增预设管理、映射备注及托盘稳定性修复v2#3

Open
qq1229037592 wants to merge 6 commits into
llnut:masterfrom
qq1229037592:master
Open

新增预设管理、映射备注及托盘稳定性修复v2#3
qq1229037592 wants to merge 6 commits into
llnut:masterfrom
qq1229037592:master

Conversation

@qq1229037592

Copy link
Copy Markdown

用AI写的代码,修正了体验。

本次 PR 为 Sorahk v0.5.0 新增三项功能:
(1) 预设管理系统——支持保存/加载/删除/重命名/一键切换按键映射预设;
(2) 映射备注编辑——每个按键映射可添加备注说明,在设置面板编辑、主界面查看;
(3) 托盘稳定性修复——修复 Win11 上托盘图标不显示、最小化到托盘后窗口无法恢复的兼容性问题,覆盖 Win10/Win11。

以下是移除所有 emoji 后的版本:


具体改动

src/config.rs — 数据模型

改动点 1:新增 Preset 结构体(name + mappings),在 AppConfig 中新增 presets: Vec<Preset>current_preset: String 字段。默认创建一个名称为"无"的空映射预设。

改动原因:用户可在不同游戏/场景之间一键切换映射配置,无需手动重配。预设数据与当前映射数据完全独立序列化。

改动点 2KeyMapping 结构体新增 note: String 字段(带 #[serde(default)])。

改动原因:允许用户为每个映射添加文字备注(如"BOSS战用"、"仅限法师职业")。

改动点 3save_to_file() 增加预设和备注的 TOML 序列化。空映射预设显式写入 mappings = [];输出 notecurrent_preset

改动原因:手工拼接 TOML 必须保证所有反序列化必需字段有输出。空映射预设若不显式写 mappings = [],重启后反序列化会报 missing field 'mappings'(toml 0.9.x 的 array-of-tables 不触发 #[serde(default)])。

src/tray.rs — 系统托盘

改动点 1cbSizesize_of::<NOTIFYICONDATAW>() 改为 offset_of!(NOTIFYICONDATAW, guidItem)(V2 尺寸)。

改动原因:全尺寸 NOTIFYICONDATAW 在 Win11 某些配置上导致 NIM_ADD 静默失败,托盘图标不显示。V2 尺寸(Vista+)全版本兼容。

改动点 2:移除所有 3 处 NIF_SHOWTIP 标志(初始 uFlagsupdate_tooltipshow_legacy_notification)。

改动原因NIF_SHOWTIP 是 Win11 专属标志,与 V2 cbSize 不兼容,保留会导致托盘操作失败。

改动点 3:新增 restore_main_window() 静态函数——通过 FindWindowW 按窗口标题查找 → ShowWindow(SW_SHOW)SetForegroundWindow。在托盘双击(WM_LBUTTONDBLCLK)和右键菜单"显示窗口"两个入口调用。

改动原因:eframe/winit 的事件循环在窗口隐藏/最小化后可能被 Win11 节流,导致 ViewportCommand::Minimized(false) 路径失效。直接 Win32 API 调用绕过 eframe 事件循环限制,确保恢复窗口可靠执行。

改动点 4NIM_ADD 返回值从 let _ = 改为检查并 eprintln! 警告。

改动原因:原代码静默吞掉托盘创建失败,故障无法排查。

src/gui/main_window.rs — 主窗口

改动点 1:标题栏增加预设快速切换 ComboBox。切换时自动 save_to_file + reload_config + 同步 temp_config。切到"无"时同步清空 current_presetmappings

改动原因:主界面一键切换预设,无需进入设置面板。

改动点 2:引入 Win32 API 导入(FindWindowWShowWindowSetForegroundWindow)。

改动点 3:关闭对话框"最小化到托盘"按钮用 ShowWindow(SW_HIDE) 直接隐藏窗口,替换原 ViewportCommand::Minimized(true)

改动原因SW_HIDE 隐藏窗口但不修改 eframe 内部"期望可见"状态,事件循环保持正常运行。Minimized(true) 会触发 winit 标记窗口为最小化,Win11 下事件循环被节流。

改动点 4check_and_clear_show_window_request 处理中增加直接 Win32 恢复调用。

改动原因:双保险机制——eframe ViewportCommand 先尝试恢复,Win32 ShowWindow(SW_SHOW) 作为兜底。

改动点 5:映射卡片中增加备注行显示(note_label() + mapping.note)。

改动原因:主界面快速查看映射备注。

src/gui/settings_dialog/ — 设置面板(4 个文件)

改动点 1general.rs):在切换键设置与全局配置之间新增"预设管理"卡片——预设下拉选择器、保存按钮(带名称输入)、删除/重命名按钮。切"无"或删除预设时同步清空 mappings

改动原因:集中管理预设的增删改查。

改动点 2mapping_list.rs):每个现有映射行末尾增加备注 TextEdit,直接绑定 mapping.note

改动原因:在设置面板编辑已有映射的备注。

改动点 3mapping_editor.rs):新增映射构造时保存 note: self.new_mapping_note.clone(),添加成功后清理 note 字段。

改动原因:新建映射时同步保存备注。

改动点 4mod.rs):保存逻辑增加"更新当前活动预设的映射"步骤,取消/保存清理逻辑增加 preset 和 note 字段清空。

改动原因:确保预设数据与映射变更保持同步,防止脏数据残留。

src/gui/mod.rs — GUI 状态

改动点SorahkGui 结构体新增 new_mapping_noteshow_preset_name_inputpreset_name_inputpreset_rename_targetpreset_rename_input 字段及构造函数初始化。

改动原因:支持备注编辑和预设管理的 UI 状态。

src/i18n/ — 国际化(8 个文件)

改动点:新增 8 个翻译键(PresetTitlePresetSaveBtnPresetDeleteBtnPresetRenameBtnPresetNameHintNoPresetNoteLabelNoteHint),覆盖英文/简中/繁中/日文/韩文 5 种语言。涉及 mod.rs(结构体+初始化)、raw_key.rs(枚举)、accessors.rs(访问器)、5 个语言文件(翻译字符串)。

改动原因:支持预设管理和备注功能的国际化。

src/main.rs — 入口

改动点TrayIcon::new().expect() 改为 match 错误处理(eprintln! 记录错误日志)。

改动原因:托盘初始化失败时优雅降级而非 panic,提高程序健壮性。


测试验证

如何验证

  • cargo checkcargo build --release 零错误通过
  • 手动功能测试:
场景 步骤 预期
预设保存 设映射 → 设置面板 → 预设管理 → 输入名称 → 保存 预设出现在下拉列表,Config.toml 含 [[presets]]
预设切换 标题栏下拉选预设 映射即时切换
切"(None)" 标题栏选"(None)" 映射清空,current_preset 清空
预设删除 选中预设 → 删除 预设移除,映射清空
预设重命名 选中预设 → 重命名 → 确认 名称更新,current_preset 同步
映射备注 编辑映射时填写/修改备注 主界面显示,Config.toml 持久化
空预设重启 创建空映射的预设 → 重启 正常加载,不报 missing field 'mappings'
托盘最小化 点 X → 最小化到托盘 窗口消失,托盘图标存在
托盘双击恢复 双击托盘图标 窗口恢复并获焦点
托盘右键恢复 右键 → 显示窗口 窗口恢复并获焦点

潜在风险/回滚方案

风险点

  1. restore_main_window() 通过 FindWindowW(None, "Sorahk - Auto Key Press Tool") 按窗口标题查找。若系统存在同名窗口,可能恢复错误目标。概率极低。
  2. ShowWindow(SW_HIDE) 绕过 eframe 的 ViewportCommand 机制,winit 内部状态可能与实际窗口状态不一致。若未来 eframe/winit 版本增加对隐藏窗口的自动恢复逻辑,需重新适配。
  3. 预设"无"名称硬编码为中文"无",与语言设置无关。

回滚方案:如需回滚,恢复以下 21 个文件到 v0.5.0 原版:src/config.rssrc/main.rssrc/tray.rssrc/gui/mod.rssrc/gui/main_window.rssrc/i18n/*(8个文件)、src/gui/settings_dialog/*(4个文件)。


相关历史教训(防重复犯错)

状态同步一致性current_presetmappingspresets 是耦合状态组。本次已在 4 处(标题栏切"无"、设置面板切"无"、设置面板删除预设、标题栏预设切换)确保三者同步更新——current_preset.clear() 必须伴随 mappings.clear()current_preset 赋值必须伴随 mappings = preset.mappings.clone()。此模式在开发过程中重复出现 3 次错误(只改标识字段而遗漏关联数据),最终通过识别耦合关系在所有触发点统一修复。建议后续若新增修改预设状态的操作,先检查是否已同步处理三个关联字段。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant