feat: improve tmux session management and UX

Replace hardcoded setTimeout timing with exec channel polling for
reliable tmux session readiness detection. Add meaningful session
naming (termix-<hostId>-<rand>), aggressive-resize for multi-client
support, and a detach button in the terminal UI.
This commit is contained in:
ZacharyZcR
2026-05-18 02:24:29 +08:00
parent ebed4a6d2e
commit 47d660a509
5 changed files with 111 additions and 44 deletions
+22
View File
@@ -220,6 +220,7 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
}>;
} | null>(null);
const tmuxSessionNameRef = useRef<string | null>(null);
const [isTmuxAttached, setIsTmuxAttached] = useState(false);
const tmuxCopyModeHintShownRef = useRef(false);
const isVisibleRef = useRef<boolean>(false);
@@ -1533,6 +1534,7 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
const sessionName =
typeof msg.sessionName === "string" ? msg.sessionName : "";
tmuxSessionNameRef.current = sessionName || "(active)";
setIsTmuxAttached(true);
addLog({
type: "info",
stage: "connection",
@@ -1556,6 +1558,10 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
stage: "connection",
message: t("terminal.tmuxUnavailable"),
});
} else if (msg.type === "tmux_detached") {
tmuxSessionNameRef.current = null;
setIsTmuxAttached(false);
toast.info(t("terminal.tmuxDetached"), { duration: 3000 });
} else if (msg.type === "connection_log") {
if (msg.data) {
addLog({
@@ -2513,6 +2519,22 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
}}
/>
{isTmuxAttached && isConnected && (
<button
onClick={() => {
if (webSocketRef.current?.readyState === WebSocket.OPEN) {
webSocketRef.current.send(
JSON.stringify({ type: "tmux_detach" }),
);
}
}}
title={t("terminal.tmuxDetach")}
className="absolute top-2 right-2 z-[110] px-2 py-1 text-xs rounded bg-black/60 text-white/70 hover:text-white hover:bg-black/80 transition-colors"
>
tmux:detach
</button>
)}
<SimpleLoader
visible={isConnecting && !isConnectionLogExpanded}
message={t("terminal.connecting")}