Skip to content

Commit b6b39ed

Browse files
committed
fix: weird selection behaviour in case of keyboard focus/blur
1 parent 96da7cd commit b6b39ed

File tree

3 files changed

+92
-58
lines changed

3 files changed

+92
-58
lines changed

package-lock.json

Lines changed: 16 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/terminal/terminalTouchSelection.js

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ export default class TerminalTouchSelection {
5555
this.wasFocusedBeforeSelection = false;
5656
this.contextMenuShouldStayVisible = false;
5757

58+
// Selection protection during keyboard events
59+
this.selectionProtected = false;
60+
this.protectionTimeout = null;
61+
5862
this.init();
5963
}
6064

@@ -460,6 +464,11 @@ export default class TerminalTouchSelection {
460464
onTerminalAreaTouchStart(event) {
461465
// Clear selection if touching terminal area while selecting, except on handles or context menu
462466
if (this.isSelecting) {
467+
// Don't clear selection if it's protected (during keyboard events)
468+
if (this.selectionProtected) {
469+
return;
470+
}
471+
463472
// Don't interfere with context menu at all
464473
if (this.contextMenu && this.contextMenu.style.display === "flex") {
465474
// Context menu is visible, check if touching it
@@ -515,18 +524,35 @@ export default class TerminalTouchSelection {
515524
setTimeout(() => {
516525
this.updateCellDimensions();
517526
if (this.isSelecting) {
518-
// Clear selection if it becomes invalid due to resize
527+
// Don't clear selection if it's protected (during keyboard events)
528+
if (this.selectionProtected) {
529+
// Just update handle positions during protected period
530+
this.updateHandlePositions();
531+
return;
532+
}
533+
534+
// Only clear selection if it becomes invalid due to actual content resize
535+
// Don't clear selection for keyboard-related resizes
519536
if (
520-
this.selectionStart.row >= size.rows ||
521-
this.selectionEnd.row >= size.rows
537+
this.selectionStart &&
538+
this.selectionEnd &&
539+
(this.selectionStart.row >= size.rows ||
540+
this.selectionEnd.row >= size.rows)
522541
) {
523542
this.clearSelection();
524-
} else {
543+
} else if (this.isSelecting) {
544+
// Maintain selection and update handle positions
525545
this.updateHandlePositions();
526-
// Hide context menu during resize
546+
// Temporarily hide context menu during resize but keep selection
527547
if (this.contextMenu && this.contextMenu.style.display === "flex") {
528548
this.hideContextMenu();
529549
}
550+
// Re-show context menu after resize if selection is still active
551+
setTimeout(() => {
552+
if (this.isSelecting && this.options.showContextMenu) {
553+
this.showContextMenu();
554+
}
555+
}, 100);
530556
}
531557
}
532558
}, 50);
@@ -539,6 +565,16 @@ export default class TerminalTouchSelection {
539565
// Store initial focus state
540566
this.wasFocusedBeforeSelection = this.isTerminalFocused();
541567

568+
// Protect selection from being cancelled by keyboard events
569+
this.selectionProtected = true;
570+
if (this.protectionTimeout) {
571+
clearTimeout(this.protectionTimeout);
572+
}
573+
// Remove protection after keyboard events have settled
574+
this.protectionTimeout = setTimeout(() => {
575+
this.selectionProtected = false;
576+
}, 1000);
577+
542578
this.isSelecting = true;
543579

544580
// Try to auto-select word at touch position
@@ -840,25 +876,30 @@ export default class TerminalTouchSelection {
840876
cordova.plugins.clipboard.copy(selectionText);
841877
}
842878

843-
this.clearSelection();
879+
this.forceClearSelection();
844880
}
845881

846882
pasteFromClipboard() {
847883
if (cordova?.plugins?.clipboard) {
848884
cordova.plugins.clipboard.paste((text) => {
849885
this.terminal.paste(text);
850-
this.clearSelection();
886+
this.forceClearSelection();
851887
});
852888
}
853889
}
854890

855891
showMoreOptions() {
856892
// Implement additional options if needed
857893
window.toast("More options are not implemented yet.");
858-
this.clearSelection();
894+
this.forceClearSelection();
859895
}
860896

861897
clearSelection() {
898+
// Don't clear if selection is protected
899+
if (this.selectionProtected) {
900+
return;
901+
}
902+
862903
// Store focus state before clearing
863904
const shouldRestoreFocus =
864905
this.wasFocusedBeforeSelection && this.isSelecting;
@@ -879,17 +920,35 @@ export default class TerminalTouchSelection {
879920
this.tapHoldTimeout = null;
880921
}
881922

882-
// Restore focus state if terminal was focused before selection
923+
// Clear protection timeout
924+
if (this.protectionTimeout) {
925+
clearTimeout(this.protectionTimeout);
926+
this.protectionTimeout = null;
927+
}
928+
this.selectionProtected = false;
929+
930+
// Only restore focus if explicitly clearing selection (not due to keyboard close)
931+
// and if terminal was focused before selection
883932
if (shouldRestoreFocus && !this.isTerminalFocused()) {
884933
setTimeout(() => {
885-
this.terminal.focus();
886-
}, 50);
934+
if (!this.isSelecting) {
935+
this.terminal.focus();
936+
}
937+
}, 150);
887938
}
888939

889940
// Reset focus tracking
890941
this.wasFocusedBeforeSelection = false;
891942
}
892943

944+
forceClearSelection() {
945+
// Temporarily disable protection to force clear
946+
const wasProtected = this.selectionProtected;
947+
this.selectionProtected = false;
948+
this.clearSelection();
949+
// Don't restore protection state since we're clearing
950+
}
951+
893952
touchToTerminalCoords(touch) {
894953
const rect = this.terminal.element.getBoundingClientRect();
895954
const x = touch.clientX - rect.left;
@@ -1084,7 +1143,7 @@ export default class TerminalTouchSelection {
10841143

10851144
destroy() {
10861145
// Clear selection
1087-
this.clearSelection();
1146+
this.forceClearSelection();
10881147

10891148
// Remove event listeners
10901149
this.terminal.element.removeEventListener(

www/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,17 @@
165165

166166
<title>Acode</title>
167167
<!--styles-->
168+
<link rel="stylesheet" href="./css/build/218.css">
169+
<link rel="stylesheet" href="./css/build/32.css">
170+
<link rel="stylesheet" href="./css/build/383.css">
171+
<link rel="stylesheet" href="./css/build/53.css">
172+
<link rel="stylesheet" href="./css/build/609.css">
168173
<link rel="stylesheet" href="./css/build/about.css">
169174
<link rel="stylesheet" href="./css/build/customTheme.css">
170175
<link rel="stylesheet" href="./css/build/donate.css">
171176
<link rel="stylesheet" href="./css/build/fileBrowser.css">
172177
<link rel="stylesheet" href="./css/build/main.css">
173178
<link rel="stylesheet" href="./css/build/plugins.css">
174-
<link rel="stylesheet" href="./css/build/src_pages_quickTools_quickTools_js.css">
175-
<link rel="stylesheet" href="./css/build/src_sidebarApps_extensions_index_js.css">
176-
<link rel="stylesheet" href="./css/build/src_sidebarApps_files_index_js.css">
177-
<link rel="stylesheet" href="./css/build/src_sidebarApps_notification_index_js.css">
178-
<link rel="stylesheet" href="./css/build/src_sidebarApps_searchInFiles_index_js.css">
179179
<link rel="stylesheet" href="./css/build/themeSetting.css">
180180
<!--styles_end-->
181181
</head>

0 commit comments

Comments
 (0)