refactor(ssh): Update Terminal page to adapt new copy and paste logic (#1054)

* refactor(ssh): Remove terminal copy button and streamline clipboard functionality

Update dependency versions and remove the copy button from the terminal page, integrating clipboard functionality into the terminal controller.

* refactor(ssh): Optimize clipboard paste functionality implementation

Convert the _OnTerminalPaste method to an asynchronous implementation and remove duplicate _paste methods.

* refactor(ssh): Rename clipboard operation function and add new functionality

Renamed _onTerminalPaste to _onClipboardAction and expanded its functionality

Now supports copying selected text to the clipboard and performing paste operations when no text is selected

* fix: Fixed an issue where clipboard operations did not wait for asynchronous completion.

* fix(ssh): Fixed terminal paste operation return logic

Prevented redundant _onTerminalPaste calls after terminal paste operations
This commit is contained in:
GT610
2026-02-27 21:56:16 +08:00
committed by GitHub
parent ad0ef52f71
commit 8b1326ff64
6 changed files with 76 additions and 78 deletions

View File

@@ -8,7 +8,6 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:icons_plus/icons_plus.dart';
import 'package:server_box/core/chan.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/core/utils/server.dart';
@@ -187,7 +186,6 @@ class SSHPageState extends ConsumerState<SSHPage>
? CustomAppBar(
leading: BackButton(onPressed: context.pop),
title: Text(widget.args.spi.name),
actions: [_buildCopyBtn],
centerTitle: false,
)
: null,
@@ -257,6 +255,9 @@ class SSHPageState extends ConsumerState<SSHPage>
hideScrollBar: false,
focusNode: widget.args.focusNode,
toolbarBuilder: _buildTerminalToolbar,
onCopied: _onTerminalCopied,
onSelectAll: _onTerminalSelectAll,
onPaste: _onTerminalPaste,
),
),
);
@@ -364,18 +365,39 @@ class SSHPageState extends ConsumerState<SSHPage>
);
}
Widget get _buildCopyBtn {
return IconButton(
icon: Icon(MingCute.copy_2_fill),
tooltip: libL10n.copy,
onPressed: () {
final selected = terminalSelected;
if (selected == null || selected.isEmpty) {
return;
}
Pfs.copy(selected);
},
);
void _onTerminalCopied() {
if (!mounted) return;
context.showSnackBar(libL10n.success);
_terminalController.clearSelection();
}
void _onTerminalSelectAll() {
if (!mounted) return;
_termKey.currentState?.renderTerminal.selectAll();
}
Future<void> _onTerminalPaste() async {
final value = await Clipboard.getData(Clipboard.kTextPlain);
if (!mounted) return;
final text = value?.text;
if (text == null) return;
_terminal.textInput(text);
_terminalController.clearSelection();
}
Future<void> _onClipboardAction() async {
if (_terminalController.selection != null) {
final selectedText = _termKey.currentState?.renderTerminal.selectedText;
if (selectedText != null && selectedText.isNotEmpty) {
await Clipboard.setData(ClipboardData(text: selectedText));
if (!mounted) return;
context.showSnackBar(libL10n.success);
_terminalController.clearSelection();
return;
}
return;
}
await _onTerminalPaste();
}
@override

View File

@@ -44,12 +44,7 @@ extension _VirtKey on SSHPageState {
_terminal.keyInput(TerminalKey.backspace);
break;
case VirtualKeyFunc.clipboard:
final selected = terminalSelected;
if (selected != null) {
Pfs.copy(selected);
} else {
_paste();
}
await _onClipboardAction();
break;
case VirtualKeyFunc.snippet:
final snippetState = ref.read(snippetProvider);
@@ -127,25 +122,6 @@ extension _VirtKey on SSHPageState {
}
}
void _paste() {
Clipboard.getData(Clipboard.kTextPlain).then((value) {
final text = value?.text;
if (text != null) {
_terminal.textInput(text);
} else {
context.showRoundDialog(title: libL10n.error, child: Text(libL10n.empty));
}
});
}
String? get terminalSelected {
final range = _terminalController.selection;
if (range == null) {
return null;
}
return _terminal.buffer.getText(range);
}
void _initVirtKeys() {
final virtKeys = VirtKeyX.loadFromStore();
for (int len = 0; len < virtKeys.length; len += 7) {

View File

@@ -85,10 +85,10 @@ packages:
dependency: transitive
description:
name: archive
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff
url: "https://pub.dev"
source: hosted
version: "4.0.7"
version: "4.0.9"
args:
dependency: transitive
description:
@@ -165,18 +165,18 @@ packages:
dependency: transitive
description:
name: built_value
sha256: "7931c90b84bc573fef103548e354258ae4c9d28d140e41961df6843c5d60d4d8"
sha256: "6ae8a6435a8c6520c7077b107e77f1fb4ba7009633259a4d49a8afd8e7efc5e9"
url: "https://pub.dev"
source: hosted
version: "8.12.3"
version: "8.12.4"
camera:
dependency: transitive
description:
name: camera
sha256: a005c6b9783d895a3a9808d65d06773d13587e22a186b6fe8ef3801b0d12f8cf
sha256: "4142a19a38e388d3bab444227636610ba88982e36dff4552d5191a86f65dc437"
url: "https://pub.dev"
source: hosted
version: "0.11.3+1"
version: "0.11.4"
camera_android_camerax:
dependency: transitive
description:
@@ -213,10 +213,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
version: "1.4.0"
version: "1.4.1"
charset:
dependency: transitive
description:
@@ -369,7 +369,7 @@ packages:
path: "packages/dartssh2"
relative: true
source: path
version: "2.12.0"
version: "2.13.0"
dbus:
dependency: transitive
description:
@@ -688,10 +688,10 @@ packages:
dependency: "direct main"
description:
name: get_it
sha256: "1d648d2dd2047d7f7450d5727ca24ee435f240385753d90b49650e3cdff32e56"
sha256: "568d62f0e68666fb5d95519743b3c24a34c7f19d834b0658c46e26d778461f66"
url: "https://pub.dev"
source: hosted
version: "9.2.0"
version: "9.2.1"
glob:
dependency: transitive
description:
@@ -817,10 +817,10 @@ packages:
dependency: transitive
description:
name: image
sha256: "492bd52f6c4fbb6ee41f781ff27765ce5f627910e1e0cbecfa3d9add5562604c"
sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce
url: "https://pub.dev"
source: hosted
version: "4.7.2"
version: "4.8.0"
intl:
dependency: "direct main"
description:
@@ -985,18 +985,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
url: "https://pub.dev"
source: hosted
version: "0.12.17"
version: "0.12.18"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.13.0"
meta:
dependency: transitive
description:
@@ -1153,10 +1153,10 @@ packages:
dependency: transitive
description:
name: petitparser
sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1"
sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675"
url: "https://pub.dev"
source: hosted
version: "7.0.1"
version: "7.0.2"
pinenacl:
dependency: transitive
description:
@@ -1210,10 +1210,10 @@ packages:
dependency: transitive
description:
name: posix
sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61"
sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07"
url: "https://pub.dev"
source: hosted
version: "6.0.3"
version: "6.5.0"
pretty_qr_code:
dependency: transitive
description:
@@ -1583,26 +1583,26 @@ packages:
dependency: "direct dev"
description:
name: test
sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7"
sha256: "54c516bbb7cee2754d327ad4fca637f78abfc3cbcc5ace83b3eda117e42cd71a"
url: "https://pub.dev"
source: hosted
version: "1.26.3"
version: "1.29.0"
test_api:
dependency: transitive
description:
name: test_api
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
url: "https://pub.dev"
source: hosted
version: "0.7.7"
version: "0.7.9"
test_core:
dependency: transitive
description:
name: test_core
sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0"
sha256: "394f07d21f0f2255ec9e3989f21e54d3c7dc0e6e9dbce160e5a9c1a6be0e2943"
url: "https://pub.dev"
source: hosted
version: "0.6.12"
version: "0.6.15"
tuple:
dependency: transitive
description:
@@ -1647,10 +1647,10 @@ packages:
dependency: transitive
description:
name: url_launcher_ios
sha256: b1aca26728b7cc7a3af971bb6f601554a8ae9df2e0a006de8450ba06a17ad36a
sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0"
url: "https://pub.dev"
source: hosted
version: "6.4.0"
version: "6.4.1"
url_launcher_linux:
dependency: transitive
description:
@@ -1695,10 +1695,10 @@ packages:
dependency: transitive
description:
name: uuid
sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
url: "https://pub.dev"
source: hosted
version: "4.5.2"
version: "4.5.3"
vector_graphics:
dependency: transitive
description:
@@ -1719,10 +1719,10 @@ packages:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "201e876b5d52753626af64b6359cd13ac6011b80728731428fd34bc840f71c9b"
sha256: "5a88dd14c0954a5398af544651c7fb51b457a2a556949bfb25369b210ef73a74"
url: "https://pub.dev"
source: hosted
version: "1.1.20"
version: "1.2.0"
vector_math:
dependency: transitive
description:
@@ -1892,5 +1892,5 @@ packages:
source: hosted
version: "1.1.4"
sdks:
dart: ">=3.10.3 <4.0.0"
flutter: ">=3.38.4"
dart: ">=3.11.0 <4.0.0"
flutter: ">=3.41.0"

View File

@@ -4,8 +4,8 @@ publish_to: "none"
version: 1.0.1316+1316
environment:
sdk: ">=3.9.0"
flutter: ">=3.38.0"
sdk: ">=3.11.0"
flutter: ">=3.41.0"
dependencies:
flutter: