fix: scroller to work on mobile
and some other bug fix
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
"@base-ui/react": "^1.4.0",
|
"@base-ui/react": "^1.4.0",
|
||||||
"@fontsource-variable/inter": "^5.2.8",
|
"@fontsource-variable/inter": "^5.2.8",
|
||||||
"@tailwindcss/vite": "^4.2.2",
|
"@tailwindcss/vite": "^4.2.2",
|
||||||
|
"@xterm/addon-clipboard": "^0.2.0",
|
||||||
"@xterm/addon-fit": "^0.11.0",
|
"@xterm/addon-fit": "^0.11.0",
|
||||||
"@xterm/xterm": "^6.0.0",
|
"@xterm/xterm": "^6.0.0",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
|||||||
Generated
+21
@@ -16,6 +16,9 @@ importers:
|
|||||||
"@tailwindcss/vite":
|
"@tailwindcss/vite":
|
||||||
specifier: ^4.2.2
|
specifier: ^4.2.2
|
||||||
version: 4.2.2([email protected](@types/[email protected])([email protected]))
|
version: 4.2.2([email protected](@types/[email protected])([email protected]))
|
||||||
|
"@xterm/addon-clipboard":
|
||||||
|
specifier: ^0.2.0
|
||||||
|
version: 0.2.0
|
||||||
"@xterm/addon-fit":
|
"@xterm/addon-fit":
|
||||||
specifier: ^0.11.0
|
specifier: ^0.11.0
|
||||||
version: 0.11.0
|
version: 0.11.0
|
||||||
@@ -1248,6 +1251,12 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||||
|
|
||||||
|
"@xterm/[email protected]":
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-Dl31BCtBhLaUEECUbEiVcCLvLBbaeGYdT7NofB8OJkGTD3MWgBsaLjXvfGAD4tQNHhm6mbKyYkR7XD8kiZsdNg==,
|
||||||
|
}
|
||||||
|
|
||||||
"@xterm/[email protected]":
|
"@xterm/[email protected]":
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -2286,6 +2295,12 @@ packages:
|
|||||||
integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==,
|
integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-5xVjhUZlHHeuO2W7w2rDFj/Kl1xLX+HjZxdOQwCsUOifl6UaoH1o1wsbsTMz+r0aeC7gCijvru02j6TfKZWzKg==,
|
||||||
|
}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -4221,6 +4236,10 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
"@xterm/[email protected]":
|
||||||
|
dependencies:
|
||||||
|
js-base64: 3.8.1
|
||||||
|
|
||||||
"@xterm/[email protected]": {}
|
"@xterm/[email protected]": {}
|
||||||
|
|
||||||
"@xterm/[email protected]": {}
|
"@xterm/[email protected]": {}
|
||||||
@@ -4767,6 +4786,8 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
import { ClipboardAddon } from "@xterm/addon-clipboard";
|
||||||
import { FitAddon } from "@xterm/addon-fit";
|
import { FitAddon } from "@xterm/addon-fit";
|
||||||
import { Terminal as XTerm } from "@xterm/xterm";
|
import { Terminal as XTerm } from "@xterm/xterm";
|
||||||
import { Eraser, PlugZap, RotateCcw, Square, Terminal } from "lucide-react";
|
import { Eraser, PlugZap, RotateCcw, Square, Terminal } from "lucide-react";
|
||||||
@@ -165,65 +166,51 @@ export function TerminalPage({
|
|||||||
fontFamily: '"SFMono-Regular", Consolas, "Liberation Mono", monospace',
|
fontFamily: '"SFMono-Regular", Consolas, "Liberation Mono", monospace',
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
lineHeight: 1.1,
|
lineHeight: 1.1,
|
||||||
|
// xterm uses this width for its internal scrollbar as well as the
|
||||||
|
// overview ruler. Reserve a larger touch target on coarse pointers.
|
||||||
|
overviewRuler: {
|
||||||
|
width: window.matchMedia("(pointer: coarse)").matches ? 22 : 16,
|
||||||
|
},
|
||||||
scrollback: 5000,
|
scrollback: 5000,
|
||||||
theme: {
|
theme: {
|
||||||
background: "#0b1117",
|
background: "#0b1117",
|
||||||
foreground: "#e5e7eb",
|
foreground: "#e5e7eb",
|
||||||
cursor: "#6ee7a8",
|
cursor: "#6ee7a8",
|
||||||
|
scrollbarSliderBackground: "#52617099",
|
||||||
|
scrollbarSliderHoverBackground: "#6b7c8dcc",
|
||||||
|
scrollbarSliderActiveBackground: "#8294a6",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const fit = new FitAddon();
|
const fit = new FitAddon();
|
||||||
|
terminal.loadAddon(new ClipboardAddon());
|
||||||
terminal.loadAddon(fit);
|
terminal.loadAddon(fit);
|
||||||
terminal.open(hostRef.current);
|
terminal.open(hostRef.current);
|
||||||
terminal.attachCustomKeyEventHandler((event) => {
|
terminal.attachCustomKeyEventHandler((event) => {
|
||||||
if (event.type !== "keydown") return true;
|
const copiesTerminalSelection =
|
||||||
|
event.type === "keydown" &&
|
||||||
|
event.ctrlKey &&
|
||||||
|
event.shiftKey &&
|
||||||
|
event.code === "KeyC";
|
||||||
|
if (!copiesTerminalSelection) return true;
|
||||||
|
|
||||||
const copy =
|
// Chromium reserves Ctrl+Shift+C for DevTools. Other clipboard shortcuts
|
||||||
(event.ctrlKey && event.shiftKey && event.code === "KeyC") ||
|
// fall through to xterm's native copy/paste event handlers.
|
||||||
(event.metaKey && event.code === "KeyC") ||
|
event.preventDefault();
|
||||||
(event.ctrlKey && event.code === "Insert");
|
event.stopPropagation();
|
||||||
if (copy) {
|
if (terminal.hasSelection()) {
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
if (terminal.hasSelection()) {
|
|
||||||
if (!navigator.clipboard) {
|
|
||||||
toast.error("Clipboard access requires HTTPS or localhost");
|
|
||||||
} else {
|
|
||||||
void navigator.clipboard
|
|
||||||
.writeText(terminal.getSelection())
|
|
||||||
.catch((error) =>
|
|
||||||
toast.error("Clipboard access was denied", {
|
|
||||||
description: String(error),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const paste =
|
|
||||||
(event.ctrlKey && event.shiftKey && event.code === "KeyV") ||
|
|
||||||
(event.metaKey && event.code === "KeyV") ||
|
|
||||||
(event.shiftKey && event.code === "Insert");
|
|
||||||
if (paste) {
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
if (!navigator.clipboard) {
|
if (!navigator.clipboard) {
|
||||||
toast.error("Clipboard access requires HTTPS or localhost");
|
toast.error("Clipboard access requires HTTPS or localhost");
|
||||||
return false;
|
} else {
|
||||||
|
void navigator.clipboard
|
||||||
|
.writeText(terminal.getSelection())
|
||||||
|
.catch((error) =>
|
||||||
|
toast.error("Clipboard access was denied", {
|
||||||
|
description: String(error),
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
void navigator.clipboard
|
|
||||||
.readText()
|
|
||||||
.then((text) => terminal.paste(text))
|
|
||||||
.catch((error) =>
|
|
||||||
toast.error("Clipboard access was denied", {
|
|
||||||
description: String(error),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
fit.fit();
|
fit.fit();
|
||||||
terminalRef.current = terminal;
|
terminalRef.current = terminal;
|
||||||
@@ -351,7 +338,9 @@ export function TerminalPage({
|
|||||||
} finally {
|
} finally {
|
||||||
setSession(null);
|
setSession(null);
|
||||||
setConnection("idle");
|
setConnection("idle");
|
||||||
terminalRef.current?.clear();
|
// xterm.clear() deliberately preserves the active cursor line. Closing
|
||||||
|
// a session should discard its complete screen and terminal modes.
|
||||||
|
terminalRef.current?.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -465,11 +465,13 @@
|
|||||||
fitted canvas, so keep it on the same surface as the terminal theme. */
|
fitted canvas, so keep it on the same surface as the terminal theme. */
|
||||||
background-color: #0b1117;
|
background-color: #0b1117;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-surface .xterm-viewport::-webkit-scrollbar {
|
.terminal-surface .xterm-scrollable-element > .scrollbar,
|
||||||
display: none;
|
.terminal-surface .xterm-scrollable-element > .scrollbar > .slider {
|
||||||
|
/* Without this, mobile browsers claim a thumb drag as page panning before
|
||||||
|
xterm's pointer-capture scrollbar can process it. */
|
||||||
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
|
|||||||
Reference in New Issue
Block a user