Skip to content

Commit

Permalink
fix(frontend): Prevent from setting multiple terminal stdin listeners…
Browse files Browse the repository at this point in the history
… on re-renders (#5653)
  • Loading branch information
amanape authored Dec 17, 2024
1 parent 5e31239 commit 8b1a7df
Showing 1 changed file with 37 additions and 18 deletions.
55 changes: 37 additions & 18 deletions frontend/src/hooks/use-terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const useTerminal = ({
const fitAddon = React.useRef<FitAddon | null>(null);
const ref = React.useRef<HTMLDivElement>(null);
const lastCommandIndex = React.useRef(0);
const keyEventDisposable = React.useRef<{ dispose: () => void } | null>(null);

const createTerminal = () =>
new Terminal({
Expand Down Expand Up @@ -143,40 +144,58 @@ export const useTerminal = ({

React.useEffect(() => {
if (terminal.current) {
// Dispose of existing listeners if they exist
if (keyEventDisposable.current) {
keyEventDisposable.current.dispose();
keyEventDisposable.current = null;
}

let commandBuffer = "";

if (!disabled) {
terminal.current.onKey(({ key, domEvent }) => {
if (domEvent.key === "Enter") {
handleEnter(commandBuffer);
commandBuffer = "";
} else if (domEvent.key === "Backspace") {
if (commandBuffer.length > 0) {
commandBuffer = handleBackspace(commandBuffer);
}
} else {
// Ignore paste event
if (key.charCodeAt(0) === 22) {
return;
// Add new key event listener and store the disposable
keyEventDisposable.current = terminal.current.onKey(
({ key, domEvent }) => {
if (domEvent.key === "Enter") {
handleEnter(commandBuffer);
commandBuffer = "";
} else if (domEvent.key === "Backspace") {
if (commandBuffer.length > 0) {
commandBuffer = handleBackspace(commandBuffer);
}
} else {
// Ignore paste event
if (key.charCodeAt(0) === 22) {
return;
}
commandBuffer += key;
terminal.current?.write(key);
}
commandBuffer += key;
terminal.current?.write(key);
}
});
},
);

// Add custom key handler and store the disposable
terminal.current.attachCustomKeyEventHandler((event) =>
pasteHandler(event, (text) => {
commandBuffer += text;
}),
);
} else {
terminal.current.onKey((e) => {
// Add a noop handler when disabled
keyEventDisposable.current = terminal.current.onKey((e) => {
e.domEvent.preventDefault();
e.domEvent.stopPropagation();
});
}
}
}, [disabled, terminal]);

return () => {
if (keyEventDisposable.current) {
keyEventDisposable.current.dispose();
keyEventDisposable.current = null;
}
};
}, [disabled]);

return ref;
};

0 comments on commit 8b1a7df

Please sign in to comment.