mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
@@ -300,6 +300,12 @@ abstract class S {
|
||||
/// **'Delete'**
|
||||
String get delete;
|
||||
|
||||
/// No description provided for @disabled.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Disabled'**
|
||||
String get disabled;
|
||||
|
||||
/// No description provided for @disconnected.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -372,6 +378,12 @@ abstract class S {
|
||||
/// **'Edit'**
|
||||
String get edit;
|
||||
|
||||
/// No description provided for @editVirtKeys.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Edit virtual keys'**
|
||||
String get editVirtKeys;
|
||||
|
||||
/// No description provided for @editor.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -106,6 +106,9 @@ class SDe extends S {
|
||||
@override
|
||||
String get delete => 'Löschen';
|
||||
|
||||
@override
|
||||
String get disabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get disconnected => 'Disconnected';
|
||||
|
||||
@@ -152,6 +155,9 @@ class SDe extends S {
|
||||
@override
|
||||
String get edit => 'Bearbeiten';
|
||||
|
||||
@override
|
||||
String get editVirtKeys => 'Edit virtual keys';
|
||||
|
||||
@override
|
||||
String get editor => 'Editor';
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get delete => 'Delete';
|
||||
|
||||
@override
|
||||
String get disabled => 'Disabled';
|
||||
|
||||
@override
|
||||
String get disconnected => 'Disconnected';
|
||||
|
||||
@@ -152,6 +155,9 @@ class SEn extends S {
|
||||
@override
|
||||
String get edit => 'Edit';
|
||||
|
||||
@override
|
||||
String get editVirtKeys => 'Edit virtual keys';
|
||||
|
||||
@override
|
||||
String get editor => 'Editor';
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get delete => '删除';
|
||||
|
||||
@override
|
||||
String get disabled => '已禁用';
|
||||
|
||||
@override
|
||||
String get disconnected => '连接断开';
|
||||
|
||||
@@ -152,6 +155,9 @@ class SZh extends S {
|
||||
@override
|
||||
String get edit => '编辑';
|
||||
|
||||
@override
|
||||
String get editVirtKeys => '编辑虚拟按键';
|
||||
|
||||
@override
|
||||
String get editor => '编辑器';
|
||||
|
||||
@@ -743,6 +749,9 @@ class SZhTw extends SZh {
|
||||
@override
|
||||
String get delete => '刪除';
|
||||
|
||||
@override
|
||||
String get disabled => '已禁用';
|
||||
|
||||
@override
|
||||
String get disconnected => '連接斷開';
|
||||
|
||||
@@ -789,6 +798,9 @@ class SZhTw extends SZh {
|
||||
@override
|
||||
String get edit => '編輯';
|
||||
|
||||
@override
|
||||
String get editVirtKeys => '編輯虛擬按鍵';
|
||||
|
||||
@override
|
||||
String get editor => '編輯器';
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ PODS:
|
||||
- Flutter (1.0.0)
|
||||
- flutter_native_splash (0.0.1):
|
||||
- Flutter
|
||||
- flutter_volume_controller (0.0.1):
|
||||
- Flutter
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -23,6 +25,7 @@ DEPENDENCIES:
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- plain_notification_token (from `.symlinks/plugins/plain_notification_token/ios`)
|
||||
- r_upgrade (from `.symlinks/plugins/r_upgrade/ios`)
|
||||
@@ -38,6 +41,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_volume_controller:
|
||||
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
plain_notification_token:
|
||||
@@ -54,6 +59,7 @@ SPEC CHECKSUMS:
|
||||
file_picker: 1d63c4949e05e386da864365f8c13e1e64787675
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||
flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
plain_notification_token: b36467dc91939a7b6754267c701bbaca14996ee1
|
||||
r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114
|
||||
@@ -62,4 +68,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 7fb15c416f8685fca4966867a8da218ec592ec2e
|
||||
|
||||
COCOAPODS: 1.11.1
|
||||
COCOAPODS: 1.12.1
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'package:toolbox/core/persistant_store.dart';
|
||||
|
||||
typedef StringOrder = List<String>;
|
||||
typedef Order<T> = List<T>;
|
||||
|
||||
extension StringOrderX on StringOrder {
|
||||
void move(int oldIndex, int newIndex, StoreProperty property) {
|
||||
extension OrderX<T> on Order<T> {
|
||||
void move(int oldIndex, int newIndex, StoreProperty<List<T>> property) {
|
||||
if (oldIndex == newIndex) return;
|
||||
if (oldIndex < newIndex) {
|
||||
newIndex -= 1;
|
||||
@@ -14,17 +14,17 @@ extension StringOrderX on StringOrder {
|
||||
property.put(this);
|
||||
}
|
||||
|
||||
void update(String id, String newId) {
|
||||
void update(T id, T newId) {
|
||||
final index = indexOf(id);
|
||||
if (index == -1) return;
|
||||
this[index] = newId;
|
||||
}
|
||||
|
||||
int index(String id) {
|
||||
int index(T id) {
|
||||
return indexOf(id);
|
||||
}
|
||||
|
||||
void moveById(String oid, String nid, StoreProperty property) {
|
||||
void moveById(T oid, T nid, StoreProperty<List<T>> property) {
|
||||
final index = indexOf(oid);
|
||||
if (index == -1) return;
|
||||
final newIndex = indexOf(nid);
|
||||
|
||||
@@ -1,20 +1,151 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:xterm/core.dart';
|
||||
|
||||
class VirtualKey {
|
||||
final String text;
|
||||
final bool toggleable;
|
||||
final TerminalKey? key;
|
||||
final IconData? icon;
|
||||
final VirtualKeyFunc? func;
|
||||
part 'virtual_key.g.dart';
|
||||
|
||||
VirtualKey(
|
||||
this.text, {
|
||||
this.key,
|
||||
this.toggleable = false,
|
||||
this.icon,
|
||||
this.func,
|
||||
});
|
||||
@HiveType(typeId: 4)
|
||||
enum VirtKey {
|
||||
@HiveField(0)
|
||||
esc,
|
||||
@HiveField(1)
|
||||
alt,
|
||||
@HiveField(2)
|
||||
home,
|
||||
@HiveField(3)
|
||||
up,
|
||||
@HiveField(4)
|
||||
end,
|
||||
@HiveField(5)
|
||||
file,
|
||||
@HiveField(6)
|
||||
snippet,
|
||||
@HiveField(7)
|
||||
tab,
|
||||
@HiveField(8)
|
||||
ctrl,
|
||||
@HiveField(9)
|
||||
left,
|
||||
@HiveField(10)
|
||||
down,
|
||||
@HiveField(11)
|
||||
right,
|
||||
@HiveField(12)
|
||||
paste,
|
||||
@HiveField(13)
|
||||
ime,
|
||||
@HiveField(14)
|
||||
pgup,
|
||||
@HiveField(15)
|
||||
pgdn;
|
||||
|
||||
String get text {
|
||||
switch (this) {
|
||||
case VirtKey.pgdn:
|
||||
return 'PgDn';
|
||||
case VirtKey.pgup:
|
||||
return 'PgUp';
|
||||
default:
|
||||
if (name.length > 1) {
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
TerminalKey? get key {
|
||||
switch (this) {
|
||||
case VirtKey.esc:
|
||||
return TerminalKey.escape;
|
||||
case VirtKey.alt:
|
||||
return TerminalKey.alt;
|
||||
case VirtKey.home:
|
||||
return TerminalKey.home;
|
||||
case VirtKey.up:
|
||||
return TerminalKey.arrowUp;
|
||||
case VirtKey.end:
|
||||
return TerminalKey.end;
|
||||
case VirtKey.tab:
|
||||
return TerminalKey.tab;
|
||||
case VirtKey.ctrl:
|
||||
return TerminalKey.control;
|
||||
case VirtKey.left:
|
||||
return TerminalKey.arrowLeft;
|
||||
case VirtKey.down:
|
||||
return TerminalKey.arrowDown;
|
||||
case VirtKey.right:
|
||||
return TerminalKey.arrowRight;
|
||||
case VirtKey.pgup:
|
||||
return TerminalKey.pageUp;
|
||||
case VirtKey.pgdn:
|
||||
return TerminalKey.pageDown;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
IconData? get icon {
|
||||
switch (this) {
|
||||
case VirtKey.up:
|
||||
return Icons.arrow_upward;
|
||||
case VirtKey.left:
|
||||
return Icons.arrow_back;
|
||||
case VirtKey.down:
|
||||
return Icons.arrow_downward;
|
||||
case VirtKey.right:
|
||||
return Icons.arrow_forward;
|
||||
case VirtKey.file:
|
||||
return Icons.file_open;
|
||||
case VirtKey.snippet:
|
||||
return Icons.code;
|
||||
case VirtKey.paste:
|
||||
return Icons.paste;
|
||||
case VirtKey.ime:
|
||||
return Icons.keyboard_hide;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Use [VirtualKeyFunc] instead of [VirtKey]
|
||||
// This can help linter to enum all [VirtualKeyFunc]
|
||||
// and make sure all [VirtualKeyFunc] are handled
|
||||
VirtualKeyFunc? get func {
|
||||
switch (this) {
|
||||
case VirtKey.file:
|
||||
return VirtualKeyFunc.file;
|
||||
case VirtKey.snippet:
|
||||
return VirtualKeyFunc.snippet;
|
||||
case VirtKey.paste:
|
||||
return VirtualKeyFunc.paste;
|
||||
case VirtKey.ime:
|
||||
return VirtualKeyFunc.toggleIME;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool get toggleable {
|
||||
switch (this) {
|
||||
case VirtKey.alt:
|
||||
case VirtKey.ctrl:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool get canLongPress {
|
||||
switch (this) {
|
||||
case VirtKey.up:
|
||||
case VirtKey.left:
|
||||
case VirtKey.down:
|
||||
case VirtKey.right:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum VirtualKeyFunc { toggleIME, backspace, copy, paste, snippet, file }
|
||||
|
||||
116
lib/data/model/ssh/virtual_key.g.dart
Normal file
116
lib/data/model/ssh/virtual_key.g.dart
Normal file
@@ -0,0 +1,116 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'virtual_key.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class VirtKeyAdapter extends TypeAdapter<VirtKey> {
|
||||
@override
|
||||
final int typeId = 4;
|
||||
|
||||
@override
|
||||
VirtKey read(BinaryReader reader) {
|
||||
switch (reader.readByte()) {
|
||||
case 0:
|
||||
return VirtKey.esc;
|
||||
case 1:
|
||||
return VirtKey.alt;
|
||||
case 2:
|
||||
return VirtKey.home;
|
||||
case 3:
|
||||
return VirtKey.up;
|
||||
case 4:
|
||||
return VirtKey.end;
|
||||
case 5:
|
||||
return VirtKey.file;
|
||||
case 6:
|
||||
return VirtKey.snippet;
|
||||
case 7:
|
||||
return VirtKey.tab;
|
||||
case 8:
|
||||
return VirtKey.ctrl;
|
||||
case 9:
|
||||
return VirtKey.left;
|
||||
case 10:
|
||||
return VirtKey.down;
|
||||
case 11:
|
||||
return VirtKey.right;
|
||||
case 12:
|
||||
return VirtKey.paste;
|
||||
case 13:
|
||||
return VirtKey.ime;
|
||||
case 14:
|
||||
return VirtKey.pgup;
|
||||
case 15:
|
||||
return VirtKey.pgdn;
|
||||
default:
|
||||
return VirtKey.esc;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, VirtKey obj) {
|
||||
switch (obj) {
|
||||
case VirtKey.esc:
|
||||
writer.writeByte(0);
|
||||
break;
|
||||
case VirtKey.alt:
|
||||
writer.writeByte(1);
|
||||
break;
|
||||
case VirtKey.home:
|
||||
writer.writeByte(2);
|
||||
break;
|
||||
case VirtKey.up:
|
||||
writer.writeByte(3);
|
||||
break;
|
||||
case VirtKey.end:
|
||||
writer.writeByte(4);
|
||||
break;
|
||||
case VirtKey.file:
|
||||
writer.writeByte(5);
|
||||
break;
|
||||
case VirtKey.snippet:
|
||||
writer.writeByte(6);
|
||||
break;
|
||||
case VirtKey.tab:
|
||||
writer.writeByte(7);
|
||||
break;
|
||||
case VirtKey.ctrl:
|
||||
writer.writeByte(8);
|
||||
break;
|
||||
case VirtKey.left:
|
||||
writer.writeByte(9);
|
||||
break;
|
||||
case VirtKey.down:
|
||||
writer.writeByte(10);
|
||||
break;
|
||||
case VirtKey.right:
|
||||
writer.writeByte(11);
|
||||
break;
|
||||
case VirtKey.paste:
|
||||
writer.writeByte(12);
|
||||
break;
|
||||
case VirtKey.ime:
|
||||
writer.writeByte(13);
|
||||
break;
|
||||
case VirtKey.pgup:
|
||||
writer.writeByte(14);
|
||||
break;
|
||||
case VirtKey.pgdn:
|
||||
writer.writeByte(15);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is VirtKeyAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -23,8 +23,8 @@ typedef ServersMap = Map<String, Server>;
|
||||
class ServerProvider extends BusyProvider {
|
||||
final ServersMap _servers = {};
|
||||
ServersMap get servers => _servers;
|
||||
final StringOrder _serverOrder = [];
|
||||
StringOrder get serverOrder => _serverOrder;
|
||||
final Order<String> _serverOrder = [];
|
||||
Order get serverOrder => _serverOrder;
|
||||
final List<String> _tags = [];
|
||||
List<String> get tags => _tags;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||
|
||||
// default server details page cards order
|
||||
const defaultDetailCardOrder = [
|
||||
'uptime',
|
||||
@@ -20,6 +22,23 @@ const defaultDiskIgnorePath = [
|
||||
'none',
|
||||
];
|
||||
|
||||
const defaultSSHVirtKeys = [
|
||||
VirtKey.esc,
|
||||
VirtKey.alt,
|
||||
VirtKey.home,
|
||||
VirtKey.up,
|
||||
VirtKey.end,
|
||||
VirtKey.file,
|
||||
VirtKey.snippet,
|
||||
VirtKey.tab,
|
||||
VirtKey.ctrl,
|
||||
VirtKey.left,
|
||||
VirtKey.down,
|
||||
VirtKey.right,
|
||||
VirtKey.paste,
|
||||
VirtKey.ime,
|
||||
];
|
||||
|
||||
const defaultPrimaryColor = Color.fromARGB(255, 145, 58, 31);
|
||||
|
||||
const defaultLaunchPageIdx = 0;
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:xterm/core.dart';
|
||||
|
||||
import '../model/ssh/virtual_key.dart';
|
||||
|
||||
final virtualKeys = [
|
||||
VirtualKey('Esc', key: TerminalKey.escape),
|
||||
VirtualKey('Alt', key: TerminalKey.alt, toggleable: true),
|
||||
VirtualKey('Home', key: TerminalKey.home),
|
||||
VirtualKey('Up', key: TerminalKey.arrowUp, icon: Icons.arrow_upward),
|
||||
VirtualKey('End', key: TerminalKey.end),
|
||||
VirtualKey(
|
||||
'File',
|
||||
func: VirtualKeyFunc.file,
|
||||
icon: Icons.file_open,
|
||||
),
|
||||
VirtualKey('Snippet', func: VirtualKeyFunc.snippet, icon: Icons.code),
|
||||
VirtualKey('Tab', key: TerminalKey.tab),
|
||||
VirtualKey('Ctrl', key: TerminalKey.control, toggleable: true),
|
||||
VirtualKey('Left', key: TerminalKey.arrowLeft, icon: Icons.arrow_back),
|
||||
VirtualKey('Down', key: TerminalKey.arrowDown, icon: Icons.arrow_downward),
|
||||
VirtualKey('Right', key: TerminalKey.arrowRight, icon: Icons.arrow_forward),
|
||||
VirtualKey('Paste', func: VirtualKeyFunc.paste, icon: Icons.paste),
|
||||
VirtualKey(
|
||||
'IME',
|
||||
func: VirtualKeyFunc.toggleIME,
|
||||
icon: Icons.keyboard_hide,
|
||||
),
|
||||
];
|
||||
@@ -1,11 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:toolbox/core/persistant_store.dart';
|
||||
import 'package:toolbox/core/utils/platform.dart';
|
||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||
|
||||
import '../res/default.dart';
|
||||
|
||||
class SettingStore extends PersistentStore {
|
||||
StoreProperty<int> get primaryColor => property(
|
||||
StoreProperty<int> get primaryColor => property<int>(
|
||||
'primaryColor',
|
||||
defaultValue: 4287106639,
|
||||
);
|
||||
@@ -76,4 +77,7 @@ class SettingStore extends PersistentStore {
|
||||
|
||||
StoreProperty<int> get keyboardType =>
|
||||
property('keyboardType', defaultValue: TextInputType.text.index);
|
||||
|
||||
StoreProperty<List<VirtKey>> get sshVirtKeys =>
|
||||
property('sshVirtKeys', defaultValue: defaultSSHVirtKeys);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"debug": "Debug",
|
||||
"decode": "Decode",
|
||||
"delete": "Delete",
|
||||
"disabled": "Disabled",
|
||||
"disconnected": "Disconnected",
|
||||
"diskIgnorePath": "Ignore path for disk",
|
||||
"dl2Local": "Download {fileName} to local?",
|
||||
@@ -46,6 +47,7 @@
|
||||
"download": "Download",
|
||||
"downloadStatus": "{percent}% of {size}",
|
||||
"edit": "Edit",
|
||||
"editVirtKeys": "Edit virtual keys",
|
||||
"editor": "Editor",
|
||||
"encode": "Encode",
|
||||
"error": "Error",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"debug": "调试",
|
||||
"decode": "解码",
|
||||
"delete": "删除",
|
||||
"disabled": "已禁用",
|
||||
"disconnected": "连接断开",
|
||||
"diskIgnorePath": "忽略的磁盘路径",
|
||||
"dl2Local": "下载 {fileName} 到本地?",
|
||||
@@ -46,6 +47,7 @@
|
||||
"download": "下载",
|
||||
"downloadStatus": "{size} 的 {percent}%",
|
||||
"edit": "编辑",
|
||||
"editVirtKeys": "编辑虚拟按键",
|
||||
"editor": "编辑器",
|
||||
"encode": "编码",
|
||||
"error": "错误",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"debug": "調試",
|
||||
"decode": "解碼",
|
||||
"delete": "刪除",
|
||||
"disabled": "已禁用",
|
||||
"disconnected": "連接斷開",
|
||||
"diskIgnorePath": "忽略的磁盤路徑",
|
||||
"dl2Local": "下載 {fileName} 到本地?",
|
||||
@@ -46,6 +47,7 @@
|
||||
"download": "下載",
|
||||
"downloadStatus": "{size} 的 {percent}%",
|
||||
"edit": "編輯",
|
||||
"editVirtKeys": "編輯虛擬按鍵",
|
||||
"editor": "編輯器",
|
||||
"encode": "編碼",
|
||||
"error": "錯誤",
|
||||
|
||||
@@ -4,6 +4,7 @@ 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/data/model/ssh/virtual_key.dart';
|
||||
|
||||
import 'app.dart';
|
||||
import 'core/analysis.dart';
|
||||
@@ -47,6 +48,7 @@ Future<void> initApp() async {
|
||||
Future<void> initHive() async {
|
||||
await Hive.initFlutter();
|
||||
Hive.registerAdapter(SnippetAdapter());
|
||||
Hive.registerAdapter(VirtKeyAdapter());
|
||||
Hive.registerAdapter(PrivateKeyInfoAdapter());
|
||||
Hive.registerAdapter(ServerPrivateInfoAdapter());
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/extension/navigator.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/view/page/ssh.dart';
|
||||
import 'package:toolbox/view/page/ssh/term.dart';
|
||||
import 'package:toolbox/view/widget/input_field.dart';
|
||||
|
||||
import '../../core/utils/ui.dart';
|
||||
|
||||
@@ -32,7 +32,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late MediaQueryData _media;
|
||||
late S _s;
|
||||
final StringOrder _cardsOrder = [];
|
||||
final Order _cardsOrder = [];
|
||||
final _setting = locator<SettingStore>();
|
||||
|
||||
@override
|
||||
|
||||
@@ -25,7 +25,7 @@ import '../../widget/round_rect_card.dart';
|
||||
import '../docker.dart';
|
||||
import '../pkg.dart';
|
||||
import '../sftp/remote.dart';
|
||||
import '../ssh.dart';
|
||||
import '../ssh/term.dart';
|
||||
import 'detail.dart';
|
||||
import 'edit.dart';
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ import 'package:flutter_material_color_picker/flutter_material_color_picker.dart
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:toolbox/core/extension/locale.dart';
|
||||
import 'package:toolbox/core/extension/navigator.dart';
|
||||
import 'package:toolbox/core/route.dart';
|
||||
import 'package:toolbox/data/model/app/tab.dart';
|
||||
import 'package:toolbox/view/page/ssh/virt_key_setting.dart';
|
||||
import 'package:toolbox/view/widget/input_field.dart';
|
||||
import 'package:toolbox/view/widget/value_notifier.dart';
|
||||
|
||||
@@ -165,6 +167,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
_buildTermFontSize(),
|
||||
_buildSSHVirtualKeyAutoOff(),
|
||||
_buildKeyboardType(),
|
||||
_buildSSHVirtKeys(),
|
||||
].map((e) => RoundRectCard(e)).toList(),
|
||||
);
|
||||
}
|
||||
@@ -739,4 +742,15 @@ class _SettingPageState extends State<SettingPage> {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSSHVirtKeys() {
|
||||
return ListTile(
|
||||
title: Text(_s.editVirtKeys),
|
||||
trailing: const Icon(Icons.arrow_forward_ios, size: 13),
|
||||
onTap: () => AppRoute(
|
||||
const SSHVirtKeySettingPage(),
|
||||
'ssh virt key edit',
|
||||
).go(context),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dartssh2/dartssh2.dart';
|
||||
@@ -10,20 +11,19 @@ import 'package:toolbox/core/extension/navigator.dart';
|
||||
import 'package:toolbox/data/res/server_cmd.dart';
|
||||
import 'package:xterm/xterm.dart';
|
||||
|
||||
import '../../core/route.dart';
|
||||
import '../../core/utils/platform.dart';
|
||||
import '../../core/utils/misc.dart';
|
||||
import '../../core/utils/ui.dart';
|
||||
import '../../core/utils/server.dart';
|
||||
import '../../data/model/server/server_private_info.dart';
|
||||
import '../../data/model/ssh/virtual_key.dart';
|
||||
import '../../data/provider/virtual_keyboard.dart';
|
||||
import '../../data/res/color.dart';
|
||||
import '../../data/res/terminal.dart';
|
||||
import '../../data/res/virtual_key.dart';
|
||||
import '../../data/store/setting.dart';
|
||||
import '../../locator.dart';
|
||||
import 'sftp/remote.dart';
|
||||
import '../../../core/route.dart';
|
||||
import '../../../core/utils/platform.dart';
|
||||
import '../../../core/utils/misc.dart';
|
||||
import '../../../core/utils/ui.dart';
|
||||
import '../../../core/utils/server.dart';
|
||||
import '../../../data/model/server/server_private_info.dart';
|
||||
import '../../../data/model/ssh/virtual_key.dart';
|
||||
import '../../../data/provider/virtual_keyboard.dart';
|
||||
import '../../../data/res/color.dart';
|
||||
import '../../../data/res/terminal.dart';
|
||||
import '../../../data/store/setting.dart';
|
||||
import '../../../locator.dart';
|
||||
import '../sftp/remote.dart';
|
||||
|
||||
class SSHPage extends StatefulWidget {
|
||||
final ServerPrivateInfo spi;
|
||||
@@ -35,22 +35,26 @@ class SSHPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SSHPageState extends State<SSHPage> {
|
||||
late final _terminal = Terminal(inputHandler: _keyboard);
|
||||
SSHClient? _client;
|
||||
late SSHSession _session;
|
||||
final _keyboard = locator<VirtualKeyboard>();
|
||||
final _setting = locator<SettingStore>();
|
||||
late MediaQueryData _media;
|
||||
final _virtualKeyboardHeight = 57.0;
|
||||
late final _terminal = Terminal(inputHandler: _keyboard);
|
||||
final TerminalController _terminalController = TerminalController();
|
||||
final ContextMenuController _menuController = ContextMenuController();
|
||||
final List<List<VirtKey>> _virtKeysList = [];
|
||||
|
||||
late MediaQueryData _media;
|
||||
late TextStyle _menuTextStyle;
|
||||
late S _s;
|
||||
late TerminalStyle _terminalStyle;
|
||||
late TerminalTheme _terminalTheme;
|
||||
late TextInputType _keyboardType;
|
||||
late SSHSession _session;
|
||||
late double _virtKeyWidth;
|
||||
late double _virtKeysHeight;
|
||||
|
||||
var _isDark = false;
|
||||
bool _isDark = false;
|
||||
Timer? _virtKeyLongPressTimer;
|
||||
SSHClient? _client;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -62,7 +66,8 @@ class _SSHPageState extends State<SSHPage> {
|
||||
);
|
||||
_terminalStyle = TerminalStyle.fromTextStyle(textStyle);
|
||||
_keyboardType = TextInputType.values[_setting.keyboardType.fetch()!];
|
||||
initTerminal();
|
||||
_initTerminal();
|
||||
_initVirtKeys();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -73,6 +78,9 @@ class _SSHPageState extends State<SSHPage> {
|
||||
_menuTextStyle = TextStyle(color: contentColor.resolve(context));
|
||||
_s = S.of(context)!;
|
||||
_terminalTheme = _isDark ? termDarkTheme : termLightTheme;
|
||||
// Calculate virtkey width / height
|
||||
_virtKeyWidth = _media.size.width / 7;
|
||||
_virtKeysHeight = _media.size.height * 0.047 * _virtKeysList.length;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -100,7 +108,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
Widget _buildBody() {
|
||||
return SizedBox(
|
||||
height: _media.size.height -
|
||||
_virtualKeyboardHeight -
|
||||
_virtKeysHeight -
|
||||
_media.padding.bottom -
|
||||
_media.padding.top,
|
||||
child: TerminalView(
|
||||
@@ -125,7 +133,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
curve: Curves.fastOutSlowIn,
|
||||
child: Container(
|
||||
color: _terminalTheme.background,
|
||||
height: _virtualKeyboardHeight,
|
||||
height: _virtKeysHeight,
|
||||
child: Consumer<VirtualKeyboard>(
|
||||
builder: (_, __, ___) => _buildVirtualKey(),
|
||||
),
|
||||
@@ -135,23 +143,18 @@ class _SSHPageState extends State<SSHPage> {
|
||||
}
|
||||
|
||||
Widget _buildVirtualKey() {
|
||||
final half = virtualKeys.length ~/ 2;
|
||||
final top = virtualKeys.sublist(0, half);
|
||||
final bottom = virtualKeys.sublist(half);
|
||||
final rows = _virtKeysList
|
||||
.map((e) => Row(
|
||||
children: e.map((ee) => _buildVirtualKeyItem(ee)).toList(),
|
||||
))
|
||||
.toList();
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
children: top.map((e) => _buildVirtualKeyItem(e)).toList(),
|
||||
),
|
||||
Row(
|
||||
children: bottom.map((e) => _buildVirtualKeyItem(e)).toList(),
|
||||
)
|
||||
],
|
||||
children: rows,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVirtualKeyItem(VirtualKey item) {
|
||||
Widget _buildVirtualKeyItem(VirtKey item) {
|
||||
var selected = false;
|
||||
switch (item.key) {
|
||||
case TerminalKey.control:
|
||||
@@ -176,9 +179,19 @@ class _SSHPageState extends State<SSHPage> {
|
||||
|
||||
return InkWell(
|
||||
onTap: () => _doVirtualKey(item),
|
||||
onTapDown: (details) {
|
||||
if (item.canLongPress) {
|
||||
_virtKeyLongPressTimer = Timer.periodic(
|
||||
const Duration(milliseconds: 137),
|
||||
(_) => _doVirtualKey(item),
|
||||
);
|
||||
}
|
||||
},
|
||||
onTapCancel: () => _virtKeyLongPressTimer?.cancel(),
|
||||
onTapUp: (_) => _virtKeyLongPressTimer?.cancel(),
|
||||
child: SizedBox(
|
||||
width: _media.size.width / (virtualKeys.length / 2),
|
||||
height: _virtualKeyboardHeight / 2,
|
||||
width: _virtKeyWidth,
|
||||
height: _virtKeysHeight / _virtKeysList.length,
|
||||
child: Center(
|
||||
child: child,
|
||||
),
|
||||
@@ -186,7 +199,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
);
|
||||
}
|
||||
|
||||
void _doVirtualKey(VirtualKey item) {
|
||||
void _doVirtualKey(VirtKey item) {
|
||||
if (item.func != null) {
|
||||
_doVirtualKeyFunc(item.func!);
|
||||
return;
|
||||
@@ -326,7 +339,19 @@ class _SSHPageState extends State<SSHPage> {
|
||||
_terminal.write('$p0\r\n');
|
||||
}
|
||||
|
||||
Future<void> initTerminal() async {
|
||||
void _initVirtKeys() {
|
||||
final virtKeys = _setting.sshVirtKeys.fetch()!;
|
||||
|
||||
for (int len = 0; len < virtKeys.length; len += 7) {
|
||||
if (len + 7 > virtKeys.length) {
|
||||
_virtKeysList.add(virtKeys.sublist(len));
|
||||
} else {
|
||||
_virtKeysList.add(virtKeys.sublist(len, len + 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initTerminal() async {
|
||||
_write('Connecting...\r\n');
|
||||
|
||||
_client = await genClient(
|
||||
100
lib/view/page/ssh/virt_key_setting.dart
Normal file
100
lib/view/page/ssh/virt_key_setting.dart
Normal file
@@ -0,0 +1,100 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:toolbox/core/extension/order.dart';
|
||||
import 'package:toolbox/core/utils/ui.dart';
|
||||
import 'package:toolbox/data/model/ssh/virtual_key.dart';
|
||||
import 'package:toolbox/data/store/setting.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
|
||||
class SSHVirtKeySettingPage extends StatefulWidget {
|
||||
const SSHVirtKeySettingPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SSHVirtKeySettingPageState createState() => _SSHVirtKeySettingPageState();
|
||||
}
|
||||
|
||||
class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
|
||||
final _setting = locator<SettingStore>();
|
||||
late S _s;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_s = S.of(context)!;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(_s.editVirtKeys),
|
||||
),
|
||||
body: _buildBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody() {
|
||||
final keys = List<VirtKey>.from(_setting.sshVirtKeys.fetch()!);
|
||||
final disabled = VirtKey.values.where((e) => !keys.contains(e)).toList();
|
||||
final allKeys = [...keys, ...disabled];
|
||||
return ReorderableListView.builder(
|
||||
padding: const EdgeInsets.fromLTRB(11, 3, 0, 3),
|
||||
itemBuilder: (_, idx) {
|
||||
final key = allKeys[idx];
|
||||
return ListTile(
|
||||
key: ValueKey(idx),
|
||||
title: _buildTitle(key),
|
||||
leading: const Icon(Icons.drag_handle, color: Colors.grey),
|
||||
trailing: _buildCheckBox(keys, key, idx, idx < keys.length),
|
||||
);
|
||||
},
|
||||
itemCount: allKeys.length,
|
||||
onReorder: (o, n) {
|
||||
if (o >= keys.length || n >= keys.length) {
|
||||
showSnackBar(context, Text(_s.disabled));
|
||||
return;
|
||||
}
|
||||
keys.moveById(keys[o], keys[n], _setting.sshVirtKeys);
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTitle(VirtKey key) {
|
||||
return key.icon == null
|
||||
? Text(
|
||||
key.text,
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(key.text),
|
||||
const SizedBox(width: 10),
|
||||
Icon(key.icon),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCheckBox(List<VirtKey> keys, VirtKey key, int idx, bool value) {
|
||||
return Checkbox(
|
||||
value: value,
|
||||
onChanged: (val) {
|
||||
if (val == null) return;
|
||||
if (val) {
|
||||
if (idx >= keys.length) {
|
||||
keys.add(key);
|
||||
} else {
|
||||
keys.insert(idx - 1, key);
|
||||
}
|
||||
} else {
|
||||
keys.remove(key);
|
||||
}
|
||||
_setting.sshVirtKeys.put(keys);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_volume_controller/flutter_volume_controller_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_volume_controller_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterVolumeControllerPlugin");
|
||||
flutter_volume_controller_plugin_register_with_registrar(flutter_volume_controller_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_volume_controller
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import flutter_volume_controller
|
||||
import path_provider_foundation
|
||||
import share_plus
|
||||
import url_launcher_macos
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FlutterVolumeControllerPlugin.register(with: registry.registrar(forPlugin: "FlutterVolumeControllerPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
PODS:
|
||||
- flutter_volume_controller (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
@@ -9,12 +11,15 @@ PODS:
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- flutter_volume_controller (from `Flutter/ephemeral/.symlinks/plugins/flutter_volume_controller/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
flutter_volume_controller:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_volume_controller/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
path_provider_foundation:
|
||||
@@ -25,6 +30,7 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
flutter_volume_controller: 25d09126b0d695560f11c80b1311d5063fed882f
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
|
||||
|
||||
@@ -377,6 +377,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_volume_controller:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_volume_controller
|
||||
sha256: "5e7d1b63d051c881450a98155024219079a1cde0cf66ef895eb96dc9d8a7f670"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.6"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
||||
@@ -66,6 +66,7 @@ dependencies:
|
||||
highlight: ^0.7.0
|
||||
flutter_highlight: ^0.7.0
|
||||
code_text_field: ^1.1.0
|
||||
flutter_volume_controller: ^1.2.6
|
||||
|
||||
dev_dependencies:
|
||||
flutter_native_splash: ^2.1.6
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_volume_controller/flutter_volume_controller_plugin_c_api.h>
|
||||
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlutterVolumeControllerPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterVolumeControllerPluginCApi"));
|
||||
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_volume_controller
|
||||
share_plus
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user