diff --git a/lib/data/model/server/server.dart b/lib/data/model/server/server.dart index ef7045ef..a18b249f 100644 --- a/lib/data/model/server/server.dart +++ b/lib/data/model/server/server.dart @@ -53,7 +53,7 @@ class ServerStatus { NetSpeed netSpeed; Temperatures temps; SystemType system; - String? failedInfo; + String? err; DiskIO diskIO; /// Whether is connectting, parsing and etc. @@ -71,7 +71,7 @@ class ServerStatus { required this.temps, required this.system, required this.diskIO, - this.failedInfo, + this.err, }); } diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 27463d38..35f1fea2 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -259,7 +259,7 @@ class ServerProvider extends ChangeNotifier { return; } - s.status.failedInfo = null; + s.status.err = 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. @@ -286,7 +286,7 @@ class ServerProvider extends ChangeNotifier { } } catch (e) { TryLimiter.inc(sid); - s.status.failedInfo = e.toString(); + s.status.err = e.toString(); _setServerState(s, ServerState.failed); /// In order to keep privacy, print [spi.name] instead of [spi.id] @@ -329,7 +329,7 @@ class ServerProvider extends ChangeNotifier { } } catch (e) { TryLimiter.inc(sid); - s.status.failedInfo = e.toString(); + s.status.err = e.toString(); _setServerState(s, ServerState.failed); Loggers.app.warning('Write script to ${spi.name} by sftp', e); return; @@ -354,13 +354,13 @@ class ServerProvider extends ChangeNotifier { segments = raw?.split(seperator).map((e) => e.trim()).toList(); if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) { TryLimiter.inc(sid); - s.status.failedInfo = 'Seperate segments failed, raw:\n$raw'; + s.status.err = 'Seperate segments failed, raw:\n$raw'; _setServerState(s, ServerState.failed); return; } } catch (e) { TryLimiter.inc(sid); - s.status.failedInfo = e.toString(); + s.status.err = e.toString(); _setServerState(s, ServerState.failed); Loggers.app.warning('Get status from ${spi.name} failed', e); return; @@ -369,7 +369,7 @@ class ServerProvider extends ChangeNotifier { final systemType = SystemType.parse(segments[0]); if (!systemType.isSegmentsLenMatch(segments.length)) { TryLimiter.inc(sid); - s.status.failedInfo = + s.status.err = 'Segments not match: expect ${systemType.segmentsLen}, got ${segments.length}'; _setServerState(s, ServerState.failed); return; @@ -385,7 +385,7 @@ class ServerProvider extends ChangeNotifier { s.status = await compute(getStatus, req); } catch (e, trace) { TryLimiter.inc(sid); - s.status.failedInfo = 'Parse failed: $e\n\n$raw'; + s.status.err = 'Parse failed: $e\n\n$raw'; _setServerState(s, ServerState.failed); Loggers.parse.warning('Server status', e, trace); return; diff --git a/lib/view/page/full_screen.dart b/lib/view/page/full_screen.dart index 97308a37..21265b0f 100644 --- a/lib/view/page/full_screen.dart +++ b/lib/view/page/full_screen.dart @@ -239,7 +239,7 @@ class _FullScreenPageState extends State with AfterLayoutMixin { cs, ss.temps.first, ss.uptime, - ss.failedInfo, + ss.err, ); return Text( topRightStr, diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index f66ee4d5..afdb3b2c 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -184,7 +184,7 @@ class _ServerPageState extends State onTap: () { if (srv.canViewDetails) { AppRoute.serverDetail(spi: srv.spi).go(context); - } else if (srv.status.failedInfo != null) { + } else if (srv.status.err != null) { _showFailReason(srv.status); } }, @@ -398,9 +398,9 @@ class _ServerPageState extends State cs, ss.temps.first, ss.uptime, - ss.failedInfo, + ss.err, ); - if (cs == ServerState.failed && ss.failedInfo != null) { + if (cs == ServerState.failed && ss.err != null) { return GestureDetector( onTap: () => _showFailReason(ss), child: Text( @@ -421,11 +421,11 @@ class _ServerPageState extends State context.showRoundDialog( title: Text(l10n.error), child: SingleChildScrollView( - child: Text(ss.failedInfo ?? l10n.unknownError), + child: Text(ss.err ?? l10n.unknownError), ), actions: [ TextButton( - onPressed: () => Shares.copy(ss.failedInfo!), + onPressed: () => Shares.copy(ss.err!), child: Text(l10n.copy), ) ], diff --git a/lib/view/page/ssh/page.dart b/lib/view/page/ssh/page.dart index 79fde63f..9270e60f 100644 --- a/lib/view/page/ssh/page.dart +++ b/lib/view/page/ssh/page.dart @@ -9,7 +9,6 @@ import 'package:provider/provider.dart'; import 'package:toolbox/core/extension/context/common.dart'; import 'package:toolbox/core/extension/context/dialog.dart'; import 'package:toolbox/core/extension/context/locale.dart'; -import 'package:toolbox/core/extension/context/snackbar.dart'; import 'package:toolbox/core/utils/platform/base.dart'; import 'package:toolbox/core/utils/share.dart'; import 'package:toolbox/data/model/server/server.dart'; @@ -27,7 +26,7 @@ import '../../../data/model/ssh/virtual_key.dart'; import '../../../data/res/color.dart'; import '../../../data/res/terminal.dart'; -const echoPWD = 'echo \$PWD'; +const _echoPWD = 'echo \$PWD'; class SSHPage extends StatefulWidget { final ServerPrivateInfo spi; @@ -55,7 +54,6 @@ class _SSHPageState extends State with AutomaticKeepAliveClientMixin { Timer? _virtKeyLongPressTimer; late final Server? _server = widget.spi.server; late final SSHClient? _client = _server?.client; - late final SSHSession? _session; Timer? _discontinuityTimer; @override @@ -68,8 +66,11 @@ class _SSHPageState extends State with AutomaticKeepAliveClientMixin { ); _terminalStyle = TerminalStyle.fromTextStyle(textStyle); _keyboardType = TextInputType.values[Stores.setting.keyboardType.fetch()]; - _initTerminal(); _initVirtKeys(); + + Future.delayed(const Duration(milliseconds: 77), () async { + await _initTerminal(); + }); } @override @@ -270,13 +271,13 @@ class _SSHPageState extends State with AutomaticKeepAliveClientMixin { break; case VirtualKeyFunc.file: // get $PWD from SSH session - _terminal.textInput(echoPWD); + _terminal.textInput(_echoPWD); _terminal.keyInput(TerminalKey.enter); final cmds = _terminal.buffer.lines.toList(); // wait for the command to finish await Future.delayed(const Duration(milliseconds: 777)); // the line below `echo $PWD` is the current path - final idx = cmds.lastIndexWhere((e) => e.toString().contains(echoPWD)); + final idx = cmds.lastIndexWhere((e) => e.toString().contains(_echoPWD)); final initPath = cmds[idx + 1].toString(); if (initPath.isEmpty || !initPath.startsWith('/')) { context.showRoundDialog( @@ -323,27 +324,12 @@ class _SSHPageState extends State with AutomaticKeepAliveClientMixin { 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...'); - // } - // }, - // timeout: Stores.setting.timeoutD, - // ); - // _write('Connected\r\n'); - _write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n'); + if (_client == null) { + await Pros.server.refreshData(spi: widget.spi); + } _write('Starting shell...\r\n'); - _session = await _client?.shell( + final session = await _client?.shell( pty: SSHPtyConfig( width: _terminal.viewWidth, height: _terminal.viewHeight, @@ -352,30 +338,30 @@ class _SSHPageState extends State with AutomaticKeepAliveClientMixin { _setupDiscontinuityTimer(); - if (_session == null) { - context.showSnackBar('Null session'); + if (session == null) { + _write(_server?.status.err ?? 'Null session'); return; } - // _terminal.buffer.clear(); - // _terminal.buffer.setCursor(0, 0); + _terminal.buffer.clear(); + _terminal.buffer.setCursor(0, 0); _terminal.onOutput = (data) { - _session?.write(utf8.encode(data) as Uint8List); + session.write(utf8.encode(data) as Uint8List); }; _terminal.onResize = (width, height, pixelWidth, pixelHeight) { - _session?.resizeTerminal(width, height); + session.resizeTerminal(width, height); }; - _listen(_session?.stdout); - _listen(_session?.stderr); + _listen(session.stdout); + _listen(session.stderr); if (widget.initCmd != null) { _terminal.textInput(widget.initCmd!); _terminal.keyInput(TerminalKey.enter); } - await _session?.done; + await session.done; if (mounted) { context.pop(); } @@ -428,7 +414,7 @@ class _SSHPageState extends State with AutomaticKeepAliveClientMixin { ], ); } - + @override bool get wantKeepAlive => true; }