From 71243ea1fe5d06f72d898a0e153d28ad0a50535a Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Sun, 23 Apr 2023 14:08:46 +0800 Subject: [PATCH] opt.: servers list -> map --- .../server/server_status_update_req.dart | 2 +- lib/data/model/server/try_limiter.dart | 2 +- lib/data/provider/server.dart | 127 +++++++++--------- lib/view/page/docker.dart | 2 +- lib/view/page/home.dart | 2 +- lib/view/page/ping.dart | 2 +- lib/view/page/pkg.dart | 4 +- lib/view/page/server/detail.dart | 12 +- lib/view/page/server/tab.dart | 10 +- lib/view/page/sftp/view.dart | 2 +- 10 files changed, 85 insertions(+), 80 deletions(-) diff --git a/lib/data/model/server/server_status_update_req.dart b/lib/data/model/server/server_status_update_req.dart index 28676eb2..7b0d9fdb 100644 --- a/lib/data/model/server/server_status_update_req.dart +++ b/lib/data/model/server/server_status_update_req.dart @@ -55,4 +55,4 @@ String? _parseSysVer(String raw) { return s[1].replaceAll('"', '').replaceFirst('\n', ''); } return null; -} \ No newline at end of file +} diff --git a/lib/data/model/server/try_limiter.dart b/lib/data/model/server/try_limiter.dart index f588af0d..d6931dcd 100644 --- a/lib/data/model/server/try_limiter.dart +++ b/lib/data/model/server/try_limiter.dart @@ -24,4 +24,4 @@ class TryLimiter { void clear() { _triedTimes.clear(); } -} \ No newline at end of file +} diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index ccf83d31..be2f6514 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; -import 'package:toolbox/core/build_mode.dart'; +import '../../core/build_mode.dart'; import '../../core/extension/uint8list.dart'; import '../../core/provider_base.dart'; import '../../core/utils/server.dart'; @@ -18,9 +18,11 @@ import '../res/status.dart'; import '../store/server.dart'; import '../store/setting.dart'; +typedef ServersMap = Map; + class ServerProvider extends BusyProvider { - List _servers = []; - List get servers => _servers; + final ServersMap _servers = {}; + ServersMap get servers => _servers; final _limiter = TryLimiter(); Timer? _timer; @@ -30,7 +32,9 @@ class ServerProvider extends BusyProvider { Future loadLocalData() async { setBusyState(true); final infos = locator().fetch(); - _servers = List.generate(infos.length, (index) => genServer(infos[index])); + for (final info in infos) { + _servers[info.id] = genServer(info); + } setBusyState(false); notifyListeners(); } @@ -45,13 +49,14 @@ class ServerProvider extends BusyProvider { await _getData(spi); return; } - await Future.wait(_servers.map((s) async { + final futures = _servers.values.map((s) async { if (onlyFailed) { if (s.state != ServerState.failed) return; _limiter.resetTryTimes(s.spi.id); } - await _getData(s.spi); - })); + return await _getData(s.spi); + }); + await Future.wait(futures); } Future startAutoRefresh() async { @@ -71,102 +76,91 @@ class ServerProvider extends BusyProvider { } } + bool get isAutoRefreshOn => _timer != null; + void setDisconnected() { - for (var i = 0; i < _servers.length; i++) { - _servers[i].state = ServerState.disconnected; + for (final s in _servers.values) { + s.state = ServerState.disconnected; } _limiter.clear(); notifyListeners(); } - void closeServer({ServerPrivateInfo? spi}) { - if (spi == null) { - for (var i = 0; i < _servers.length; i++) { - _servers[i].client?.close(); - _servers[i].client = null; + void closeServer({String? id}) { + if (id == null) { + for (final s in _servers.values) { + _closeOneServer(s.spi.id); } return; } - final idx = getServerIdx(spi.id); - _servers[idx].client?.close(); - _servers[idx].client = null; + _closeOneServer(id); + } + + void _closeOneServer(String id) { + _servers[id]?.client?.close(); + _servers[id]?.client = null; } void addServer(ServerPrivateInfo spi) { - _servers.add(genServer(spi)); + _servers[spi.id] = genServer(spi); notifyListeners(); locator().put(spi); refreshData(spi: spi); } void delServer(String id) { - final idx = getServerIdx(id); - _servers[idx].client?.close(); - _servers.removeAt(idx); + _servers.remove(id); notifyListeners(); locator().delete(id); } Future updateServer( ServerPrivateInfo old, ServerPrivateInfo newSpi) async { - final idx = _servers.indexWhere((e) => e.spi.id == old.id); - if (idx < 0) { - throw RangeError.index(idx, _servers); - } - _servers[idx].spi = newSpi; + _servers.remove(old.id); locator().update(old, newSpi); - _servers[idx].client = await genClient(newSpi); + _servers[newSpi.id] = genServer(newSpi); + _servers[newSpi.id]?.client = await genClient(newSpi); notifyListeners(); refreshData(spi: newSpi); } - int getServerIdx(String id) { - final idx = _servers.indexWhere((s) => s.spi.id == id); - if (idx < 0) { - throw Exception('Server not found: $id'); - } - return idx; - } - - Server getServer(String id) => _servers[getServerIdx(id)]; - Future _getData(ServerPrivateInfo spi) async { final sid = spi.id; - final s = getServer(sid); - final state = s.state; - if (!state.shouldConnect) { - return; - } - if (!_limiter.shouldTry(sid)) { - s.state = ServerState.failed; - notifyListeners(); - return; - } - s.state = ServerState.connecting; - notifyListeners(); + final s = _servers[sid]; + if (s == null) return; try { - // try to connect - final time1 = DateTime.now(); - s.client = await genClient(spi); - final time2 = DateTime.now(); - final spentTime = time2.difference(time1).inMilliseconds; - _logger.info('Connected to [$sid] in $spentTime ms.'); + final state = s.state; + if (state.shouldConnect) { + if (!_limiter.shouldTry(sid)) { + s.state = ServerState.failed; + notifyListeners(); + return; + } + s.state = ServerState.connecting; + notifyListeners(); - // after connected - s.state = ServerState.connected; - notifyListeners(); + // try to connect + final time1 = DateTime.now(); + s.client = await genClient(spi); + final time2 = DateTime.now(); + final spentTime = time2.difference(time1).inMilliseconds; + _logger.info('Connected to [$sid] in $spentTime ms.'); - // write script to server - final writeResult = await s.client!.run(installShellCmd).string; + // after connected + s.state = ServerState.connected; + notifyListeners(); + // write script to server + final writeResult = await s.client!.run(installShellCmd).string; - // if write failed - if (writeResult.isNotEmpty) { - throw Exception(writeResult); + // if write failed + if (writeResult.isNotEmpty) { + throw Exception(writeResult); + } + // reset try times if connected successfully + _limiter.resetTryTimes(sid); } - // reset try times if connected successfully - _limiter.resetTryTimes(sid); if (s.client == null) return; // run script to get server status final raw = await s.client!.run("sh $shellPath").string; @@ -181,6 +175,7 @@ class ServerProvider extends BusyProvider { // remove first empty segment // for `export xxx` in shell script segments.removeAt(0); + final req = ServerStatusUpdateReq(s.status, segments); s.status = await compute(getStatus, req); } catch (e) { @@ -196,7 +191,7 @@ class ServerProvider extends BusyProvider { } Future runSnippet(String id, Snippet snippet) async { - final client = getServer(id).client; + final client = _servers[id]?.client; if (client == null) { return null; } diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index 06023cb6..093be7f5 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -48,7 +48,7 @@ class _DockerManagePageState extends State { @override void initState() { super.initState(); - final client = locator().getServer(widget.spi.id).client; + final client = locator().servers[widget.spi.id]?.client; if (client == null) { showSnackBar(context, Text(_s.noClient)); context.pop(); diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index 4728bea1..99bfa935 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -84,7 +84,7 @@ class _MyHomePageState extends State switch (state) { case AppLifecycleState.resumed: - if (isIOS) { + if (!_serverProvider.isAutoRefreshOn) { _serverProvider.startAutoRefresh(); } break; diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index 29fac5a8..20fd167d 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -156,7 +156,7 @@ class _PingPageState extends State } try { - await Future.wait(_serverProvider.servers.map((e) async { + await Future.wait(_serverProvider.servers.values.map((e) async { if (e.client == null) { return; } diff --git a/lib/view/page/pkg.dart b/lib/view/page/pkg.dart index 8cc69ea6..9da8c9bb 100644 --- a/lib/view/page/pkg.dart +++ b/lib/view/page/pkg.dart @@ -49,8 +49,8 @@ class _PkgManagePageState extends State @override void initState() { super.initState(); - final si = locator().getServer(widget.spi.id); - if (si.client == null) { + final si = locator().servers[widget.spi.id]; + if (si == null || si.client == null) { showSnackBar(context, Text(_s.waitConnection)); context.pop(); return; diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 5b119cea..20da05fd 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -40,9 +40,15 @@ class _ServerDetailPageState extends State @override Widget build(BuildContext context) { return Consumer(builder: (_, provider, __) { - return _buildMainPage( - provider.getServer(widget.id), - ); + final s = provider.servers[widget.id]; + if (s == null) { + return Scaffold( + body: Center( + child: Text(_s.noClient), + ), + ); + } + return _buildMainPage(s); }); } diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 304b05e3..1eec302c 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -75,6 +75,7 @@ class _ServerPageState extends State ), ); } + final keys = pro.servers.keys.toList(); return ListView.separated( padding: const EdgeInsets.all(7), controller: ScrollController(), @@ -83,9 +84,9 @@ class _ServerPageState extends State if (idx == pro.servers.length) { return SizedBox(height: _media.padding.bottom); } - return _buildEachServerCard(pro.servers[idx]); + return _buildEachServerCard(pro.servers[keys[idx]]); }, - itemCount: pro.servers.length + 1, + itemCount: pro.servers.length, separatorBuilder: (_, __) => const SizedBox( height: 3, ), @@ -105,7 +106,10 @@ class _ServerPageState extends State ); } - Widget _buildEachServerCard(Server si) { + Widget _buildEachServerCard(Server? si) { + if (si == null) { + return const SizedBox(); + } return RoundRectCard( InkWell( onLongPress: () => AppRoute( diff --git a/lib/view/page/sftp/view.dart b/lib/view/page/sftp/view.dart index 7d392600..d41698cb 100644 --- a/lib/view/page/sftp/view.dart +++ b/lib/view/page/sftp/view.dart @@ -53,7 +53,7 @@ class _SFTPPageState extends State { void initState() { super.initState(); final serverProvider = locator(); - _si = serverProvider.getServer(widget.spi.id); + _si = serverProvider.servers[widget.spi.id]; _client = _si?.client; }