Skip to content

fix: reconnect terminal on non-modified key presses #9686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 18, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions site/src/pages/TerminalPage/TerminalPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -470,21 +470,48 @@ const useReloading = (isDisconnected: boolean) => {

// Retry connection on key press when it is disconnected
useEffect(() => {
if (!isDisconnected) {
if (!isDisconnected || status === "reloading") {
return;
}

const keyDownHandler = () => {
setStatus("reloading");
window.location.reload();
// Modifier keys should not trigger a reload.
const ignoredKeys = [
"Alt",
"AltGraph",
"CapsLock",
"Control",
"Fn",
"FnLock",
"Meta",
"NumLock",
"ScrollLock",
"Shift",
"Symbol",
"SymbolLock",
];

const keyDownHandler = (event: KeyboardEvent) => {
// In addition to ignored keys, avoid reloading while modifiers are held
// to cover cases where the terminal unexpectedly tries to reconnect like
// when pressing ctrl+w, ctrl+r, and so on.
if (
!ignoredKeys.includes(event.key) &&
!event.altKey &&
!event.ctrlKey &&
!event.metaKey &&
!event.shiftKey
) {
setStatus("reloading");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kind of a nit: this call won't really do anything. window.location.reload() will block/kill the execution context before the event loop circles back to this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I thought the same thing, it could depend on the browser or something, but in Chromium I tested via a console.log statement and it will happily run multiple times until the reload "kicks in".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, running window.location.reload() multiple times is probably harmless.

Copy link
Member Author

@code-asher code-asher Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more thing, setting the status here to reloading causes the overlay to display "Reloading...", so whatever window.location.reload() is doing, it appears to not quite be instant, or there is some other trick at play here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, ok 😅 I thought I'd even played with this before and touching location instantly killed your code

Copy link
Member

@aslilac aslilac Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that said, it seems like this would benefit from being instant, rather than waiting for react to do an update cycle. maybe we should use useRef for this?

although I guess the ui uses this... maybe it needs to be both 🙃

Copy link
Member Author

@code-asher code-asher Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol I know what you mean, I could have sworn I did and saw the same!

Copy link
Member Author

@code-asher code-asher Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, good point. Maybe it would be nice if the UI could update immediately as well since if the reload happens too fast they might never see the Reloading... text? Wonder if we can force an update or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I experimented a bit to see if I could get the keydown handler firing twice before React updates and the listener is removed but apparently I am not able to mash a key fast enough lol

I did find a bug though, if you ctrl+tab away then come back via click, the page still thinks ctrl is being pressed and nothing will reload until you press and release ctrl again. Not sure if this can be solved with keydown...too bad it is not like the deprecated keypress event that would tell you if modifier keys were being held down.

Copy link
Member Author

@code-asher code-asher Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait what no keydown does have that information. What am I even doing?? Will refactor. It does not cover all the keys listed in documentation as modifiers, but all the ones that really matter imo.

window.location.reload();
}
};

document.addEventListener("keydown", keyDownHandler);
document.addEventListener("keydown", keyDownHandler, true);

return () => {
document.removeEventListener("keydown", keyDownHandler);
document.removeEventListener("keydown", keyDownHandler, true);
};
}, [isDisconnected]);
}, [status, isDisconnected]);

return {
status,
Expand Down