mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-07-16 05:13:36 +00:00
v2.3.0
This commit is contained in:
+64
-4
@@ -8,9 +8,11 @@ import "./ui/i18n/i18n";
|
||||
import { isElectron } from "@/lib/electron";
|
||||
import { Toaster } from "@/components/sonner";
|
||||
import { Auth, getStoredAuth, clearStoredAuth } from "@/auth/Auth";
|
||||
import { getUserInfo, getCurrentToken, appReadyPromise } from "@/main-axios";
|
||||
import { applyAccentColor, applyFontSize } from "@/lib/theme";
|
||||
import type { FontSizeId } from "@/types/ui-types";
|
||||
import { useServiceWorker } from "@/hooks/use-service-worker";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const AppShell = lazy(() =>
|
||||
import("@/AppShell").then((m) => ({ default: m.AppShell })),
|
||||
@@ -34,7 +36,12 @@ const ElectronVersionCheck = lazy(() =>
|
||||
})),
|
||||
);
|
||||
|
||||
type Phase = "idle-auth" | "fading-in" | "idle-app" | "fading-out";
|
||||
type Phase =
|
||||
| "verifying"
|
||||
| "idle-auth"
|
||||
| "fading-in"
|
||||
| "idle-app"
|
||||
| "fading-out";
|
||||
|
||||
function useWindowWidth() {
|
||||
const [width, setWidth] = useState(window.innerWidth);
|
||||
@@ -105,7 +112,7 @@ function FullscreenApp() {
|
||||
function App() {
|
||||
const stored = getStoredAuth();
|
||||
const [phase, setPhase] = useState<Phase>(
|
||||
stored?.loggedIn ? "idle-app" : "idle-auth",
|
||||
stored?.loggedIn ? "verifying" : "idle-auth",
|
||||
);
|
||||
const [authUsername, setAuthUsername] = useState(stored?.username ?? "");
|
||||
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
@@ -122,10 +129,38 @@ function App() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Verify stored session against the server before rendering AppShell.
|
||||
// Wait for API instances to be initialized with correct embedded/server config first.
|
||||
// In Electron, also repopulate localStorage["jwt"] so WebSocket connections can auth
|
||||
// after a session restore (the token is only written to localStorage during a fresh login).
|
||||
useEffect(() => {
|
||||
if (phase !== "verifying") return;
|
||||
appReadyPromise
|
||||
.then(() => getUserInfo())
|
||||
.then(() => {
|
||||
if (isElectron()) {
|
||||
getCurrentToken()
|
||||
.then((token) => {
|
||||
if (token) localStorage.setItem("jwt", token);
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
setPhase("fading-in");
|
||||
timerRef.current = setTimeout(() => setPhase("idle-app"), 450);
|
||||
})
|
||||
.catch(() => {
|
||||
clearStoredAuth();
|
||||
setPhase("idle-auth");
|
||||
});
|
||||
}, [phase]);
|
||||
|
||||
function handleLogin(u: string) {
|
||||
setAuthUsername(u);
|
||||
setPhase("fading-in");
|
||||
timerRef.current = setTimeout(() => setPhase("idle-app"), 450);
|
||||
if (isElectron()) {
|
||||
window.electronAPI?.startC2SAutoStartTunnels?.().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
@@ -144,11 +179,36 @@ function App() {
|
||||
const appOpacity = phase === "idle-app" ? 1 : 0;
|
||||
const authOpacity = phase === "idle-auth" ? 1 : 0;
|
||||
|
||||
const { t } = useTranslation();
|
||||
const isTransitioning = phase === "fading-in" || phase === "fading-out";
|
||||
|
||||
if (phase === "verifying") {
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-background">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="w-5 h-5 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">{t("common.loading")}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isTransitioning && (
|
||||
<div className="fixed inset-0 z-0 flex items-center justify-center bg-background">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="w-5 h-5 border-2 border-primary border-t-transparent rounded-full animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t("common.loading")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showApp && (
|
||||
<div
|
||||
className="fixed inset-0 z-0 transition-opacity duration-[450ms] ease-in-out"
|
||||
className="fixed inset-0 z-10 transition-opacity duration-[450ms] ease-in-out"
|
||||
style={{
|
||||
opacity: appOpacity,
|
||||
pointerEvents: phase === "idle-app" ? "auto" : "none",
|
||||
@@ -162,7 +222,7 @@ function App() {
|
||||
|
||||
{showAuth && (
|
||||
<div
|
||||
className="fixed inset-0 z-10 transition-opacity duration-[450ms] ease-in-out"
|
||||
className="fixed inset-0 z-20 transition-opacity duration-[450ms] ease-in-out"
|
||||
style={{
|
||||
opacity: authOpacity,
|
||||
pointerEvents: phase === "idle-auth" ? "auto" : "none",
|
||||
|
||||
Reference in New Issue
Block a user