improvemtns

This commit is contained in:
iliya 2026-02-27 14:44:02 +02:00
parent f0c2677c6a
commit 17e20847d6
4 changed files with 37 additions and 0 deletions

View file

@ -101,6 +101,7 @@
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-virtual": "^3.10.8",
"@xterm/addon-fit": "^0.11.0",
"@xterm/addon-web-links": "^0.12.0",
"@xterm/xterm": "^6.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",

View file

@ -128,6 +128,9 @@ importers:
'@xterm/addon-fit':
specifier: ^0.11.0
version: 0.11.0
'@xterm/addon-web-links':
specifier: ^0.12.0
version: 0.12.0
'@xterm/xterm':
specifier: ^6.0.0
version: 6.0.0
@ -2133,6 +2136,9 @@ packages:
'@xterm/addon-fit@0.11.0':
resolution: {integrity: sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==}
'@xterm/addon-web-links@0.12.0':
resolution: {integrity: sha512-4Smom3RPyVp7ZMYOYDoC/9eGJJJqYhnPLGGqJ6wOBfB8VxPViJNSKdgRYb8NpaM6YSelEKbA2SStD7lGyqaobw==}
'@xterm/xterm@6.0.0':
resolution: {integrity: sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==}
@ -7624,6 +7630,8 @@ snapshots:
'@xterm/addon-fit@0.11.0': {}
'@xterm/addon-web-links@0.12.0': {}
'@xterm/xterm@6.0.0': {}
abbrev@1.1.1: {}

View file

@ -4,6 +4,7 @@ import { useEffect, useRef } from 'react';
import { api } from '@renderer/api';
import { FitAddon } from '@xterm/addon-fit';
import { WebLinksAddon } from '@xterm/addon-web-links';
import { Terminal } from '@xterm/xterm';
import type { PtySpawnOptions } from '@shared/types/terminal';
@ -51,11 +52,30 @@ export const EmbeddedTerminal = ({
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
// Clickable URLs — opens in external browser
const webLinksAddon = new WebLinksAddon((_event, uri) => {
void api.openExternal(uri);
});
term.loadAddon(webLinksAddon);
term.open(container);
// Fit after opening so dimensions are correct
const rafId = requestAnimationFrame(() => fitAddon.fit());
// Ctrl+C with selection → copy to clipboard (instead of sending SIGINT)
term.attachCustomKeyEventHandler((event) => {
if (event.type === 'keydown' && event.key === 'c' && (event.ctrlKey || event.metaKey)) {
const selection = term.getSelection();
if (selection) {
void navigator.clipboard.writeText(selection);
return false; // Prevent sending to PTY
}
}
return true;
});
// User input → PTY (returns IDisposable — must dispose in cleanup)
const inputDisposable = term.onData((data) => {
if (ptyId) api.terminal.write(ptyId, data);

View file

@ -2,7 +2,9 @@ import '@xterm/xterm/css/xterm.css';
import { useEffect, useRef } from 'react';
import { api } from '@renderer/api';
import { FitAddon } from '@xterm/addon-fit';
import { WebLinksAddon } from '@xterm/addon-web-links';
import { Terminal } from '@xterm/xterm';
interface TerminalLogPanelProps {
@ -40,6 +42,12 @@ export const TerminalLogPanel = ({
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
const webLinksAddon = new WebLinksAddon((_event, uri) => {
void api.openExternal(uri);
});
term.loadAddon(webLinksAddon);
term.open(container);
const rafId = requestAnimationFrame(() => fitAddon.fit());