Repository navigation
Releases
SnipForge 0.2.1
[0.2.1] - 2026-11-08
变更 · 开机自启改为静默启动(重新打包)
- 注册表 Run 项写入
"…\snipforge.exe" --silent。登录 Windows 后只驻留托盘图标,
不再弹主界面抢焦点;主窗口照常创建,热键、托盘、剪贴板监听全都正常,
点托盘或按热键随时亮出来 - 手动双击 exe 不带该参数,行为不变(照常显示主界面)
- 老版本写入的自启项在下次启动时自动校正成带
--silent的写法,不用手动重开开关 - 静默启动时撞上已有实例直接安静退出,不弹"已经在运行"的对话框
新增 · 开发者工具箱(插件形式)
21 个本地工具,侧边栏「开发工具」进入,手势里也能挂一条。
- 编码转换:Base64(URL-safe / 折行)、URL、Hex、HTML 实体、Unicode 转义、JWT 解析
- 格式化 / 校验:JSON(带行列报错、键排序)、XML、SQL、正则测试(高亮 + 分组明细 + 替换预览)
- 生成 / 计算:UUID、时间戳互转、哈希(MD5/SHA-1/256/384/512)、随机密码、进制转换、Cron 下次触发
- 文本处理:命名风格(camel/snake/kebab…)、去重排序、行级 diff、行处理、字数统计
- 工具目录写在
plugins/devkit.plugin.json,算法在前端注册表src/lib/devkit/。
清单一改,导航和工具列表跟着变;插件页可以整体开关这个工具箱 - MD5 是手写的(Web Crypto 不提供),已和 Node 的
crypto对过 8 组输入;
密码用拒绝采样 + 保证每类字符至少一个;进制转换走 BigInt,超过 2^53 不丢精度
变更 · 手势引擎换 8 方向(破坏性)
- 方向从 4 个扩到 8 个:上下左右 + 四个斜向。位移按 45° 扇区判定,
一个方向走够step才记一个 token - 逗号分隔 token:
D,R= 先下后右,DR= 一条右下斜线 —— 不分开的话
这两种手势会撞成同一个串 - 容错一个 token:转折处多判/少判一个方向是常态,要求逐字相等太脆。
DR,UR和DR,U,UR都能命中 V - 掉头要 1.8 倍距离:上↔下、左↔右这种正相反的方向,防转折点抖动
切出多余 token - 删掉形状识别:点云匹配、模板阈值、
@前缀、自定义笔画全部去掉。
S / H 改用方向串写(S =DL,DR,DL,H =D,R,D),行为从"黑盒猜"
变成"画什么就是什么" - 默认绑定全部重配(配置迁移 v5 会重置,旧绑定在新语义下意思全变了):
四个主方向 +DR/DL两条斜线 + 若干组合 - 录制框改成「画一遍 → 后端翻译成方向串」,和真手势共用同一套判定
变更 · 默认手势定稿(8 方向)
按实际使用习惯重排,配置迁移 v6 会重置绑定:
| 手势 | 动作 | 手势 | 动作 |
|---|---|---|---|
| ↑ | 复制 | ↓ | 粘贴 |
| → | 前进 | ← | 后退 |
| ↓→ | 关闭窗口 | ↓← | 关闭同程序其他窗口 |
| ↗ | 最大化/还原 | ↙ | 最小化 |
| ↖ | Esc | ↘ | Del |
| ←↓→↓← | 搜索选中文字 | ↑→↓← | Ping 选中地址 |
| ↓↑→↓ | 编辑 hosts | ↓→↑← | 贴图 |
| ↓←↑→ | OCR | →↙→ | 排除当前程序 |
| ↙↘↙ | 截图 |
浏览器专用集:↑ 页顶 / ↓ 页底 / ↘↗ 刷新 / ↗↘ 强制刷新 / ↓→ 关标签 /
↑→ 右侧标签 / ↑← 左侧标签 / ↓→↓ 主页。
新增三个动作:
- 关闭同程序其他窗口:枚举同进程、可见、有标题的顶层窗口发
WM_CLOSE,
当前窗口留着。没有标题的多是隐藏辅助窗口,关掉会伤到正在运行的程序 - 搜索选中文字:先
Ctrl+C,180ms 后读剪贴板,开 Bing - Ping 选中地址:
Ctrl+C后只保留域名/IP/端口的合法字符,
直接spawn ping—— 不经过任何 shell,没有命令注入面
修复
- 右键点一下菜单不弹(被"吞"了)。判定的顺序错了:先看方向串再看位移。
手抖 40 多像素时path_to_dir已经能切出一个 token(R/D/…),而单 token
手势是精确匹配的 —— 于是"点一下"变成执行动作,菜单自然不出来。
现在位移 < 48px 一律按单击补发,不看向量算出了什么 - 补发点击加了诊断日志(光标位置 + 光标下的窗口类名 +
SendInput的返回值和
错误码)。以后"补发没生效"能一眼看出是没发出去,还是发到了别的窗口
审计(第二轮)
- 方向解析(
dir8/ RDP / 折线简化)搬进snipforge_core::stroke,
补 8 条单测。这块以前一条测试都没有 —— 而"画 3 段出 5 个 token"
正是这里出过的 bug。现在覆盖:8 个扇区、22.5° 边界、直线单 token、
直角两 token、↙↘↙三段、锯齿抖动仍是一段、相邻同向合并、过短轨迹不出 token step字段已废弃:RDP 之后"几段就是几个 token",本来按"走够多少像素
算一次转向"的step不再参与任何判定。从Snapshot和on_move里删掉,
配置字段保留但注明废弃(删了会让旧配置文件丢字段)gesture_trace去掉没用的step参数(前后端一起改)- 文档对齐现状:
docs/FEATURES.md还在写"画一个 S 截图""@S/@H
形状命名空间""接管右键按下开关""$P 点云匹配"—— 这些都是已经删掉的东西。
整章按 8 方向重写,含默认手势表和三条匹配规则;README.md的
"画一个 S 就截图"一并改掉
审计(手势链路)
一轮完整代码审计,按"会不会在钩子线程里出事"这条线逐层过:
-
handle_event每个 mousemove 都拿配置锁 +clone()一个 String。
这个函数就在钩子线程里同步跑,等于持续分配内存。改为配置变更时写进
AtomicBool+RwLock<String>,热路径只做一次原子读 -
on_move在轨迹点数封顶后每个事件都做全量 RDP。pts到 1500 后长度
不再变,1500 % 6 == 0让重算条件恒成立 —— 越划越卡。改成只有真的压入
新点时才重算 -
match_action每次方向变化都整体 clone 专用手势集(连所有绑定的轨迹点)。
改成按引用索引 -
inject_click在钩子回调里调SendInput。整理成整对发送都在工作线程
里做,回调只负责"决定要补点一下" -
"关闭同程序其他窗口"会把自己也关掉:枚举时没有排除当前窗口,
说是"其他窗口",实际连用户正在用的那个一起WM_CLOSE -
path_to_dir里有两处unwrap()(包围盒)。虽然前面对点数有保护,
但这段跑在钩子线程,panic 会连带整个输入链。改成单次遍历算包围盒 -
on_move的兜底之外,on_down也会处理"上一次抬起丢了"的残留状态,
先把旧轨迹收掉再开新的 -
修正
gesture.rs顶部过时的模块文档(还在描述已删除的点云形状识别、
四个方向)和window.rs里一段粘错位置的注释 -
在浏览器里画
↓↑→↓打开的是主页,而不是编辑 hosts。原因是匹配顺序:
先查浏览器专用集,里面↓→↓(主页)只要"差一个 token"就算命中,
于是把通用集里精确命中的↓↑→↓挡住了。现在改成:- 先比距离,精确匹配永远赢过模糊匹配;距离相同才让专用集优先
(专用集的意义是"在这个程序里覆盖",不是"随便糊一个") - 容错按长度收紧:两段以内只认精确(
↓→是关窗口,↓→→不该命中它);
三段以上才允许差一个 - 只容忍"多画",不容忍"少画":转折处手抖多切一个 token 可以,
但 3 段手势不会去命中 4 段绑定 —— 否则画↓→↓会误触↓↑→↓
- 先比距离,精确匹配永远赢过模糊匹配;距离相同才让专用集优先
-
匹配规则搬到
snipforge_core::pattern。主 crate 的测试 harness 在本机
起不来(STATUS_ENTRYPOINT_NOT_FOUND),所以gesture.rs里的测试从来没跑过,
其中两条断言一直是错的(normalize("D-X,R")和一处编辑距离)。搬进 core 后
36 项单测全绿,这两条也一并修正 -
吞一半按下/抬起会让系统按键状态卡死(这是这一轮所有怪现象的根)。
鼠标钩子吞掉一个事件,系统那颗键的状态就不会跟着变 —— 实测:放行
RButtondown、吞掉RButtonup之后,GetAsyncKeyState(VK_RBUTTON)
会一直返回 DOWN。后果是目标窗口一直以为右键按着:捕获不放、
菜单卡住、左键跟着失灵,得再点一次右键才恢复。
规则:按下和抬起必须成对处理,要么都放行,要么都吞掉 -
桌面右键菜单跳两下。整对吞掉后必须补发一次点击,而补发时按下和抬起
之间的间隔太短(35ms),桌面/任务栏的菜单还没建完,合成的抬起落在了底下
的桌面上,于是又开一次菜单。间隔改成 100ms(接近真人点击),抬起就能落到
已经建好的菜单窗口上 -
松手后手势不结束、轨迹一直跟着鼠标。根因是同时跑了两个实例:
两套钩子互相截事件,一边拿了按下、另一边拿了抬起,前者状态永远不清。
启动时用会话内命名互斥体挡掉第二个实例(弹提示后退出);另外加 20 秒
超时兜底,任何情况下都不会再"永久跟随" -
删掉
swallowDown开关(配置项和界面都去掉):两种模式只有一种是对的,
留个开关只会让人选到错的那个 -
手势只认 S 和 H,其余字母不再内置识别。一笔画的折线本来就是方向串
(↓→既是「向下再向右」,又恰好是字母 L 的写法),全字母参与识别时
每次「下再右」都被判成画字母。更要紧的是RLR(画 Z 形)是「排除当前
程序」的默认绑定,会被@Z吃掉,排除功能直接失效。
现在只有 S / H 参与内置识别;其他字母在「鼠标手势」页画一遍存成自定义
手势即可 —— 只认你加的那一个,不干扰任何方向手势 -
画
↓→时浮标报「未绑定」,但松手却执行了动作。原因:↓→的形状正好
等于字母L的模板(竖下 + 横右),被形状识别抢成@L。执行层有回落
(@L没绑就按方向串DR找),浮标层却只查@L—— 显示和执行用了两套规则。
现在两处共用同一套回落,浮标显示的永远是真正会执行的那个动作
SnipForge 0.2.0
[0.2.0] - 2026-11-03
剪贴板 · 富文本与隐私
对照 TieZ 的剪贴板实现补齐三块:
- 富文本 HTML 保留(以前挂在 📋 计划里的那条)。采集时读 Windows 的
HTML Format,粘贴时同时写CF_UNICODETEXT和 HTML —— 从网页复制的表格、
带样式的文字,粘到 Word / 邮件 / 飞书里格式不丢;记事本、终端这类只认纯文本的
地方照常能粘。去重仍按纯文本 hash:同一段话复制两次不该变成两条历史 - 隐私遮罩预览:列表里手机号、身份证、银行卡、邮箱自动打码
(138****8000/110101********1234)。只影响显示,选中后写进剪贴板的
还是原文。面板和主窗口都生效 —— 投屏、录屏、旁边有人的时候不至于把证件号念出来 - 按来源程序筛选:卡片底部的程序名现在可点,点一下只看那个程序里的复制记录;
再点一下(或点顶部「来自 xxx ✕」)取消 - 粘贴为纯文本:面板里
Alt+Enter,丢掉网页带来的字体颜色等样式,
只把文字塞过去。配合上面的富文本保留,两种场景各取所需
不做的事:WebDAV / MQTT 跨设备同步。这个工具的定位是本地常驻,剪贴板历史里
经常有密码和证件号,不上传比"能同步"重要。
鼠标手势 · 支持画字母
以前只能认方向(←→↑↓ 及其组合)和 S / H 两个形状,画 W、V、B、M
一律落到"未绑定"。原因是形状和方向串共用同一批字符:D 既是"向下划"
又是"字母 D",加一个字母就得跟方向抢名字。
现在按主流工具的做法拆开:
- 一笔画字母基本都认:A B C D E F G H J K L M N P R S T U V W X Y
(I是一条竖线、等于方向串;O是闭合圆;Q一笔画不自然) - 形状用
@前缀,和方向串分处两个命名空间:@W是字母,DR是方向。
用户手写W也认(自动补前缀) - 形状没绑动作时自动回落方向串:画 Z 会先认成
@Z,没绑就落回RLR,
「画 Z 排除当前程序」照常工作,不需要为每个字母补绑定 - 配置迁移 v4:老绑定里的
S/H自动改成@S/@H S补了两个斜写模板(±10°):点云不抗旋转,以前斜着写 S 认不出- 形状识别从主 crate 搬到
snipforge-core,第一次有了真正能跑的测试
(letters_recognize_themselves:每个字母 6 个抖动/缩放变体必须认回自己)
鼠标手势 · 手感修复
反馈「划起来不流畅、不灵活,和其它手势工具差距极大」。定位到四个实现问题,
全部在轨迹层和默认参数上,与 UI 框架无关:
- 不再每帧重建 GDI 资源:画笔、画刷、字体改成随窗口缓存,只在分辨率或
轨迹色变化时重建。以前每帧CreateFontW一次,字体面查询就是几毫秒 - 重绘合并 + 66fps 上限:高刷鼠标每秒上千次位移,以前每次都投递一次重绘,
消息队列被灌满,表现是轨迹越划越落后于光标 - 只贴脏区:以前每帧清空并回贴整个虚拟屏(4K 双屏 800 万像素每帧),
现在只处理「轨迹包围盒 ∪ 浮标包围盒 ∪ 上一帧范围」 - 灵敏度默认值 30/55 → 16/38:旧值划一小段没反应、短促手势划不出方向。
配置里两个值都还是旧默认的自动升级(v3 迁移),自己调过的不动 - 浮标停留 520 → 240ms:连续划两个手势不再互相干扰
- 轨迹采样加 2px 阈值,去掉一像素一报的抖动点
决策记录
- 新增
docs/ADR-001-ui-stack.md:评估 Rust + egui 迁移,结论是不迁。
内存 27 MB 不是瓶颈,且 egui 的立即模式对全屏覆盖层是负优化;
手势卡顿的根因在 GDI 重绘方式,换框架解决不了。文档里留了重新评估的触发条件
SnipForge 0.1.0
[0.1.0] - 2026-11-01
第一个预览版。Windows 10/11 x64。
截图
- 一个入口:
Alt+Q打开冻结画面,拖拽框选区域、单击选窗口、Ctrl选整窗、
Ctrl+A整屏、S滚动长截图 - 滚动长截图按行签名拼接,最高 24000px
- 取完之后做什么可配:打开编辑器 / 直接复制到剪贴板 / 直接保存 / 钉在屏幕上。
选「直接复制」完全不弹窗口
标注与美化
- 矩形、椭圆、箭头、画笔、文字、序号、高亮、马赛克
V切选择工具,点中标注可拖动、Delete删除,Esc先退选中再退编辑器- 撤销重做、颜色/粗细/字号可调;对象化模型(标注是数据不是像素)
- 美化:背景、边距、圆角、阴影;水印:文字/平铺/九宫格
取字(OCR)
- Windows 系统 OCR(需对应语言包);可选 PaddleOCR 引擎,设置页一键下载安装
(多镜像 + 体积校验 + 离线导入) - 识别结果手动触发翻译;点词复制:原图上每个词都是可点区域
剪贴板
- 文本 / 图片 / 文件 / 颜色四类全收,按
GetClipboardSequenceNumber变更检测 Alt+V面板:搜索、分类、收藏、来源程序识别;Win+V可用键盘钩子接管- 历史落盘做了节流,连续复制不会反复重写索引
安全
- 主密码:Argon2id 派生 + AES-256-GCM,加密收藏的密码、图床 token、翻译 key。
设了主密码后磁盘上没有明文;启动即锁定,可随时「立即锁定」 - 忘记密码没有后门,唯一出路是「清空保险箱」(两段式确认)
- 路径穿越防护:图床目录、文件名、保存文件名统一出口校验
图床
- GitHub、S3 兼容、SM.MS、自定义、本地目录;声明式插件(JSON 描述即可接入新图床)
- 上传历史、连通性测试、目录浏览
录屏
- 视频(H.264 MP4)与 GIF 分开录,
Ctrl+Alt+R/Ctrl+Alt+G - 系统声音(WASAPI loopback,不用装虚拟声卡)+ 麦克风,两路自动混音,
静音时段按视频时间轴补静音 - 摄像头画中画:圆角+描边、四角位置、大小比例、水平镜像
- 恒定帧率、光标合成、点击高亮环、放大镜、暂停续录
其他
- 图标提取:exe / dll / lnk / APK / IPA → 各尺寸原始图标,可导出 PNG / ICO。
Android 自适应图标会合成背景+前景 - 图片工具:格式互转、质量压缩、等比缩放
- Hosts 编辑:可视化编辑,写入自动提权
- 鼠标手势:自定义手势绑定到任意功能
- 检查更新:启动后静默检查一次 GitHub Release,只提示不自动安装。
API 被限流时自动改用 releases 订阅(不受 60 次/小时配额限制) - 联网走系统代理:图床上传、OCR 引擎下载、翻译、检查更新统一读取
Windows「Internet 选项」的代理设置(Clash / v2rayN 默认就是系统代理),
也认HTTPS_PROXY/ALL_PROXY环境变量
已知限制
- 只支持 Windows;多显示器不支持跨屏框选
- 没有代码签名,首次运行 SmartScreen 会拦一下
- 录屏的摄像头设备不支持热切换,录制后不能剪辑
- 长截图依赖目标窗口响应合成滚轮事件(部分 Electron 应用和游戏不响应)
产物已重打包(2026-11-01 15:30):设置 → 关于新增「产品主页 / GitHub / 反馈 / 更新日志」入口;
产品主页上线 https://adream2.github.io/SnipForge/。版本号不变,直接覆盖同名产物。