From 58b950f8146ae46a1847196775c38421356a8e6a Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Wed, 15 Mar 2023 13:37:19 +0800 Subject: [PATCH] #14 add `ssh` log --- .dart_tool/flutter_gen/gen_l10n/l10n.dart | 18 ++++++++ .dart_tool/flutter_gen/gen_l10n/l10n_en.dart | 9 ++++ .dart_tool/flutter_gen/gen_l10n/l10n_zh.dart | 9 ++++ lib/core/utils/platform.dart | 1 - lib/core/utils/server.dart | 13 +++++- lib/data/res/build_data.dart | 3 +- lib/data/store/setting.dart | 3 +- lib/l10n/app_en.arb | 3 ++ lib/l10n/app_zh.arb | 3 ++ lib/view/page/setting.dart | 48 ++++++++++---------- lib/view/page/ssh.dart | 27 +++++++++-- lib/view/widget/future_widget.dart | 47 +++++++++++++++++++ pubspec.lock | 4 +- pubspec.yaml | 2 +- 14 files changed, 153 insertions(+), 37 deletions(-) create mode 100644 lib/view/widget/future_widget.dart diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n.dart b/.dart_tool/flutter_gen/gen_l10n/l10n.dart index 2e7ed705..1038a1b4 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n.dart @@ -453,6 +453,12 @@ abstract class S { /// **'Can\'t fetch push token'** String get getPushTokenFailed; + /// No description provided for @gettingToken. + /// + /// In en, this message translates to: + /// **'Getting token...'** + String get gettingToken; + /// No description provided for @go. /// /// In en, this message translates to: @@ -675,6 +681,12 @@ abstract class S { /// **'No update available'** String get noUpdateAvailable; + /// No description provided for @nullToken. + /// + /// In en, this message translates to: + /// **'Null token'** + String get nullToken; + /// No description provided for @ok. /// /// In en, this message translates to: @@ -687,6 +699,12 @@ abstract class S { /// **'On server detail page'** String get onServerDetailPage; + /// No description provided for @onlyIOS. + /// + /// In en, this message translates to: + /// **'Only valid on iOS'** + String get onlyIOS; + /// No description provided for @open. /// /// In en, this message translates to: diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart index 815a219b..4c5ea530 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_en.dart @@ -200,6 +200,9 @@ class SEn extends S { @override String get getPushTokenFailed => 'Can\'t fetch push token'; + @override + String get gettingToken => 'Getting token...'; + @override String get go => 'Go'; @@ -317,12 +320,18 @@ class SEn extends S { @override String get noUpdateAvailable => 'No update available'; + @override + String get nullToken => 'Null token'; + @override String get ok => 'OK'; @override String get onServerDetailPage => 'On server detail page'; + @override + String get onlyIOS => 'Only valid on iOS'; + @override String get open => 'Open'; diff --git a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart index 74d20189..d4ba37d5 100644 --- a/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart +++ b/.dart_tool/flutter_gen/gen_l10n/l10n_zh.dart @@ -200,6 +200,9 @@ class SZh extends S { @override String get getPushTokenFailed => '未能获取到推送token'; + @override + String get gettingToken => '正在获取Token...'; + @override String get go => '开始'; @@ -317,12 +320,18 @@ class SZh extends S { @override String get noUpdateAvailable => '没有可用更新'; + @override + String get nullToken => '无Token'; + @override String get ok => '好'; @override String get onServerDetailPage => '在服务器详情页'; + @override + String get onlyIOS => '仅在iOS上有效'; + @override String get open => '打开'; diff --git a/lib/core/utils/platform.dart b/lib/core/utils/platform.dart index 7cef0ff0..e5d8ab88 100644 --- a/lib/core/utils/platform.dart +++ b/lib/core/utils/platform.dart @@ -41,4 +41,3 @@ bool get isLinux => _p == PlatformType.linux; bool get isMacOS => _p == PlatformType.macos; bool get isWindows => _p == PlatformType.windows; bool get isWeb => _p == PlatformType.web; - diff --git a/lib/core/utils/server.dart b/lib/core/utils/server.dart index 55668894..9ebd5ffd 100644 --- a/lib/core/utils/server.dart +++ b/lib/core/utils/server.dart @@ -24,13 +24,23 @@ String decyptPem(List args) { return sshKey.first.toPem(); } -Future genClient(ServerPrivateInfo spi) async { +enum GenSSHClientStatus { + socket, + key, + pwd, +} + +Future genClient(ServerPrivateInfo spi, + {void Function(GenSSHClientStatus)? onStatus}) async { + final onStatus_ = onStatus ?? (_) {}; + onStatus_(GenSSHClientStatus.socket); final socket = await SSHSocket.connect( spi.ip, spi.port, timeout: const Duration(seconds: 5), ); if (spi.pubKeyId == null) { + onStatus_(GenSSHClientStatus.pwd); return SSHClient( socket, username: spi.user, @@ -38,6 +48,7 @@ Future genClient(ServerPrivateInfo spi) async { ); } final key = locator().get(spi.pubKeyId!); + onStatus_(GenSSHClientStatus.key); return SSHClient( socket, username: spi.user, diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 777ccbed..4132e539 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -3,7 +3,8 @@ class BuildData { static const String name = "ServerBox"; static const int build = 231; - static const String engine = "Flutter 3.7.6 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 12cb4eb7a0 (11 days ago) • 2023-03-01 10:29:26 -0800\nEngine • revision ada363ee93\nTools • Dart 2.19.3 • DevTools 2.20.1\n"; + static const String engine = + "Flutter 3.7.6 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 12cb4eb7a0 (11 days ago) • 2023-03-01 10:29:26 -0800\nEngine • revision ada363ee93\nTools • Dart 2.19.3 • DevTools 2.20.1\n"; static const String buildAt = "2023-03-13 11:33:00.843861"; static const int modifications = 13; } diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 52eb9488..b62bc456 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -31,6 +31,5 @@ class SettingStore extends PersistentStore { property('maxRetryCount', defaultValue: 7); /// Night mode: 0 -> auto, 1 -> light, 2 -> dark - StoreProperty get themeMode => - property('nightMode', defaultValue: ThemeMode.system.index); + StoreProperty get themeMode => property('themeMode', defaultValue: 0); } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 24f1af58..fda572ae 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -59,6 +59,7 @@ "files": "Files", "foundNUpdate": "Found {count} update", "getPushTokenFailed": "Can't fetch push token", + "gettingToken": "Getting token...", "go": "Go", "goto": "Go to", "host": "Host", @@ -96,8 +97,10 @@ "noSavedSnippet": "No saved snippets.", "noServerAvailable": "No server available.", "noUpdateAvailable": "No update available", + "nullToken": "Null token", "ok": "OK", "onServerDetailPage": "On server detail page", + "onlyIOS": "Only valid on iOS", "open": "Open", "path": "Path", "pickFile": "Pick file", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index c1df9108..a77e7422 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -59,6 +59,7 @@ "files": "文件", "foundNUpdate": "找到 {count} 个更新", "getPushTokenFailed": "未能获取到推送token", + "gettingToken": "正在获取Token...", "go": "开始", "goto": "前往", "host": "主机", @@ -96,8 +97,10 @@ "noSavedSnippet": "没有已保存的代码片段。", "noServerAvailable": "没有可用的服务器。", "noUpdateAvailable": "没有可用更新", + "nullToken": "无Token", "ok": "好", "onServerDetailPage": "在服务器详情页", + "onlyIOS": "仅在iOS上有效", "open": "打开", "path": "路径", "pickFile": "选择文件", diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index ef6d8c6d..67997b83 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -2,8 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_material_color_picker/flutter_material_color_picker.dart'; import 'package:provider/provider.dart'; -import 'package:toolbox/core/utils/misc.dart'; +import '../../core/utils/misc.dart'; +import '../../core/utils/platform.dart'; import '../../data/model/ssh/terminal_color.dart'; import '../../core/update.dart'; import '../../core/utils/ui.dart'; @@ -15,6 +16,7 @@ import '../../data/res/tab.dart'; import '../../data/res/ui.dart'; import '../../data/store/setting.dart'; import '../../locator.dart'; +import '../widget/future_widget.dart'; import '../widget/round_rect_card.dart'; class SettingPage extends StatefulWidget { @@ -85,6 +87,7 @@ class _SettingPageState extends State { child: Center( child: Text( text, + style: grey, ), ), ); @@ -371,7 +374,7 @@ class _SettingPageState extends State { _s.themeMode, ), trailing: Text( - _buildNightModeStr(_nightMode), + _buildThemeModeStr(_nightMode), ), children: [ Slider( @@ -388,14 +391,14 @@ class _SettingPageState extends State { onChangeEnd: (val) { _setting.themeMode.put(val.toInt()); }, - label: _buildNightModeStr(_nightMode), + label: _buildThemeModeStr(_nightMode), divisions: 2, ), ], ); } - String _buildNightModeStr(int n) { + String _buildThemeModeStr(int n) { switch (n) { case 1: return _s.light; @@ -422,29 +425,24 @@ class _SettingPageState extends State { } }, ), - subtitle: FutureBuilder( + subtitle: FutureWidget( future: getToken(), - builder: (context, snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.none: - case ConnectionState.waiting: - return const Text('Getting Token...'); - default: - var text = _pushToken; - if (snapshot.hasError) { - text = 'Error: ${snapshot.error}'; - } - _pushToken = snapshot.data; - if (_pushToken == null) { - text = 'Null token'; - } - return Text( - text!, - style: grey, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ); + loading: Text(_s.gettingToken), + error: (error, trace) => Text('${_s.error}: $error'), + noData: Text(_s.nullToken), + success: (text) { + if (_pushToken == null) { + text = _s.nullToken; } + if (!isIOS) { + text = _s.onlyIOS; + } + return Text( + text!, + style: grey, + overflow: TextOverflow.ellipsis, + maxLines: 1, + ); }, ), ); diff --git a/lib/view/page/ssh.dart b/lib/view/page/ssh.dart index f1f352a5..52f0077d 100644 --- a/lib/view/page/ssh.dart +++ b/lib/view/page/ssh.dart @@ -67,11 +67,30 @@ class _SSHPageState extends State { super.dispose(); } - Future initTerminal() async { - _terminal.write('Connecting...\r\n'); + void _write(String p0) { + _terminal.write('$p0\r\n'); + } - _client = await genClient(widget.spi); - _terminal.write('Connected\r\n'); + Future initTerminal() async { + _write('Connecting...\r\n'); + + _client = await genClient( + widget.spi, + onStatus: (p0) { + switch (p0) { + case GenSSHClientStatus.socket: + _write('Destination: ${widget.spi.id}'); + return _write('Establishing socket...'); + case GenSSHClientStatus.key: + return _write('Using private key to connect...'); + case GenSSHClientStatus.pwd: + return _write('Sending password to auth...'); + } + }, + ); + _write('Connected\r\n'); + _write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n'); + _write('Starting shell...\r\n'); final session = await _client!.shell( pty: SSHPtyConfig( diff --git a/lib/view/widget/future_widget.dart b/lib/view/widget/future_widget.dart new file mode 100644 index 00000000..d3fe30c4 --- /dev/null +++ b/lib/view/widget/future_widget.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +class FutureWidget extends StatelessWidget { + final Future future; + final Widget loading; + final Widget Function(Object? error, StackTrace? trace) error; + final Widget Function(T data) success; + final Widget noData; + final Widget Function(AsyncSnapshot snapshot)? active; + + const FutureWidget({ + super.key, + required this.future, + required this.loading, + required this.error, + required this.success, + required this.noData, + this.active, + }); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: future, + builder: (context, snapshot) { + if (snapshot.hasError) { + return error(snapshot.error, snapshot.stackTrace); + } + switch (snapshot.connectionState) { + case ConnectionState.none: + case ConnectionState.waiting: + return loading; + case ConnectionState.active: + if (active != null) { + return active!(snapshot); + } + return loading; + case ConnectionState.done: + if (snapshot.hasData) { + return success(snapshot.data as T); + } + return noData; + } + }, + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 021ca76f..4d7a7c31 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -230,10 +230,10 @@ packages: dependency: "direct main" description: name: dartssh2 - sha256: "4c44ad7bb6a12cd56f775fc72b64e81fcc3f7971dc731c48359f2aa551d6f6a7" + sha256: "53a230c7dd6f487b704ceef1b29323ad64d19be89e786ccbc81e157a70417a56" url: "https://pub.dev" source: hosted - version: "2.7.3" + version: "2.8.2" dio: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9a73b8e9..ae809bff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,7 +39,7 @@ dependencies: extended_image: ^6.0.3 url_launcher: ^6.1.8 countly_flutter: ^22.2.0 - dartssh2: ^2.7.1 + dartssh2: ^2.8.2 logging: ^1.0.2 flutter_material_color_picker: ^1.1.0+2 circle_chart: