mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-15 21:03:47 +00:00
perf: frontend request cache, poll pause, and code-split shell (#1052)
Host/status caching, shell code-split, SSH pool waits, host-metrics concurrency, background-tab idle, per-host status subscriptions, homepage poll quieting, and virtualized host sidebar + file manager lists.
This commit is contained in:
@@ -801,6 +801,7 @@ function CardItem({
|
||||
onAddServiceLink,
|
||||
onDeleteServiceLink,
|
||||
statusLoading,
|
||||
isVisible = true,
|
||||
}: {
|
||||
slot: CardSlot;
|
||||
editMode: boolean;
|
||||
@@ -830,6 +831,7 @@ function CardItem({
|
||||
onAddServiceLink: (label: string, url: string) => Promise<void>;
|
||||
onDeleteServiceLink: (id: number) => Promise<void>;
|
||||
statusLoading?: boolean;
|
||||
isVisible?: boolean;
|
||||
}) {
|
||||
const cardRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
@@ -926,6 +928,7 @@ function CardItem({
|
||||
{slot.id === "network_graph" && (
|
||||
<NetworkGraphCard
|
||||
embedded={true}
|
||||
isVisible={isVisible}
|
||||
onOpenInNewTab={() => onOpenSingletonTab("network_graph")}
|
||||
/>
|
||||
)}
|
||||
@@ -1055,6 +1058,7 @@ type PanelColumnProps = {
|
||||
onAddServiceLink: (label: string, url: string) => Promise<void>;
|
||||
onDeleteServiceLink: (id: number) => Promise<void>;
|
||||
statusLoading: boolean;
|
||||
isVisible?: boolean;
|
||||
};
|
||||
|
||||
function PanelColumn({
|
||||
@@ -1086,6 +1090,7 @@ function PanelColumn({
|
||||
onAddServiceLink,
|
||||
onDeleteServiceLink,
|
||||
statusLoading,
|
||||
isVisible = true,
|
||||
}: PanelColumnProps) {
|
||||
const { t } = useTranslation();
|
||||
const sorted = [...slots].sort((a, b) => a.order - b.order);
|
||||
@@ -1142,6 +1147,7 @@ function PanelColumn({
|
||||
onAddServiceLink={onAddServiceLink}
|
||||
onDeleteServiceLink={onDeleteServiceLink}
|
||||
statusLoading={statusLoading}
|
||||
isVisible={isVisible}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
@@ -1192,9 +1198,12 @@ function ColumnDivider({
|
||||
export function DashboardTab({
|
||||
onOpenSingletonTab,
|
||||
onOpenTab,
|
||||
isVisible = true,
|
||||
}: {
|
||||
onOpenSingletonTab: (type: TabType, pendingEvent?: string) => void;
|
||||
onOpenTab: (host: Host, type: TabType) => void;
|
||||
/** When false, pause dashboard metrics refresh while the tab stays mounted. */
|
||||
isVisible?: boolean;
|
||||
}) {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { initialLoadComplete } = useServerStatus();
|
||||
@@ -1349,7 +1358,9 @@ export function DashboardTab({
|
||||
const mapped = raw.map(sshHostToHost);
|
||||
const statusHosts = mapped.filter(isStatusCheckEnabled);
|
||||
if (mounted) setHosts(mapped);
|
||||
fetchMetrics(statusHosts).catch(() => {});
|
||||
if (isVisible) {
|
||||
fetchMetrics(statusHosts).catch(() => {});
|
||||
}
|
||||
};
|
||||
load();
|
||||
|
||||
@@ -1399,7 +1410,14 @@ export function DashboardTab({
|
||||
})
|
||||
.catch(() => {});
|
||||
|
||||
if (!isVisible) {
|
||||
return () => {
|
||||
mounted = false;
|
||||
};
|
||||
}
|
||||
|
||||
const metricsInterval = setInterval(async () => {
|
||||
if (document.visibilityState === "hidden") return;
|
||||
const raw = await getSSHHosts().catch(() => []);
|
||||
const mapped = raw.map(sshHostToHost);
|
||||
const statusHosts = mapped.filter(isStatusCheckEnabled);
|
||||
@@ -1411,17 +1429,18 @@ export function DashboardTab({
|
||||
mounted = false;
|
||||
clearInterval(metricsInterval);
|
||||
};
|
||||
}, [fetchMetrics]);
|
||||
}, [fetchMetrics, isVisible]);
|
||||
|
||||
useEffect(() => {
|
||||
if (viewerSessionsRef.current.size === 0) return;
|
||||
if (!isVisible || viewerSessionsRef.current.size === 0) return;
|
||||
const heartbeat = setInterval(async () => {
|
||||
if (document.visibilityState === "hidden") return;
|
||||
for (const [, sessionId] of viewerSessionsRef.current) {
|
||||
sendMetricsHeartbeat(sessionId).catch(() => {});
|
||||
}
|
||||
}, 30000);
|
||||
return () => clearInterval(heartbeat);
|
||||
}, [hostMetrics]);
|
||||
}, [hostMetrics, isVisible]);
|
||||
|
||||
const handleClearActivity = async () => {
|
||||
try {
|
||||
@@ -1594,6 +1613,7 @@ export function DashboardTab({
|
||||
onAddServiceLink: handleAddServiceLink,
|
||||
onDeleteServiceLink: handleDeleteServiceLink,
|
||||
statusLoading,
|
||||
isVisible,
|
||||
};
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
@@ -1733,6 +1753,7 @@ export function DashboardTab({
|
||||
{slot.id === "network_graph" && (
|
||||
<NetworkGraphCard
|
||||
embedded={true}
|
||||
isVisible={isVisible}
|
||||
onOpenInNewTab={() => onOpenSingletonTab("network_graph")}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user