new: open sftp in ssh

This commit is contained in:
lollipopkit
2023-05-28 18:58:38 +08:00
parent 06be4503ca
commit edaffb736c
3 changed files with 40 additions and 11 deletions

View File

@@ -4,6 +4,8 @@ const seperator = 'SrvBox';
const serverBoxDir = r'$HOME/.config/server_box'; const serverBoxDir = r'$HOME/.config/server_box';
const shellPath = '$serverBoxDir/mobile_app.sh'; const shellPath = '$serverBoxDir/mobile_app.sh';
const echoPWD = 'echo \$PWD';
enum CmdType { enum CmdType {
export, export,
net, net,

View File

@@ -32,7 +32,8 @@ import 'downloading.dart';
class SFTPPage extends StatefulWidget { class SFTPPage extends StatefulWidget {
final ServerPrivateInfo spi; final ServerPrivateInfo spi;
const SFTPPage(this.spi, {Key? key}) : super(key: key); final String? initPath;
const SFTPPage(this.spi, {Key? key, this.initPath}) : super(key: key);
@override @override
_SFTPPageState createState() => _SFTPPageState(); _SFTPPageState createState() => _SFTPPageState();
@@ -184,8 +185,9 @@ class _SFTPPageState extends State<SFTPPage> {
} }
if (_status.files == null) { if (_status.files == null) {
_status.path = AbsolutePath('/'); final p_ = widget.initPath ?? '/';
_listDir(path: '/', client: _client); _status.path = AbsolutePath(p_);
_listDir(path: p_, client: _client);
return centerLoading; return centerLoading;
} else { } else {
return RefreshIndicator( return RefreshIndicator(

View File

@@ -7,8 +7,10 @@ import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/core/extension/navigator.dart';
import 'package:toolbox/data/res/server_cmd.dart';
import 'package:xterm/xterm.dart'; import 'package:xterm/xterm.dart';
import '../../core/route.dart';
import '../../core/utils/platform.dart'; import '../../core/utils/platform.dart';
import '../../core/utils/misc.dart'; import '../../core/utils/misc.dart';
import '../../core/utils/ui.dart'; import '../../core/utils/ui.dart';
@@ -21,6 +23,7 @@ import '../../data/res/terminal.dart';
import '../../data/res/virtual_key.dart'; import '../../data/res/virtual_key.dart';
import '../../data/store/setting.dart'; import '../../data/store/setting.dart';
import '../../locator.dart'; import '../../locator.dart';
import 'sftp/view.dart';
class SSHPage extends StatefulWidget { class SSHPage extends StatefulWidget {
final ServerPrivateInfo spi; final ServerPrivateInfo spi;
@@ -34,6 +37,7 @@ class SSHPage extends StatefulWidget {
class _SSHPageState extends State<SSHPage> { class _SSHPageState extends State<SSHPage> {
late final _terminal = Terminal(inputHandler: _keyboard); late final _terminal = Terminal(inputHandler: _keyboard);
SSHClient? _client; SSHClient? _client;
late SSHSession _session;
final _keyboard = locator<VirtualKeyboard>(); final _keyboard = locator<VirtualKeyboard>();
final _setting = locator<SettingStore>(); final _setting = locator<SettingStore>();
late MediaQueryData _media; late MediaQueryData _media;
@@ -205,7 +209,7 @@ class _SSHPageState extends State<SSHPage> {
} }
} }
void _doVirtualKeyFunc(VirtualKeyFunc type) { Future<void> _doVirtualKeyFunc(VirtualKeyFunc type) async {
switch (type) { switch (type) {
case VirtualKeyFunc.toggleIME: case VirtualKeyFunc.toggleIME:
FocusScope.of(context).requestFocus(FocusNode()); FocusScope.of(context).requestFocus(FocusNode());
@@ -229,8 +233,29 @@ class _SSHPageState extends State<SSHPage> {
}); });
break; break;
case VirtualKeyFunc.file: case VirtualKeyFunc.file:
// TODO // get $PWD from SSH session
showRoundDialog(context: context, child: const Text('TODO')); _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 initPath = cmds[idx + 1].toString();
if (initPath.isEmpty || !initPath.startsWith('/')) {
showRoundDialog(
context: context,
child: const Text('Failed to get current path'),
);
return;
}
AppRoute(
SFTPPage(
widget.spi,
initPath: initPath,
),
'SSH SFTP')
.go(context);
} }
} }
@@ -321,7 +346,7 @@ class _SSHPageState extends State<SSHPage> {
_write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n'); _write('Terminal size: ${_terminal.viewWidth}x${_terminal.viewHeight}\r\n');
_write('Starting shell...\r\n'); _write('Starting shell...\r\n');
final session = await _client!.shell( _session = await _client!.shell(
pty: SSHPtyConfig( pty: SSHPtyConfig(
width: _terminal.viewWidth, width: _terminal.viewWidth,
height: _terminal.viewHeight, height: _terminal.viewHeight,
@@ -332,18 +357,18 @@ class _SSHPageState extends State<SSHPage> {
_terminal.buffer.setCursor(0, 0); _terminal.buffer.setCursor(0, 0);
_terminal.onOutput = (data) { _terminal.onOutput = (data) {
session.write(utf8.encode(data) as Uint8List); _session.write(utf8.encode(data) as Uint8List);
}; };
_listen(session.stdout); _listen(_session.stdout);
_listen(session.stderr); _listen(_session.stderr);
if (widget.initCmd != null) { if (widget.initCmd != null) {
_terminal.textInput(widget.initCmd!); _terminal.textInput(widget.initCmd!);
_terminal.keyInput(TerminalKey.enter); _terminal.keyInput(TerminalKey.enter);
} }
await session.done; await _session.done;
if (mounted) { if (mounted) {
context.pop(); context.pop();
} }