Code cleanup
This commit is contained in:
@@ -57,14 +57,11 @@ interface LeftSidebarProps {
|
||||
|
||||
async function handleLogout() {
|
||||
try {
|
||||
// Call backend logout endpoint to clear HttpOnly cookie and data session
|
||||
await logoutUser();
|
||||
|
||||
// Reload the page to reset the application state
|
||||
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
console.error("Logout failed:", error);
|
||||
// Even if logout fails, reload the page to reset state
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,35 +48,25 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
isVisibleRef.current = isVisible;
|
||||
}, [isVisible]);
|
||||
|
||||
// Monitor authentication state - Linus principle: explicit state management
|
||||
useEffect(() => {
|
||||
const checkAuth = () => {
|
||||
const jwtToken = getCookie("jwt");
|
||||
const isAuth = !!(jwtToken && jwtToken.trim() !== "");
|
||||
|
||||
// Only update state if it actually changed - prevent unnecessary re-renders
|
||||
setIsAuthenticated(prev => {
|
||||
setIsAuthenticated((prev) => {
|
||||
if (prev !== isAuth) {
|
||||
console.debug("Mobile Auth State Changed:", {
|
||||
from: prev,
|
||||
to: isAuth,
|
||||
jwtPresent: !!jwtToken,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
return isAuth;
|
||||
}
|
||||
return prev; // No change, don't trigger re-render
|
||||
return prev;
|
||||
});
|
||||
};
|
||||
|
||||
// Check immediately
|
||||
checkAuth();
|
||||
|
||||
// Reduced frequency - check every 5 seconds instead of every second
|
||||
const authCheckInterval = setInterval(checkAuth, 5000);
|
||||
|
||||
return () => clearInterval(authCheckInterval);
|
||||
}, []); // No dependencies - prevent infinite loop
|
||||
}, []);
|
||||
|
||||
function hardRefresh() {
|
||||
try {
|
||||
@@ -139,8 +129,6 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
[terminal],
|
||||
);
|
||||
|
||||
// Resize handling optimized to avoid conflicts - Linus principle: eliminate duplicate complexity
|
||||
|
||||
function handleWindowResize() {
|
||||
if (!isVisibleRef.current) return;
|
||||
fitAddonRef.current?.fit();
|
||||
@@ -174,10 +162,10 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
else if (msg.type === "error")
|
||||
terminal.writeln(`\r\n[${t("terminal.error")}] ${msg.message}`);
|
||||
else if (msg.type === "connected") {
|
||||
isConnectingRef.current = false; // Clear connecting state
|
||||
isConnectingRef.current = false;
|
||||
} else if (msg.type === "disconnected") {
|
||||
wasDisconnectedBySSH.current = true;
|
||||
isConnectingRef.current = false; // Clear connecting state
|
||||
isConnectingRef.current = false;
|
||||
terminal.writeln(
|
||||
`\r\n[${msg.message || t("terminal.disconnected")}]`,
|
||||
);
|
||||
@@ -186,17 +174,13 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
});
|
||||
|
||||
ws.addEventListener("close", (event) => {
|
||||
isConnectingRef.current = false; // Clear connecting state
|
||||
isConnectingRef.current = false;
|
||||
|
||||
// Handle authentication errors (code 1008)
|
||||
if (event.code === 1008) {
|
||||
console.error("WebSocket authentication failed:", event.reason);
|
||||
terminal.writeln(`\r\n[Authentication failed - please re-login]`);
|
||||
|
||||
// Clear invalid JWT token
|
||||
localStorage.removeItem("jwt");
|
||||
|
||||
// Don't attempt to reconnect on auth failure
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -206,7 +190,7 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
});
|
||||
|
||||
ws.addEventListener("error", () => {
|
||||
isConnectingRef.current = false; // Clear connecting state
|
||||
isConnectingRef.current = false;
|
||||
terminal.writeln(`\r\n[${t("terminal.connectionError")}]`);
|
||||
});
|
||||
}
|
||||
@@ -214,9 +198,7 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
useEffect(() => {
|
||||
if (!terminal || !xtermRef.current || !hostConfig) return;
|
||||
|
||||
// Critical auth check - prevent terminal setup without authentication - Linus principle: fail fast
|
||||
if (!isAuthenticated) {
|
||||
console.debug("Terminal setup delayed - waiting for authentication");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -231,7 +213,6 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
allowTransparency: true,
|
||||
convertEol: true,
|
||||
windowsMode: false,
|
||||
// Keep Option key for special characters on macOS (false = allows special chars, true = Meta key)
|
||||
macOptionIsMeta: false,
|
||||
macOptionClickForcesSelection: false,
|
||||
rightClickSelectsWord: false,
|
||||
@@ -271,7 +252,7 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
fitAddonRef.current?.fit();
|
||||
if (terminal) scheduleNotify(terminal.cols, terminal.rows);
|
||||
hardRefresh();
|
||||
}, 150); // Increased debounce for better stability
|
||||
}, 150);
|
||||
});
|
||||
|
||||
resizeObserver.observe(xtermRef.current);
|
||||
@@ -280,24 +261,22 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
(document as any).fonts?.ready instanceof Promise
|
||||
? (document as any).fonts.ready
|
||||
: Promise.resolve();
|
||||
// Show terminal immediately - better UX for mobile
|
||||
setVisible(true);
|
||||
|
||||
readyFonts.then(() => {
|
||||
// Fixed delay and authentication check - Linus principle: eliminate race conditions
|
||||
setTimeout(() => {
|
||||
fitAddon.fit();
|
||||
if (terminal) scheduleNotify(terminal.cols, terminal.rows);
|
||||
hardRefresh();
|
||||
|
||||
// Verify authentication before attempting WebSocket connection
|
||||
const jwtToken = getCookie("jwt");
|
||||
if (!jwtToken || jwtToken.trim() === "") {
|
||||
console.warn("WebSocket connection delayed - no authentication token");
|
||||
console.warn(
|
||||
"WebSocket connection delayed - no authentication token",
|
||||
);
|
||||
setIsConnected(false);
|
||||
setIsConnecting(false);
|
||||
setConnectionError("Authentication required");
|
||||
// Don't show toast here - let auth system handle it
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,27 +304,24 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
})()
|
||||
: `${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.host}/ssh/websocket/`;
|
||||
|
||||
// Prevent duplicate connections - Linus principle: fail fast
|
||||
if (isConnectingRef.current) {
|
||||
console.debug("Skipping connection - already connecting");
|
||||
return;
|
||||
}
|
||||
|
||||
isConnectingRef.current = true;
|
||||
|
||||
// Clean up existing connection to prevent duplicates - Linus principle: eliminate complexity
|
||||
if (webSocketRef.current && webSocketRef.current.readyState !== WebSocket.CLOSED) {
|
||||
console.log("Closing existing WebSocket connection before creating new one");
|
||||
if (
|
||||
webSocketRef.current &&
|
||||
webSocketRef.current.readyState !== WebSocket.CLOSED
|
||||
) {
|
||||
webSocketRef.current.close();
|
||||
}
|
||||
|
||||
// Clear existing ping interval
|
||||
if (pingIntervalRef.current) {
|
||||
clearInterval(pingIntervalRef.current);
|
||||
pingIntervalRef.current = null;
|
||||
}
|
||||
|
||||
// Add JWT token as query parameter for authentication
|
||||
const wsUrl = `${baseWsUrl}?token=${encodeURIComponent(jwtToken)}`;
|
||||
|
||||
setIsConnecting(true);
|
||||
@@ -356,7 +332,7 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
wasDisconnectedBySSH.current = false;
|
||||
|
||||
setupWebSocketListeners(ws, cols, rows);
|
||||
}, 200); // Increased from 100ms to 200ms for auth stability
|
||||
}, 200);
|
||||
});
|
||||
|
||||
return () => {
|
||||
@@ -369,7 +345,7 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
|
||||
}
|
||||
webSocketRef.current?.close();
|
||||
};
|
||||
}, [xtermRef, terminal, hostConfig]); // Removed isAuthenticated to prevent infinite loop
|
||||
}, [xtermRef, terminal, hostConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible && fitAddonRef.current) {
|
||||
|
||||
Reference in New Issue
Block a user