fix(client): 自动连接竞态真因 — 等设置加载完再判(1.0.22)
日志实证:节点就绪(~450ms)与设置加载几乎同时完成,节点回调早 1ms 读到还没加载完的 autoConnect=false → 不连。AppSettings 加 loaded 标志(_load 完成置 true,失败也置); _maybeAutoConnect 同时监听 nodes + settings,二者都就绪(settings.loaded && 节点 uuid 非空) 才决策一次。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,17 +20,21 @@ class AppSettings {
|
||||
this.autoConnect = false,
|
||||
this.smartRoute = true,
|
||||
this.killSwitch = true,
|
||||
this.loaded = false,
|
||||
});
|
||||
final bool autostart;
|
||||
final bool autoConnect; // 启动 app 时自动连接(opt-in,默认关)
|
||||
final bool smartRoute;
|
||||
final bool killSwitch;
|
||||
final bool loaded; // 是否已从持久化加载完(自动连接要等它 true 再读 autoConnect,避免竞态)
|
||||
|
||||
AppSettings copyWith({bool? autostart, bool? autoConnect, bool? smartRoute, bool? killSwitch}) => AppSettings(
|
||||
AppSettings copyWith({bool? autostart, bool? autoConnect, bool? smartRoute, bool? killSwitch, bool? loaded}) =>
|
||||
AppSettings(
|
||||
autostart: autostart ?? this.autostart,
|
||||
autoConnect: autoConnect ?? this.autoConnect,
|
||||
smartRoute: smartRoute ?? this.smartRoute,
|
||||
killSwitch: killSwitch ?? this.killSwitch,
|
||||
loaded: loaded ?? this.loaded,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,22 +55,25 @@ class SettingsController extends StateNotifier<AppSettings> {
|
||||
final bool _desktop = Platform.isMacOS || Platform.isWindows || Platform.isLinux;
|
||||
|
||||
Future<void> _load() async {
|
||||
var s = const AppSettings(loaded: true); // 失败也标 loaded:true,自动连接才不会永久等
|
||||
try {
|
||||
final p = await SharedPreferences.getInstance();
|
||||
if (!mounted) return; // 异步初始化期间已 dispose:别再写 state。
|
||||
state = AppSettings(
|
||||
s = AppSettings(
|
||||
autostart: p.getBool(_kAutostart) ?? true,
|
||||
autoConnect: p.getBool(_kAutoConnect) ?? false,
|
||||
smartRoute: p.getBool(_kSmartRoute) ?? true,
|
||||
killSwitch: p.getBool(_kKillSwitch) ?? true,
|
||||
loaded: true,
|
||||
);
|
||||
logLine('Settings', 'loaded autoConnect=${state.autoConnect} autostart=${state.autostart}');
|
||||
} catch (_) {
|
||||
// 测试/无平台:保留默认值。
|
||||
// 测试/无平台:用默认值(已标 loaded)。
|
||||
}
|
||||
if (!mounted) return;
|
||||
_applyKillSwitch(state.killSwitch);
|
||||
if (_desktop) await _applyAutostart(state.autostart);
|
||||
state = s;
|
||||
logLine('Settings', 'loaded autoConnect=${s.autoConnect} autostart=${s.autostart}');
|
||||
_applyKillSwitch(s.killSwitch);
|
||||
if (_desktop) await _applyAutostart(s.autostart);
|
||||
}
|
||||
|
||||
Future<void> setAutostart(bool v) async {
|
||||
|
||||
Reference in New Issue
Block a user