Fix for pasting
This commit is contained in:
@@ -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 = '';
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
+41
-19
@@ -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(
|
||||||
if (term.buffer.active !== term.buffer.alternate) return;
|
"wheel",
|
||||||
// Only intercept when mouse tracking is NOT active (if mouse mode
|
(e) => {
|
||||||
// is on, xterm.js already forwards events correctly).
|
if (term.buffer.active !== term.buffer.alternate) return;
|
||||||
if (term.modes && term.modes.mouseTrackingMode &&
|
// Only intercept when mouse tracking is NOT active (if mouse mode
|
||||||
term.modes.mouseTrackingMode !== "none") return;
|
// is on, xterm.js already forwards events correctly).
|
||||||
|
if (
|
||||||
|
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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user