diff --git a/client/lib/state/connection_provider.dart b/client/lib/state/connection_provider.dart index a122933..688b631 100644 --- a/client/lib/state/connection_provider.dart +++ b/client/lib/state/connection_provider.dart @@ -81,6 +81,7 @@ class ConnectionController extends StateNotifier { _statusSub = _bridge.statusStream.listen(_onKernelStatus); // 订阅内核 stats:连接态把 urltest 实测回写连接节点的 ping,让连接页与节点列表同源一致。 _statsSub = _bridge.statsStream.listen(_onStats); + logLine('Stats', 'ConnectionController constructed, statsStream subscribed'); // 登出(主动退出 / 被强制下线 / 会话过期)→ 一律断开隧道:别让已登出/被踢的设备继续用 // 数据面。一处监听 auth 覆盖所有登出路径。token 续期(仍登录)不触发。 _authSub = _ref.listen(authProvider, (prev, next) { @@ -244,13 +245,16 @@ class ConnectionController extends StateNotifier { // 连接态:取内核 urltest 最小正延迟,回写连接节点 ping。全局 TUN 下 App 直接探测节点不可行, // 内核(经 REALITY 真实直连数据面)是唯一能实测的;回写到 node.ping → 连接页/节点列表同源。 void _onStats(VpnStatsEvent e) { + // 无条件打点:确认 _onStats 是否被调用、当前 phase、urltest 是否到达 Dart 侧。 + logLine('Stats', + 'onStats phase=${state.phase.name} ' + 'urltest=[${e.urltestResults.map((r) => "${r.tag}:${r.delayMs}").join(",")}]'); if (state.phase != VpnPhase.on) return; // 自动连接/重连到已在跑的隧道时不会走 _connect → _connectedNode 为 null;回退到 // effectiveNode(当前/智能所选),否则 urltest 实测无处回写、连接页延迟一直显示 —。 final Node node = _connectedNode ?? _ref.read(effectiveNodeProvider); final ds = e.urltestResults.where((r) => r.delayMs > 0).map((r) => r.delayMs).toList(); logLine('Stats', - 'urltest=[${e.urltestResults.map((r) => "${r.tag}:${r.delayMs}").join(",")}] ' 'conn=${_connectedNode == null ? "null" : _connectedNode!.code} ' 'eff=${node.code}/${node.uuid.isEmpty ? "EMPTY" : "ok"} ds=$ds'); if (node.uuid.isEmpty) return;