From f3c670d82cf0e5a3642c0fe281109ea22ef89f04 Mon Sep 17 00:00:00 2001 From: LollipopKit Date: Sun, 29 Jan 2023 16:56:40 +0800 Subject: [PATCH] opt. proj struct --- lib/core/utils.dart | 8 ++ lib/data/model/server/cpu_status.dart | 64 +++++++--- lib/data/model/server/memory.dart | 28 +++-- lib/data/model/server/net_speed.dart | 31 +++-- lib/data/model/server/server_status.dart | 10 -- lib/data/model/server/tcp_status.dart | 15 +++ lib/data/model/ssh/virtual_key.dart | 26 ++++ lib/data/provider/server.dart | 144 ++++------------------- lib/data/provider/virtual_keyboard.dart | 29 +++++ lib/data/res/status.dart | 48 ++++++++ lib/locator.dart | 3 + lib/main.dart | 51 +++----- lib/view/page/server/tab.dart | 6 +- lib/view/page/sftp/view.dart | 2 +- lib/view/page/ssh.dart | 50 +------- 15 files changed, 266 insertions(+), 249 deletions(-) create mode 100644 lib/data/model/ssh/virtual_key.dart create mode 100644 lib/data/provider/virtual_keyboard.dart create mode 100644 lib/data/res/status.dart diff --git a/lib/core/utils.dart b/lib/core/utils.dart index 1ce06ace..1a2bebb8 100644 --- a/lib/core/utils.dart +++ b/lib/core/utils.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:io'; +import 'package:dartssh2/dartssh2.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:share_plus/share_plus.dart'; @@ -10,6 +11,13 @@ import 'package:toolbox/view/widget/card_dialog.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:toolbox/core/extension/stringx.dart'; +/// Must put this func out of any Class. +/// Because of this function is called by [compute] in [ServerProvider.genClient]. +/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure +List loadIndentity(String key) { + return SSHKeyPair.fromPem(key); +} + bool isDarkMode(BuildContext context) => Theme.of(context).brightness == Brightness.dark; diff --git a/lib/data/model/server/cpu_status.dart b/lib/data/model/server/cpu_status.dart index 6824c14a..f6772541 100644 --- a/lib/data/model/server/cpu_status.dart +++ b/lib/data/model/server/cpu_status.dart @@ -1,19 +1,3 @@ -get initOneTimeCpuStatus => OneTimeCpuStatus( - 'cpu', - 0, - 0, - 0, - 0, - 0, - 0, - 0, - ); -get initCpuStatus => CpuStatus( - [initOneTimeCpuStatus], - [initOneTimeCpuStatus], - '', - ); - class CpuStatus { List _pre; List _now; @@ -107,3 +91,51 @@ class OneTimeCpuStatus { int get total => user + sys + nice + idle + iowait + irq + softirq; } + +List parseCPU(String raw) { + final List cpus = []; + + for (var item in raw.split('\n')) { + if (item == '') break; + final id = item.split(' ').first; + final matches = item.replaceFirst(id, '').trim().split(' '); + cpus.add(OneTimeCpuStatus( + id, + int.parse(matches[0]), + int.parse(matches[1]), + int.parse(matches[2]), + int.parse(matches[3]), + int.parse(matches[4]), + int.parse(matches[5]), + int.parse(matches[6]))); + } + return cpus; +} + +final cpuTempReg = RegExp(r'(x86_pkg_temp|cpu_thermal)'); + +String parseCPUTemp(List segments) { + const noMatch = "/sys/class/thermal/thermal_zone*/type"; + final type = segments[0]; + final value = segments[1]; + // Not support to get CPU temperature + if (value.contains(noMatch) || + type.contains(noMatch) || + value.isEmpty || + type.isEmpty) { + return ''; + } + final split = type.split('\n'); + int idx = 0; + for (var item in split) { + if (item.contains(cpuTempReg)) { + break; + } + idx++; + } + final valueSplited = value.split('\n'); + if (idx >= valueSplited.length) return ''; + final temp = int.tryParse(valueSplited[idx].trim()); + if (temp == null) return ''; + return '${(temp / 1000).toStringAsFixed(1)}°C'; +} diff --git a/lib/data/model/server/memory.dart b/lib/data/model/server/memory.dart index 7c05b10a..928ea054 100644 --- a/lib/data/model/server/memory.dart +++ b/lib/data/model/server/memory.dart @@ -1,11 +1,3 @@ -get initMemory => Memory( - total: 1, - used: 0, - free: 1, - cache: 0, - avail: 1, - ); - class Memory { int total; int used; @@ -19,3 +11,23 @@ class Memory { required this.cache, required this.avail}); } + +final memItemReg = RegExp(r'([A-Z].+:)\s+([0-9]+) kB'); + +Memory parseMem(String raw) { + final items = raw.split('\n').map((e) => memItemReg.firstMatch(e)).toList(); + final total = int.parse( + items.firstWhere((e) => e?.group(1) == 'MemTotal:')?.group(2) ?? '1'); + final free = int.parse( + items.firstWhere((e) => e?.group(1) == 'MemFree:')?.group(2) ?? '0'); + final cached = int.parse( + items.firstWhere((e) => e?.group(1) == 'Cached:')?.group(2) ?? '0'); + final available = int.parse( + items.firstWhere((e) => e?.group(1) == 'MemAvailable:')?.group(2) ?? '0'); + return Memory( + total: total, + used: total - available, + free: free, + cache: cached, + avail: available); +} diff --git a/lib/data/model/server/net_speed.dart b/lib/data/model/server/net_speed.dart index 283963c5..f832bf00 100644 --- a/lib/data/model/server/net_speed.dart +++ b/lib/data/model/server/net_speed.dart @@ -1,16 +1,5 @@ import 'package:toolbox/core/extension/numx.dart'; -get initNetSpeedPart => NetSpeedPart( - '', - 0, - 0, - 0, - ); -get initNetSpeed => NetSpeed( - [initNetSpeedPart], - [initNetSpeedPart], - ); - class NetSpeedPart { String device; int bytesIn; @@ -69,3 +58,23 @@ class NetSpeed { String buildStandardOutput(double speed) => '${speed.convertBytes.toLowerCase()}/s'; } + +List parseNetSpeed(String raw) { + final split = raw.split('\n'); + if (split.length < 4) { + return []; + } + + final time = int.parse(split[split.length - 1]); + final results = []; + for (final item in split.sublist(2, split.length - 1)) { + final data = item.trim().split(':'); + final device = data.first; + final bytes = data.last.trim().split(' '); + bytes.removeWhere((element) => element == ''); + final bytesIn = int.parse(bytes.first); + final bytesOut = int.parse(bytes[8]); + results.add(NetSpeedPart(device, bytesIn, bytesOut, time)); + } + return results; +} diff --git a/lib/data/model/server/server_status.dart b/lib/data/model/server/server_status.dart index 728ce5f8..91df6870 100644 --- a/lib/data/model/server/server_status.dart +++ b/lib/data/model/server/server_status.dart @@ -8,16 +8,6 @@ import 'package:toolbox/data/model/server/tcp_status.dart'; /// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/ /// -get initStatus => ServerStatus( - initCpuStatus, - initMemory, - 'Loading...', - '', - [DiskInfo('/', '/', 0, '0', '0', '0')], - TcpStatus(0, 0, 0, 0), - initNetSpeed, - ); - class ServerStatus { /* { diff --git a/lib/data/model/server/tcp_status.dart b/lib/data/model/server/tcp_status.dart index daf0d3e7..19cfd39b 100644 --- a/lib/data/model/server/tcp_status.dart +++ b/lib/data/model/server/tcp_status.dart @@ -1,3 +1,5 @@ +import '../../../core/extension/stringx.dart'; + /// /// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/ /// @@ -39,3 +41,16 @@ class TcpStatus { return data; } } + +final numReg = RegExp(r'\s{1,}'); + +TcpStatus? parseTcp(String raw) { + final lines = raw.split('\n'); + final idx = lines.lastWhere((element) => element.startsWith('Tcp:'), + orElse: () => ''); + if (idx != '') { + final vals = idx.split(numReg); + return TcpStatus(vals[5].i, vals[6].i, vals[7].i, vals[8].i); + } + return null; +} diff --git a/lib/data/model/ssh/virtual_key.dart b/lib/data/model/ssh/virtual_key.dart new file mode 100644 index 00000000..2cccaf0f --- /dev/null +++ b/lib/data/model/ssh/virtual_key.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:xterm/core.dart'; + +class VirtualKey { + final TerminalKey key; + final String text; + final bool toggleable; + final IconData? icon; + + VirtualKey(this.key, this.text, {this.toggleable = false, this.icon}); +} + +var virtualKeys = [ + VirtualKey(TerminalKey.escape, 'Esc'), + VirtualKey(TerminalKey.alt, 'Alt', toggleable: true), + VirtualKey(TerminalKey.pageUp, 'PgUp'), + VirtualKey(TerminalKey.arrowUp, 'Up', icon: Icons.arrow_upward), + VirtualKey(TerminalKey.pageDown, 'PgDn'), + VirtualKey(TerminalKey.end, 'End'), + VirtualKey(TerminalKey.tab, 'Tab'), + VirtualKey(TerminalKey.control, 'Ctrl', toggleable: true), + VirtualKey(TerminalKey.arrowLeft, 'Left', icon: Icons.arrow_back), + VirtualKey(TerminalKey.arrowDown, 'Down', icon: Icons.arrow_downward), + VirtualKey(TerminalKey.arrowRight, 'Right', icon: Icons.arrow_forward), + VirtualKey(TerminalKey.home, 'Home'), +]; diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 24eb1144..1a4efc9a 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -3,29 +3,23 @@ import 'dart:async'; import 'package:dartssh2/dartssh2.dart'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; -import 'package:toolbox/core/extension/stringx.dart'; -import 'package:toolbox/core/extension/uint8list.dart'; -import 'package:toolbox/core/provider_base.dart'; -import 'package:toolbox/data/model/server/cpu_status.dart'; -import 'package:toolbox/data/model/server/memory.dart'; -import 'package:toolbox/data/model/server/net_speed.dart'; -import 'package:toolbox/data/model/server/disk_info.dart'; -import 'package:toolbox/data/model/server/server.dart'; -import 'package:toolbox/data/model/server/server_private_info.dart'; -import 'package:toolbox/data/model/server/server_status.dart'; -import 'package:toolbox/data/model/server/snippet.dart'; -import 'package:toolbox/data/model/server/tcp_status.dart'; -import 'package:toolbox/data/store/private_key.dart'; -import 'package:toolbox/data/store/server.dart'; -import 'package:toolbox/data/store/setting.dart'; -import 'package:toolbox/locator.dart'; -/// Must put this func out of any Class. -/// Because of this function is called by [compute] in [ServerProvider.genClient]. -/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure -List loadIndentity(String key) { - return SSHKeyPair.fromPem(key); -} +import '../../core/extension/uint8list.dart'; +import '../../core/provider_base.dart'; +import '../../core/utils.dart'; +import '../../locator.dart'; +import '../model/server/cpu_status.dart'; +import '../model/server/disk_info.dart'; +import '../model/server/memory.dart'; +import '../model/server/net_speed.dart'; +import '../model/server/server.dart'; +import '../model/server/server_private_info.dart'; +import '../model/server/snippet.dart'; +import '../model/server/tcp_status.dart'; +import '../res/status.dart'; +import '../store/private_key.dart'; +import '../store/server.dart'; +import '../store/setting.dart'; const seperator = 'A====A'; const shellCmd = "export LANG=en_US.utf-8 \necho '$seperator' \n" @@ -39,9 +33,6 @@ const shellCmd = "export LANG=en_US.utf-8 \necho '$seperator' \n" "cat /sys/class/thermal/thermal_zone*/type \necho $seperator \n" "cat /sys/class/thermal/thermal_zone*/temp"; const shellPath = '.serverbox.sh'; -final cpuTempReg = RegExp(r'(x86_pkg_temp|cpu_thermal)'); -final numReg = RegExp(r'\s{1,}'); -final memItemReg = RegExp(r'([A-Z].+:)\s+([0-9]+) kB'); class ServerProvider extends BusyProvider { List _servers = []; @@ -221,7 +212,7 @@ class ServerProvider extends BusyProvider { /// 1635752901 Future _getNetSpeed(ServerPrivateInfo spi, String raw) async { final info = _servers.firstWhere((e) => e.spi == spi); - info.status.netSpeed.update(await compute(_parseNetSpeed, raw)); + info.status.netSpeed.update(await compute(parseNetSpeed, raw)); } void _getSysVer(ServerPrivateInfo spi, String raw) { @@ -235,11 +226,11 @@ class ServerProvider extends BusyProvider { Future _getCPU(ServerPrivateInfo spi, String raw, String tempType, String tempValue) async { final info = _servers.firstWhere((e) => e.spi == spi); - final cpus = await compute(_parseCPU, raw); + final cpus = await compute(parseCPU, raw); if (cpus.isNotEmpty) { info.status.cpu - .update(cpus, await compute(_getCPUTemp, [tempType, tempValue])); + .update(cpus, await compute(parseCPUTemp, [tempType, tempValue])); } } @@ -250,7 +241,7 @@ class ServerProvider extends BusyProvider { Future _getTcp(ServerPrivateInfo spi, String raw) async { final info = _servers.firstWhere((e) => e.spi == spi); - final status = await compute(_parseTcp, raw); + final status = await compute(parseTcp, raw); if (status != null) { info.status.tcp = status; } @@ -273,7 +264,7 @@ class ServerProvider extends BusyProvider { Future _getMem(ServerPrivateInfo spi, String raw) async { final info = _servers.firstWhere((e) => e.spi == spi); - final mem = await compute(_parseMem, raw); + final mem = await compute(parseMem, raw); info.status.mem = mem; } @@ -286,96 +277,3 @@ class ServerProvider extends BusyProvider { return await client.run(snippet.script).string; } } - -Memory _parseMem(String raw) { - final items = raw.split('\n').map((e) => memItemReg.firstMatch(e)).toList(); - final total = int.parse( - items.firstWhere((e) => e?.group(1) == 'MemTotal:')?.group(2) ?? '1'); - final free = int.parse( - items.firstWhere((e) => e?.group(1) == 'MemFree:')?.group(2) ?? '0'); - final cached = int.parse( - items.firstWhere((e) => e?.group(1) == 'Cached:')?.group(2) ?? '0'); - final available = int.parse( - items.firstWhere((e) => e?.group(1) == 'MemAvailable:')?.group(2) ?? '0'); - return Memory( - total: total, - used: total - available, - free: free, - cache: cached, - avail: available); -} - -TcpStatus? _parseTcp(String raw) { - final lines = raw.split('\n'); - final idx = lines.lastWhere((element) => element.startsWith('Tcp:'), - orElse: () => ''); - if (idx != '') { - final vals = idx.split(numReg); - return TcpStatus(vals[5].i, vals[6].i, vals[7].i, vals[8].i); - } - return null; -} - -List _parseCPU(String raw) { - final List cpus = []; - - for (var item in raw.split('\n')) { - if (item == '') break; - final id = item.split(' ').first; - final matches = item.replaceFirst(id, '').trim().split(' '); - cpus.add(OneTimeCpuStatus( - id, - int.parse(matches[0]), - int.parse(matches[1]), - int.parse(matches[2]), - int.parse(matches[3]), - int.parse(matches[4]), - int.parse(matches[5]), - int.parse(matches[6]))); - } - return cpus; -} - -String _getCPUTemp(List segments) { - const noMatch = "/sys/class/thermal/thermal_zone*/type"; - final type = segments[0]; - final value = segments[1]; - // Not support to get CPU temperature - if (value.contains(noMatch) || - type.contains(noMatch) || - value.isEmpty || - type.isEmpty) { - return ''; - } - final split = type.split('\n'); - int idx = 0; - for (var item in split) { - if (item.contains(cpuTempReg)) { - break; - } - idx++; - } - final valueSplited = value.split('\n'); - if (idx >= valueSplited.length) return ''; - final temp = int.tryParse(valueSplited[idx].trim()); - if (temp == null) return ''; - return '${(temp / 1000).toStringAsFixed(1)}°C'; -} - -List _parseNetSpeed(String raw) { - final split = raw.split('\n'); - final deviceCount = split.length - 3; - if (deviceCount < 1) return []; - final time = int.parse(split[split.length - 1]); - final results = []; - for (int idx = 2; idx < deviceCount; idx++) { - final data = split[idx].trim().split(':'); - final device = data.first; - final bytes = data.last.trim().split(' '); - bytes.removeWhere((element) => element == ''); - final bytesIn = int.parse(bytes.first); - final bytesOut = int.parse(bytes[8]); - results.add(NetSpeedPart(device, bytesIn, bytesOut, time)); - } - return results; -} diff --git a/lib/data/provider/virtual_keyboard.dart b/lib/data/provider/virtual_keyboard.dart new file mode 100644 index 00000000..624baa05 --- /dev/null +++ b/lib/data/provider/virtual_keyboard.dart @@ -0,0 +1,29 @@ +import 'package:flutter/widgets.dart'; +import 'package:xterm/core.dart'; + +class VirtualKeyboard extends TerminalInputHandler with ChangeNotifier { + VirtualKeyboard(); + + bool ctrl = false; + bool alt = false; + + void reset(TerminalKeyboardEvent e) { + if (e.ctrl) { + ctrl = false; + } + if (e.alt) { + alt = false; + } + notifyListeners(); + } + + @override + String? call(TerminalKeyboardEvent event) { + final e = event.copyWith( + ctrl: event.ctrl || ctrl, + alt: event.alt || alt, + ); + reset(e); + return defaultInputHandler.call(e); + } +} diff --git a/lib/data/res/status.dart b/lib/data/res/status.dart new file mode 100644 index 00000000..509af40d --- /dev/null +++ b/lib/data/res/status.dart @@ -0,0 +1,48 @@ +import '../model/server/cpu_status.dart'; +import '../model/server/disk_info.dart'; +import '../model/server/memory.dart'; +import '../model/server/net_speed.dart'; +import '../model/server/server_status.dart'; +import '../model/server/tcp_status.dart'; + +get _initMemory => Memory( + total: 1, + used: 0, + free: 1, + cache: 0, + avail: 1, +); +get _initOneTimeCpuStatus => OneTimeCpuStatus( + 'cpu', + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ); +get initCpuStatus => CpuStatus( + [_initOneTimeCpuStatus], + [_initOneTimeCpuStatus], + '', + ); +get _initNetSpeedPart => NetSpeedPart( + '', + 0, + 0, + 0, + ); +get initNetSpeed => NetSpeed( + [_initNetSpeedPart], + [_initNetSpeedPart], + ); +get initStatus => ServerStatus( + initCpuStatus, + _initMemory, + 'Loading...', + '', + [DiskInfo('/', '/', 0, '0', '0', '0')], + TcpStatus(0, 0, 0, 0), + initNetSpeed, + ); \ No newline at end of file diff --git a/lib/locator.dart b/lib/locator.dart index b1faf26a..dcc9e3d2 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -14,6 +14,8 @@ import 'package:toolbox/data/store/server.dart'; import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/data/store/snippet.dart'; +import 'data/provider/virtual_keyboard.dart'; + GetIt locator = GetIt.instance; void setupLocatorForServices() { @@ -26,6 +28,7 @@ void setupLocatorForProviders() { locator.registerSingleton(DebugProvider()); locator.registerSingleton(DockerProvider()); locator.registerSingleton(ServerProvider()); + locator.registerSingleton(VirtualKeyboard()); locator.registerSingleton(SnippetProvider()); locator.registerSingleton(PrivateKeyProvider()); locator.registerSingleton(SftpDownloadProvider()); diff --git a/lib/main.dart b/lib/main.dart index cb2d1a67..602416f6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,30 +4,26 @@ import 'package:flutter/material.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; -import 'package:toolbox/app.dart'; -import 'package:toolbox/core/analysis.dart'; -import 'package:toolbox/core/persistant_store.dart'; -import 'package:toolbox/data/model/server/private_key_info.dart'; -import 'package:toolbox/data/model/server/server_private_info.dart'; -import 'package:toolbox/data/model/server/snippet.dart'; -import 'package:toolbox/data/provider/app.dart'; -import 'package:toolbox/data/provider/pkg.dart'; -import 'package:toolbox/data/provider/debug.dart'; -import 'package:toolbox/data/provider/docker.dart'; -import 'package:toolbox/data/provider/private_key.dart'; -import 'package:toolbox/data/provider/server.dart'; -import 'package:toolbox/data/provider/sftp_download.dart'; -import 'package:toolbox/data/provider/snippet.dart'; -import 'package:toolbox/data/store/private_key.dart'; -import 'package:toolbox/data/store/server.dart'; -import 'package:toolbox/data/store/setting.dart'; -import 'package:toolbox/data/store/snippet.dart'; -import 'package:toolbox/locator.dart'; + +import 'app.dart'; +import 'core/analysis.dart'; +import 'data/model/server/private_key_info.dart'; +import 'data/model/server/server_private_info.dart'; +import 'data/model/server/snippet.dart'; +import 'data/provider/app.dart'; +import 'data/provider/debug.dart'; +import 'data/provider/docker.dart'; +import 'data/provider/pkg.dart'; +import 'data/provider/private_key.dart'; +import 'data/provider/server.dart'; +import 'data/provider/sftp_download.dart'; +import 'data/provider/snippet.dart'; +import 'data/provider/virtual_keyboard.dart'; +import 'locator.dart'; Future initApp() async { await initHive(); await setupLocator(); - await upgradeStore(); locator().loadData(); locator().loadData(); @@ -47,20 +43,6 @@ Future initHive() async { Hive.registerAdapter(ServerPrivateInfoAdapter()); } -Future upgradeStore() async { - final setting = locator(); - final version = setting.storeVersion.fetch(); - if (version == 0) { - final snippet = locator(); - final key = locator(); - final spi = locator(); - for (final s in [snippet, key, spi]) { - await s.box.deleteAll(s.box.keys); - } - setting.storeVersion.put(1); - } -} - void runInZone(dynamic Function() body) { final zoneSpec = ZoneSpecification( print: (Zone self, ZoneDelegate parent, Zone zone, String line) { @@ -101,6 +83,7 @@ Future main() async { ChangeNotifierProvider(create: (_) => locator()), ChangeNotifierProvider(create: (_) => locator()), ChangeNotifierProvider(create: (_) => locator()), + ChangeNotifierProvider(create: (_) => locator()), ChangeNotifierProvider(create: (_) => locator()), ChangeNotifierProvider( create: (_) => locator()), diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 12fddf71..e263ae90 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -388,8 +388,10 @@ class _ServerPageState extends State child: Text(_s.ok), ), TextButton( - onPressed: () => - AppRoute(const SnippetEditPage(), 'edit snippet').go(context), + onPressed: () { + Navigator.of(context).pop(); + AppRoute(const SnippetEditPage(), 'edit snippet').go(context); + }, child: Text(_s.addOne), ) ], diff --git a/lib/view/page/sftp/view.dart b/lib/view/page/sftp/view.dart index 7778f875..73115b39 100644 --- a/lib/view/page/sftp/view.dart +++ b/lib/view/page/sftp/view.dart @@ -71,7 +71,7 @@ class _SFTPPageState extends State { ], ), body: _buildFileView(), - bottomNavigationBar: _buildBottom(), + bottomNavigationBar: SafeArea(child: _buildBottom()), ); } diff --git a/lib/view/page/ssh.dart b/lib/view/page/ssh.dart index c5df64fb..50a10855 100644 --- a/lib/view/page/ssh.dart +++ b/lib/view/page/ssh.dart @@ -4,11 +4,13 @@ import 'package:dartssh2/dartssh2.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; import 'package:xterm/xterm.dart'; import '../../core/utils.dart'; import '../../data/model/server/server_private_info.dart'; -import '../../data/provider/server.dart'; +import '../../data/model/ssh/virtual_key.dart'; +import '../../data/provider/virtual_keyboard.dart'; import '../../data/res/terminal_theme.dart'; import '../../data/store/private_key.dart'; import '../../locator.dart'; @@ -24,7 +26,7 @@ class SSHPage extends StatefulWidget { class _SSHPageState extends State { late final terminal = Terminal(inputHandler: keyboard); late final SSHClient client; - final keyboard = VirtualKeyboard(defaultInputHandler); + final keyboard = locator(); late double _screenWidth; var isDark = false; @@ -99,7 +101,8 @@ class _SSHPageState extends State { keyboardAppearance: isDark ? Brightness.dark : Brightness.light, ), ), - _buildVirtualKey(), + Consumer( + builder: (_, __, ___) => _buildVirtualKey()), ], ), ); @@ -189,44 +192,3 @@ Future genClient(ServerPrivateInfo spi) async { identities: await compute(loadIndentity, key.privateKey), ); } - -class VirtualKey { - final TerminalKey key; - final String text; - final bool toggleable; - final IconData? icon; - - VirtualKey(this.key, this.text, {this.toggleable = false, this.icon}); -} - -var virtualKeys = [ - VirtualKey(TerminalKey.escape, 'Esc'), - VirtualKey(TerminalKey.alt, 'Alt', toggleable: true), - VirtualKey(TerminalKey.pageUp, 'PgUp'), - VirtualKey(TerminalKey.arrowUp, 'Up', icon: Icons.arrow_upward), - VirtualKey(TerminalKey.pageDown, 'PgDn'), - VirtualKey(TerminalKey.end, 'End'), - VirtualKey(TerminalKey.tab, 'Tab'), - VirtualKey(TerminalKey.control, 'Ctrl', toggleable: true), - VirtualKey(TerminalKey.arrowLeft, 'Left', icon: Icons.arrow_back), - VirtualKey(TerminalKey.arrowDown, 'Down', icon: Icons.arrow_downward), - VirtualKey(TerminalKey.arrowRight, 'Right', icon: Icons.arrow_forward), - VirtualKey(TerminalKey.home, 'Home'), -]; - -class VirtualKeyboard extends TerminalInputHandler with ChangeNotifier { - final TerminalInputHandler inputHandler; - - VirtualKeyboard(this.inputHandler); - - bool ctrl = false; - bool alt = false; - - @override - String? call(TerminalKeyboardEvent event) { - return inputHandler.call(event.copyWith( - ctrl: event.ctrl || ctrl, - alt: event.alt || alt, - )); - } -}