diff --git a/lib/main.dart b/lib/main.dart index f76a28f..a8619b2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -81,12 +81,23 @@ class MyHomePage extends StatefulWidget { class _MyHomePageState extends State { int navIndex = 0; OpenSSHEd25519KeyPair? keyPair; - String _output = ''; + String? _output; + SSHClient? client; String key = ''; Future doSSH(String user) async { SSHSocket? socket; + if (client != null) { + // If we already have a client, close it + client!.close(); + client = null; + } + + setState(() { + _output = null; + }); + try { socket = await SSHSocket.connect( '192.168.0.15', @@ -94,17 +105,48 @@ class _MyHomePageState extends State { timeout: const Duration(seconds: 0, milliseconds: 500), ); - final client = SSHClient( + client = SSHClient( socket, username: user, identities: List.of(keyPair != null ? [keyPair!] : []), ); - final uptime = await client.run('uptime'); setState(() { - _output = utf8.decode(uptime); + _output = 'Connecting to SSH server...\n\n'; + }); + + if (client == null) { + return; + } + + final shell = await client!.shell(); + + shell.stdout.listen((data) { + setState(() { + if (_output == null) { + return; + } + _output = _output! + utf8.decode(data); + }); + }); + + if (client == null) { + return; + } + + await shell.done; + + if (client == null) { + return; + } + client!.close(); + setState(() { + _output = null; }); } on SSHAuthError catch (_) { + setState(() { + _output = null; + }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( @@ -115,6 +157,9 @@ class _MyHomePageState extends State { ); return; } on SocketException catch (_) { + setState(() { + _output = null; + }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( @@ -382,11 +427,7 @@ class _MyHomePageState extends State { ), ); - if (authentikApiState.isClosed()) { - return mainPage; - } - - Widget title; + Widget? title; var children = []; var actions = [ TextButton(onPressed: authentikApiState.exit, child: Text("Cancel")), @@ -394,7 +435,7 @@ class _MyHomePageState extends State { switch (authentikApiState.status) { case AuthentikUserSettingsChangeDialogStatus.closed: - return mainPage; + break; case AuthentikUserSettingsChangeDialogStatus.waitingForOAuth: title = Text("Waiting for OAuth"); children = [Text("Please complete the OAuth flow in your browser.")]; @@ -429,6 +470,31 @@ class _MyHomePageState extends State { children = [Text("Saving...")]; } + if (_output != null) { + title = Text("SSH Output"); + children.add(Text(_output!, style: TextStyle(fontSize: 12))); + // TODO: fix action. + actions = [ + TextButton( + onPressed: () { + setState(() { + _output = null; + if (client != null) { + client!.close(); + client = null; + } + }); + }, + child: Text("Cancel"), + ), + ]; + } + + if (title == null) { + // If we have no title, just return the main page + return mainPage; + } + final dialog = AlertDialog( title: title, content: SingleChildScrollView(child: Column(children: children)),