Fix for pasting

This commit is contained in:
Andy Dixon
2026-06-02 10:47:31 +01:00
parent 759485fc47
commit 2eed4ea548
4 changed files with 63 additions and 21 deletions
+5 -1
View File
@@ -236,7 +236,11 @@ class RawViewer {
} }
try { try {
const b64 = btoa(dataToSend); // For hex/escaped, data is already raw bytes (0-255) so btoa is correct.
// For text mode, UTF-8 encode so non-ASCII characters are transmitted properly.
const b64 = (format === 'hex' || format === 'escaped')
? btoa(dataToSend)
: window.NexusTerminal.utf8ToBase64(dataToSend);
await window.go.api.Service.WriteSession(sessionId, b64); await window.go.api.Service.WriteSession(sessionId, b64);
input.value = ''; input.value = '';
+1 -1
View File
@@ -91,7 +91,7 @@
/** @private */ /** @private */
_sendCommand(sessionId, command) { _sendCommand(sessionId, command) {
try { try {
const b64 = btoa(command + "\n"); const b64 = window.NexusTerminal.utf8ToBase64(command + "\n");
window.go.api.Service.WriteSession(sessionId, b64); window.go.api.Service.WriteSession(sessionId, b64);
this.app.notifications.info("Snippet sent"); this.app.notifications.info("Snippet sent");
} catch (err) { } catch (err) {
+28 -6
View File
@@ -7,6 +7,20 @@
/* global Terminal, FitAddon, SearchAddon, WebLinksAddon, Unicode11Addon */ /* global Terminal, FitAddon, SearchAddon, WebLinksAddon, Unicode11Addon */
/**
* Encode a string as UTF-8 bytes then base64-encode them.
* Unlike bare btoa(), this handles characters above U+007F correctly
* (e.g. degree symbol °, emoji) and won't throw InvalidCharacterError.
*/
function utf8ToBase64(str) {
const bytes = new TextEncoder().encode(str);
let binary = '';
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
class TerminalManager { class TerminalManager {
/** /**
* @param {App} app * @param {App} app
@@ -119,25 +133,33 @@
// scrollback content in alternate mode). // scrollback content in alternate mode).
const viewportEl = container.querySelector(".xterm-viewport"); const viewportEl = container.querySelector(".xterm-viewport");
if (viewportEl) { if (viewportEl) {
viewportEl.addEventListener("wheel", (e) => { viewportEl.addEventListener(
"wheel",
(e) => {
if (term.buffer.active !== term.buffer.alternate) return; if (term.buffer.active !== term.buffer.alternate) return;
// Only intercept when mouse tracking is NOT active (if mouse mode // Only intercept when mouse tracking is NOT active (if mouse mode
// is on, xterm.js already forwards events correctly). // is on, xterm.js already forwards events correctly).
if (term.modes && term.modes.mouseTrackingMode && if (
term.modes.mouseTrackingMode !== "none") return; term.modes &&
term.modes.mouseTrackingMode &&
term.modes.mouseTrackingMode !== "none"
)
return;
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
const lines = Math.max(1, Math.round(Math.abs(e.deltaY) / 40)); const lines = Math.max(1, Math.round(Math.abs(e.deltaY) / 40));
const seq = e.deltaY < 0 ? "\x1b[A" : "\x1b[B"; const seq = e.deltaY < 0 ? "\x1b[A" : "\x1b[B";
const data = seq.repeat(lines); const data = seq.repeat(lines);
const b64 = btoa(data); const b64 = utf8ToBase64(data);
try { try {
window.go.api.Service.WriteSession(sessionId, b64); window.go.api.Service.WriteSession(sessionId, b64);
} catch (_) { } catch (_) {
/* non-critical */ /* non-critical */
} }
}, { passive: false }); },
{ passive: false },
);
} }
// Drag-and-drop file handling // Drag-and-drop file handling
@@ -177,7 +199,7 @@
// Forward user keystrokes to the backend // Forward user keystrokes to the backend
term.onData((data) => { term.onData((data) => {
try { try {
const b64 = btoa(data); const b64 = utf8ToBase64(data);
window.go.api.Service.WriteSession(sessionId, b64); window.go.api.Service.WriteSession(sessionId, b64);
// Broadcast to other connected sessions if enabled // Broadcast to other connected sessions if enabled
+16
View File
@@ -163,6 +163,21 @@
return btoa(str); return btoa(str);
} }
/**
* UTF-8-encodes a string and then base64-encodes the bytes.
* Unlike bare btoa(), this handles characters above U+007F correctly.
* @param {string} str
* @returns {string}
*/
function utf8ToBase64(str) {
const bytes = new TextEncoder().encode(str);
let binary = '';
for (let i = 0; i < bytes.length; i++) {
binary += String.fromCharCode(bytes[i]);
}
return btoa(binary);
}
/** /**
* Base64-decodes a string. * Base64-decodes a string.
* @param {string} str * @param {string} str
@@ -295,6 +310,7 @@
debounce, debounce,
fuzzyMatch, fuzzyMatch,
base64Encode, base64Encode,
utf8ToBase64,
base64Decode, base64Decode,
generateId, generateId,
formatBytes, formatBytes,