feat: continued improvements

This commit is contained in:
LukeGus
2026-05-14 00:55:12 -05:00
parent 2a45cfea9a
commit c26288e024
51 changed files with 2933 additions and 9103 deletions
+30 -5
View File
@@ -688,9 +688,28 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
}
},
fit: () => {
fitAddonRef.current?.fit();
if (terminal) scheduleNotify(terminal.cols, terminal.rows);
hardRefresh();
if (!fitAddonRef.current || !terminal || isFittingRef.current) return;
isFittingRef.current = true;
try {
fitAddonRef.current.fit();
if (terminal.cols > 0 && terminal.rows > 0) {
const lastSize = lastFittedSizeRef.current;
if (
!lastSize ||
lastSize.cols !== terminal.cols ||
lastSize.rows !== terminal.rows
) {
scheduleNotify(terminal.cols, terminal.rows);
lastFittedSizeRef.current = {
cols: terminal.cols,
rows: terminal.rows,
};
}
}
setIsFitted(true);
} finally {
isFittingRef.current = false;
}
},
sendInput: (data: string) => {
if (webSocketRef.current?.readyState === 1) {
@@ -2448,7 +2467,13 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
}, [terminal, hostConfig.id, isVisible, isConnected, isConnecting]);
useEffect(() => {
if (!terminal || !fitAddonRef.current || !isVisible) return;
if (!terminal || !fitAddonRef.current) return;
if (!isVisible) {
lastFittedSizeRef.current = null;
lastSentSizeRef.current = null;
return;
}
const fitTimeoutId = setTimeout(() => {
if (!isFittingRef.current && terminal.cols > 0 && terminal.rows > 0) {
@@ -2457,7 +2482,7 @@ const TerminalInner = forwardRef<TerminalHandle, SSHTerminalProps>(
requestAnimationFrame(() => terminal.focus());
}
}
}, 0);
}, 50);
return () => clearTimeout(fitTimeoutId);
}, [terminal, isVisible, splitScreen, isConnecting]);
+6 -2
View File
@@ -1,4 +1,5 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { Terminal } from "@/features/terminal/Terminal.tsx";
import { FullScreenAppWrapper } from "@/features/FullScreenAppWrapper.tsx";
@@ -7,6 +8,7 @@ interface TerminalAppProps {
}
const TerminalApp: React.FC<TerminalAppProps> = ({ hostId }) => {
const { t } = useTranslation();
return (
<FullScreenAppWrapper hostId={hostId}>
{(hostConfig, loading) => {
@@ -15,7 +17,9 @@ const TerminalApp: React.FC<TerminalAppProps> = ({ hostId }) => {
<div className="flex items-center justify-center h-full">
<div className="text-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-white mx-auto mb-2"></div>
<p className="text-muted-foreground">Loading host...</p>
<p className="text-muted-foreground">
{t("hosts.loadingHost")}
</p>
</div>
</div>
);
@@ -25,7 +29,7 @@ const TerminalApp: React.FC<TerminalAppProps> = ({ hostId }) => {
return (
<div className="flex items-center justify-center h-full">
<div className="text-center">
<p className="text-red-500 mb-4">Host not found</p>
<p className="text-red-500 mb-4">{t("hosts.hostNotFound")}</p>
</div>
</div>
);
@@ -1,122 +0,0 @@
import { TERMINAL_THEMES, TERMINAL_FONTS } from "@/lib/terminal-themes.ts";
import { useTheme } from "@/components/theme-provider.tsx";
interface TerminalPreviewProps {
theme: string;
fontSize?: number;
fontFamily?: string;
cursorStyle?: "block" | "underline" | "bar";
cursorBlink?: boolean;
letterSpacing?: number;
lineHeight?: number;
}
export function TerminalPreview({
theme = "termix",
fontSize = 14,
fontFamily = "Caskaydia Cove Nerd Font Mono",
cursorStyle = "bar",
cursorBlink = true,
letterSpacing = 0,
lineHeight = 1.2,
}: TerminalPreviewProps) {
const { theme: appTheme } = useTheme();
const resolvedTheme =
theme === "termix"
? appTheme === "dark" ||
(appTheme === "system" &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
? "termixDark"
: "termixLight"
: theme;
return (
<div className="border border-input rounded-md overflow-hidden">
<div
className="p-4 font-mono text-sm"
style={{
fontSize: `${fontSize}px`,
fontFamily:
TERMINAL_FONTS.find((f) => f.value === fontFamily)?.fallback ||
TERMINAL_FONTS[0].fallback,
letterSpacing: `${letterSpacing}px`,
lineHeight,
background:
TERMINAL_THEMES[resolvedTheme]?.colors.background ||
"var(--bg-base)",
color:
TERMINAL_THEMES[resolvedTheme]?.colors.foreground ||
"var(--foreground)",
}}
>
<div>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.green }}>
user@termix
</span>
<span>:</span>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.blue }}>
~
</span>
<span>$ ls -la</span>
</div>
<div>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.blue }}>
drwxr-xr-x
</span>
<span> 5 user </span>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.cyan }}>
docs
</span>
</div>
<div>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.green }}>
-rwxr-xr-x
</span>
<span> 1 user </span>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.green }}>
script.sh
</span>
</div>
<div>
<span>-rw-r--r--</span>
<span> 1 user </span>
<span>README.md</span>
</div>
<div>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.green }}>
user@termix
</span>
<span>:</span>
<span style={{ color: TERMINAL_THEMES[resolvedTheme]?.colors.blue }}>
~
</span>
<span>$ </span>
<span
className="inline-block"
style={{
width: cursorStyle === "block" ? "0.6em" : "0.1em",
height:
cursorStyle === "underline"
? "0.15em"
: cursorStyle === "bar"
? `${fontSize}px`
: `${fontSize}px`,
background:
TERMINAL_THEMES[resolvedTheme]?.colors.cursor || "#f7f7f7",
animation: cursorBlink ? "blink 1s step-end infinite" : "none",
verticalAlign:
cursorStyle === "underline" ? "bottom" : "text-bottom",
}}
/>
</div>
</div>
<style>{`
@keyframes blink {
0%, 49% { opacity: 1; }
50%, 100% { opacity: 0; }
}
`}</style>
</div>
);
}