import React, { useCallback, useEffect } from 'react'; import { Box, Header, Scroll, Spinner, Text, color } from 'folds'; import { Outlet, generatePath, matchPath, useLocation, useNavigate, useParams, } from 'react-router-dom'; import classNames from 'classnames'; import { AuthFooter } from './AuthFooter'; import * as css from './styles.css'; import * as PatternsCss from '../../styles/Patterns.css'; import { clientAllowedServer, clientDefaultServer, useClientConfig, } from '../../hooks/useClientConfig'; import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback'; import { LOGIN_PATH, REGISTER_PATH, RESET_PASSWORD_PATH } from '../paths'; import CinnySVG from '../../../../public/res/svg/cinny.svg'; import { ServerPicker } from './ServerPicker'; import { AutoDiscoveryAction, autoDiscovery } from '../../cs-api'; import { SpecVersionsLoader } from '../../components/SpecVersionsLoader'; import { SpecVersionsProvider } from '../../hooks/useSpecVersions'; import { AutoDiscoveryInfoProvider } from '../../hooks/useAutoDiscoveryInfo'; import { AuthFlowsLoader } from '../../components/AuthFlowsLoader'; import { AuthFlowsProvider } from '../../hooks/useAuthFlows'; import { AuthServerProvider } from '../../hooks/useAuthServer'; import { tryDecodeURIComponent } from '../../utils/dom'; const currentAuthPath = (pathname: string): string => { if (matchPath(LOGIN_PATH, pathname)) { return LOGIN_PATH; } if (matchPath(RESET_PASSWORD_PATH, pathname)) { return RESET_PASSWORD_PATH; } if (matchPath(REGISTER_PATH, pathname)) { return REGISTER_PATH; } return LOGIN_PATH; }; function AuthLayoutLoading({ message }: { message: string }) { return ( {message} ); } function AuthLayoutError({ message }: { message: string }) { return ( {message} ); } export function AuthLayout() { const navigate = useNavigate(); const location = useLocation(); const { server: urlEncodedServer } = useParams(); const clientConfig = useClientConfig(); const defaultServer = clientDefaultServer(clientConfig); let server: string = urlEncodedServer ? tryDecodeURIComponent(urlEncodedServer) : defaultServer; if (!clientAllowedServer(clientConfig, server)) { server = defaultServer; } const [discoveryState, discoverServer] = useAsyncCallback( useCallback(async (serverName: string) => { const response = await autoDiscovery(fetch, serverName); return { serverName, response, }; }, []) ); useEffect(() => { if (server) discoverServer(server); }, [discoverServer, server]); // if server is mismatches with path server, update path useEffect(() => { if (!urlEncodedServer || tryDecodeURIComponent(urlEncodedServer) !== server) { navigate( generatePath(currentAuthPath(location.pathname), { server: encodeURIComponent(server), }), { replace: true } ); } }, [urlEncodedServer, navigate, location, server]); const selectServer = useCallback( (newServer: string) => { if (newServer === server) { if (discoveryState.status === AsyncStatus.Loading) return; discoverServer(server); return; } navigate( generatePath(currentAuthPath(location.pathname), { server: encodeURIComponent(newServer) }) ); }, [navigate, location, discoveryState, server, discoverServer] ); const [autoDiscoveryError, autoDiscoveryInfo] = discoveryState.status === AsyncStatus.Success ? discoveryState.data.response : []; return (
Cinny Logo Cinny
Homeserver {discoveryState.status === AsyncStatus.Loading && ( )} {discoveryState.status === AsyncStatus.Error && ( )} {autoDiscoveryError?.action === AutoDiscoveryAction.FAIL_PROMPT && ( )} {autoDiscoveryError?.action === AutoDiscoveryAction.FAIL_ERROR && ( )} {discoveryState.status === AsyncStatus.Success && autoDiscoveryInfo && ( ( )} error={() => ( )} > {(specVersions) => ( ( )} error={() => ( )} > {(authFlows) => ( )} )} )}
); }