diff --git a/lib/data/model/server/server.dart b/lib/data/model/server/server.dart index e792b9bf..b2437a88 100644 --- a/lib/data/model/server/server.dart +++ b/lib/data/model/server/server.dart @@ -22,6 +22,12 @@ class Server implements TagPickable { @override String get tagName => spi.id; + + bool get needGenClient => state < ServerState.connecting; + + bool get canViewDetails => state == ServerState.finished; + + String get id => spi.id; } enum ServerState { @@ -38,9 +44,5 @@ enum ServerState { /// Status parsing finished finished; - bool get shouldConnect => this < ServerState.connecting; - - bool get canViewDetails => this == ServerState.finished; - operator <(ServerState other) => index < other.index; } diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 44c11cf1..315c1e7e 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -118,35 +118,25 @@ class ServerProvider extends ChangeNotifier { return; } - Future connectFn(Server s) async { - if (onlyFailed) { - if (s.state != ServerState.failed) return; - _limiter.reset(s.spi.id); - } + await Future.wait(_servers.values.map((s) => _connectFn(s, onlyFailed))); + } - /// If [spi.autoConnect] is false and server is disconnected, then skip. - /// - /// If [spi.autoConnect] is false and server is connected, then refresh. - /// If no this, the server will only refresh once by clicking refresh button. - /// - /// If [spi.autoConnect] is true, then refresh. - if (!(s.spi.autoConnect ?? true) && s.state == ServerState.disconnected) { - return; - } - return await _getData(s.spi); + Future _connectFn(Server s, bool onlyFailed) async { + if (onlyFailed) { + if (s.state != ServerState.failed) return; + _limiter.reset(s.spi.id); } - final directServers = []; - final proxyServers = []; - for (final s in _servers.values) { - if (s.spi.jumpId == null) { - directServers.add(s); - } else { - proxyServers.add(s); - } + /// If [spi.autoConnect] is false and server is disconnected, then skip. + /// + /// If [spi.autoConnect] is false and server is connected, then refresh. + /// If no this, the server will only refresh once by clicking refresh button. + /// + /// If [spi.autoConnect] is true, then refresh. + if (!(s.spi.autoConnect ?? true) && s.state == ServerState.disconnected) { + return; } - await Future.wait(directServers.map(connectFn)); - await Future.wait(proxyServers.map(connectFn)); + return await _getData(s.spi); } Future startAutoRefresh() async { @@ -236,6 +226,8 @@ class ServerProvider extends ChangeNotifier { // Only reconnect if neccessary if (newSpi.shouldReconnect(old)) { + // Use [newSpi.id] instead of [old.id] because [old.id] may be changed + _limiter.reset(newSpi.id); refreshData(spi: newSpi); } @@ -271,21 +263,31 @@ class ServerProvider extends ChangeNotifier { return; } + s.status.failedInfo = null; + /// If busy, it may be because of network reasons that the last request /// has not been completed, and the request should not be made again at this time. if (s.isBusy) return; s.isBusy = true; - if (s.state.shouldConnect || (s.client?.isClosed ?? true)) { + if (s.needGenClient || (s.client?.isClosed ?? true)) { _setServerState(s, ServerState.connecting); - final time1 = DateTime.now(); - try { + final time1 = DateTime.now(); s.client = await genClient( spi, timeout: Stores.setting.timeoutD, ); + final time2 = DateTime.now(); + final spentTime = time2.difference(time1).inMilliseconds; + if (spi.jumpId == null) { + Loggers.app.info('Connected to ${spi.name} in $spentTime ms.'); + } else { + Loggers.app.info( + 'Connected to ${spi.name} via jump server in $spentTime ms.', + ); + } } catch (e) { _limiter.inc(sid); s.status.failedInfo = e.toString(); @@ -296,15 +298,6 @@ class ServerProvider extends ChangeNotifier { return; } - final time2 = DateTime.now(); - final spentTime = time2.difference(time1).inMilliseconds; - if (spi.jumpId == null) { - Loggers.app.info('Connected to ${spi.name} in $spentTime ms.'); - } else { - Loggers.app - .info('Connected to ${spi.name} via jump server in $spentTime ms.'); - } - _setServerState(s, ServerState.connected); // Write script to server diff --git a/lib/main.dart b/lib/main.dart index c12a7704..3d7bb1a3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -113,6 +113,7 @@ void _setupLogger() { Logger.root.onRecord.listen((record) { Pros.debug.addLog(record); print(record); + if (record.error != null) print(record.error); if (record.stackTrace != null) print(record.stackTrace); }); } diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index ee74a7c6..91079bfe 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -173,37 +173,37 @@ class _ServerPageState extends State ); } - Widget _buildEachServerCard(Server? si) { - if (si == null) { + Widget _buildEachServerCard(Server? srv) { + if (srv == null) { return UIs.placeholder; } return CardX( - key: Key(si.spi.id + (_tag ?? '')), + key: Key(srv.spi.id + (_tag ?? '')), InkWell( onTap: () { - if (si.state.canViewDetails) { - AppRoute.serverDetail(spi: si.spi).go(context); - } else if (si.status.failedInfo != null) { - _showFailReason(si.status); + if (srv.canViewDetails) { + AppRoute.serverDetail(spi: srv.spi).go(context); + } else if (srv.status.failedInfo != null) { + _showFailReason(srv.status); } }, onLongPress: () { - if (si.state == ServerState.finished) { + if (srv.state == ServerState.finished) { setState(() { - if (_flipedCardIds.contains(si.spi.id)) { - _flipedCardIds.remove(si.spi.id); + if (_flipedCardIds.contains(srv.spi.id)) { + _flipedCardIds.remove(srv.spi.id); } else { - _flipedCardIds.add(si.spi.id); + _flipedCardIds.add(srv.spi.id); } }); } else { - AppRoute.serverEdit(spi: si.spi).go(context); + AppRoute.serverEdit(spi: srv.spi).go(context); } }, child: Padding( padding: const EdgeInsets.all(13), - child: _buildRealServerCard(si), + child: _buildRealServerCard(srv), ), ), ); @@ -465,8 +465,12 @@ class _ServerPageState extends State ); } - Widget _buildIOData(String up, String down, - {void Function()? onTap, Key? key}) { + Widget _buildIOData( + String up, + String down, { + void Function()? onTap, + Key? key, + }) { final child = Column( children: [ const SizedBox(height: 5),