chore(client): 1.0.19 — 自动连接诊断日志

排查「自动连接没生效」:在 _RootFlow 自动连接路径(HomeShell 显示 / 节点就绪 / autoConnect/phase 判定 / 触发)
与 Settings(_load 读到的 autoConnect、setAutoConnect 落盘)加 logLine 日志,定位卡在哪一步。诊断完移除。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-29 18:26:47 +08:00
parent 6beed211b9
commit f734126eb6
4 changed files with 22 additions and 5 deletions
+17 -3
View File
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:window_manager/window_manager.dart';
import 'bridge/log.dart';
import 'bridge/vpn_bridge_provider.dart';
import 'pangolin_theme.dart';
import 'services/token_store.dart';
@@ -117,22 +118,31 @@ class _RootFlowState extends ConsumerState<RootFlow> {
final _store = const TokenStore();
bool _forceOnboarding = false;
bool _autoConnectArmed = false; // 自动连接每进程只尝试一次
bool _homeLogged = false; // 仅日志:HomeShell 首次显示打一行
// 进入登录态主界面后:若开了「自动连接」且当前未连接,等节点就绪后自动连一次。
void _maybeAutoConnect() {
if (_autoConnectArmed) return;
_autoConnectArmed = true;
logLine('AutoConnect', 'armed; waiting for nodes ready');
// 注意:不在此处早读 settingsProvider.autoConnect —— 其 _load 是异步(SharedPreferences),
// 启动这一刻多半还没加载完,会读到默认 false 而永久跳过。改到「节点就绪」回调里再判:
// 节点要走网络拉取,远慢于本地设置读取,那时 autoConnect 必已加载到位。
late final ProviderSubscription sub;
sub = ref.listenManual(nodesProvider, (prev, next) {
final ready = (next.valueOrNull ?? const []).any((n) => n.uuid.isNotEmpty);
final nodes = next.valueOrNull ?? const [];
final ready = nodes.any((n) => n.uuid.isNotEmpty);
logLine('AutoConnect', 'nodes update: total=${nodes.length} ready=$ready loading=${next.isLoading} err=${next.hasError}');
if (!ready) return;
sub.close();
if (ref.read(settingsProvider).autoConnect &&
ref.read(connectionProvider).phase == VpnPhase.off) {
final ac = ref.read(settingsProvider).autoConnect;
final phase = ref.read(connectionProvider).phase;
logLine('AutoConnect', 'nodes ready → autoConnect=$ac phase=$phase');
if (ac && phase == VpnPhase.off) {
logLine('AutoConnect', 'triggering connect');
ref.read(connectionProvider.notifier).toggle();
} else {
logLine('AutoConnect', 'NOT connecting (autoConnect=$ac phase=$phase)');
}
}, fireImmediately: true);
}
@@ -162,6 +172,10 @@ class _RootFlowState extends ConsumerState<RootFlow> {
if (_forceOnboarding) {
return OnboardingScreen(t: t, onDone: () { _afterOnboarding(); });
}
if (!_homeLogged) {
_homeLogged = true;
logLine('AutoConnect', 'HomeShell shown; scheduling auto-connect check');
}
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) _maybeAutoConnect();
});
+3
View File
@@ -11,6 +11,7 @@ import 'package:launch_at_startup/launch_at_startup.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../bridge/log.dart';
import '../bridge/vpn_bridge_provider.dart';
class AppSettings {
@@ -59,6 +60,7 @@ class SettingsController extends StateNotifier<AppSettings> {
smartRoute: p.getBool(_kSmartRoute) ?? true,
killSwitch: p.getBool(_kKillSwitch) ?? true,
);
logLine('Settings', 'loaded autoConnect=${state.autoConnect} autostart=${state.autostart}');
} catch (_) {
// 测试/无平台:保留默认值。
}
@@ -76,6 +78,7 @@ class SettingsController extends StateNotifier<AppSettings> {
Future<void> setAutoConnect(bool v) async {
state = state.copyWith(autoConnect: v);
await _persist(_kAutoConnect, v);
logLine('Settings', 'setAutoConnect=$v persisted');
}
Future<void> setSmartRoute(bool v) async {
+1 -1
View File
@@ -1,7 +1,7 @@
name: pangolin_vpn
description: 穿山甲 · Pangolin — 极简、稳定、跨平台网络加速客户端。
publish_to: "none"
version: 1.0.18+19
version: 1.0.19+20
environment:
sdk: ^3.5.0
+1 -1
View File
@@ -3,7 +3,7 @@
; 前置: 先在 client/ 跑 `flutter build windows`(Release),产物在
; ..\..\build\windows\x64\runner\Release
#define MyAppName "穿山甲 Pangolin"
#define MyAppVersion "1.0.18"
#define MyAppVersion "1.0.19"
#define MyAppPublisher "Pangolin"
#define MyAppExeName "pangolin_vpn.exe"
#define BuildDir "..\..\build\windows\x64\runner\Release"