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