termites 1.0.21 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server.js +88 -48
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -591,8 +591,6 @@ class TermitesServer {
|
|
|
591
591
|
.header-title .sep { color: var(--sep-color, #657b83); }
|
|
592
592
|
.no-client { color: #888; font-style: italic; }
|
|
593
593
|
#terminal-container { flex: 1; padding: 4px; transition: background 0.3s; overflow: hidden; min-height: 0; position: relative; }
|
|
594
|
-
#terminal-container.select-mode { cursor: text; }
|
|
595
|
-
#terminal-container.select-mode::after { content: 'Select Mode'; position: absolute; top: 8px; right: 8px; background: rgba(0,0,0,0.7); color: #fff; padding: 4px 8px; border-radius: 4px; font-size: 11px; pointer-events: none; }
|
|
596
594
|
.xterm { height: 100%; }
|
|
597
595
|
.overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.4); z-index: 99; opacity: 0; visibility: hidden; transition: all 0.3s; }
|
|
598
596
|
.overlay.open { opacity: 1; visibility: visible; }
|
|
@@ -723,9 +721,14 @@ class TermitesServer {
|
|
|
723
721
|
<button data-key="ArrowDown">↓</button>
|
|
724
722
|
<div class="sep"></div>
|
|
725
723
|
<button data-seq="/">/</button>
|
|
724
|
+
<button id="sel-start-btn">Sel▶</button>
|
|
725
|
+
<button id="sel-left-btn" class="sel-ctrl" style="display:none">◀</button>
|
|
726
|
+
<button id="sel-right-btn" class="sel-ctrl" style="display:none">▶</button>
|
|
727
|
+
<button id="sel-up-btn" class="sel-ctrl" style="display:none">▲</button>
|
|
728
|
+
<button id="sel-down-btn" class="sel-ctrl" style="display:none">▼</button>
|
|
729
|
+
<button id="sel-end-btn" class="sel-ctrl" style="display:none">End</button>
|
|
726
730
|
<button id="copy-btn">Copy</button>
|
|
727
731
|
<button id="paste-btn">Paste</button>
|
|
728
|
-
<button id="select-btn" class="mod-btn">Select</button>
|
|
729
732
|
</div>
|
|
730
733
|
|
|
731
734
|
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
|
|
@@ -1062,58 +1065,95 @@ class TermitesServer {
|
|
|
1062
1065
|
pasteBtn.addEventListener('touchstart', handlePaste, { passive: false });
|
|
1063
1066
|
pasteBtn.addEventListener('click', handlePaste);
|
|
1064
1067
|
|
|
1065
|
-
//
|
|
1066
|
-
let
|
|
1067
|
-
|
|
1068
|
-
|
|
1068
|
+
// Selection mode with start/end control
|
|
1069
|
+
let selMode = false; // false=off, 'start'=adjusting start, 'end'=adjusting end
|
|
1070
|
+
let selStart = { col: 0, row: 0 };
|
|
1071
|
+
let selEnd = { col: 0, row: 0 };
|
|
1072
|
+
const selStartBtn = document.getElementById('sel-start-btn');
|
|
1073
|
+
const selEndBtn = document.getElementById('sel-end-btn');
|
|
1074
|
+
const selLeftBtn = document.getElementById('sel-left-btn');
|
|
1075
|
+
const selRightBtn = document.getElementById('sel-right-btn');
|
|
1076
|
+
const selUpBtn = document.getElementById('sel-up-btn');
|
|
1077
|
+
const selDownBtn = document.getElementById('sel-down-btn');
|
|
1078
|
+
const selCtrls = document.querySelectorAll('.sel-ctrl');
|
|
1079
|
+
|
|
1080
|
+
function updateSelection() {
|
|
1081
|
+
const startOffset = selStart.row * term.cols + selStart.col;
|
|
1082
|
+
const endOffset = selEnd.row * term.cols + selEnd.col;
|
|
1083
|
+
const length = endOffset - startOffset + 1;
|
|
1084
|
+
if (length > 0) {
|
|
1085
|
+
term.select(selStart.col, selStart.row, length);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1069
1088
|
|
|
1070
|
-
|
|
1089
|
+
function showSelCtrls(show) {
|
|
1090
|
+
selCtrls.forEach(el => el.style.display = show ? '' : 'none');
|
|
1091
|
+
selStartBtn.textContent = show ? 'Start' : 'Sel▶';
|
|
1092
|
+
selStartBtn.classList.toggle('active', selMode === 'start');
|
|
1093
|
+
selEndBtn.classList.toggle('active', selMode === 'end');
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
const handleSelStart = (e) => {
|
|
1071
1097
|
e.preventDefault();
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1098
|
+
if (!selMode) {
|
|
1099
|
+
// Enter selection mode, start from last line
|
|
1100
|
+
selMode = 'start';
|
|
1101
|
+
const lastRow = term.buffer.active.cursorY;
|
|
1102
|
+
selStart = { col: 0, row: Math.max(0, lastRow - 2) };
|
|
1103
|
+
selEnd = { col: term.cols - 1, row: lastRow };
|
|
1104
|
+
showSelCtrls(true);
|
|
1105
|
+
updateSelection();
|
|
1106
|
+
} else if (selMode === 'end') {
|
|
1107
|
+
// Switch to adjusting start
|
|
1108
|
+
selMode = 'start';
|
|
1109
|
+
selStartBtn.classList.add('active');
|
|
1110
|
+
selEndBtn.classList.remove('active');
|
|
1080
1111
|
} else {
|
|
1081
|
-
|
|
1082
|
-
|
|
1112
|
+
// Already adjusting start, switch to end
|
|
1113
|
+
selMode = 'end';
|
|
1114
|
+
selStartBtn.classList.remove('active');
|
|
1115
|
+
selEndBtn.classList.add('active');
|
|
1083
1116
|
}
|
|
1084
1117
|
};
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
// Handle touch selection
|
|
1089
|
-
let touchStartPos = null;
|
|
1090
|
-
termContainer.addEventListener('touchstart', (e) => {
|
|
1091
|
-
if (selectMode && e.touches.length === 1) {
|
|
1092
|
-
const touch = e.touches[0];
|
|
1093
|
-
const rect = termContainer.getBoundingClientRect();
|
|
1094
|
-
touchStartPos = { x: touch.clientX - rect.left, y: touch.clientY - rect.top };
|
|
1095
|
-
}
|
|
1096
|
-
}, { passive: true });
|
|
1097
|
-
|
|
1098
|
-
termContainer.addEventListener('touchmove', (e) => {
|
|
1099
|
-
if (selectMode && touchStartPos && e.touches.length === 1) {
|
|
1100
|
-
e.preventDefault();
|
|
1101
|
-
const touch = e.touches[0];
|
|
1102
|
-
const rect = termContainer.getBoundingClientRect();
|
|
1103
|
-
const currentPos = { x: touch.clientX - rect.left, y: touch.clientY - rect.top };
|
|
1104
|
-
|
|
1105
|
-
// Convert pixel positions to terminal coordinates
|
|
1106
|
-
const cellWidth = term._core._renderService.dimensions.css.cell.width;
|
|
1107
|
-
const cellHeight = term._core._renderService.dimensions.css.cell.height;
|
|
1108
|
-
|
|
1109
|
-
const startCol = Math.floor(touchStartPos.x / cellWidth);
|
|
1110
|
-
const startRow = Math.floor(touchStartPos.y / cellHeight);
|
|
1111
|
-
const endCol = Math.floor(currentPos.x / cellWidth);
|
|
1112
|
-
const endRow = Math.floor(currentPos.y / cellHeight);
|
|
1118
|
+
selStartBtn.addEventListener('touchstart', handleSelStart, { passive: false });
|
|
1119
|
+
selStartBtn.addEventListener('click', handleSelStart);
|
|
1113
1120
|
|
|
1114
|
-
|
|
1121
|
+
const handleSelEnd = (e) => {
|
|
1122
|
+
e.preventDefault();
|
|
1123
|
+
if (selMode === 'start') {
|
|
1124
|
+
selMode = 'end';
|
|
1125
|
+
selStartBtn.classList.remove('active');
|
|
1126
|
+
selEndBtn.classList.add('active');
|
|
1127
|
+
} else {
|
|
1128
|
+
// Exit selection mode
|
|
1129
|
+
selMode = false;
|
|
1130
|
+
showSelCtrls(false);
|
|
1115
1131
|
}
|
|
1116
|
-
}
|
|
1132
|
+
};
|
|
1133
|
+
selEndBtn.addEventListener('touchstart', handleSelEnd, { passive: false });
|
|
1134
|
+
selEndBtn.addEventListener('click', handleSelEnd);
|
|
1135
|
+
|
|
1136
|
+
// Arrow controls for selection
|
|
1137
|
+
const moveSelection = (dCol, dRow) => {
|
|
1138
|
+
if (selMode === 'start') {
|
|
1139
|
+
selStart.col = Math.max(0, Math.min(term.cols - 1, selStart.col + dCol));
|
|
1140
|
+
selStart.row = Math.max(0, selStart.row + dRow);
|
|
1141
|
+
} else if (selMode === 'end') {
|
|
1142
|
+
selEnd.col = Math.max(0, Math.min(term.cols - 1, selEnd.col + dCol));
|
|
1143
|
+
selEnd.row = Math.max(0, selEnd.row + dRow);
|
|
1144
|
+
}
|
|
1145
|
+
updateSelection();
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1148
|
+
const addSelHandler = (btn, dCol, dRow) => {
|
|
1149
|
+
const handler = (e) => { e.preventDefault(); moveSelection(dCol, dRow); };
|
|
1150
|
+
btn.addEventListener('touchstart', handler, { passive: false });
|
|
1151
|
+
btn.addEventListener('click', handler);
|
|
1152
|
+
};
|
|
1153
|
+
addSelHandler(selLeftBtn, -1, 0);
|
|
1154
|
+
addSelHandler(selRightBtn, 1, 0);
|
|
1155
|
+
addSelHandler(selUpBtn, 0, -1);
|
|
1156
|
+
addSelHandler(selDownBtn, 0, 1);
|
|
1117
1157
|
}
|
|
1118
1158
|
|
|
1119
1159
|
function updateClientList() {
|