ssh: long press menu bar

This commit is contained in:
lollipopkit
2023-02-01 23:36:21 +08:00
parent 1063916474
commit c47e24ac5b
6 changed files with 138 additions and 57 deletions

View File

@@ -356,7 +356,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 208; CURRENT_PROJECT_VERSION = 209;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -364,7 +364,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.208; MARKETING_VERSION = 1.0.209;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -486,7 +486,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 208; CURRENT_PROJECT_VERSION = 209;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -494,7 +494,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.208; MARKETING_VERSION = 1.0.209;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -510,7 +510,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 208; CURRENT_PROJECT_VERSION = 209;
DEVELOPMENT_TEAM = BA88US33G6; DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
@@ -518,7 +518,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.208; MARKETING_VERSION = 1.0.209;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";

View File

@@ -2,9 +2,9 @@
class BuildData { class BuildData {
static const String name = "ServerBox"; static const String name = "ServerBox";
static const int build = 208; static const int build = 209;
static const String engine = static const String engine =
"Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (8 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n"; "Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (9 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n";
static const String buildAt = "2023-02-01 18:33:57.761096"; static const String buildAt = "2023-02-01 23:33:10.191128";
static const int modifications = 4; static const int modifications = 2;
} }

View File

@@ -3,27 +3,25 @@ import 'package:xterm/core.dart';
import '../model/ssh/virtual_key.dart'; import '../model/ssh/virtual_key.dart';
final virtualKeys = [ var virtualKeys = [
VirtualKey('Esc', key: TerminalKey.escape), VirtualKey('Esc', key: TerminalKey.escape),
VirtualKey('Alt', key: TerminalKey.alt, toggleable: true), VirtualKey('Alt', key: TerminalKey.alt, toggleable: true),
VirtualKey('Home', key: TerminalKey.home), VirtualKey('Home', key: TerminalKey.home),
VirtualKey('Up', key: TerminalKey.arrowUp, icon: Icons.arrow_upward), VirtualKey('Up', key: TerminalKey.arrowUp, icon: Icons.arrow_upward),
VirtualKey('End', key: TerminalKey.end), VirtualKey('End', key: TerminalKey.end),
VirtualKey( // VirtualKey(
'Copy', // 'Del',
func: VirtualKeyFunc.copy, // key: TerminalKey.delete,
icon: Icons.copy, // ),
), VirtualKey('Paste', func: VirtualKeyFunc.paste, icon: Icons.paste),
VirtualKey('Backspace', func: VirtualKeyFunc.backspace, icon: Icons.backspace,),
VirtualKey('Tab', key: TerminalKey.tab), VirtualKey('Tab', key: TerminalKey.tab),
VirtualKey('Ctrl', key: TerminalKey.control, toggleable: true), VirtualKey('Ctrl', key: TerminalKey.control, toggleable: true),
VirtualKey('Left', key: TerminalKey.arrowLeft, icon: Icons.arrow_back), VirtualKey('Left', key: TerminalKey.arrowLeft, icon: Icons.arrow_back),
VirtualKey('Down', key: TerminalKey.arrowDown, icon: Icons.arrow_downward), VirtualKey('Down', key: TerminalKey.arrowDown, icon: Icons.arrow_downward),
VirtualKey('Right', key: TerminalKey.arrowRight, icon: Icons.arrow_forward), VirtualKey('Right', key: TerminalKey.arrowRight, icon: Icons.arrow_forward),
VirtualKey( VirtualKey(
'Paste', 'IME',
func: VirtualKeyFunc.paste, func: VirtualKeyFunc.toggleIME,
icon: Icons.paste, icon: Icons.keyboard_hide,
), ),
VirtualKey('IME', func: VirtualKeyFunc.toggleIME, icon: Icons.keyboard_hide,),
]; ];

View File

@@ -33,6 +33,8 @@ class _SSHPageState extends State<SSHPage> {
late MediaQueryData _media; late MediaQueryData _media;
final _virtualKeyboardHeight = 57.0; final _virtualKeyboardHeight = 57.0;
final TerminalController _terminalController = TerminalController(); final TerminalController _terminalController = TerminalController();
final ContextMenuController _menuController = ContextMenuController();
late TextStyle _menuTextStyle;
var isDark = false; var isDark = false;
@@ -47,6 +49,7 @@ class _SSHPageState extends State<SSHPage> {
super.didChangeDependencies(); super.didChangeDependencies();
isDark = isDarkMode(context); isDark = isDarkMode(context);
_media = MediaQuery.of(context); _media = MediaQuery.of(context);
_menuTextStyle = TextStyle(color: contentColor.resolve(context));
} }
@override @override
@@ -96,7 +99,13 @@ class _SSHPageState extends State<SSHPage> {
final termTheme = isDark ? termDarkTheme : termLightTheme; final termTheme = isDark ? termDarkTheme : termLightTheme;
return Scaffold( return Scaffold(
backgroundColor: termTheme.background, backgroundColor: termTheme.background,
body: SizedBox( body: _buildBody(termTheme),
bottomNavigationBar: _buildBottom(),
);
}
Widget _buildBody(TerminalTheme termTheme) {
return SizedBox(
height: _media.size.height - height: _media.size.height -
_virtualKeyboardHeight - _virtualKeyboardHeight -
_media.padding.bottom - _media.padding.bottom -
@@ -107,11 +116,15 @@ class _SSHPageState extends State<SSHPage> {
keyboardType: TextInputType.visiblePassword, keyboardType: TextInputType.visiblePassword,
theme: termTheme, theme: termTheme,
deleteDetection: Platform.isIOS, deleteDetection: Platform.isIOS,
onTapUp: _onTapUp,
autofocus: true, autofocus: true,
keyboardAppearance: isDark ? Brightness.dark : Brightness.light, keyboardAppearance: isDark ? Brightness.dark : Brightness.light,
), ),
), );
bottomNavigationBar: AnimatedPadding( }
Widget _buildBottom() {
return AnimatedPadding(
padding: _media.viewInsets, padding: _media.viewInsets,
duration: const Duration(milliseconds: 23), duration: const Duration(milliseconds: 23),
curve: Curves.fastOutSlowIn, curve: Curves.fastOutSlowIn,
@@ -121,7 +134,6 @@ class _SSHPageState extends State<SSHPage> {
builder: (_, __, ___) => _buildVirtualKey(), builder: (_, __, ___) => _buildVirtualKey(),
), ),
), ),
),
); );
} }
@@ -216,17 +228,87 @@ class _SSHPageState extends State<SSHPage> {
_terminal.keyInput(TerminalKey.backspace); _terminal.keyInput(TerminalKey.backspace);
break; break;
case VirtualKeyFunc.paste: case VirtualKeyFunc.paste:
_paste();
break;
case VirtualKeyFunc.copy:
_copy(terminalSelected);
break;
}
}
void _paste() {
Clipboard.getData(Clipboard.kTextPlain).then((value) { Clipboard.getData(Clipboard.kTextPlain).then((value) {
if (value != null) { if (value != null) {
_terminal.textInput(value.text!); _terminal.textInput(value.text!);
} }
}); });
break; }
case VirtualKeyFunc.copy:
String get terminalSelected {
final range = _terminalController.selection; final range = _terminalController.selection;
final text = _terminal.buffer.getText(range); if (range == null) {
return '';
}
return _terminal.buffer.getText(range);
}
void _copy(String text) {
Clipboard.setData(ClipboardData(text: text)); Clipboard.setData(ClipboardData(text: text));
break; }
void _onTapUp(TapUpDetails details, CellOffset offset) {
{
if (_menuController.isShown) {
_menuController.remove();
return;
}
final selected = terminalSelected;
if (selected.trim().isEmpty) {
// _menuController.show(
// context: context,
// contextMenuBuilder: (context) {
// return TextSelectionToolbar(
// anchorAbove: detail.globalPosition,
// anchorBelow: detail.globalPosition,
// children: [
// TextButton(
// child: Text(
// 'Paste',
// style: _menuTextStyle,
// ),
// onPressed: () async {
// _paste();
// _menuController.remove();
// },
// )
// ],
// );
// },
// );
return;
}
_menuController.show(
context: context,
contextMenuBuilder: (context) {
return TextSelectionToolbar(
anchorAbove: details.globalPosition,
anchorBelow: details.globalPosition,
children: [
TextButton(
child: Text(
'Copy',
style: _menuTextStyle,
),
onPressed: () {
_terminalController.setSelection(null);
_copy(selected);
_menuController.remove();
},
),
],
);
},
);
} }
} }
} }

View File

@@ -998,10 +998,9 @@ packages:
xterm: xterm:
dependency: "direct main" dependency: "direct main"
description: description:
name: xterm path: "../xterm.dart"
sha256: f65619cb24d03507812e346ddb8386cad9e16a01a481a8f5c8a2eba55b4edada relative: true
url: "https://pub.dev" source: path
source: hosted
version: "3.4.1" version: "3.4.1"
yaml: yaml:
dependency: transitive dependency: transitive

View File

@@ -53,7 +53,9 @@ dependencies:
share_plus: ^6.3.0 share_plus: ^6.3.0
intl: ^0.17.0 intl: ^0.17.0
share_plus_web: ^3.1.0 share_plus_web: ^3.1.0
xterm: ^3.4.1 # xterm: ^3.4.1
xterm:
path: ../xterm.dart
dev_dependencies: dev_dependencies:
flutter_native_splash: ^2.1.6 flutter_native_splash: ^2.1.6