Small fixes

This commit is contained in:
Reckless_Satoshi 2023-02-20 04:44:30 -08:00
parent 8644432ab2
commit 04abffee44
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
8 changed files with 101 additions and 930 deletions

View File

@ -70,20 +70,15 @@ const Onboarding = ({
<Typography variant='h5' color={step == '1' ? 'text.primary' : 'text.disabled'}>
{t('1. Generate a token')}
</Typography>
<Collapse in={step == '1'}>
<Box
sx={{
padding: '0.5em',
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '4px',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
'&:hover': {
borderColor: theme.palette.mode === 'dark' ? '#ffffff' : '#2f2f2f',
},
}}
>
<Box
sx={{
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '4px',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
}}
>
<Collapse in={step == '1'}>
<Grid container direction='column' alignItems='center' spacing={1} padding={1.5}>
<Grid item>
<Typography>
@ -154,28 +149,23 @@ const Onboarding = ({
</Grid>
)}
</Grid>
</Box>
</Collapse>
</Collapse>
</Box>
</Grid>
<Grid item sx={{ width: '100%' }}>
<Typography variant='h5' color={step == '2' ? 'text.primary' : 'text.disabled'}>
{t('2. Meet your robot identity')}
</Typography>
<Collapse in={step == '2'}>
<Box
sx={{
padding: '0.5em',
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '4px',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
'&:hover': {
borderColor: theme.palette.mode === 'dark' ? '#ffffff' : '#2f2f2f',
},
}}
>
<Box
sx={{
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '4px',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
}}
>
<Collapse in={step == '2'}>
<Grid container direction='column' alignItems='center' spacing={1} padding={1.5}>
<Grid item>
<Typography>
@ -248,27 +238,23 @@ const Onboarding = ({
</Collapse>
</Grid>
</Grid>
</Box>
</Collapse>
</Collapse>
</Box>
</Grid>
<Grid item>
<Typography variant='h5' color={step == '3' ? 'text.primary' : 'text.disabled'}>
{t('3. Browse or create an order')}
</Typography>
<Collapse in={step == '3'}>
<Box
sx={{
padding: '0.5em',
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '4px',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
'&:hover': {
borderColor: theme.palette.mode === 'dark' ? '#ffffff' : '#2f2f2f',
},
}}
>
<Box
sx={{
backgroundColor: 'background.paper',
border: '1px solid',
borderRadius: '4px',
borderColor: theme.palette.mode === 'dark' ? '#434343' : '#c4c4c4',
}}
>
<Collapse in={step == '3'}>
<Grid container direction='column' alignItems='center' spacing={1} padding={1.5}>
<Grid item>
<Typography>
@ -316,8 +302,8 @@ const Onboarding = ({
</Button>
</Grid>
</Grid>
</Box>
</Collapse>
</Collapse>
</Box>
</Grid>
<Grid item>
<Button color='inherit' onClick={() => setView('profile')}>

View File

@ -35,7 +35,7 @@ const Recovery = ({
const theme = useTheme();
const recoveryDisabled = () => {
return inputToken.length > 10 ? false : true;
return inputToken.length > 20 ? false : true;
};
const onClickRecover = () => {
if (recoveryDisabled()) {

View File

@ -1,10 +1,8 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Button, Grid, LinearProgress, Typography, useTheme } from '@mui/material';
import { FastForward, RocketLaunch } from '@mui/icons-material';
import SmartToy from '@mui/icons-material/SmartToy';
import { Button, Grid, LinearProgress, Typography, useTheme } from '@mui/material';
import { Bolt, Logout } from '@mui/icons-material';
import RobotAvatar from '../../components/RobotAvatar';
import Bolt from '@mui/icons-material/Bolt';
import TokenInput from './TokenInput';
import { Page } from '../NavBar';
import { Robot } from '../../models';
@ -14,6 +12,7 @@ interface RobotProfileProps {
setRobot: (state: Robot) => void;
setView: (state: 'welcome' | 'onboarding' | 'recovery' | 'profile') => void;
inputToken: string;
logoutRobot: () => void;
setInputToken: (state: string) => void;
getGenerateRobot: (token: string) => void;
setPage: (state: Page) => void;
@ -28,8 +27,8 @@ const RobotProfile = ({
setRobot,
inputToken,
setInputToken,
getGenerateRobot,
setPage,
logoutRobot,
setView,
badRequest,
baseUrl,
robotFound,
@ -109,10 +108,19 @@ const RobotProfile = ({
) : (
<></>
)}
<Grid item>
{/* This robot has an active order
This robot has a past order. Reusing Robot degrades your privacy: Get a new robot! */}
</Grid>
<Grid item sx={{ width: '100%' }}>
<TokenInput
inputToken={inputToken}
editable={false}
showDownload={true}
label={t('Store your token safely')}
setInputToken={setInputToken}
setRobot={setRobot}
badRequest={badRequest}
@ -120,6 +128,21 @@ const RobotProfile = ({
onPressEnter={() => null}
/>
</Grid>
<Grid item>
<Button
disabled={robot.avatarLoaded && robot.nickname}
size='small'
color='primary'
onClick={() => {
logoutRobot();
setView('welcome');
}}
>
<Logout /> <div style={{ width: '0.5em' }} />
{t('Logout Robot')}
</Button>
</Grid>
</Grid>
);
};

View File

@ -48,7 +48,7 @@ const TokenInput = ({
}: TokenInputProps): JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
const [showCopied, setShowCopied] = useState<boolean>(false);
const createJsonFile = () => {
return {
token: robot.token,
@ -80,23 +80,24 @@ const TokenInput = ({
}}
InputProps={{
startAdornment: showDownload ? (
<Tooltip enterTouchDelay={250} title={t('Save token to file')}>
<span>
<IconButton
color='primary'
onClick={() => saveAsJson(robot.nickname + '.json', createJsonFile())}
>
<Download sx={{ width: '1em', height: '1em' }} />
</IconButton>
</span>
<Tooltip enterTouchDelay={250} title={t('Download token and PGP credentials')}>
<IconButton
color='primary'
sx={{ position: 'relative', top: label ? '0.4em' : '0em' }}
onClick={() => saveAsJson(robot.nickname + '.json', createJsonFile())}
>
<Download sx={{ width: '1em', height: '1em' }} />
</IconButton>
</Tooltip>
) : null,
endAdornment: showCopy ? (
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
<Tooltip open={showCopied} title={t('Copied!')}>
<IconButton
color={robot.copiedToken ? 'inherit' : 'primary'}
onClick={() => {
systemClient.copyToClipboard(inputToken);
setShowCopied(true);
setTimeout(() => setShowCopied(false), 1000);
setRobot({ ...robot, copiedToken: true });
}}
>

View File

@ -3,13 +3,15 @@ import { useTranslation } from 'react-i18next';
import { Box, Button, Grid, Typography, useTheme } from '@mui/material';
import { RoboSatsTextIcon } from '../../components/Icons';
import { FastForward, RocketLaunch, Key } from '@mui/icons-material';
import { genBase62Token } from '../../utils';
interface WelcomeProps {
setView: (state: 'welcome' | 'onboarding' | 'recovery' | 'profile') => void;
getGenerateRobot: (token: string) => void;
width: number;
}
const Welcome = ({ setView, width }: WelcomeProps): JSX.Element => {
const Welcome = ({ setView, width, getGenerateRobot }: WelcomeProps): JSX.Element => {
const { t } = useTranslation();
const theme = useTheme();
@ -99,9 +101,16 @@ const Welcome = ({ setView, width }: WelcomeProps): JSX.Element => {
</Box>
</Grid>
<Grid item sx={{ position: 'relative', bottom: '0.5em' }}>
<Button size='small' color='primary' onClick={() => setView('profile')}>
<Button
size='small'
color='primary'
onClick={() => {
setView('profile');
getGenerateRobot(genBase62Token(36));
}}
>
<FastForward /> <div style={{ width: '0.5em' }} />
{t('Skip to Robot')}
{t('Fast Generate Robot')}
</Button>
</Grid>
</Grid>

View File

@ -36,14 +36,12 @@ const RobotPage = ({
}: RobotPageProps): JSX.Element => {
const { t } = useTranslation();
const params = useParams();
const theme = useTheme();
const refCode = params.refCode;
const width = Math.min(windowSize.width * 0.8, 28);
const maxHeight = windowSize.height * 0.85 - 3;
const [robotFound, setRobotFound] = useState<boolean>(false);
const [badRequest, setBadRequest] = useState<string | undefined>(undefined);
const [tokenChanged, setTokenChanged] = useState<boolean>(false);
const [inputToken, setInputToken] = useState<string>('');
const [view, setView] = useState<'welcome' | 'onboarding' | 'recovery' | 'profile'>(
robot.token ? 'profile' : 'welcome',
@ -61,6 +59,7 @@ const RobotPage = ({
const getGenerateRobot = (token: string) => {
const strength = tokenStrength(token);
setRobot({ ...robot, loading: true, avatarLoaded: false });
setInputToken(token);
const requestBody = genKey(token).then(function (key) {
return {
@ -129,17 +128,19 @@ const RobotPage = ({
const deleteRobot = () => {
apiClient.delete(baseUrl, '/api/user');
logoutRobot();
};
const logoutRobot = () => {
setRobot({ ...robot, nickname: undefined, token: undefined, avatarLoaded: false });
setInputToken('');
setRobotFound(false);
systemClient.deleteCookie('sessionid');
systemClient.deleteItem('robot_token');
systemClient.deleteItem('pub_key');
systemClient.deleteItem('enc_priv_key');
};
const logoutRobot = () => {};
const handleChangeToken = () => {};
const handleClickSubmitToken = () => {};
const handleClickNewRandomToken = () => {};
return (
<Paper
elevation={12}
@ -151,11 +152,12 @@ const RobotPage = ({
}}
>
{/* TOR LOADING
Your connection is being encrypted and annonimized using the TOR Network. This ensures maximum privacy, however you might feel it is a bit slow or even lose connection from time to time.
Your connection is being encrypted and annonimized using the TOR Network. This ensures maximum privacy, however you might feel it is a bit slow. You could eventually lose connection from time to time, restart the app.
*/}
{view === 'welcome' ? <Welcome setView={setView} width={width} /> : null}
{view === 'welcome' ? (
<Welcome setView={setView} getGenerateRobot={getGenerateRobot} width={width} />
) : null}
{view === 'onboarding' ? (
<Onboarding
@ -178,6 +180,7 @@ const RobotPage = ({
robotFound={robotFound}
setRobot={setRobot}
badRequest={badRequest}
logoutRobot={logoutRobot}
width={width}
inputToken={inputToken}
setInputToken={setInputToken}
@ -205,459 +208,3 @@ const RobotPage = ({
};
export default RobotPage;
// return (
// <Grid container spacing={1}>
// {/* <Grid item>
// <div className='clickTrough' />
// </Grid>
// <Grid item xs={12} sx={{ width: '26.4em', height: '18.6' }}>
// {robot.avatarLoaded && robot.nickname ? (
// <div>
// <Grid item xs={12}>
// <Typography component='h5' variant='h5'>
// <b>
// {robot.nickname && systemClient.getCookie('sessionid') ? (
// <div
// style={{
// display: 'flex',
// alignItems: 'center',
// justifyContent: 'center',
// flexWrap: 'wrap',
// height: 45 * 1.000004,
// }}
// >
// <Bolt
// sx={{
// color: '#fcba03',
// height: 33 * 1.000004,
// width: 33 * 1.000004,
// }}
// />
// <a>{robot.nickname}</a>
// <Bolt
// sx={{
// color: '#fcba03',
// height: 33 * 1.000004,
// width: 33 * 1.000004,
// }}
// />
// </div>
// ) : (
// ''
// )}
// </b>
// </Typography>
// </Grid>
// <Grid item xs={12}>
// <RobotAvatar
// nickname={robot.nickname}
// smooth={true}
// style={{ maxWidth: 203 * 1.000004, maxHeight: 203 * 1.000004 }}
// imageStyle={{
// transform: '',
// border: '2px solid #555',
// filter: 'drop-shadow(1px 1px 1px #000000)',
// height: `${201 * 1.000004}px`,
// width: `${201 * 1.000004}px`,
// }}
// tooltip={t('This is your trading avatar')}
// tooltipPosition='top'
// baseUrl={baseUrl}
// />
// <br />
// </Grid>
// </div>
// ) : (
// <CircularProgress sx={{ position: 'relative', top: 100 }} />
// )}
// </Grid>
// {robotFound ? (
// <Grid item xs={12}>
// <Typography variant='subtitle2' color='primary'>
// {t('A robot avatar was found, welcome back!')}
// <br />
// </Typography>
// </Grid>
// ) : (
// <></>
// )}
// <Grid container>
// <Grid item xs={12}>
// <TextField
// sx={{ maxWidth: 280 * 1.000004 }}
// error={!!badRequest}
// label={t('Store your token safely')}
// required={true}
// value={inputToken}
// variant='standard'
// helperText={badRequest}
// size='small'
// onChange={handleChangeToken}
// onKeyPress={(e) => {
// if (e.key === 'Enter') {
// handleClickSubmitToken();
// }
// }}
// InputProps={{
// startAdornment: (
// <div
// style={{
// width: 50 * 1.000004,
// minWidth: 50 * 1.000004,
// position: 'relative',
// left: -6,
// }}
// >
// <Grid container>
// <Grid item xs={6}>
// <Tooltip
// enterTouchDelay={250}
// title={t('Save token and PGP credentials to file')}
// >
// <span>
// <IconButton
// color='primary'
// disabled={
// !robot.avatarLoaded ||
// !(systemClient.getItem('robot_token') == inputToken)
// }
// onClick={() => saveAsJson(robot.nickname + '.json', createJsonFile())}
// >
// <Download sx={{ width: 22 * 1.000004, height: 22 * 1.000004 }} />
// </IconButton>
// </span>
// </Tooltip>
// </Grid>
// <Grid item xs={6}>
// <Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
// <IconButton
// color={robot.copiedToken ? 'inherit' : 'primary'}
// disabled={
// !robot.avatarLoaded ||
// !(systemClient.getItem('robot_token') === inputToken)
// }
// onClick={() =>
// systemClient.copyToClipboard(systemClient.getItem('robot_token')) &
// setRobot({ ...robot, copiedToken: true })
// }
// >
// <ContentCopy sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }} />
// </IconButton>
// </Tooltip>
// </Grid>
// </Grid>
// </div>
// ),
// endAdornment: (
// <Tooltip enterTouchDelay={250} title={t('Generate a new token')}>
// <IconButton onClick={handleClickNewRandomToken}>
// <Casino sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }} />
// </IconButton>
// </Tooltip>
// ),
// }}
// />
// </Grid>
// </Grid>
// <Grid item xs={12}>
// {tokenChanged ? (
// <Button type='submit' size='small' onClick={handleClickSubmitToken}>
// <SmartToy sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }} />
// <span> {t('Generate Robot')}</span>
// </Button>
// ) : (
// <Tooltip
// enterTouchDelay={0}
// enterDelay={500}
// enterNextDelay={2000}
// title={t('You must enter a new token first')}
// >
// <div>
// <Button disabled={true} type='submit' size='small'>
// <SmartToy sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }} />
// <span>{t('Generate Robot')}</span>
// </Button>
// </div>
// </Tooltip>
// )}
// </Grid>
// {/* <Grid item xs={12} align='center' sx={{ width: '26.43em' }}>
// <Grid item>
// <div style={{ height: '2.143em' }} />
// </Grid>
// <div style={{ width: '26.43em', left: '2.143em' }}>
// <Grid container align='center'>
// <Grid item xs={0.8} />
// <Grid item xs={7.5} align='right'>
// <Typography component='h5' variant='h5'>
// {t('Simple and Private LN P2P Exchange')}
// </Typography>
// </Grid>
// <Grid item xs={2.5} align='left'>
// <RoboSatsNoTextIcon color='primary' sx={{ height: '3.143em', width: '3.143em' }} />
// </Grid>
// </Grid>
// </div>
// </Grid> */}
// </Grid>
// );
// };
// export default RobotPage; */}
// class UserGenPage extends Component {
// handleClickNewRandomToken = () => {
// const inputToken = genBase62Token(36);
// this.setState({
// inputToken,
// tokenHasChanged: true,
// });
// setRobot({ ...robot, copiedToken: true });
// };
// handleChangeToken = (e) => {
// this.setState({
// inputToken: e.target.value.split(' ').join(''),
// tokenHasChanged: true,
// });
// };
// handleClickSubmitToken = () => {
// this.delGeneratedUser();
// this.getGeneratedUser(inputToken);
// this.setState({ tokenHasChanged: false });
// setRobot({
// ...robot,
// avatarLoaded: false,
// nickname: null,
// token: null,
// copiedToken: false,
// lastOrderId: null,
// activeOrderId: null,
// });
// };
// render() {
// const { t, i18n } = this.props;
// const fontSize = this.props.theme.typography.fontSize;
// const 1.000004 = fontSize / 14; // to scale sizes, default fontSize is 14
// return (
// <Grid container spacing={1}>
// <Grid item>
// <div className='clickTrough' />
// </Grid>
// <Grid
// item
// xs={12}
// align='center'
// sx={{ width: 370 * 1.000004, height: 260 * 1.000004 }}
// >
// {robot.avatarLoaded && robot.nickname ? (
// <div>
// <Grid item xs={12} align='center'>
// <Typography component='h5' variant='h5'>
// <b>
// {robot.nickname && systemClient.getCookie('sessionid') ? (
// <div
// style={{
// display: 'flex',
// alignItems: 'center',
// justifyContent: 'center',
// flexWrap: 'wrap',
// height: 45 * 1.000004,
// }}
// >
// <BoltIcon
// sx={{
// color: '#fcba03',
// height: 33 * 1.000004,
// width: 33 * 1.000004,
// }}
// />
// <a>{robot.nickname}</a>
// <BoltIcon
// sx={{
// color: '#fcba03',
// height: 33 * 1.000004,
// width: 33 * 1.000004,
// }}
// />
// </div>
// ) : (
// ''
// )}
// </b>
// </Typography>
// </Grid>
// <Grid item xs={12} align='center'>
// <RobotAvatar
// nickname={robot.nickname}
// smooth={true}
// style={{ maxWidth: 203 * 1.000004, maxHeight: 203 * 1.000004 }}
// imageStyle={{
// transform: '',
// border: '2px solid #555',
// filter: 'drop-shadow(1px 1px 1px #000000)',
// height: `${201 * 1.000004}px`,
// width: `${201 * 1.000004}px`,
// }}
// tooltip={t('This is your trading avatar')}
// tooltipPosition='top'
// baseUrl={baseUrl}
// />
// <br />
// </Grid>
// </div>
// ) : (
// <CircularProgress sx={{ position: 'relative', top: 100 }} />
// )}
// </Grid>
// {this.state.found ? (
// <Grid item xs={12} align='center'>
// <Typography variant='subtitle2' color='primary'>
// {this.state.found ? t('A robot avatar was found, welcome back!') : null}
// <br />
// </Typography>
// </Grid>
// ) : (
// ''
// )}
// <Grid container align='center'>
// <Grid item xs={12} align='center'>
// <TextField
// sx={{ maxWidth: 280 * 1.000004 }}
// error={!!this.state.bad_request}
// label={t('Store your token safely')}
// required={true}
// value={inputToken}
// variant='standard'
// helperText={this.state.bad_request}
// size='small'
// onChange={this.handleChangeToken}
// onKeyPress={(e) => {
// if (e.key === 'Enter') {
// this.handleClickSubmitToken();
// }
// }}
// InputProps={{
// startAdornment: (
// <div
// style={{
// width: 50 * 1.000004,
// minWidth: 50 * 1.000004,
// position: 'relative',
// left: -6,
// }}
// >
// <Grid container>
// <Grid item xs={6}>
// <Tooltip
// enterTouchDelay={250}
// title={t('Save token and PGP credentials to file')}
// >
// <span>
// <IconButton
// color='primary'
// disabled={
// !robot.avatarLoaded ||
// !(systemClient.getItem('robot_token') == inputToken)
// }
// onClick={() =>
// saveAsJson(
// robot.nickname + '.json',
// this.createJsonFile(),
// )
// }
// >
// <DownloadIcon
// sx={{ width: 22 * 1.000004, height: 22 * 1.000004 }}
// />
// </IconButton>
// </span>
// </Tooltip>
// </Grid>
// <Grid item xs={6}>
// <Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
// <IconButton
// color={robot.copiedToken ? 'inherit' : 'primary'}
// disabled={
// !robot.avatarLoaded ||
// !(systemClient.getItem('robot_token') === inputToken)
// }
// onClick={() =>
// systemClient.copyToClipboard(systemClient.getItem('robot_token')) &
// setRobot({ ...robot, copiedToken: true })
// }
// >
// <ContentCopy
// sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }}
// />
// </IconButton>
// </Tooltip>
// </Grid>
// </Grid>
// </div>
// ),
// endAdornment: (
// <Tooltip enterTouchDelay={250} title={t('Generate a new token')}>
// <IconButton onClick={this.handleClickNewRandomToken}>
// <CasinoIcon
// sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }}
// />
// </IconButton>
// </Tooltip>
// ),
// }}
// />
// </Grid>
// </Grid>
// <Grid item xs={12} align='center'>
// {this.state.tokenHasChanged ? (
// <Button type='submit' size='small' onClick={this.handleClickSubmitToken}>
// <SmartToyIcon sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }} />
// <span> {t('Generate Robot')}</span>
// </Button>
// ) : (
// <Tooltip
// enterTouchDelay={0}
// enterDelay={500}
// enterNextDelay={2000}
// title={t('You must enter a new token first')}
// >
// <div>
// <Button disabled={true} type='submit' size='small'>
// <SmartToyIcon sx={{ width: 18 * 1.000004, height: 18 * 1.000004 }} />
// <span>{t('Generate Robot')}</span>
// </Button>
// </div>
// </Tooltip>
// )}
// </Grid>
// <Grid item xs={12} align='center' sx={{ width: '26.43em' }}>
// <Grid item>
// <div style={{ height: '2.143em' }} />
// </Grid>
// <div style={{ width: '26.43em', left: '2.143em' }}>
// <Grid container align='center'>
// <Grid item xs={0.8} />
// <Grid item xs={7.5} align='right'>
// <Typography component='h5' variant='h5'>
// {t('Simple and Private LN P2P Exchange')}
// </Typography>
// </Grid>
// <Grid item xs={2.5} align='left'>
// <RoboSatsNoTextIcon color='primary' sx={{ height: '3.143em', width: '3.143em' }} />
// </Grid>
// </Grid>
// </div>
// </Grid>
// </Grid>
// );
// }
// }
// export default withTranslation()(UserGenPage);

View File

@ -1,395 +0,0 @@
import React, { Component } from 'react';
import { withTranslation } from 'react-i18next';
import {
Button,
Tooltip,
Grid,
Typography,
TextField,
ButtonGroup,
CircularProgress,
IconButton,
} from '@mui/material';
import SmartToyIcon from '@mui/icons-material/SmartToy';
import CasinoIcon from '@mui/icons-material/Casino';
import ContentCopy from '@mui/icons-material/ContentCopy';
import BoltIcon from '@mui/icons-material/Bolt';
import DownloadIcon from '@mui/icons-material/Download';
import { RoboSatsNoTextIcon } from '../components/Icons';
import { sha256 } from 'js-sha256';
import { genBase62Token, tokenStrength, saveAsJson } from '../utils';
import { genKey } from '../pgp';
import { systemClient } from '../services/System';
import { apiClient } from '../services/api/index';
import RobotAvatar from '../components/RobotAvatar';
class UserGenPage extends Component {
constructor(props) {
super(props);
this.state = {
tokenHasChanged: false,
inputToken: '',
found: false,
};
this.refCode = this.props.match.params.refCode;
}
componentDidMount() {
// Checks in parent HomePage if there is already a nick and token
// Displays the existing one
if (this.props.robot.nickname != null) {
this.setState({ inputToken: this.props.robot.token });
} else if (this.props.robot.token) {
this.setState({ inputToken: this.props.robot.token });
this.getGeneratedUser(this.props.robot.token);
} else {
const newToken = genBase62Token(36);
this.setState({
inputToken: newToken,
});
this.getGeneratedUser(newToken);
}
}
getGeneratedUser = (token) => {
const strength = tokenStrength(token);
const refCode = this.refCode;
this.props.setRobot({ ...this.props.robot, loading: true, avatarLoaded: false });
const requestBody = genKey(token).then(function (key) {
return {
token_sha256: sha256(token),
public_key: key.publicKeyArmored,
encrypted_private_key: key.encryptedPrivateKeyArmored,
unique_values: strength.uniqueValues,
counts: strength.counts,
length: token.length,
ref_code: refCode,
};
});
requestBody.then((body) =>
apiClient.post(this.props.baseUrl, '/api/user/', body).then((data) => {
this.setState({ found: data.found, bad_request: data.bad_request });
this.props.setCurrentOrder(
data.active_order_id
? data.active_order_id
: data.last_order_id
? data.last_order_id
: null,
);
// Add nick and token to App state (token only if not a bad request)
data.bad_request
? this.props.setRobot({
...this.props.robot,
avatarLoaded: true,
loading: false,
nickname: data.nickname ?? this.props.robot.nickname,
activeOrderId: data.active_order_id ?? null,
referralCode: data.referral_code ?? this.props.referralCode,
earnedRewards: data.earned_rewards ?? this.props.earnedRewards,
lastOrderId: data.last_order_id ?? this.props.lastOrderId,
stealthInvoices: data.wants_stealth ?? this.props.stealthInvoices,
tgEnabled: data.tg_enabled,
tgBotName: data.tg_bot_name,
tgToken: data.tg_token,
})
: this.props.setRobot({
...this.props.robot,
nickname: data.nickname,
token,
loading: false,
activeOrderId: data.active_order_id ? data.active_order_id : null,
lastOrderId: data.last_order_id ? data.last_order_id : null,
referralCode: data.referral_code,
earnedRewards: data.earned_rewards ?? 0,
stealthInvoices: data.wants_stealth,
tgEnabled: data.tg_enabled,
tgBotName: data.tg_bot_name,
tgToken: data.tg_token,
bitsEntropy: data.token_bits_entropy,
shannonEntropy: data.token_shannon_entropy,
pubKey: data.public_key,
encPrivKey: data.encrypted_private_key,
copiedToken: data.found ? true : this.props.robot.copiedToken,
}) &
systemClient.setItem('robot_token', token) &
systemClient.setItem('pub_key', data.public_key.split('\n').join('\\')) &
systemClient.setItem('enc_priv_key', data.encrypted_private_key.split('\n').join('\\'));
}),
);
};
delGeneratedUser() {
apiClient.delete(this.props.baseUrl, '/api/user');
systemClient.deleteCookie('sessionid');
systemClient.deleteItem('robot_token');
systemClient.deleteItem('pub_key');
systemClient.deleteItem('enc_priv_key');
}
handleClickNewRandomToken = () => {
const inputToken = genBase62Token(36);
this.setState({
inputToken,
tokenHasChanged: true,
});
this.props.setRobot({ ...this.props.robot, copiedToken: true });
};
handleChangeToken = (e) => {
this.setState({
inputToken: e.target.value.split(' ').join(''),
tokenHasChanged: true,
});
};
handleClickSubmitToken = () => {
this.delGeneratedUser();
this.getGeneratedUser(this.state.inputToken);
this.setState({ tokenHasChanged: false });
this.props.setRobot({
...this.props.robot,
avatarLoaded: false,
nickname: null,
token: null,
copiedToken: false,
lastOrderId: null,
activeOrderId: null,
});
};
createJsonFile = () => {
return {
token: this.props.robot.token,
token_shannon_entropy: this.props.robot.shannonEntropy,
token_bit_entropy: this.props.robot.bitsEntropy,
public_key: this.props.robot.pub_key,
encrypted_private_key: this.props.robot.enc_priv_key,
};
};
render() {
const { t, i18n } = this.props;
const fontSize = this.props.theme.typography.fontSize;
const fontSizeFactor = fontSize / 14; // to scale sizes, default fontSize is 14
return (
<Grid container spacing={1}>
<Grid item>
<div className='clickTrough' />
</Grid>
<Grid
item
xs={12}
align='center'
sx={{ width: 370 * fontSizeFactor, height: 260 * fontSizeFactor }}
>
{this.props.robot.avatarLoaded && this.props.robot.nickname ? (
<div>
<Grid item xs={12} align='center'>
<Typography component='h5' variant='h5'>
<b>
{this.props.robot.nickname && systemClient.getCookie('sessionid') ? (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexWrap: 'wrap',
height: 45 * fontSizeFactor,
}}
>
<BoltIcon
sx={{
color: '#fcba03',
height: 33 * fontSizeFactor,
width: 33 * fontSizeFactor,
}}
/>
<a>{this.props.robot.nickname}</a>
<BoltIcon
sx={{
color: '#fcba03',
height: 33 * fontSizeFactor,
width: 33 * fontSizeFactor,
}}
/>
</div>
) : (
''
)}
</b>
</Typography>
</Grid>
<Grid item xs={12} align='center'>
<RobotAvatar
nickname={this.props.robot.nickname}
smooth={true}
style={{ maxWidth: 203 * fontSizeFactor, maxHeight: 203 * fontSizeFactor }}
imageStyle={{
transform: '',
border: '2px solid #555',
filter: 'drop-shadow(1px 1px 1px #000000)',
height: `${201 * fontSizeFactor}px`,
width: `${201 * fontSizeFactor}px`,
}}
tooltip={t('This is your trading avatar')}
tooltipPosition='top'
baseUrl={this.props.baseUrl}
/>
<br />
</Grid>
</div>
) : (
<CircularProgress sx={{ position: 'relative', top: 100 }} />
)}
</Grid>
{this.state.found ? (
<Grid item xs={12} align='center'>
<Typography variant='subtitle2' color='primary'>
{this.state.found ? t('A robot avatar was found, welcome back!') : null}
<br />
</Typography>
</Grid>
) : (
''
)}
<Grid container align='center'>
<Grid item xs={12} align='center'>
<TextField
sx={{ maxWidth: 280 * fontSizeFactor }}
error={!!this.state.bad_request}
label={t('Store your token safely')}
required={true}
value={this.state.inputToken}
variant='standard'
helperText={this.state.bad_request}
size='small'
onChange={this.handleChangeToken}
onKeyPress={(e) => {
if (e.key === 'Enter') {
this.handleClickSubmitToken();
}
}}
InputProps={{
startAdornment: (
<div
style={{
width: 50 * fontSizeFactor,
minWidth: 50 * fontSizeFactor,
position: 'relative',
left: -6,
}}
>
<Grid container>
<Grid item xs={6}>
<Tooltip
enterTouchDelay={250}
title={t('Save token and PGP credentials to file')}
>
<span>
<IconButton
color='primary'
disabled={
!this.props.robot.avatarLoaded ||
!(systemClient.getItem('robot_token') == this.state.inputToken)
}
onClick={() =>
saveAsJson(
this.props.robot.nickname + '.json',
this.createJsonFile(),
)
}
>
<DownloadIcon
sx={{ width: 22 * fontSizeFactor, height: 22 * fontSizeFactor }}
/>
</IconButton>
</span>
</Tooltip>
</Grid>
<Grid item xs={6}>
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
<IconButton
color={this.props.robot.copiedToken ? 'inherit' : 'primary'}
disabled={
!this.props.robot.avatarLoaded ||
!(systemClient.getItem('robot_token') === this.state.inputToken)
}
onClick={() =>
systemClient.copyToClipboard(systemClient.getItem('robot_token')) &
this.props.setRobot({ ...this.props.robot, copiedToken: true })
}
>
<ContentCopy
sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }}
/>
</IconButton>
</Tooltip>
</Grid>
</Grid>
</div>
),
endAdornment: (
<Tooltip enterTouchDelay={250} title={t('Generate a new token')}>
<IconButton onClick={this.handleClickNewRandomToken}>
<CasinoIcon
sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }}
/>
</IconButton>
</Tooltip>
),
}}
/>
</Grid>
</Grid>
<Grid item xs={12} align='center'>
{this.state.tokenHasChanged ? (
<Button type='submit' size='small' onClick={this.handleClickSubmitToken}>
<SmartToyIcon sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }} />
<span> {t('Generate Robot')}</span>
</Button>
) : (
<Tooltip
enterTouchDelay={0}
enterDelay={500}
enterNextDelay={2000}
title={t('You must enter a new token first')}
>
<div>
<Button disabled={true} type='submit' size='small'>
<SmartToyIcon sx={{ width: 18 * fontSizeFactor, height: 18 * fontSizeFactor }} />
<span>{t('Generate Robot')}</span>
</Button>
</div>
</Tooltip>
)}
</Grid>
<Grid item xs={12} align='center' sx={{ width: '26.43em' }}>
<Grid item>
<div style={{ height: '2.143em' }} />
</Grid>
<div style={{ width: '26.43em', left: '2.143em' }}>
<Grid container align='center'>
<Grid item xs={0.8} />
<Grid item xs={7.5} align='right'>
<Typography component='h5' variant='h5'>
{t('Simple and Private LN P2P Exchange')}
</Typography>
</Grid>
<Grid item xs={2.5} align='left'>
<RoboSatsNoTextIcon color='primary' sx={{ height: '3.143em', width: '3.143em' }} />
</Grid>
</Grid>
</div>
</Grid>
</Grid>
);
}
}
export default withTranslation()(UserGenPage);

View File

@ -147,7 +147,7 @@ const ProfileDialog = ({
</div>
<DialogContent>
<Typography component='h5' variant='h5'>
{t('Your Profile')}
{t('Your Robot')}
</Typography>
<List>