diff --git a/lib/core/extension/ssh_client.dart b/lib/core/extension/ssh_client.dart index 54ad23d8..eac86131 100644 --- a/lib/core/extension/ssh_client.dart +++ b/lib/core/extension/ssh_client.dart @@ -15,20 +15,34 @@ extension SSHClientX on SSHClient { {OnStd? onStderr, OnStd? onStdout, OnStdin? stdin}) async { final session = await execute(cmd); - if (onStderr != null) { - await for (final data in session.stderr) { - onStderr(data.string, session.stdin); - } - } + final stdoutDone = Completer(); + final stderrDone = Completer(); + if (onStdout != null) { - await for (final data in session.stdout) { - onStdout(data.string, session.stdin); - } + session.stdout.listen( + (e) => onStdout(e.string, session.stdin), + onDone: stdoutDone.complete, + ); + } else { + stdoutDone.complete(); } + + if (onStderr != null) { + session.stderr.listen( + (e) => onStderr(e.string, session.stdin), + onDone: stderrDone.complete, + ); + } else { + stderrDone.complete(); + } + if (stdin != null) { stdin(session.stdin); } + await stdoutDone.future; + await stderrDone.future; + session.close(); return session.exitCode; } diff --git a/lib/data/provider/apt.dart b/lib/data/provider/apt.dart index 67ced9be..7c58b968 100644 --- a/lib/data/provider/apt.dart +++ b/lib/data/provider/apt.dart @@ -99,7 +99,7 @@ class AptProvider extends BusyProvider { onStdout: (data, sink) { updateLog = (updateLog ?? '') + data; notifyListeners(); - onUpdate!(); + if (onUpdate != null) onUpdate!(); }, ); return await client @@ -120,13 +120,13 @@ class AptProvider extends BusyProvider { await client!.exec( _wrap(upgradeCmd), - onStderr: (data, sink) => _onPwd(data, sink), + onStderr: _onPwd, onStdout: (log, sink) { if (lastLog == log.trim()) return; upgradeLog = (upgradeLog ?? '') + log; lastLog = log.trim(); notifyListeners(); - onUpgrade!(); + if (onUpgrade != null) onUpgrade!(); }, ); diff --git a/lib/data/provider/docker.dart b/lib/data/provider/docker.dart index c1f491f4..326eaf32 100644 --- a/lib/data/provider/docker.dart +++ b/lib/data/provider/docker.dart @@ -30,7 +30,6 @@ class DockerProvider extends BusyProvider { DockerErr? error; PwdRequestFunc? onPwdReq; String? hostId; - String? runLog; bool isRequestingPwd = false; void init(SSHClient client, String userName, PwdRequestFunc onPwdReq, @@ -44,7 +43,7 @@ class DockerProvider extends BusyProvider { void clear() { client = userName = error = items = version = edition = onPwdReq = null; isRequestingPwd = false; - hostId = runLog = null; + hostId = null; } Future refresh() async { @@ -124,14 +123,8 @@ class DockerProvider extends BusyProvider { final code = await client!.exec( _wrapHost(cmd), onStderr: _onPwd, - onStdout: (data, _) { - runLog = '$runLog$data'; - notifyListeners(); - }, ); - runLog = null; - if (code != 0) { setBusyState(false); return DockerErr(type: DockerErrType.unknown, message: errs.join('\n')); diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 25a95fe3..a5bd043d 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,9 +2,9 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 166; + static const int build = 169; static const String engine = - "Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b8f7f1f986 (12 days ago) • 2022-11-23 06:43:51 +0900\nEngine • revision 8f2221fbef\nTools • Dart 2.18.5 • DevTools 2.15.0\n"; - static const String buildAt = "2022-12-04 21:57:10.591121"; - static const int modifications = 2; + "Flutter 3.3.9 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b8f7f1f986 (3 weeks ago) • 2022-11-23 06:43:51 +0900\nEngine • revision 8f2221fbef\nTools • Dart 2.18.5 • DevTools 2.15.0\n"; + static const String buildAt = "2022-12-11 12:36:17.737879"; + static const int modifications = 8; } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index b00006bf..c835d03f 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -142,6 +142,7 @@ class MessageLookup extends MessageLookupByLibrary { "invalidVersion": MessageLookupByLibrary.simpleMessage("Invalid version"), "invalidVersionHelp": m6, + "isBusy": MessageLookupByLibrary.simpleMessage("Is busy now"), "keepForeground": MessageLookupByLibrary.simpleMessage("Keep app foreground!"), "keyAuth": MessageLookupByLibrary.simpleMessage("Key Auth"), diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index 1e4146eb..2d97b3b2 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -127,6 +127,7 @@ class MessageLookup extends MessageLookupByLibrary { "invalidJson": MessageLookupByLibrary.simpleMessage("无效的json,存在格式问题"), "invalidVersion": MessageLookupByLibrary.simpleMessage("不支持的版本"), "invalidVersionHelp": m6, + "isBusy": MessageLookupByLibrary.simpleMessage("当前正忙"), "keepForeground": MessageLookupByLibrary.simpleMessage("请保持应用处于前台!"), "keyAuth": MessageLookupByLibrary.simpleMessage("公钥认证"), "lastTry": MessageLookupByLibrary.simpleMessage("最后尝试"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 75806453..5c414794 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -1450,6 +1450,16 @@ class S { args: [], ); } + + /// `Is busy now` + String get isBusy { + return Intl.message( + 'Is busy now', + name: 'isBusy', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 8d0722ae..3544ff22 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -138,5 +138,6 @@ "dockerImage": "Image", "dockerContainerName": "Container name", "extraArgs": "Extra args", - "preview": "Preview" + "preview": "Preview", + "isBusy": "Is busy now" } \ No newline at end of file diff --git a/lib/l10n/intl_zh.arb b/lib/l10n/intl_zh.arb index f1a4a1ca..20908fd9 100644 --- a/lib/l10n/intl_zh.arb +++ b/lib/l10n/intl_zh.arb @@ -138,5 +138,6 @@ "dockerImage": "镜像", "dockerContainerName": "容器名", "extraArgs": "额外参数", - "preview": "预览" + "preview": "预览", + "isBusy": "当前正忙" } \ No newline at end of file diff --git a/lib/view/page/docker.dart b/lib/view/page/docker.dart index a13fd982..41396e01 100644 --- a/lib/view/page/docker.dart +++ b/lib/view/page/docker.dart @@ -260,22 +260,10 @@ class _DockerManagePageState extends State { Widget _buildLoading(DockerProvider docker) { if (docker.isBusy) { - final runLog = - docker.runLog == null ? const SizedBox() : Text(docker.runLog!); - return Padding( - padding: const EdgeInsets.all(17), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - runLog, - SizedBox( - width: docker.runLog == null ? 0 : 17, - ), - const Center( - child: CircularProgressIndicator(), - ), - ], + return const Padding( + padding: EdgeInsets.all(17), + child: Center( + child: CircularProgressIndicator(), ), ); } @@ -380,15 +368,14 @@ class _DockerManagePageState extends State { return ListTile( title: Text(item.image), subtitle: Text(item.status), - trailing: docker.isBusy - ? const CircularProgressIndicator() - : _buildMoreBtn(item.running, item.containerId), + trailing: + _buildMoreBtn(item.running, item.containerId, docker.isBusy), ); }).toList(), ); } - Widget _buildMoreBtn(bool running, String containerId) { + Widget _buildMoreBtn(bool running, String containerId, bool busy) { final item = running ? DockerMenuItems.stop : DockerMenuItems.start; return buildPopuopMenu( items: [ @@ -402,6 +389,10 @@ class _DockerManagePageState extends State { ), ], onSelected: (value) { + if (busy) { + showSnackBar(context, Text(s.isBusy)); + return; + } final item = value as DropdownBtnItem; switch (item) { case DockerMenuItems.rm: