From 18db52ede3634b5f87ee666f362fe5e8701ed542 Mon Sep 17 00:00:00 2001 From: lim Date: Fri, 15 Nov 2024 09:31:38 +0000 Subject: [PATCH] feat(web):i18n sync with sealos desktop --- web/.env | 2 +- web/src/App.tsx | 2 + web/src/components/InitSealosApp/index.tsx | 119 +++++++++++++++++++++ web/src/pages/auth/index.tsx | 69 +++++------- 4 files changed, 146 insertions(+), 46 deletions(-) create mode 100644 web/src/components/InitSealosApp/index.tsx diff --git a/web/.env b/web/.env index 9a5dde2..5289a46 100644 --- a/web/.env +++ b/web/.env @@ -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/ diff --git a/web/src/App.tsx b/web/src/App.tsx index 7937188..4b701d0 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -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"; @@ -70,6 +71,7 @@ function APP() { + diff --git a/web/src/components/InitSealosApp/index.tsx b/web/src/components/InitSealosApp/index.tsx new file mode 100644 index 0000000..b50781a --- /dev/null +++ b/web/src/components/InitSealosApp/index.tsx @@ -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; diff --git a/web/src/pages/auth/index.tsx b/web/src/pages/auth/index.tsx index 3a68881..c385790 100644 --- a/web/src/pages/auth/index.tsx +++ b/web/src/pages/auth/index.tsx @@ -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({ @@ -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 (