signal-desktop/ts/components/App.tsx

142 lines
4 KiB
TypeScript
Raw Normal View History

2023-01-03 11:55:46 -08:00
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useEffect } from 'react';
2021-06-14 15:01:00 -04:00
import classNames from 'classnames';
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
2023-08-29 02:41:32 +02:00
import type { VerificationTransport } from '../types/VerificationTransport';
import { ThemeType } from '../types/Util';
2024-08-27 17:00:41 -04:00
import { missingCaseError } from '../util/missingCaseError';
import { type AppStateType, AppViewType } from '../state/ducks/app';
2021-12-16 09:02:22 -06:00
import { SmartInstallScreen } from '../state/smart/InstallScreen';
2021-06-14 15:01:00 -04:00
import { StandaloneRegistration } from './StandaloneRegistration';
2021-09-17 18:24:21 -04:00
import { usePageVisibility } from '../hooks/usePageVisibility';
2021-06-14 15:01:00 -04:00
type PropsType = {
2024-08-27 17:00:41 -04:00
state: AppStateType;
2022-03-04 16:14:52 -05:00
openInbox: () => void;
getCaptchaToken: () => Promise<string>;
2023-08-29 02:41:32 +02:00
registerSingleDevice: (
number: string,
code: string,
sessionId: string
) => Promise<void>;
uploadProfile: (opts: {
firstName: string;
lastName: string;
}) => Promise<void>;
2021-06-17 17:15:09 -04:00
renderCallManager: () => JSX.Element;
renderGlobalModalContainer: () => JSX.Element;
hasSelectedStoryData: boolean;
readyForUpdates: () => void;
renderStoryViewer: (closeView: () => unknown) => JSX.Element;
2022-12-09 21:02:22 -05:00
renderLightbox: () => JSX.Element | null;
2021-11-30 18:51:53 +01:00
requestVerification: (
number: string,
2023-08-29 02:41:32 +02:00
captcha: string,
transport: VerificationTransport
) => Promise<{ sessionId: string }>;
2021-06-14 15:01:00 -04:00
theme: ThemeType;
isMaximized: boolean;
isFullScreen: boolean;
2023-01-12 19:24:59 -05:00
osClassName: string;
scrollToMessage: (conversationId: string, messageId: string) => unknown;
viewStory: ViewStoryActionCreatorType;
2023-01-02 16:34:41 -05:00
renderInbox: () => JSX.Element;
};
2021-06-14 15:01:00 -04:00
2022-11-17 16:45:19 -08:00
export function App({
2024-08-27 17:00:41 -04:00
state,
getCaptchaToken,
hasSelectedStoryData,
isFullScreen,
2022-06-16 15:12:50 -04:00
isMaximized,
2023-01-02 16:34:41 -05:00
openInbox,
2023-01-12 19:24:59 -05:00
osClassName,
readyForUpdates,
2022-06-16 15:12:50 -04:00
registerSingleDevice,
2021-06-17 17:15:09 -04:00
renderCallManager,
renderGlobalModalContainer,
2023-01-02 16:34:41 -05:00
renderInbox,
2022-12-09 21:02:22 -05:00
renderLightbox,
2022-07-06 15:06:20 -04:00
renderStoryViewer,
2021-11-30 18:51:53 +01:00
requestVerification,
2021-06-14 15:01:00 -04:00
theme,
uploadProfile,
viewStory,
2022-11-17 16:45:19 -08:00
}: PropsType): JSX.Element {
2021-06-14 15:01:00 -04:00
let contents;
2024-08-27 17:00:41 -04:00
if (state.appView === AppViewType.Installer) {
2021-12-16 09:02:22 -06:00
contents = <SmartInstallScreen />;
2024-08-27 17:00:41 -04:00
} else if (state.appView === AppViewType.Standalone) {
2021-11-30 18:51:53 +01:00
const onComplete = () => {
2023-01-12 19:24:59 -05:00
window.IPC.removeSetupMenuItems();
2021-11-30 18:51:53 +01:00
openInbox();
};
contents = (
<StandaloneRegistration
onComplete={onComplete}
getCaptchaToken={getCaptchaToken}
readyForUpdates={readyForUpdates}
2021-11-30 18:51:53 +01:00
requestVerification={requestVerification}
registerSingleDevice={registerSingleDevice}
uploadProfile={uploadProfile}
2021-11-30 18:51:53 +01:00
/>
);
2024-08-27 17:00:41 -04:00
} else if (state.appView === AppViewType.Inbox) {
2023-01-02 16:34:41 -05:00
contents = renderInbox();
2024-08-27 17:00:41 -04:00
} else if (state.appView === AppViewType.Blank) {
contents = undefined;
} else {
2024-09-03 19:56:13 -07:00
throw missingCaseError(state.appView);
2021-06-14 15:01:00 -04:00
}
// This are here so that themes are properly applied to anything that is
2021-06-17 17:15:09 -04:00
// created in a portal and exists outside of the <App /> container.
useEffect(() => {
document.body.classList.remove('light-theme');
document.body.classList.remove('dark-theme');
if (theme === ThemeType.dark) {
document.body.classList.add('dark-theme');
}
if (theme === ThemeType.light) {
document.body.classList.add('light-theme');
}
}, [theme]);
2023-01-12 19:24:59 -05:00
useEffect(() => {
document.body.classList.add(osClassName);
}, [osClassName]);
useEffect(() => {
document.body.classList.toggle('full-screen', isFullScreen);
document.body.classList.toggle('maximized', isMaximized);
}, [isFullScreen, isMaximized]);
const isPageVisible = usePageVisibility();
useEffect(() => {
document.body.classList.toggle('page-is-visible', isPageVisible);
}, [isPageVisible]);
2021-06-14 15:01:00 -04:00
return (
<div
className={classNames({
App: true,
'light-theme': theme === ThemeType.light,
'dark-theme': theme === ThemeType.dark,
})}
2021-06-14 15:01:00 -04:00
>
{contents}
{renderGlobalModalContainer()}
{renderCallManager()}
{renderLightbox()}
{hasSelectedStoryData &&
renderStoryViewer(() => viewStory({ closeViewer: true }))}
</div>
2021-06-14 15:01:00 -04:00
);
2022-11-17 16:45:19 -08:00
}