import React, { useContext, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Paper, Grid, CircularProgress, Box, Alert, Typography, useTheme, AlertTitle, } from '@mui/material'; import { useParams } from 'react-router-dom'; import { Robot } from '../../models'; import Onboarding from './Onboarding'; import Welcome from './Welcome'; import RobotProfile from './RobotProfile'; import Recovery from './Recovery'; import { TorIcon } from '../../components/Icons'; import { genKey } from '../../pgp'; import { AppContext, type UseAppStoreType } from '../../contexts/AppContext'; import { validateTokenEntropy } from '../../utils'; import { FederationContext, UseFederationStoreType } from '../../contexts/FederationContext'; import { GarageContext, UseGarageStoreType } from '../../contexts/GarageContext'; interface RobotPageProps { avatarBaseUrl: string; } const RobotPage = ({ avatarBaseUrl }: RobotPageProps): JSX.Element => { const { torStatus, windowSize, settings, page } = useContext(AppContext); const { garage } = useContext(GarageContext); const { federation } = useContext(FederationContext); const { t } = useTranslation(); const params = useParams(); const urlToken = settings.selfhostedClient ? params.token : null; const width = Math.min(windowSize.width * 0.8, 28); const maxHeight = windowSize.height * 0.85 - 3; const theme = useTheme(); const [badToken, setBadToken] = useState(''); const [inputToken, setInputToken] = useState(''); const [view, setView] = useState<'welcome' | 'onboarding' | 'recovery' | 'profile'>( garage.getRobot().token !== undefined ? 'profile' : 'welcome', ); useEffect(() => { const token = urlToken ?? garage.getRobot().token; if (token !== undefined) { setInputToken(token); } if (garage.getRobot().nickname !== undefined && token !== undefined) { if (window.NativeRobosats === undefined || torStatus === '"Done"') { getGenerateRobot(token); setView('profile'); } } }, [torStatus, page]); useEffect(() => { if (inputToken.length < 20) { setBadToken(t('The token is too short')); } else if (!validateTokenEntropy(inputToken).hasEnoughEntropy) { setBadToken(t('Not enough entropy, make it more complex')); } else { setBadToken(''); } }, [inputToken]); const getGenerateRobot = (token: string): void => { setInputToken(token); genKey(token) .then((key) => { const slot = garage.createRobot({ token, pubKey: key.publicKeyArmored, encPrivKey: key.encryptedPrivateKeyArmored, }); federation.fetchRobot(garage, slot); }) .catch((error) => { console.error('Error:', error); }); }; const logoutRobot = (): void => { setInputToken(''); garage.deleteSlot(garage.currentSlot); }; if (!(window.NativeRobosats === undefined) && !(torStatus === 'DONE' || torStatus === '"Done"')) { return ( {t('Connecting to TOR')} {t('Connection encrypted and anonymized using TOR.')} {t( 'This ensures maximum privacy, however you might feel the app behaves slow. If connection is lost, restart the app.', )} ); } else { return ( {view === 'welcome' ? ( ) : null} {view === 'onboarding' ? ( ) : null} {view === 'profile' ? ( ) : null} {view === 'recovery' ? ( ) : null} ); } }; export default RobotPage;