Skip to content

Commit beea986

Browse files
committed
Fit on initial mount instead of on reconnect
Reconnecting does not change any sizes so we only need to do it on the initial mount and when the window size changes.
1 parent f9e06b7 commit beea986

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

site/src/pages/TerminalPage/TerminalPage.tsx

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ const TerminalPage: FC = () => {
4747
const workspaceName = params.workspace;
4848
const xtermRef = useRef<HTMLDivElement>(null);
4949
const [terminal, setTerminal] = useState<XTerm.Terminal | null>(null);
50-
const [fitAddon, setFitAddon] = useState<FitAddon | null>(null);
5150
const [searchParams] = useSearchParams();
5251
// The reconnection token is a unique token that identifies
5352
// a terminal session. It's generated by the client to reduce
@@ -173,7 +172,6 @@ const TerminalPage: FC = () => {
173172
terminal.loadAddon(new CanvasAddon());
174173
}
175174
const fitAddon = new FitAddon();
176-
setFitAddon(fitAddon);
177175
terminal.loadAddon(fitAddon);
178176
terminal.loadAddon(new Unicode11Addon());
179177
terminal.unicode.activeVersion = "11";
@@ -190,6 +188,16 @@ const TerminalPage: FC = () => {
190188
},
191189
});
192190
});
191+
192+
terminal.open(xtermRef.current);
193+
194+
// We have to fit twice here. It's unknown why, but the first fit will
195+
// overflow slightly in some scenarios. Applying a second fit resolves this.
196+
fitAddon.fit();
197+
fitAddon.fit();
198+
199+
// The initial size will be sent on connection. For future resizes, add a
200+
// listener to update the backend (this triggers on fit()).
193201
terminal.onResize((event) => {
194202
sendEvent({
195203
type: "WRITE",
@@ -199,13 +207,14 @@ const TerminalPage: FC = () => {
199207
},
200208
});
201209
});
202-
setTerminal(terminal);
203-
terminal.open(xtermRef.current);
204-
const listener = () => {
205-
// This will trigger a resize event on the terminal.
206-
fitAddon.fit();
207-
};
210+
211+
// Run a fit every time the window size changes.
212+
const listener = () => fitAddon.fit();
208213
window.addEventListener("resize", listener);
214+
215+
// Terminal is now ready.
216+
setTerminal(terminal);
217+
209218
return () => {
210219
window.removeEventListener("resize", listener);
211220
terminal.dispose();
@@ -232,16 +241,10 @@ const TerminalPage: FC = () => {
232241

233242
// Apply terminal options based on connection state.
234243
useEffect(() => {
235-
if (!terminal || !fitAddon) {
244+
if (!terminal) {
236245
return;
237246
}
238247

239-
// We have to fit twice here. It's unknown why, but
240-
// the first fit will overflow slightly in some
241-
// scenarios. Applying a second fit resolves this.
242-
fitAddon.fit();
243-
fitAddon.fit();
244-
245248
if (!isConnected) {
246249
// Disable user input when not connected.
247250
terminal.options = {
@@ -278,7 +281,10 @@ const TerminalPage: FC = () => {
278281
windowsMode: workspaceAgent?.operating_system === "windows",
279282
};
280283

281-
// Update the terminal size post-fit.
284+
// Send the initial terminal size.
285+
// Ideally this would happen together with the connection via the query
286+
// parameters on the web socket URL to avoid the extra trip and possible
287+
// weirdness of starting at a different size and immediately resizing.
282288
sendEvent({
283289
type: "WRITE",
284290
request: {
@@ -292,7 +298,6 @@ const TerminalPage: FC = () => {
292298
websocketError,
293299
workspaceAgent,
294300
terminal,
295-
fitAddon,
296301
isConnected,
297302
sendEvent,
298303
]);

0 commit comments

Comments
 (0)