diff options
Diffstat (limited to 'packages/app/src')
| -rw-r--r-- | packages/app/src/components/terminal.tsx | 46 | ||||
| -rw-r--r-- | packages/app/src/context/terminal.tsx | 1 |
2 files changed, 39 insertions, 8 deletions
diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx index e87670f59..4d44d5f7e 100644 --- a/packages/app/src/components/terminal.tsx +++ b/packages/app/src/components/terminal.tsx @@ -70,6 +70,7 @@ export const Terminal = (props: TerminalProps) => { let handleTextareaBlur: () => void let disposed = false const cleanups: VoidFunction[] = [] + let tail = local.pty.tail ?? "" const cleanup = () => { if (!cleanups.length) return @@ -256,6 +257,7 @@ export const Terminal = (props: TerminalProps) => { serializeAddon = serializer t.open(container) + container.addEventListener("pointerdown", handlePointerDown) cleanups.push(() => container.removeEventListener("pointerdown", handlePointerDown)) @@ -276,15 +278,11 @@ export const Terminal = (props: TerminalProps) => { focusTerminal() + fit.fit() + if (local.pty.buffer) { - if (local.pty.rows && local.pty.cols) { - t.resize(local.pty.cols, local.pty.rows) - } t.write(local.pty.buffer, () => { - if (local.pty.scrollY) { - t.scrollToLine(local.pty.scrollY) - } - fitAddon.fit() + if (local.pty.scrollY) t.scrollToLine(local.pty.scrollY) }) } @@ -322,6 +320,19 @@ export const Terminal = (props: TerminalProps) => { // console.log("Scroll position:", ydisp) // }) + const limit = 16_384 + const seed = tail + let sync = !!seed + + const overlap = (data: string) => { + if (!seed) return 0 + const max = Math.min(seed.length, data.length) + for (let i = max; i > 0; i--) { + if (seed.slice(-i) === data.slice(0, i)) return i + } + return 0 + } + const handleOpen = () => { local.onConnect?.() sdk.client.pty @@ -338,7 +349,25 @@ export const Terminal = (props: TerminalProps) => { cleanups.push(() => socket.removeEventListener("open", handleOpen)) const handleMessage = (event: MessageEvent) => { - t.write(event.data) + const data = typeof event.data === "string" ? event.data : "" + if (!data) return + + const next = (() => { + if (!sync) return data + const n = overlap(data) + if (!n) { + sync = false + return data + } + const trimmed = data.slice(n) + if (trimmed) sync = false + return trimmed + })() + + if (!next) return + + t.write(next) + tail = next.length >= limit ? next.slice(-limit) : (tail + next).slice(-limit) } socket.addEventListener("message", handleMessage) cleanups.push(() => socket.removeEventListener("message", handleMessage)) @@ -392,6 +421,7 @@ export const Terminal = (props: TerminalProps) => { props.onCleanup({ ...local.pty, buffer, + tail, rows: t.rows, cols: t.cols, scrollY: t.getViewportY(), diff --git a/packages/app/src/context/terminal.tsx b/packages/app/src/context/terminal.tsx index e01b8bc4d..0c383a78d 100644 --- a/packages/app/src/context/terminal.tsx +++ b/packages/app/src/context/terminal.tsx @@ -13,6 +13,7 @@ export type LocalPTY = { cols?: number buffer?: string scrollY?: number + tail?: string } const WORKSPACE_KEY = "__workspace__" |
