diff --git a/lib/data/store/history.dart b/lib/data/store/history.dart new file mode 100644 index 00000000..7f424365 --- /dev/null +++ b/lib/data/store/history.dart @@ -0,0 +1,32 @@ +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:toolbox/core/persistant_store.dart'; + +typedef _HistoryType = List; + +/// index from 0 -> n : latest -> oldest +class _History { + final _HistoryType _history; + final String _name; + final Box<_HistoryType> _box; + + _History({ + required Box<_HistoryType> box, + required String name, + }) : _box = box, + _name = name, + _history = box.get(name, defaultValue: [])!; + + void add(String path) { + _history.remove(path); + _history.insert(0, path); + _box.put(_name, _history); + } + + _HistoryType get all => _history; +} + +class HistoryStore extends PersistentStore<_HistoryType> { + late final _History sftpPath = _History(box: box, name: 'sftpPath'); + + late final _History sshCmds = _History(box: box, name: 'sshCmds'); +} diff --git a/lib/locator.dart b/lib/locator.dart index a6867b50..ffaeaa1d 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -11,6 +11,7 @@ import 'data/provider/snippet.dart'; import 'data/provider/virtual_keyboard.dart'; import 'data/service/app.dart'; import 'data/store/docker.dart'; +import 'data/store/history.dart'; import 'data/store/private_key.dart'; import 'data/store/server.dart'; import 'data/store/setting.dart'; @@ -54,6 +55,10 @@ Future _setupLocatorForStores() async { final docker = DockerStore(); await docker.init(boxName: 'docker'); locator.registerSingleton(docker); + + final history = HistoryStore(); + await history.init(boxName: 'history'); + locator.registerSingleton(history); } Future setupLocator() async { diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 48e89f71..c5df864e 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -129,7 +129,7 @@ class _ServerDetailPageState extends State _buildDetailPercent(ss.cpu.iowait, 'io'), ]); } - + return RoundRectCard( Padding( padding: roundRectCardPadding, diff --git a/lib/view/page/storage/sftp.dart b/lib/view/page/storage/sftp.dart index 0f3f0d11..d54bbc81 100644 --- a/lib/view/page/storage/sftp.dart +++ b/lib/view/page/storage/sftp.dart @@ -8,6 +8,7 @@ import 'package:logging/logging.dart'; import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/core/extension/sftpfile.dart'; import 'package:toolbox/data/res/misc.dart'; +import 'package:toolbox/data/store/history.dart'; import 'package:toolbox/view/page/editor.dart'; import 'package:toolbox/view/page/storage/local.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; @@ -52,6 +53,7 @@ class _SftpPageState extends State { final SftpBrowserStatus _status = SftpBrowserStatus(); final _sftp = locator(); + final _history = locator(); late S _s; @@ -156,7 +158,6 @@ class _SftpPageState extends State { onPressed: () async { final idx = await showRoundDialog( context: context, - title: Text(_s.choose), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -224,12 +225,6 @@ class _SftpPageState extends State { onTap: () => _newFile(context)), ], ), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text(_s.close), - ) - ], )), icon: const Icon(Icons.add), ); @@ -242,31 +237,30 @@ class _SftpPageState extends State { final p = await showRoundDialog( context: context, title: Text(_s.goto), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Input( + child: Autocomplete( + optionsBuilder: (val) => _history.sftpPath.all.where( + (element) => element.contains(val.text), + ), + fieldViewBuilder: (_, controller, node, __) { + return Input( autoFocus: true, icon: Icons.abc, label: _s.path, + node: node, + controller: controller, onSubmitted: (value) => context.pop(value), - ), - ], + ); + }, ), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text(_s.close), - ) - ], ); - // p == null || p.isEmpty - if (p?.isEmpty ?? true) { + if (p == null || p.isEmpty) { return; } - _status.path?.update(p!); - _listDir(path: p); + + _status.path?.update(p); + final suc = await _listDir(path: p); + if (suc) _history.sftpPath.add(p); }, icon: const Icon(Icons.gps_fixed), ); @@ -624,9 +618,10 @@ class _SftpPageState extends State { return '${(await sftpDir).path}$remotePath'; } - Future _listDir({String? path, SSHClient? client}) async { + /// Only return true if the path is changed + Future _listDir({String? path, SSHClient? client}) async { if (_status.isBusy) { - return; + return false; } _status.isBusy = true; if (client != null) { @@ -657,7 +652,9 @@ class _SftpPageState extends State { _status.files = fs; _status.isBusy = false; }); + return true; } + return false; } catch (e, trace) { _logger.warning('list dir failed', e, trace); await _backward(); @@ -675,6 +672,7 @@ class _SftpPageState extends State { ], ), ); + return false; } }