Path: blob/master/src/packages/frontend/app/render.tsx
1496 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import {6redux,7Redux,8useAsyncEffect,9useTypedRedux,10} from "@cocalc/frontend/app-framework";11import {12getLocale,13LOCALIZATIONS,14OTHER_SETTINGS_LOCALE_KEY,15} from "@cocalc/frontend/i18n";16import { QueryParams } from "@cocalc/frontend/misc/query-params";17import { createRoot } from "react-dom/client";18import { AppContext, useAppContextProvider } from "./context";19import { Localize, useLocalizationCtx } from "./localize";2021// App uses the context provided by Redux (for the locale, etc.) and Localize.22function App({ children }) {23const appState = useAppContextProvider();24const { setLocale } = useLocalizationCtx();25const other_settings = useTypedRedux("account", "other_settings");2627// setting via ?lang=[locale] takes precedence over account settings28// additionally ?lang_temp=[locale] temporarily changes it, used by these impersonation admin links29useAsyncEffect(async () => {30const lang_set = QueryParams.get("lang");31// lang_temp sets the language *temporarily*, i.e. without changing the account settings and it is sticky32// this is useful for impersonation – https://github.com/sagemathinc/cocalc/issues/778233const lang_temp = QueryParams.get("lang_temp");34const temp = lang_temp != null;35const lang = temp ? lang_temp : lang_set;36if (lang != null) {37if (lang in LOCALIZATIONS) {38console.warn(39`URL query parameter 'lang=${lang}' – overriding user configuration ${40temp ? "temporary" : "permanent"41}.`,42);43if (!temp) {44const store = redux.getStore("account");45// we have to ensure the account store is available, because this code runs very early46await store.async_wait({47until: () => store.get_account_id() != null,48});49redux50.getActions("account")51.set_other_settings(OTHER_SETTINGS_LOCALE_KEY, lang);52}53setLocale(lang);54} else {55console.warn(56`URL query parameter '${JSON.stringify({57lang_set,58lang_temp,59})}' provided, but not a valid locale.`,60`Known values: ${Object.keys(LOCALIZATIONS)}`,61);62}63if (!temp) {64// removing the parameter, otherwise this conflicts with further changes of account settings65QueryParams.remove("lang");66}67} else {68setLocale(getLocale(other_settings));69}70}, [getLocale(other_settings)]);7172const timeAgo = {73timeAgoAbsolute: other_settings.get("time_ago_absolute"),74setTimeAgoAbsolute: (absolute: boolean) => {75redux76.getActions("account")77.set_other_settings("time_ago_absolute", absolute);78},79};8081return (82<AppContext.Provider value={{ ...appState, ...timeAgo }}>83{children}84</AppContext.Provider>85);86}8788function Root({ Page }) {89return (90<Redux>91<Localize>92<App>93<Page />94</App>95</Localize>96</Redux>97);98}99100export async function render(): Promise<void> {101finishedLoading(); // comment this out to leave the loading/startup banner visible so you can use the Chrome dev tools with it.102const container = document.getElementById("cocalc-webapp-container");103const root = createRoot(container!);104const { Page } = await import("./page");105root.render(<Root Page={Page} />);106}107108// When loading is done, remove any visible artifacts.109// This doesn't remove anything added to the head.110function finishedLoading() {111const load = document.getElementById("cocalc-load-container");112if (load != null) {113load.innerHTML = "";114load.remove();115}116}117118119