Cleanup - unused files / unused exports / duplicate exports
[ProtonMail-WebClient.git] / applications / calendar / src / app / bootstrap.ts
blobdf928619a58c987253eb32c448a015d3b4530844
1 import {
2     addressesThunk,
3     initEvent,
4     organizationThunk,
5     serverEvent,
6     userSettingsThunk,
7     userThunk,
8     welcomeFlagsActions,
9 } from '@proton/account';
10 import * as bootstrap from '@proton/account/bootstrap';
11 import { bootstrapEvent } from '@proton/account/bootstrap/action';
12 import {
13     calendarSettingsThunk,
14     calendarsThunk,
15     createCalendarModelEventManager,
16     holidaysDirectoryThunk,
17 } from '@proton/calendar';
18 import { setupGuestCrossStorage } from '@proton/cross-storage/account-impl/guestInstance';
19 import { FeatureCode, fetchFeatures } from '@proton/features';
20 import createApi from '@proton/shared/lib/api/createApi';
21 import { getSilentApi } from '@proton/shared/lib/api/helpers/customConfig';
22 import { loadAllowedTimeZones } from '@proton/shared/lib/date/timezone';
23 import { listenFreeTrialSessionExpiration } from '@proton/shared/lib/desktop/endOfTrialHelpers';
24 import { createDrawerApi } from '@proton/shared/lib/drawer/createDrawerApi';
25 import { getIsAuthorizedApp } from '@proton/shared/lib/drawer/helpers';
26 import { isElectronMail } from '@proton/shared/lib/helpers/desktop';
27 import { initElectronClassnames } from '@proton/shared/lib/helpers/initElectronClassnames';
28 import { initSafariFontFixClassnames } from '@proton/shared/lib/helpers/initSafariFontFixClassnames';
29 import { captureMessage } from '@proton/shared/lib/helpers/sentry';
30 import type { ProtonConfig } from '@proton/shared/lib/interfaces';
31 import initLogicalProperties from '@proton/shared/lib/logical/logical';
32 import noop from '@proton/utils/noop';
34 import { embeddedDrawerAppInfos } from './helpers/drawer';
35 import locales from './locales';
36 import { extendStore, setupStore } from './store/store';
38 const getAppContainer = () =>
39     import(/* webpackChunkName: "MainContainer" */ './containers/calendar/MainContainer').then(
40         (result) => result.default
41     );
43 const { isIframe, isDrawerApp, parentApp } = embeddedDrawerAppInfos;
45 export const bootstrapApp = async ({ config, signal }: { config: ProtonConfig; signal?: AbortSignal }) => {
46     const pathname = window.location.pathname;
47     const searchParams = new URLSearchParams(window.location.search);
49     const api = isDrawerApp ? createDrawerApi({ parentApp, appVersion: config.APP_VERSION }) : createApi({ config });
50     const silentApi = getSilentApi(api);
51     const authentication = bootstrap.createAuthentication();
52     bootstrap.init({ config, authentication, locales });
54     setupGuestCrossStorage();
55     initElectronClassnames();
56     initLogicalProperties();
57     initSafariFontFixClassnames();
59     const appName = config.APP_NAME;
61     if (isElectronMail) {
62         listenFreeTrialSessionExpiration(appName, authentication, api);
63     }
65     // Temporary log for debugging
66     if (isIframe && !isDrawerApp) {
67         captureMessage('Drawer iframe bootstrap', {
68             level: 'info',
69             extra: {
70                 isIframe,
71                 parentApp,
72                 isAuthorizedApp: getIsAuthorizedApp(parentApp || ''),
73                 locationOrigin: window.location.origin,
74                 locationHref: window.location.href,
75             },
76         });
77     }
79     const run = async () => {
80         const appContainerPromise = getAppContainer();
82         const sessionResult =
83             (isDrawerApp && parentApp
84                 ? await bootstrap.loadDrawerSession({
85                       authentication,
86                       api,
87                       parentApp,
88                       pathname,
89                   })
90                 : undefined) || (await bootstrap.loadSession({ authentication, api, pathname, searchParams }));
92         const history = bootstrap.createHistory({ sessionResult, pathname });
93         const unleashClient = bootstrap.createUnleash({ api: silentApi });
95         const user = sessionResult.session?.User;
96         extendStore({ config, api, authentication, unleashClient, history });
98         const store = setupStore();
99         const dispatch = store.dispatch;
101         if (user) {
102             dispatch(initEvent({ User: user }));
103         }
105         const loadUser = async () => {
106             const [user, userSettings, features] = await Promise.all([
107                 dispatch(userThunk()),
108                 dispatch(userSettingsThunk()),
109                 dispatch(fetchFeatures([FeatureCode.EarlyAccessScope, FeatureCode.AutoAddHolidaysCalendars])),
110             ]);
112             dispatch(welcomeFlagsActions.initial(userSettings));
114             const [scopes] = await Promise.all([
115                 bootstrap.initUser({ appName, user, userSettings }),
116                 bootstrap.loadLocales({ userSettings, locales }),
117             ]);
119             return { user, userSettings, earlyAccessScope: features[FeatureCode.EarlyAccessScope], scopes };
120         };
122         const loadPreload = () => {
123             return Promise.all([
124                 dispatch(addressesThunk()),
125                 dispatch(calendarsThunk()),
126                 dispatch(calendarSettingsThunk()),
127             ]);
128         };
130         const loadPreloadButIgnored = () => {
131             loadAllowedTimeZones(silentApi).catch(noop);
132             dispatch(holidaysDirectoryThunk()).catch(noop);
133             dispatch(organizationThunk()).catch(noop);
134         };
136         const userPromise = loadUser();
137         const preloadPromise = loadPreload();
138         const evPromise = bootstrap.eventManager({ api: silentApi });
139         const unleashPromise = bootstrap.unleashReady({ unleashClient }).catch(noop);
140         loadPreloadButIgnored();
142         await unleashPromise;
143         // Needs unleash to be loaded.
144         await bootstrap.loadCrypto({ appName, unleashClient });
145         const [MainContainer, userData, eventManager] = await Promise.all([
146             appContainerPromise,
147             userPromise,
148             evPromise,
149         ]);
150         // Needs everything to be loaded.
151         await bootstrap.postLoad({ appName, authentication, ...userData, history });
152         // Preloaded models are not needed until the app starts, and also important do it postLoad as these requests might fail due to missing scopes.
153         await preloadPromise;
155         const calendarModelEventManager = createCalendarModelEventManager({ api: silentApi });
157         extendStore({ eventManager, calendarModelEventManager });
158         const unsubscribeEventManager = eventManager.subscribe((event) => {
159             dispatch(serverEvent(event));
160         });
161         eventManager.start();
163         bootstrap.onAbort(signal, () => {
164             unsubscribeEventManager();
165             eventManager.reset();
166             unleashClient.stop();
167             store.unsubscribe();
168         });
170         dispatch(bootstrapEvent({ type: 'complete' }));
172         return {
173             ...userData,
174             eventManager,
175             unleashClient,
176             history,
177             store,
178             MainContainer,
179         };
180     };
182     return bootstrap.wrap({ appName, authentication }, run());