@cplieger/web-terminal-ui 7.0.0 → 7.0.1
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cplieger/web-terminal-ui",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reference touch-first browser UI for @cplieger/web-terminal-engine: a composable kernel + feature modules (tabs, activity monitor, mobile toolbar, context menu, IME, predictive echo, viewport handling) and CSS. One createTerminal() call.",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -188,9 +188,6 @@ export function contextMenu(opts: ContextMenuOptions = {}): TerminalFeature {
|
|
|
188
188
|
clipboard.paste();
|
|
189
189
|
});
|
|
190
190
|
}
|
|
191
|
-
if (menu.childElementCount === 0) {
|
|
192
|
-
return; // nothing to offer
|
|
193
|
-
}
|
|
194
191
|
// Make visible (so it has measurable size), then place it within the
|
|
195
192
|
// visible viewport via the shared point-anchored positioner (clamp to the
|
|
196
193
|
// visual viewport; flip above the finger near the bottom edge).
|
|
@@ -244,7 +244,12 @@ async function createSessionHonouringRetry(
|
|
|
244
244
|
isTornDown: () => boolean,
|
|
245
245
|
): Promise<SessionInfo> {
|
|
246
246
|
const startedAt = Date.now();
|
|
247
|
-
|
|
247
|
+
// The elapsed reading of the last announcement, or null when nothing has been
|
|
248
|
+
// announced yet. NOT a 0 sentinel: elapsed is legitimately 0 when the server
|
|
249
|
+
// refuses inside the first millisecond (a host on the same machine), and a 0
|
|
250
|
+
// sentinel read that as "never spoken" and re-announced on the next refusal —
|
|
251
|
+
// the one thing the throttle below exists to prevent.
|
|
252
|
+
let lastAnnouncedAt: number | null = null;
|
|
248
253
|
for (;;) {
|
|
249
254
|
try {
|
|
250
255
|
return await api.create();
|
|
@@ -266,7 +271,7 @@ async function createSessionHonouringRetry(
|
|
|
266
271
|
// only said "not yet" -- and the first announcement fires before any retry
|
|
267
272
|
// has happened at all, so a user two seconds into a boot was told
|
|
268
273
|
// "retrying" about a request that had been made exactly once.
|
|
269
|
-
if (lastAnnouncedAt ===
|
|
274
|
+
if (lastAnnouncedAt === null || elapsed - lastAnnouncedAt >= CREATE_RETRY_REANNOUNCE_MS) {
|
|
270
275
|
lastAnnouncedAt = elapsed;
|
|
271
276
|
const reason = err.serverMessage ?? "Server is not ready yet";
|
|
272
277
|
ctx.toast(`${reason}; waiting…`, 8000);
|
package/src/kernel/kernel.ts
CHANGED
|
@@ -790,29 +790,29 @@ function buildTerminal(
|
|
|
790
790
|
);
|
|
791
791
|
|
|
792
792
|
/**
|
|
793
|
-
* Applies
|
|
794
|
-
*
|
|
795
|
-
*
|
|
796
|
-
*
|
|
797
|
-
*
|
|
798
|
-
* coming
|
|
793
|
+
* Applies a `mapKeyboardEvent` result. BOTH keydown paths — the focused textarea
|
|
794
|
+
* below, and the document-level type-to-focus fallback in the focus-strategy
|
|
795
|
+
* section — handle every arm identically, including "ignore": the textarea lets
|
|
796
|
+
* its own `input` event deliver the character, and the fallback has already
|
|
797
|
+
* resolved that case before it gets here, computing the typed character itself
|
|
798
|
+
* because no `input` event is coming for a key that targeted the body.
|
|
799
799
|
*
|
|
800
|
-
* Switching over the whole `KeyboardResult` union in one place is what keeps
|
|
801
|
-
*
|
|
802
|
-
*
|
|
803
|
-
*
|
|
800
|
+
* Switching over the whole `KeyboardResult` union in one place is what keeps the
|
|
801
|
+
* two paths from drifting — handling only "send" in the fallback silently dropped
|
|
802
|
+
* Shift+PageUp, which is exactly what a reader who just selected some scrollback
|
|
803
|
+
* presses next.
|
|
804
804
|
*/
|
|
805
|
-
function applyMappedKey(ev: KeyboardEvent, result: keyboard.KeyboardResult):
|
|
805
|
+
function applyMappedKey(ev: KeyboardEvent, result: keyboard.KeyboardResult): void {
|
|
806
806
|
switch (result.kind) {
|
|
807
807
|
case "send":
|
|
808
808
|
ev.preventDefault();
|
|
809
809
|
sendText(result.bytes);
|
|
810
|
-
return
|
|
810
|
+
return;
|
|
811
811
|
case "scroll-up": {
|
|
812
812
|
ev.preventDefault();
|
|
813
813
|
const h = termWrap.clientHeight;
|
|
814
814
|
termWrap.scrollTop = Math.max(0, termWrap.scrollTop - h);
|
|
815
|
-
return
|
|
815
|
+
return;
|
|
816
816
|
}
|
|
817
817
|
case "scroll-down": {
|
|
818
818
|
ev.preventDefault();
|
|
@@ -823,10 +823,10 @@ function buildTerminal(
|
|
|
823
823
|
// reasoning as the engine's bottom writes.
|
|
824
824
|
const max = Math.max(0, termWrap.scrollHeight - h);
|
|
825
825
|
termWrap.scrollTop = Math.min(max, termWrap.scrollTop + h);
|
|
826
|
-
return
|
|
826
|
+
return;
|
|
827
827
|
}
|
|
828
828
|
case "ignore":
|
|
829
|
-
return
|
|
829
|
+
return;
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
832
|
|
|
@@ -842,9 +842,9 @@ function buildTerminal(
|
|
|
842
842
|
return;
|
|
843
843
|
}
|
|
844
844
|
}
|
|
845
|
-
//
|
|
846
|
-
//
|
|
847
|
-
//
|
|
845
|
+
// Nothing more is needed for an "ignore": the `input` listener above delivers
|
|
846
|
+
// the character, which is also how IME and dead-key composition output
|
|
847
|
+
// reaches the terminal.
|
|
848
848
|
applyMappedKey(ev, mapKeyboardEvent(ev, modes));
|
|
849
849
|
},
|
|
850
850
|
{ signal },
|