wangjia
211fda37e3
fix(client/macos): urltest 完全照搬 Windows 策略——读 /proxies history + active 刷新
...
Windows(kernel_process.dart)的策略:显示源是 /proxies 各 URLTest 成员的 history.last.delay
(每拍读、缓存住、稳定);/group/<name>/delay 只为让内核重测并写进 history,其结果不直接用。
我之前直接用 active 结果,拥塞链路上 active 恒返回 {} 就全空了。
本次照搬:主显示读 /proxies history(extractUrltestResults 字段与 Windows 一致),active
/group/delay 既刷新 history 又顺手缓存(双保险);非空才更新,单次失败不覆盖旧值。
CURRENT_PROJECT_VERSION 50→51。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 14:45:14 +08:00
wangjia
e8e6a0dc24
fix(client/macos): urltest 回到 active /group/delay 取值(v48 验证可行),跳过 GLOBAL
...
v49 改读 /proxies history 后为空:sing-box 的 /proxies 不带 member history。回到 v48 验证
可行的 active 取法——/group/<name>/delay(跳过 GLOBAL 选择器组),成功就缓存,超时/空不
覆盖旧值,显示稳定。移除无效的 extractUrltestResults。
扩展代码变更 → CURRENT_PROJECT_VERSION 49→50。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 14:22:52 +08:00
wangjia
a228a1d221
fix(client/macos): urltest 主源改读 /proxies history(稳定),修连接页延迟
...
v48 验证延迟已打通(urltest=reality-out=576 到达主 app),但 active /group/delay 在拥塞
链路上常超时返回 {}。改为与 Windows extractUrltestResults 完全一致:主源读 /proxies 里各
URLTest 组成员的 history 缓存延迟(稳定,active 探测超时也不丢),并对 URLTest 组(跳过
GLOBAL 选择器)主动跑 /group/<name>/delay 刷新 history。延迟显示由此稳定。
扩展代码变更 → CURRENT_PROJECT_VERSION 48→49。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 14:13:58 +08:00
wangjia
70e8f67702
diag(client/macos): 把 /group/delay 原始响应塞进 diag,定位 urltest 为空
...
v47 诊断:clash 注入生效(组名 auto 已识别),但 /group/auto/delay 返回无数字延迟。
本次把该接口原始响应体(含 HTTP 状态码)透出到 diag,并兼容嵌套 {tag:{delay:ms}} 形态,
一眼区分:内核探测失败(raw={} / 错误消息)还是返回结构不符(解析问题)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 13:28:55 +08:00
wangjia
03dbbf8db9
fix(client/macos): urltest 延迟改走注入的 clash API(对齐 Windows),内核侧打点
...
诊断:即便专开 Group client,扩展回的 urltest 数组恒空——根因是服务端下发配置无
experimental.clash_api,sing-box 不暴露出站组/urltest 历史,libbox Group 命令拿不到。
修复(与 Windows 完全同法):扩展内向配置注入 clash_api(127.0.0.1 本地监听)+ cache_file,
StatsCollector 经本地 HTTP 查 /proxies 找 URLTest 组、/group/<name>/delay 取真实延迟。
速率仍走 libbox Status。新增内核侧 NSLog 打点 kernel delay(<group>)=<tag:ms>,并把该值
塞进 stats 的 diag 字段经主 app 可读日志透出——一眼分清「内核有没有算出延迟」vs「外面没拿到」。
扩展代码变更 → CURRENT_PROJECT_VERSION 46→47。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 12:54:40 +08:00
wangjia
783687d7c2
fix(client/macos): StatsCollector 用独立 client 订阅 Group,修 urltest 延迟为空
...
诊断确认:连接页延迟显示 — 是因为扩展回给主 app 的 urltest 数组恒为空(speeds 正常)。
根因:libbox command 协议是「一连接一命令」,把 Status 与 Group addCommand 到同一 client
只有 Status 生效,Group 永不回调 → 无 urltest。对齐 sing-box-for-apple:每命令各开一个
client。新增 groupClient 专订 Group + 跑 urlTest,延迟即随统计帧回到连接页(与 Windows 同源)。
扩展代码变更 → CURRENT_PROJECT_VERSION 45→46,让 sysextd 重装。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 12:33:00 +08:00
wangjia
a43f8a93de
diag(client/macos): StatsClient 每5帧打印收到的 urltest 延迟,排查连接页延迟为 —
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 12:25:33 +08:00
wangjia
6809e0a377
fix(client): 连接态延迟只认内核 urltest,跳过直连实测(对齐 Windows 方法)
...
连接页延迟显示 ~3ms:连接态下 _measure 的直连 TCP 实测被全局 TUN 在本地接住,
connect() 几毫秒即返回(假值),覆盖了内核 urltest 经 setLivePing 回写的真实 RTT
(macOS system 栈 TUN 尤其明显)。Windows 端延迟本就取 sing-box urltest(clash API
/proxies 的 history delay),macOS 经 libbox writeGroups 的 item.urlTestDelay 同源。
修复:_measure 在 connectionProvider.phase==on 时直接返回,不做直连实测——连接态延迟
只认 urltest(与 Windows 一致),断开后再恢复直连实测。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 12:18:32 +08:00
wangjia
6c19b1bd92
fix(client/macos): 实时统计改走 sendProviderMessage,根治容器路径死局
...
上一版试图让 root 扩展把 command.sock 建到用户容器,反而让 startTunnel 抛错、隧道连不上
(root 在用户 home 建 socket、属主/路径与无 root 的 app 对不上,且方向本就错)。回退该路子。
正解:用 NetworkExtension 官方跨进程通道,绕开「root 扩展容器 vs 用户 app 容器」死局——
- 扩展内新增 StatsCollector:连本进程自己的 command.sock(同容器、root 可达),订阅
status/group 缓存最新上下行 + urltest;handleAppMessage 收到 "stats" 即回最新 JSON。
- 主 app StatsClient 改为每秒 NETunnelProviderSession.sendProviderMessage("stats") 拉取、
解析后推 onStats(不再直连 socket);VpnChannel 三处启动点改传 session。
- 扩展代码变更 → CURRENT_PROJECT_VERSION 44→45,让 sysextd 重装。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 12:05:43 +08:00
wangjia
71132df669
fix(client/macos): sysext 把 command.sock 建在登录用户容器并 chown,修实时统计断流
...
根因:系统扩展以 root 运行,其 App Group 容器是 /var/root/Library/Group Containers/...,
而用户 app 的是 /Users/<user>/...(容器 home 相对)。libbox 把 command.sock 建在 basePath
下 → 落在 root 容器;无 root 权限的 app 永远 connect 不上 → 连接页 — KB/s + 延迟不刷新。
(经 sudo ls 实测确认:socket 在 /var/root 容器,用户容器里没有。)
- PacketTunnelProvider 用 SCDynamicStoreCopyConsoleUser 取登录用户,把 libbox basePath/
workingPath 指向该用户的同名容器(root 可写),command.sock 即落在 app 查找的路径。
- server.start() 后 chown 容器/work/command.sock 给登录用户:Unix socket connect() 需写
权限,仅 owner 满足,否则 app 仍 EACCES。拿不到登录用户时回退 root 容器(隧道可用、仅统计不可用)。
- sysext 代码改动 → CURRENT_PROJECT_VERSION 43→44,让 sysextd 重装新扩展。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 11:43:41 +08:00
wangjia
4f727beb60
fix(client/macos): 启动即激活 sysext + command.sock 打点
...
旧 sysext(on-demand/常驻)会在 app 启动前自动重连,app 走 primeExistingConnection
而非 start() → 永不提交 OSSystemExtensionRequest → bundle 内的新版 sysext 永远装不上,
运行的还是旧版(无 CommandServer)→ command.sock 不存在 → StatsClient 断流(— KB/s + 旧延迟)。
- VpnChannel.register 阶段调 activateOnLaunch():同开发者高版本静默 replace 运行中的旧扩展。
- StatsClient 连接前打点 command.sock 路径与存在性,直接暴露「旧 sysext 没起 CommandServer」。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 10:50:23 +08:00
wangjia
77f31c90ec
fix(client/macos): 递增 PacketTunnel CFBundleVersion 23→43,让 sysextd 重装新 sysext
...
根因:PacketTunnel 的 CURRENT_PROJECT_VERSION 写死 23(其配置无 baseConfig、拿不到
FLUTTER_BUILD_NUMBER 自动递增)→ 每次构建出的 sysext 都是 v23 → sysextd 视为同版本拒绝
重装 → 跑的一直是老 v23 sysext(没有 LibboxCommandServer)→ App Group 容器无 command.sock
→ 主 app StatsClient 连不上(no such file)→ 实时流量/urltest 全失效(连接页 0 B/s + 延迟 1ms)。
bump 到 43(高于主 app 的 42)→ sysextd 重装带命令服务的新 sysext。
注:sysext 代码改动后须手动递增此值(CLAUDE.md 铁律)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 10:34:15 +08:00
wangjia
cf19ca2d34
feat(client/macos): 开机自启用 SMAppService + LoginItem helper(学 Tailscale)
...
根因:launch_at_startup 0.5.1 在 macOS 无自带实现,需宿主接 MethodChannel,而我们 Runner
从没实现 → enable() 抛 MissingPluginException 被 try/catch 吞掉 → 登录项从未注册,自启失败。
学 Tailscale(LoginItemHelper-macsys + SMAppService):
- 新增无界面 LoginItem helper(macos/login_helper,LSBackgroundOnly),登录时带 --autostart
拉起主 app(→隐藏到托盘);
- build_login_helper.sh 构建期编译+签名+嵌入 Contents/Library/LoginItems/(新 Run Script 阶段);
- MainFlutterWindow 接 launch_at_startup MethodChannel → SMAppService.loginItem 注册/注销。
构建通过:helper 嵌入+签名,主 app --deep --strict 校验过。Windows 自启(schtasks)不变。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 10:25:27 +08:00
wangjia
9e26dd6d97
chore: bump 1.0.41+42
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 09:00:00 +08:00
wangjia
8680131b3d
fix(client): 登出(主动/被强退/会话过期)一律断开隧道
...
bug:logout() 只清 token,不碰隧道 → 被强制下线/正常退出后 VPN 还连着、继续用数据面。
修:ConnectionController 监听 authProvider,isLoggedIn 由 true→false 时断开隧道(_disconnect)。
一处覆盖所有登出路径(设置页登出/会话轮询强退/token 续期失败登出);token 续期仍登录不触发。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 09:00:00 +08:00
wangjia
f0af3bcc94
fix(server): 强退设备立即离线 — online 须含活跃会话 + 撤销会话不刷 last_seen
...
trick bug:强退后被踢设备的下一次会话轮询会先刷 last_seen 再发现 active=false,那一刷
把它顶成「在线」直到 90s 窗口过期。修:① online = last_seen 新 且 有未撤销会话
(ActiveSessionDeviceIDs);被强退设备无活跃会话 → 立即离线。② SessionActive 仅在 active
时才 TouchLastSeen,撤销会话的轮询不再刷新。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 08:51:10 +08:00
wangjia
2fbaba7608
chore: bump 1.0.40+41
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 08:05:32 +08:00
wangjia
d192d96d95
fix(client): 设备页每 15s 静默刷新列表,其他设备状态变化 ~15s 内可见
...
原设备列表打开时加载一次就不动(感觉十几分钟才同步)。加透传式轮询包装器
_DevicesAutoRefresh:在设备页期间每 15s 调 DevicesNotifier.refresh()(静默、不闪 loading、
失败保留旧列表)。配合服务端会话轮询刷 last_seen + 90s 窗口,其他设备上/下线 ~15s 内反映。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 08:05:32 +08:00
wangjia
3167ca8a74
fix(server): 设备「在线」准确反映 app 运行中 — 会话轮询刷 last_seen + 窗口缩到 90s
...
原 online=last_seen 在 3min 内,而 last_seen 只在连接/用量上报时刷 → app 运行≠刷新,
显示成'最近连过'而非'正在运行';关 app 后还'在线'到窗口过期。修:SessionActive(每 15s
轮询)顺便 TouchLastSeen → 运行中的 app 持续刷新;onlineWindow 3min→90s,关 app ~90s 转离线。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 07:55:17 +08:00
wangjia
ca34d0cadb
chore: bump 1.0.39+40
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 07:33:43 +08:00
wangjia
6bab18a1bf
feat(client): 被强制下线时弹对话框告知原因再登出
...
会话轮询检测到 active=false → 先弹「此设备已被强制下线/需重新登录」对话框(沿用现有
AlertDialog 样式:surface 底/xl 圆角/accent 按钮),用户确认后再 logout 跳登录页,
不再默默跳走。_forcedLogoutHandling 防重复弹。新增 l10n sessionRevoked{Title,Body,Ok}。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 07:33:43 +08:00
wangjia
af24612e04
chore: bump 1.0.38+39
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 07:26:31 +08:00
wangjia
0b33f12400
feat: 近实时远程下线 — 客户端轮询会话有效性(~15s),服务端 GET /v1/me/session
...
控制面无推送通道,access token 是无状态 JWT(15min),强制退出后被踢设备要等 token 过期
(≤15min)才登出。改成客户端每 15s 轮询会话是否仍有效,被强制退出即登出 → 延迟压到 ~15s。
- 服务端:sessions.HasActiveSession(user,device) + devices.SessionActive(按 UUID,fail-open)
+ GET /v1/me/session?device_id= 返回 {active}(恒 200,判据在 body)。无新迁移。
- 客户端:account_api.sessionActive + main.dart _RootFlowState 15s 轮询,active=false 即 logout
(网络/鉴权异常不据此登出,fail-safe)。
- 测试:TestSQLite_SessionHasActiveSession(建会话=活跃→RevokeByDevice→非活跃)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 07:25:16 +08:00
wangjia
7f070a0693
fix(client): 看门狗 path A 仅在「连上(on)后掉线」触发,排除 connecting 握手瞬态
...
macOS NE 连接序列是 off→connecting→off→connecting→on,connecting 期有瞬态 off。原 path A
条件 wasActive 含 connecting → 一连接就在握手瞬态 off 上误报「节点异常」(实际连上了)。
改:仅 phase==on(真正连上过)再非用户主动掉线才判节点异常;connecting→off(握手抖动/
连接失败)不触发。跨端修复(桌面也更稳)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 07:01:13 +08:00
wangjia
48bc5c6b39
chore: bump 1.0.37+38
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 01:32:15 +08:00
wangjia
b99d6d71ae
fix(client): 修 _disposed 潜伏 bug + build 只 watch isLoggedIn,根治延迟冻成 —
...
根因:1.0.36 的 401 自愈触发 auth token 续期 → authProvider 状态变 → nodesProvider.build()
重跑 → Riverpod 先调上一轮 ref.onDispose(()=>_disposed=true),新 build 没复位 → _disposed
永久 true → setLivePing/_measure 开头的 if(_disposed)return 让 urltest 回写/延迟实测全部静默
→ 延迟冻在 —。修:① build 开头 _disposed=false 复位;② build 改 watch authProvider.select
((s)=>s.isLoggedIn),token 续期(accessToken 变但仍登录)不再重建 nodesProvider、不清延迟。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 01:32:15 +08:00
wangjia
15133b8a72
feat(client/macos): 开机自启隐藏到托盘(--autostart),与 Windows 对齐
...
macOS 登录项(launch_at_startup)注册时带 args:['--autostart'];main() 读该参数
windowManager.hide();MainFlutterWindow.awakeFromNib 检测到 --autostart 时 orderOut
兜底(避免 storyboard Visible At Launch 闪窗)。常规启动无参数,正常显示窗口。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 01:27:30 +08:00
wangjia
ba65b03fd5
chore: bump 1.0.36+37
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 01:23:13 +08:00
wangjia
a03de6c06a
fix(client): 节点拉取 401 自愈+失败不清空列表;看门狗 path A 跨端(urltest 陈旧判活)
...
bug:周期刷新拿到 401(token 过期)时 _fetchNodes return const [] → 把节点列表清空,
用户「看不到节点」误以为 server 挂。修:① 非 200 抛异常,refresh 失败保留旧列表(绝不清空);
② 401 用 refresh token 续期重试一次自愈,续期失败才登出。
看门狗 path A 全平台统一:不再只靠原生报 off/error(libbox/NE 行为不一),改用内核 urltest
陈旧度(经 proxy 探测,四端都有 stats)——urltest 超 45s 未成功即判上游死 → _onNodeUnhealthy。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 01:23:13 +08:00
wangjia
93a31a9415
chore: bump 1.0.35+36
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 00:50:58 +08:00
wangjia
795082066e
fix(client): 刷新节点列表时保留已有 ping,修延迟被 refresh 清成 — 的根因
...
日志实证:urltest 回写正常(best=561ms→setLivePing),但看门狗/节点页每15s refresh()
重拉服务端列表、解析时 ping=0(占位),state=result 把刚写进去的延迟清零 → 显示 —,
下一帧 setLivePing 又写回 → 来回闪。修:refresh 用 _mergePings 按 uuid 保留已有 ping
(ping 是客户端实测,服务端列表不带)。去掉诊断日志。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-30 00:50:58 +08:00
wangjia
53eb982254
chore: bump 1.0.34+35
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:50:48 +08:00
wangjia
a06bfda45c
diag(client): _onStats 加 urltest 诊断日志,定位延迟显示 — 根因
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:50:48 +08:00
wangjia
e292775c7e
chore: bump 1.0.33+34
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:35:40 +08:00
wangjia
16af1c9f02
fix(client): 连接态把内核 urltest 回写连接节点 ping,修延迟显示 — + 保持同源一致
...
1.0.32 纯 direct node.ping 的代价:auto-connect 太快连上、没有断开窗口让 direct TCP 量到
延迟 → node.ping 一直 0 → 显示 —。修:ConnectionController 订阅 stats,连接态把内核 urltest
最小正延迟回写连接节点的 node.ping(setLivePing)。连接页与节点列表都读 node.ping → 同一个数;
连接节点有实时 urltest 值、其余节点保留 direct 实测。断开态仍 direct TCP。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:35:40 +08:00
wangjia
0736014552
fix(client): 延迟统一用 node.ping(client→数据面 RTT),连接页与节点列表同源一致
...
撤掉连接页连接态的内核 urltest —— 它与节点列表的 node.ping 是两套口径、两处显示不一致。
统一全部用 node.ping(直接 TCP 握手 节点:443),连接页显示生效节点的 ping、节点列表显示
各节点 ping,永远同一个数。连接态 TUN 测不到新值则保留上次实测(_measure 已改保留)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:28:39 +08:00
wangjia
7c7e8e4f6c
chore: bump 1.0.32+33
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:26:19 +08:00
wangjia
d08b908e1f
fix(client): 节点列表延迟探测失败时保留旧值,修连接后整列延迟消失
...
返工引入的回归:看门狗连接态周期 refresh→_measure 重测所有节点 TCP ping,但连接态
全局 TUN 把到节点的握手接住→probeAll 返回 0→pings[uuid]??n.ping 因 0 非 null 覆盖成空。
改:探测返回 0 时保留旧 ping。连接态保留上次延迟,断开态正常刷新。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:26:19 +08:00
wangjia
e9dbe9aa7d
chore: bump 1.0.31+32
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:21:18 +08:00
wangjia
d9378b6729
fix(client): 看门狗返工 — 意外掉线捕获+服务端down轮询,撤销TUN下假阳性的TCP探测
...
测试暴露:全局TUN下App的socket到节点IP被本地TUN当场接住(假1ms),客户端TCP探数据口
不可行;且节点死时内核先掉线、提示被kernel off覆盖、节点页status不刷新显示绿色。返工:
- 撤销 DataPlaneProber/livePingMs;延迟改回内核urltest(sing-box经REALITY真实直连数据面
探出的RTT,唯一可靠口径),连接态urltest=0→显示—不回退旧ping。
- 看门狗两条可靠路径:A 捕获「非用户主动的内核掉线」→置「节点异常」+刷列表;
B 连接态周期刷/v1/nodes,所连节点被判down→智能切/手动断。
- _offNotice 让显式断开与kernel off读同一提示字段,不再互相覆盖(修「断开但没报错」)。
- 节点页周期15s刷新,让服务端down状态浮现(tile已按isDown置灰)。
返工测试:意外掉线提示/服务端down切/断/健康保持,全过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 23:21:09 +08:00
wangjia
cd143af248
chore: bump 1.0.30+31
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 21:28:08 +08:00
wangjia
554708a092
fix(client): 看门狗+延迟统一到数据面 IP TCP 探测 + 消费服务端 down 信号
...
修复:数据面挂了客户端无感。原看门狗探 generate_204,会被分流判 direct 走本地
出网假阳性,永不触发。改为三路融合判活,针对「实际所连节点」(_connectedNode,
非会随 ping 漂移的 effectiveNode):
① 客户端→数据口 TCP 握手(节点 host:443,TUN 内必 direct→直奔真实节点,不被分流糊弄);
② 延迟同源:①的 RTT 回填连接页延迟(ConnectionState.livePingMs),挂了掉成 —;
③ 服务端权威:刷 /v1/nodes,所连节点被判 down(dp_healthy=0/agent掉线/运维下线)即处理。
看门狗即时首测 + 周期 15s;连续 3 次握不上 / 服务端 down → 智能切节点 / 手动告警断开。
连接页延迟改读 livePingMs(删除内核 urltest 取数)。补信号③测试。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 21:27:49 +08:00
wangjia
23bf3077c8
docs(kb): 流量记账口径知识库 — 连接页实时(含直连) vs 统计页累计(仅代理)
...
记录两处上下行数字口径差异:连接页来自内核 Clash API 全局吞吐含直连,
统计页来自节点 v2ray_api per-user 计数仅代理;差额=直连,设计使然。
含对账口径警示。登记进 docs/index.html 知识库分类。决策:保持现状不改连接页口径。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 21:04:50 +08:00
wangjia
2b20a611d7
docs(test): 记录本轮交互组件人工验证(确认框/搜索框/toast);toast 超长文本待测
...
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 20:33:48 +08:00
wangjia
701d9eb095
fix(client): 开机自启隐藏窗口在原生 runner 层跳过首帧 Show()(1.0.29)
...
1.0.28 的 Dart hide() 早于 Flutter Windows runner 首帧回调的 Show(),被覆盖,
窗口仍弹出。改在 flutter_window.cpp 检测命令行 --autostart 时不注册首帧 Show()
回调,窗口(WS_OVERLAPPEDWINDOW 无 WS_VISIBLE)保持隐藏;Dart hide() 保留以同步
window_manager 状态。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 20:20:55 +08:00
wangjia
49bef2fb27
feat(client): 开机自启拉起直接最小化到托盘(--autostart 标志)(1.0.28)
...
计划任务 /tr 命令带 --autostart;main() 检测到该参数在首帧前 windowManager.hide()
隐藏主窗口到托盘,自动连接逻辑照常跑。手动打开(无参数)仍正常显示窗口。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 20:11:36 +08:00
wangjia
ada99e6c3a
fix(client): 自动连接死锁兜底(轮询)+ 逐次门控日志(1.0.27)
...
复现:armed→设置已加载后无 ready。死锁:selLoaded 靠 selectedNode controller 的 loaded 标志,
而该标志完成时若选中值未变(==默认)不会发通知,若 nodeSub 已先于它触发则此后无人再调 tryGo。
修:_maybeAutoConnect 加 Timer.periodic(400ms,≤12s)兜底复查,decided 后停;并恢复每次 tryGo
打 check 日志(settingsLoaded/selLoaded/node uuid)以确认卡点。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 19:58:53 +08:00
wangjia
277d1c6e97
feat(client): toast 限定主显示区/自适应宽/上限80%/超长多行居中(1.0.26)
...
按真相源新规:toast 改为自定义 Overlay 实现(widgets/pangolin_toast.dart),完全控制布局——
不覆盖左侧栏(left=侧栏宽 desktop204/tablet232/mobile0)、宽度自适应内容上限主区80%、超长文本
多行、主区内水平居中贴底、淡入轻起;仍走语义 token 明暗适配。自动连接改用 showPangolinToast。
同步 design/CONTRACT.md §2 toast 规格(canonical=showPangolinToast)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 19:50:33 +08:00
wangjia
143104b861
docs(design): toast 规格入真相源 + 铁律14「UI 组件必须取自真相源」
...
- design/CLAUDE.md §1 加铁律 14:新增/改 UI 组件必须用真相源已定义的组件与令牌;
真相源没有的先补规格再用,绝不在业务代码凭空造样式(如 Material 默认外观);须符合当前设计。
- design/CONTRACT.md §2 加 Toast/SnackBar 组件规格(surface 底/fg1 字/border 描边/md 圆角/floating,
明暗自动适配),canonical 实现=pangolin_theme snackBarTheme。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 19:43:54 +08:00
wangjia
828bb4ca94
style(client): toast 跟随明暗主题(1.0.25)
...
真相源/主题里原无 toast 定义,SnackBar 用 Material 默认黑底,明亮主题下突兀。
PangolinTheme 加 snackBarTheme:surface 底 + fg1 字 + 描边圆角(与卡片同风格)、floating,
浅色得浅 toast、深色得深 toast。自动连接的 toast 随之适配。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 19:39:00 +08:00