Repository navigation
Releases: cv-superding/clash-subscope
Release list
v1.2.9
修复内容
🐛 拖动窗口边缘卡 10 秒 —— 根因确诊
症状:任何 resize(最大化/还原/拖拽边框)都卡到几乎不可用。
根因(用脚本逐个隔离定位,诊断脚本见 _scratch/):
- 真凶是
ttk.Scrollbar(表格区两个滚动条)。 - ttk 滚动条带主题引擎的复杂样式计算,Treeview 尺寸变化 → 滚动条重算范围
→ 反向触发 Treeview 调整 → 连锁重排。 - 垂直+水平两个滚动条叠加成 394ms/次,拖动边框时每移动一次触发一次 → 卡 10 秒。
- 实测对比:无滚动条 54ms / 仅垂直 159ms / 仅水平 219ms / 垂直+水平 394ms。
修复:表格区滚动条 ttk.Scrollbar → 原生 tk.Scrollbar(轻量无主题开销),
resize 耗时从 394ms → 48ms(提速 88%),滚动功能完整保留。
🔧 启动自动扫描改为默认关闭
早期「启动 200ms 后自动扫描一次」本意是「打开即见结果」,
但用户感觉自作主张,且扫描线程在后台抢资源加重卡顿。
现改为默认关闭,需要时点「一键扫描」手动触发。
设环境变量 SUBSCOPE_AUTOSCAN=1 可恢复自动扫描行为。
🧹 其他优化
- 移除
WS_EX_COMPOSITED双缓冲默认启用(对 Tk 是性能灾难,卡 10 秒)。 - 移除
<Configure>事件中的update_idletasks()(每次鼠标移动同步重绘全界面)。 - 保留 v1.2.8 的
GetAncestor(GA_ROOT)改对顶层 HWND + 类背景画刷 +WM_ERASEBKGND子类化 +DwmSetWindowAttribute关 DWM 动画。
已知限制
- 点「一键扫描」完成后表格全量重建,可能瞬时闪一下(扫描完成瞬间 Treeview 清空重建,非性能问题,仅视觉)。
- 黑闪(v1.2.3 的 DWM 层修复)仍需真实屏幕确认。
v1.2.8
🐛 黑闪真因修复:之前一直修错了窗口
v1.2.3 的诊断是错的。 当时认为黑闪来自 DWM 最大化缩放动画的合成层,
于是做了「类画刷 + WM_ERASEBKGND + 关闭 DWM 动画」三件套——
但黑闪始终没消失。
实测诊断(_scratch/diag_top.py)
winfo_id() -> class=TkChild (Tk 的内部子窗口)
GetAncestor(GA_ROOT) -> class=TkTopLevel (真正的顶层窗口)
root.winfo_id() 返回的不是顶层 HWND,而是 Tk 用来承载控件的内部子窗口
TkChild。所以那三件套全都作用在了 TkChild 上,真正的顶层窗口 TkTopLevel
从未被修复过——它一直是 brush=0x0(无画刷 → 系统默认黑)
外加 CS_HREDRAW | CS_VREDRAW。
本版修复(四管齐下)
- 拿到真正的顶层 HWND:新增
_top_level_hwnd(),用
GetAncestor(GA_ROOT)从 TkChild 上溯到 TkTopLevel。 - 对 TkTopLevel 与 TkChild 两层都应用修复——两层都有同样的问题。
- 清除
CS_HREDRAW | CS_VREDRAW(v1.2.3 完全漏掉的关键一步)。
这两个窗口类标志会让 Windows 在尺寸变化时强制擦除并重绘整个客户区,
是 Win32 闪烁最经典的根因。 - 保留类画刷替换、
WM_ERASEBKGND子类化、DWM 关动画,
但 DWM 那步现在作用于真实顶层 HWND。
验证(_scratch/verify_winfix.py)
| 修复前 | 修复后 | |
|---|---|---|
| TkTopLevel 类样式 | 0x0003(HREDRAW+VREDRAW) |
0x0000(已清除) |
| TkTopLevel 背景画刷 | 0x0(无 → 系统黑) |
已设为应用浅色 |
| TkChild | 同样问题 | 同样修复 |
结果 VERIFY_OK。exe 启动存活测试通过。
需要你确认
黑闪属纯视觉效果,无界面环境无法自证。请实测:反复最大化 / 还原 /
拖拽拉伸窗口。
若黑闪已消失但你想要回平滑的缩放动画,告诉我——清除了重绘标志后
很可能已经不需要靠"关动画"来兜底了。
v1.2.7
修复内容
🐛 根因修复:Clash Verge Rev 的服务会立刻拉起被关闭的主进程
症状:用户反馈「点确认后 Clash 依旧存在,并没有关闭」——导入按钮的关闭步骤看似没生效。
根因(实测复现):
- Clash Verge Rev 后台有
clash-verge-service.exe常驻 - 之前的
close_and_wait只 killprocesses字段的主进程,不动 service_processes - 服务检测到主进程退出后立刻拉起 → 写入 profiles.yaml 仍被新进程覆盖
- 之前的代码还会在「调用方明确传入要 kill、但实际什么都没杀掉」时静默返回 True,
把矛盾吞掉让用户看不到任何反馈
这正是 v1.1.1 时已经出现过的同一个 bug 的根因再现。
修复
-
clashctl.close_and_wait新增kill_service参数:False(默认):不动 service_processes(普通场景)True:把 service_processes 也加入 kill 目标(导入订阅这种"必须让 Clash 完全退出"的场景)
-
修复静默吞矛盾:当调用方明确传入
kill_service=True但一个都没杀掉时,
返回(False, ...)而不是(True, "未检测到..."),让上层弹窗告诉用户问题所在 -
清晰的错误消息:杀 Windows 服务需管理员权限。失败时会明确提示
「请以管理员身份运行本工具」 -
ui._import_worker在导入场景显式传kill_service=True——导入订阅时,
服务必须一起杀,否则服务会立刻拉起主进程。
验证
- 冒烟测试
_scratch/smoke_close_service.py实测复现了根因并验证修复路径:
旧版本静默返回 True;新版本返回 False + 明确提示管理员权限 - 全模块
py_compile通过 - exe 启动存活测试通过
用户操作建议
如果之前导入反复失败,**请右键 clash-subscope.exe →「以管理员身份运行」**再导入。
v1.2.6
修复内容
🆕 默认窗口大小调整
启动时底部「诊断与排查建议 / 选中项详情」标签页内容显示不全,
需要手动拉大窗口才能看到。现已将默认窗口尺寸调整如下:
- 默认高度:
760→900 - 最小高度:
640→720
首启即可看到完整内容,无需手动调整。
验证
- 全模块
py_compile通过 - exe 启动存活测试通过
v1.2.5 已修:N1 关窗恢复代理、N2 脏数据不再让订阅全空、N3-N9 等
黑闪(v1.2.3 的 DWM 层修复)仍需真实屏幕确认。
v1.2.5
修复内容(第二轮代码复查)
🆕 新增修复(N1–N9)
- 关窗未恢复代理(N1):导入成功后系统代理处于关闭态,若直接关窗会被永久遗留。
现在关闭时若代理仍待恢复,会弹窗询问一次——可选「恢复后退出」或「保持关闭直接退出」
(后者适用于你还要先在 Clash 里点「更新」拉节点的场景)。 - 一条脏数据让整个客户端订阅全空(N2,实测复现):
profiles.yaml里若某条
name写成数字(如name: 12345),解析会抛异常,导致该客户端所有条目全部丢失
(连后面正常的配置也一起消失)。已加类型防护,脏数据不再影响其余条目。 - 导入中扫描按钮被竞态重新点亮(N5):导入进行中禁用扫描按钮。
- 导入后刷新列表被静默跳过(N6):扫描正忙时标记补扫,结束后自动补跑一次。
- 关代理失败残留旧状态(N3):清空状态,避免之后用旧状态去「恢复」。
- 收尾
after未包 try(N4):关窗时不再抛未处理异常。 - 同秒两次导入备份名碰撞(N7):备份名改为可读时间戳 + uuid 后缀。
- 空数据目录误命中 CWD 文件(N8):无数据目录时跳过裸文件名查找。
- 等待进程退出全量枚举开销大(N9):新增
clashctl.close_and_wait,
只对被 kill 的 pid 做探测。
上一版(v1.2.4)已修
运行时密钥永不生效、导入时界面冻结、写失败代理遗留关闭、
ProxyEnable 字符串型兼容、HTTP 大响应 O(n^2) 等。
验证
- 全模块
py_compile通过 - 冒烟测试全绿:
_short_name脏数据、备份名防碰撞、空目录跳过、close_and_wait就位 - exe 启动存活测试通过
⚠️ 黑闪(v1.2.3 的 DWM 层修复)属纯视觉效果,需你在真实屏幕确认。
v1.2.4
修复内容(基于代码审查)
- 运行时接口:控制器要求密钥时,原先 401 直接中断、导致已发现的密钥永不生效;现改为继续尝试密钥,mihomo/CFW 等带 secret 的客户端也能连上。
- 导入流程:整体移入后台线程,消除原先主线程 sleep 造成的界面冻结;写配置失败时自动恢复系统代理并提示,避免代理遗留关闭。
- 系统代理兼容:
ProxyEnable以字符串型(REG_SZ)存储时也能正确识别与还原。 - 性能:HTTP 响应读取改用 bytearray,消除大响应下的 O(n^2)。
- 健壮性:移除全局副作用、修复 importer 诊断信息丢失、释放 GDI 画刷泄漏、短链接脱敏保留头尾、依赖缺失提示区分 ttkbootstrap/PyYAML。
- 打包依赖精简(移除多余 requests),界面仍为 ttkbootstrap / cosmo 现代化主题。
v1.2.3
Clash SubScope · 订阅透镜 v1.2.3
再次根治最大化/拉伸时的黑闪(之前两版都没修干净)。
根因:黑闪来自 DWM 最大化缩放动画的合成层,单靠应用层 WM_ERASEBKGND 盖不住。
本版改为三管齐下:
SetClassLongPtrW(GCLP_HBRBACKGROUND)把窗口类背景画刷换成应用浅色,DWM 合成时用浅色而非黑;- 继续子类化
WM_ERASEBKGND应用层兜底; DwmSetWindowAttribute(DWMWA_TRANSITIONS_FORCEDISABLED)关闭最大化缩放动画,消除动画黑帧。
副作用:最大化变为「瞬间切换」、不再有缩放动画(换来零黑闪)。
若你更想要动画,告诉我,我可回退第 3 步只保留类背景画刷。
其余保持 v1.2.x(ttkbootstrap/cosmo 现代化主题 + 导入前自动关 Clash + 零上传)。
v1.2.2
Clash SubScope · 订阅透镜 v1.2.2
彻底修复最大化/拉伸时的黑闪(上一版 update_idletasks() 不够早)。
- 改用 Win32 层方案:用 ctypes 子类化顶层窗口过程,接管
WM_ERASEBKGND,
在尺寸变动期间用应用背景色(浅灰)刷底,不再露出系统默认的黑色; - 其余窗口消息全部转发给原窗口过程,对 Tk / ttkbootstrap 行为零侵入;
- 非 Windows 平台或安装失败均为 no-op,不影响启动。
其余保持 v1.2.x(ttkbootstrap/cosmo 现代化主题 + 导入前自动关 Clash + 零上传)。
v1.2.1
Clash SubScope · 订阅透镜 v1.2.1
Bug 修复:修复最大化/拉伸窗口时的瞬间黑闪。
- 在 Windows 上 Tk 收到 WM_SIZE 与实际重绘之间存在一个时间窗,期间 OS 会露出未填充区域;
- 现在给根窗口绑
<Configure>,尺寸变化时立即调用update_idletasks()强制 Tk 同步重绘,堵住那个黑帧; - 顺带把
__version__从1.0.0升到1.2.1,窗口标题版本号也对了。
其余保持 v1.2.0(ttkbootstrap/cosmo 现代化主题 + 导入前自动关 Clash + 零上传)。
v1.2.0
Clash SubScope · 订阅透镜 v1.2.0
界面现代化重构:用 ttkbootstrap(cosmo 主题) 全面替换了原来混搭的 Win32 原生控件。
- 统一视觉语言:圆角主按钮、现代切换式勾选框、纤细主题化滚动条;
- 对话框主题化:12 处
messagebox与文件保存框改用 ttkbootstrap 主题对话框,不再弹出生硬的原生 Win32 窗口; - 文本框滚动条改为自带的 ttk 滚动条(移除原生 scrollbar);
- 业务逻辑零改动:扫描 / 脱敏 / 复制 / 导出 / 导入到 Clash(自动关代理+关 Clash)全部保留。
纯本地、零上传、默认脱敏。详见 README。