/* * Wire * Copyright (C) 2018 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import {FC, ReactNode, useEffect} from 'react'; import {pathWithParams} from '@wireapp/commons/lib/util/UrlUtil'; import {IntlProvider} from 'react-intl'; import {connect} from 'react-redux'; import {HashRouter as Router, Navigate, Route, Routes} from 'react-router-dom'; import {AnyAction, Dispatch} from 'redux'; import {ContainerXS, Loading, StyledApp, THEME_ID} from '@wireapp/react-ui-kit'; import {t} from 'Util/LocalizerUtil'; import {ClientManager} from './ClientManager'; import {ConversationJoin} from './ConversationJoin'; import {ConversationJoinInvalid} from './ConversationJoinInvalid'; import {CreateAccount} from './CreateAccount'; import {CreatePersonalAccount} from './CreatePersonalAccount'; import {CustomEnvironmentRedirect} from './CustomEnvironmentRedirect'; import {HistoryInfo} from './HistoryInfo'; import {Index} from './Index'; import {InitialInvite} from './InitialInvite'; import {Login} from './Login'; import {OAuthPermissions} from './OAuthPermissions'; import {SetAccountType} from './SetAccountType'; import {SetEmail} from './SetEmail'; import {SetEntropyPage} from './SetEntropyPage'; import {SetHandle} from './SetHandle'; import {SetPassword} from './SetPassword'; import {SingleSignOn} from './SingleSignOn'; import {TeamName} from './TeamName'; import {VerifyEmailCode} from './VerifyEmailCode'; import {VerifyEmailLink} from './VerifyEmailLink'; import {Config} from '../../Config'; import {mapLanguage, normalizeLanguage} from '../localeConfig'; import {actionRoot as ROOT_ACTIONS} from '../module/action/'; import {bindActionCreators, RootState} from '../module/reducer'; import * as AuthSelector from '../module/selector/AuthSelector'; import * as LanguageSelector from '../module/selector/LanguageSelector'; import {ROUTE} from '../route'; import {getOAuthQueryString} from '../util/oauthUtil'; interface RootProps {} const Title: FC<{title: string; children: ReactNode}> = ({title, children}) => { useEffect(() => { document.title = title; }, [title]); return <>{children}; }; const RootComponent: FC = ({ isAuthenticated, language, isFetchingSSOSettings, doGetSSOSettings, }) => { useEffect(() => { // Force the hash url to have a initial `/` (see https://stackoverflow.com/a/71864506) const forceSlashAfterHash = () => { const hash = window.location.hash; if (!hash.startsWith('#/')) { window.location.hash = `#/${hash.slice(1)}`; } }; forceSlashAfterHash(); window.addEventListener('hashchange', forceSlashAfterHash); return () => { window.removeEventListener('hashchange', forceSlashAfterHash); }; }, []); useEffect(() => { doGetSSOSettings(); }, []); const loadLanguage = (language: string) => { return require(`I18n/${mapLanguage(language)}.json`); }; const navigate = (route: string): null => { window.location.assign(pathWithParams(route)); return null; }; const isAuthenticatedCheck = (page: ReactNode): ReactNode => page ? (isAuthenticated ? page : navigate('/auth')) : null; const isOAuthCheck = (page: ReactNode): ReactNode => { if (page) { if (isAuthenticated) { return page; } const queryString = getOAuthQueryString(window.location); return queryString ? : ; } return null; }; const ProtectedHistoryInfo = () => isAuthenticatedCheck(); const ProtectedInitialInvite = () => isAuthenticatedCheck(); const ProtectedClientManager = () => isAuthenticatedCheck(); const ProtectedSetHandle = () => isAuthenticatedCheck(); const ProtectedSetEmail = () => isAuthenticatedCheck(); const ProtectedSetPassword = () => isAuthenticatedCheck(); const ProtectedOAuthPermissions = () => isOAuthCheck(); // Send user back to index page after e2ei oauth redirect // This is needed because the oauth redirect is only done by logged in users // and the user would otherwise be stuck on login page without getting logged in if (window.location.hash.includes(ROUTE.E2EI_OAUTH_REDIRECT)) { navigate(ROUTE.INDEX); } const brandName = Config.getConfig().BRAND_NAME; return ( {isFetchingSSOSettings ? ( ) : ( } /> } /> } /> } /> {Config.getConfig().FEATURE.ENABLE_ACCOUNT_REGISTRATION && ( } /> )} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {Config.getConfig().FEATURE.ENABLE_EXTRA_CLIENT_ENTROPY && ( } /> )} {Config.getConfig().FEATURE.ENABLE_ACCOUNT_REGISTRATION && ( } /> )} {Config.getConfig().FEATURE.ENABLE_ACCOUNT_REGISTRATION && ( } /> )} {Config.getConfig().FEATURE.ENABLE_ACCOUNT_REGISTRATION && ( } /> )} } /> )} ); }; type ConnectedProps = ReturnType; const mapStateToProps = (state: RootState) => ({ isAuthenticated: AuthSelector.isAuthenticated(state), isFetchingSSOSettings: AuthSelector.isFetchingSSOSettings(state), language: LanguageSelector.getLanguage(state), }); type DispatchProps = ReturnType; const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators( { doGetSSOSettings: ROOT_ACTIONS.authAction.doGetSSOSettings, }, dispatch, ); const Root = connect(mapStateToProps, mapDispatchToProps)(RootComponent); export {Root};