From 744510520db97a24efa2a88444c53738eac28d58 Mon Sep 17 00:00:00 2001 From: LukeGus Date: Thu, 1 Oct 2026 13:14:00 -0500 Subject: [PATCH] fix: session log player scrolling off screen horizontally --- .../src/frontend/SessionLogsPanel.tsx | 4 +- .../src/frontend/SessionRecordingPlayer.tsx | 41 ++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/plugins/session-recording/src/frontend/SessionLogsPanel.tsx b/plugins/session-recording/src/frontend/SessionLogsPanel.tsx index 8e3d20f1b..857a241da 100644 --- a/plugins/session-recording/src/frontend/SessionLogsPanel.tsx +++ b/plugins/session-recording/src/frontend/SessionLogsPanel.tsx @@ -517,7 +517,9 @@ export function SessionLogsPanel() { {/* Log content */} -
+
{viewLoading ? (
diff --git a/plugins/session-recording/src/frontend/SessionRecordingPlayer.tsx b/plugins/session-recording/src/frontend/SessionRecordingPlayer.tsx index 51f07666e..be7642c0f 100644 --- a/plugins/session-recording/src/frontend/SessionRecordingPlayer.tsx +++ b/plugins/session-recording/src/frontend/SessionRecordingPlayer.tsx @@ -2,7 +2,6 @@ import { useTranslation } from "@termix/plugin-sdk/frontend"; import { useCallback, useEffect, useRef, useState } from "react"; import { Pause, Play } from "lucide-react"; import { Terminal } from "@xterm/xterm"; -import { FitAddon } from "@xterm/addon-fit"; import Guacamole from "guacamole-common-js"; import "@xterm/xterm/css/xterm.css"; import { parseAsciicast, type Asciicast } from "./asciicast"; @@ -144,6 +143,7 @@ function PlaybackControls({ function AsciicastPlayer({ blob }: { blob: Blob }) { const containerRef = useRef(null); + const screenRef = useRef(null); const terminalRef = useRef(null); const recordingRef = useRef(null); const positionRef = useRef(0); @@ -178,7 +178,9 @@ function AsciicastPlayer({ blob }: { blob: Blob }) { }, []); useEffect(() => { - if (!containerRef.current) return; + const container = containerRef.current; + const screen = screenRef.current; + if (!container || !screen) return; const terminal = new Terminal({ cursorBlink: false, disableStdin: true, @@ -186,13 +188,24 @@ function AsciicastPlayer({ blob }: { blob: Blob }) { fontSize: 12, theme: { background: "#09090b" }, }); - const fitAddon = new FitAddon(); - terminal.loadAddon(fitAddon); - terminal.open(containerRef.current); + terminal.open(screen); terminalRef.current = terminal; - const observer = new ResizeObserver(() => fitAddon.fit()); - observer.observe(containerRef.current); - fitAddon.fit(); + // The recording keeps its own size, scaled down to fit the panel. + const fit = () => { + const width = screen.offsetWidth; + const height = screen.offsetHeight; + if (!width || !height) return; + const scale = Math.min( + 1, + container.clientWidth / width, + container.clientHeight / height, + ); + screen.style.transform = `scale(${scale})`; + }; + const observer = new ResizeObserver(fit); + observer.observe(container); + observer.observe(screen); + const resizeListener = terminal.onResize(() => requestAnimationFrame(fit)); blob .text() @@ -207,6 +220,7 @@ function AsciicastPlayer({ blob }: { blob: Blob }) { return () => { observer.disconnect(); + resizeListener.dispose(); terminal.dispose(); terminalRef.current = null; }; @@ -232,8 +246,13 @@ function AsciicastPlayer({ blob }: { blob: Blob }) { if (error) return
{error}
; return ( -
-
+
+
+
+
{error}
; return ( -
+