Fix terminal log follow and wrapping

This commit is contained in:
npc0-hue
2026-08-11 00:16:27 +08:00
parent 75a2c5aac5
commit 82ee28522c
5 changed files with 88 additions and 29 deletions
@@ -261,9 +261,9 @@ export function ServerManagementTerminalDrawer({ open, serverId, serverName, plu
</div>
</div>
<div ref={outputRef} className="terminal-output" role="log" aria-live="polite" onScroll={handleTerminalScroll}>
{streams.status === "error" && <div className="terminal-line terminal-line-error"><time>{new Date().toLocaleTimeString()}</time><span className="terminal-stream">LOGS</span><span className="terminal-text">{streams.reason}</span></div>}
{streams.status === "ready" && streams.data.length === 0 && <div className="terminal-line terminal-line-warn"><time>{new Date().toLocaleTimeString()}</time><span className="terminal-stream">LOGS</span><span className="terminal-text">Run </span></div>}
{lines.map((line) => <div key={line.id} className={`terminal-line terminal-line-${line.tone}`}><time>{line.at}</time><span className="terminal-stream">{line.streamKey || line.level || "LOG"}</span><span className="terminal-text">{line.text}</span></div>)}
{streams.status === "error" && <div className="terminal-line terminal-line-error terminal-source-system"><time>{new Date().toLocaleTimeString()}</time><span className="terminal-text">{streams.reason}</span></div>}
{streams.status === "ready" && streams.data.length === 0 && <div className="terminal-line terminal-line-warn terminal-source-system"><time>{new Date().toLocaleTimeString()}</time><span className="terminal-text">Run </span></div>}
{lines.map((line) => <div key={line.id} className={terminalLineClassName(line)}><time>{line.at}</time><span className="terminal-text">{line.text}</span></div>)}
</div>
</section>
<section className="terminal-command-dock" aria-label="terminal command controls">
@@ -316,6 +316,21 @@ function terminalSystemLine(tone: TerminalLine["tone"], text: string, streamKey:
return { id, tone, text, at: new Date(now).toLocaleTimeString(), sortKey: now, streamKey };
}
function terminalLineClassName(line: TerminalLine): string {
return `terminal-line terminal-line-${line.tone} terminal-source-${terminalSourceClass(line.streamKey || line.level)}`;
}
function terminalSourceClass(value?: string): string {
const key = (value ?? "").toLowerCase();
if (key.includes("stderr") || key === "error") return "stderr";
if (key.includes("stdout")) return "stdout";
if (key.includes("command")) return "command";
if (key.includes("platform")) return "platform";
if (key.includes("bridge")) return "bridge";
if (key.includes("system")) return "system";
return "log";
}
function isTerminalBridgeCommandState(state: GameClientBridgeCommandResponse["state"]): boolean {
return state === "succeeded" || state === "failed" || state === "cancelled" || state === "expired" || state === "unknown";
}