Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web):i18n sync with sealos desktop #18

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ VITE_SERVER_BASE_URL=

# this only used for dev environment, change it to your local api server url if needed
# don't change it directly, you should create a .env.local file and set it there
VITE_DEV_SERVER_URL=http://api.laf.run
VITE_DEV_SERVER_URL=https://sealaf-api.bja.sealos.run/
2 changes: 2 additions & 0 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ClickToComponent } from "click-to-react-component";

import "@/utils/i18n";

import InitSealosApp from "./components/InitSealosApp";
import UpgradePrompt from "./components/UpgradePrompt";
import useSiteSettingStore from "./pages/siteSetting";
import theme from "./chakraTheme";
Expand Down Expand Up @@ -70,6 +71,7 @@ function APP() {
<ChakraProvider theme={colorMode === "light" ? theme : darkTheme}>
<Global styles={GlobalStyles} />
<UpgradePrompt />
<InitSealosApp />
<BrowserRouter>
<RouteElement />
</BrowserRouter>
Expand Down
119 changes: 119 additions & 0 deletions web/src/components/InitSealosApp/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// components/SealosProvider.tsx
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { EVENT_NAME } from "@zjy365/sealos-desktop-sdk";
import { SessionV1 } from "@zjy365/sealos-desktop-sdk/*";
import { createSealosApp, sealosApp } from "@zjy365/sealos-desktop-sdk/app";

import useSessionStore from "@/pages/auth/store";

const InitSealosApp = () => {
const { i18n } = useTranslation();
const { setSession } = useSessionStore();

const handleI18nChange = (data: { currentLanguage: string }) => {
const currentLng = i18n.resolvedLanguage;
const newLng = data.currentLanguage;
if (currentLng !== newLng) {
i18n.changeLanguage(newLng);
}
};

const initLang = async () => {
const lang = await sealosApp.getLanguage();
const lng = lang.lng;
if (i18n.resolvedLanguage !== lng) {
i18n.changeLanguage(lng);
}
};

const initApp = async () => {
const sealosUser = import.meta.env.VITE_SEALOS_MOCK_USER;
const sealosKc = import.meta.env.VITE_SEALOS_MOCK_KC;

if (sealosUser && sealosKc) {
const testSession: SessionV1 = {
user: {
id: "",
name: sealosUser,
avatar: "",
k8sUsername: "",
nsid: "",
},
kubeconfig: sealosKc,
};
setSession(testSession);
return;
}

const result = await sealosApp.getSession();

setSession(result);
};

useEffect(() => {
const cleanupApp = createSealosApp();
let cleanupEventListener: (() => void) | undefined;

// handle iframe focus
const handleIframeFocus = () => {
const iframes = document.querySelectorAll("iframe");
iframes.forEach((iframe) => {
iframe.style.pointerEvents = "auto";
});
};

// handle iframe visibility change
const handleVisibilityChange = () => {
if (!document.hidden) {
handleIframeFocus();
}
};

const setup = async () => {
try {
window.addEventListener("blur", handleIframeFocus);
document.addEventListener("visibilitychange", handleVisibilityChange);

cleanupEventListener = sealosApp?.addAppEventListen(
EVENT_NAME.CHANGE_I18N,
handleI18nChange,
);

handleIframeFocus();

await initLang();
await initApp();
} catch (error) {
if (error instanceof Error) {
// eslint-disable-next-line no-console
console.error("Sealos app init error:", error.message);
} else {
// eslint-disable-next-line no-console
console.error("Sealos app init error:", error);
}
}
};

setup().finally(() => {
// eslint-disable-next-line no-console
console.info("##### sealos app and sealos info init success #####");
});

return () => {
window.removeEventListener("blur", handleIframeFocus);
document.removeEventListener("visibilitychange", handleVisibilityChange);

if (cleanupEventListener && typeof cleanupEventListener === "function") {
cleanupEventListener();
}
if (cleanupApp && typeof cleanupApp === "function") {
cleanupApp();
}
};
}, []);

return null;
};

export default InitSealosApp;
69 changes: 24 additions & 45 deletions web/src/pages/auth/index.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,15 @@
import { useEffect, useState } from "react";
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { Center, Spinner } from "@chakra-ui/react";
import { useMutation } from "@tanstack/react-query";
import { SessionV1 } from "@zjy365/sealos-desktop-sdk/*";
import { createSealosApp, sealosApp } from "@zjy365/sealos-desktop-sdk/app";

import useSessionStore from "./store";

import { AuthenticationControllerSignin } from "@/apis/v1/auth";

const AuthPage = () => {
const { session, setSession, getKubeconfig, getNamespace } = useSessionStore();
const [isInit, setIsInit] = useState(false);

useEffect(() => {
return createSealosApp();
}, []);

useEffect(() => {
const initApp = async () => {
const sealosUser = import.meta.env.VITE_SEALOS_MOCK_USER;
const sealosKc = import.meta.env.VITE_SEALOS_MOCK_KC;

if (sealosUser && sealosKc) {
const testSession: SessionV1 = {
user: {
id: "",
name: sealosUser,
avatar: "",
k8sUsername: "",
nsid: "",
},
kubeconfig: sealosKc,
};
setSession(testSession);
return;
}

const result = await sealosApp.getSession();

setSession(result);
};

initApp().finally(() => setIsInit(true));
}, []);
const navigate = useNavigate();
const { session, getKubeconfig, getNamespace } = useSessionStore();

const { mutateAsync: signin } = useMutation(["signin"], () => {
return AuthenticationControllerSignin({
Expand All @@ -52,23 +19,35 @@ const AuthPage = () => {
});
});

useEffect(() => {
if (!isInit) return;

const handleAuth = async () => {
const localNamespace = localStorage.getItem("sealos-namespace");
const localToken = localStorage.getItem("token");
const namespace = getNamespace();

if (session.user && namespace && (localNamespace !== namespace || !localToken)) {
signin().then((res) => {
try {
const res = await signin();
localStorage.setItem("token", res?.data.token);
localStorage.setItem("sealos-namespace", namespace);
window.location.href = "/dashboard";
});
navigate("/dashboard");
} catch (error) {
if (error instanceof Error) {
// eslint-disable-next-line no-console
console.error("login error:", error.message);
} else {
// eslint-disable-next-line no-console
console.error("login error:", error);
}
}
} else if (localToken && namespace && localNamespace === namespace) {
window.location.href = "/dashboard";
navigate("/dashboard");
}
}, [session, isInit]);
};

// after signin, handle auth and goto dashboard
useEffect(() => {
handleAuth();
}, [session]);

return (
<Center w="100vw" h="100vh">
Expand Down
Loading