Functional UnsafeAlert and other Icons (#371)

* Add unsafe alert functional component

* Convert icons to functional components

* Run lin fix

* Fix webln uncaught error
This commit is contained in:
Reckless_Satoshi 2023-03-02 14:20:30 +00:00 committed by GitHub
parent c0b8a6d3ac
commit 9412764f1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 220 additions and 329 deletions

View File

@ -40,7 +40,6 @@
"react-i18next": "^11.16.2",
"react-image": "^4.0.3",
"react-qr-code": "^2.0.3",
"react-responsive": "^9.0.0-beta.6",
"react-router-dom": "^5.2.0",
"react-smooth-image": "^1.1.0",
"react-world-flags": "^1.4.0",
@ -5429,11 +5428,6 @@
"node": ">= 8"
}
},
"node_modules/css-mediaquery": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
"integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q=="
},
"node_modules/css-select": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
@ -7442,11 +7436,6 @@
"node": ">=10.17.0"
}
},
"node_modules/hyphenate-style-name": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
},
"node_modules/i18next": {
"version": "21.9.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.1.tgz",
@ -9986,14 +9975,6 @@
"tmpl": "1.0.5"
}
},
"node_modules/matchmediaquery": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz",
"integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==",
"dependencies": {
"css-mediaquery": "^0.1.2"
}
},
"node_modules/mdn-data": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
@ -13237,23 +13218,6 @@
"react": ">= 16.3"
}
},
"node_modules/react-responsive": {
"version": "9.0.0-beta.10",
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-9.0.0-beta.10.tgz",
"integrity": "sha512-41H8g4FYP46ln16rsHvs9/0ZoZxAPfnNiHET86/5pgS+Vw8fSKfLBuOS2SAquaxOxq7DgPviFoHmybgVvSKCNQ==",
"dependencies": {
"hyphenate-style-name": "^1.0.0",
"matchmediaquery": "^0.3.0",
"prop-types": "^15.6.1",
"shallow-equal": "^1.2.1"
},
"engines": {
"node": ">=0.10"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/react-router": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.3.tgz",
@ -13691,11 +13655,6 @@
"node": ">=8"
}
},
"node_modules/shallow-equal": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -18899,11 +18858,6 @@
"which": "^2.0.1"
}
},
"css-mediaquery": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
"integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q=="
},
"css-select": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
@ -20415,11 +20369,6 @@
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true
},
"hyphenate-style-name": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
"integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
},
"i18next": {
"version": "21.9.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.1.tgz",
@ -22284,14 +22233,6 @@
"tmpl": "1.0.5"
}
},
"matchmediaquery": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz",
"integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==",
"requires": {
"css-mediaquery": "^0.1.2"
}
},
"mdn-data": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
@ -24515,17 +24456,6 @@
"react-draggable": "^4.0.3"
}
},
"react-responsive": {
"version": "9.0.0-beta.10",
"resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-9.0.0-beta.10.tgz",
"integrity": "sha512-41H8g4FYP46ln16rsHvs9/0ZoZxAPfnNiHET86/5pgS+Vw8fSKfLBuOS2SAquaxOxq7DgPviFoHmybgVvSKCNQ==",
"requires": {
"hyphenate-style-name": "^1.0.0",
"matchmediaquery": "^0.3.0",
"prop-types": "^15.6.1",
"shallow-equal": "^1.2.1"
}
},
"react-router": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.3.tgz",
@ -24855,11 +24785,6 @@
"kind-of": "^6.0.2"
}
},
"shallow-equal": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",

View File

@ -78,7 +78,6 @@
"react-i18next": "^11.16.2",
"react-image": "^4.0.3",
"react-qr-code": "^2.0.3",
"react-responsive": "^9.0.0-beta.6",
"react-router-dom": "^5.2.0",
"react-smooth-image": "^1.1.0",
"react-world-flags": "^1.4.0",

View File

@ -30,11 +30,10 @@ import { EnableTelegramDialog } from '.';
import BoltIcon from '@mui/icons-material/Bolt';
import SendIcon from '@mui/icons-material/Send';
import NumbersIcon from '@mui/icons-material/Numbers';
import PasswordIcon from '@mui/icons-material/Password';
import ContentCopy from '@mui/icons-material/ContentCopy';
import PersonAddAltIcon from '@mui/icons-material/PersonAddAlt';
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import { UserNinjaIcon, BitcoinIcon } from '../Icons';
import { UserNinjaIcon } from '../Icons';
import { systemClient } from '../../services/System';
import { getHost, getWebln } from '../../utils';
@ -76,9 +75,12 @@ const ProfileDialog = ({
const [openEnableTelegram, setOpenEnableTelegram] = useState<boolean>(false);
useEffect(() => {
getWebln().then((webln) => {
setWeblnEnabled(webln !== undefined);
});
const handleWebln = async (order: Order) => {
const webln = await getWebln().catch(() => console.log('WebLN not available'));
return webln;
};
const webln = handleWebln();
setWeblnEnabled(webln !== undefined);
}, []);
const copyReferralCodeHandler = () => {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function AmbossIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function BasqueCountryFlag(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function BitcoinIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function BitcoinSignIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function BuySatsIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function BuySatsCheckedIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function CataloniaFlag(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function EarthIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function ExportIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function GoldIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function NewTabIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function RoboSatsIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function RoboSatsTextIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function SellSatsIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function SellSatsCheckedIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function SendReceiveIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function TorIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import { SvgIcon } from '@mui/material';
export default function UserNinjaIcon(props) {

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react';
import React from 'react';
import DashboardCustomizeIcon from '@mui/icons-material/DashboardCustomize';
const icons = {
@ -424,29 +424,25 @@ const icons = {
},
};
export default class PaymentIcon extends Component {
constructor(props) {
super(props);
const PaymentIcon: React.FC = (props) => {
if (props.icon === undefined) {
return null;
} else if (props.icon === 'custom') {
return (
<DashboardCustomizeIcon
sx={{ ...props, filter: 'drop-shadow(1.5px 1.5px 1.5px rgba(0, 0, 0, 0.2))' }}
color='primary'
/>
);
} else {
return (
<img
{...props}
src={icons[props.icon].image}
style={{ borderRadius: '23%', filter: 'drop-shadow(1.5px 1.5px 2px rgba(0, 0, 0, 0.2))' }}
/>
);
}
};
render() {
if (this.props.icon === undefined) {
return null;
} else if (this.props.icon === 'custom') {
return (
<DashboardCustomizeIcon
sx={{ ...this.props, filter: 'drop-shadow(1.5px 1.5px 1.5px rgba(0, 0, 0, 0.2))' }}
color='primary'
/>
);
} else {
return (
<img
{...this.props}
src={icons[this.props.icon].image}
style={{ borderRadius: '23%', filter: 'drop-shadow(1.5px 1.5px 2px rgba(0, 0, 0, 0.2))' }}
/>
);
}
}
}
export default PaymentIcon;

View File

@ -1,4 +1,9 @@
export const fiatMethods = [
export interface PaymentMethod {
name: string;
icon: string;
}
export const fiatMethods: PaymentMethod[] = [
{ name: 'Revolut', icon: 'revolut' },
{ name: 'CashApp', icon: 'cashapp' },
{ name: 'Zelle', icon: 'zelle' },
@ -78,7 +83,7 @@ export const fiatMethods = [
{ name: 'Amazon TR GiftCard', icon: 'amazontr' },
];
export const swapMethods = [
export const swapMethods: PaymentMethod[] = [
{ name: 'On-Chain BTC', icon: 'onchain' },
{ name: 'On-Chain w/ Stowaway', icon: 'stowaway' },
{ name: 'RBTC', icon: 'rbtc' },

View File

@ -6,8 +6,8 @@ Scripts taken from https://github.com/hsjoberg/blixt-wallet/blob/master/contrib/
1. Run `cd Icons` and `./gen-webp.sh` to generate the WebP files to used
2. Run `cd Icons` and `./gen-code.sh` to generate code to either be used in react js source files
3. Copy/Paste and replace the dict from `frontend/src/components/PaymentMethods/Icons/code/code.js` to `frontend/src/components/PaymentMethods/Icons/index.js`
4. Add the new entry to `paymentMethods` or `swapMethods` array in `frontend/src/components/PaymentMethods/MethodList.js`
3. Copy/Paste and replace the dict from `frontend/src/components/PaymentMethods/Icons/code/code.js` to `frontend/src/components/PaymentMethods/Icons/index.tsx`
4. Add the new entry to `paymentMethods` or `swapMethods` array in `frontend/src/components/PaymentMethods/MethodList.ts`
# Trademarks belong to their respective owners

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { withTranslation } from 'react-i18next';
import React from 'react';
import { useTranslation } from 'react-i18next';
import PaymentIcon from './Icons';
import { Tooltip } from '@mui/material';
import { fiatMethods, swapMethods } from './MethodList';
@ -7,18 +7,15 @@ import { fiatMethods, swapMethods } from './MethodList';
const ns = [{ name: 'not specified', icon: 'notspecified' }];
const methods = ns.concat(swapMethods).concat(fiatMethods);
class StringAsIcons extends Component {
constructor(props) {
super(props);
}
const StringAsIcons: React.FC = (props) => {
const { t } = useTranslation();
parseText() {
const { t } = this.props;
const parseText = () => {
const rows = [];
let custom_methods = this.props.text;
let custom_methods = props.text;
// Adds icons for each PaymentMethod that matches
methods.forEach((method, i) => {
if (this.props.text.includes(method.name)) {
if (props.text.includes(method.name)) {
custom_methods = custom_methods.replace(method.name, '');
rows.push(
<Tooltip
@ -30,11 +27,11 @@ class StringAsIcons extends Component {
<div
style={{
display: 'inline-block',
width: this.props.size + 2,
height: this.props.size,
width: props.size + 2,
height: props.size,
}}
>
<PaymentIcon width={this.props.size} height={this.props.size} icon={method.icon} />
<PaymentIcon width={props.size} height={props.size} icon={method.icon} />
</div>
</Tooltip>,
);
@ -55,32 +52,24 @@ class StringAsIcons extends Component {
key={'pushed'}
placement='top'
enterTouchDelay={0}
title={
this.props.verbose
? this.props.othersText
: this.props.othersText + ': ' + custom_methods
}
title={props.verbose ? props.othersText : props.othersText + ': ' + custom_methods}
>
<div
style={{
position: 'relative',
display: 'inline-block',
width: this.props.size + 2,
maxHeight: this.props.size,
width: props.size + 2,
maxHeight: props.size,
top: '-1px',
}}
>
<PaymentIcon
width={this.props.size * 1.1}
height={this.props.size * 1.1}
icon={'custom'}
/>
<PaymentIcon width={props.size * 1.1} height={props.size * 1.1} icon={'custom'} />
</div>
</Tooltip>,
);
}
if (this.props.verbose) {
if (props.verbose) {
return (
<>
{rows}{' '}
@ -93,15 +82,11 @@ class StringAsIcons extends Component {
} else {
return rows;
}
}
};
render() {
return (
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
{this.parseText()}
</div>
);
}
}
return (
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>{parseText()}</div>
);
};
export default withTranslation()(StringAsIcons);
export default StringAsIcons;

View File

@ -1,4 +1,3 @@
export { default as PaymentStringAsIcons } from './StringAsIcons';
export { fiatMethods } from './MethodList';
export { swapMethods } from './MethodList';
export { fiatMethods, swapMethods } from './MethodList';
export { default as PaymentIcon } from './Icons';

View File

@ -1,153 +0,0 @@
import React, { Component } from 'react';
import { withTranslation, Trans } from 'react-i18next';
import { Paper, Alert, AlertTitle, Button, Link } from '@mui/material';
import MediaQuery from 'react-responsive';
import { getHost } from '../utils';
class UnsafeAlert extends Component {
constructor(props) {
super(props);
this.state = {
show: true,
};
}
// To do. Read from Coordinators state Obj.
safe_urls = [
'robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion',
'robotestagw3dcxmd66r4rgksb4nmmr43fh77bzn2ia2eucduyeafnyd.onion',
'robodevs7ixniseezbv7uryxhamtz3hvcelzfwpx3rvoipttjomrmpqd.onion',
'robosats.i2p',
'r7r4sckft6ptmk4r2jajiuqbowqyxiwsle4iyg4fijtoordc6z7a.b32.i2p',
];
checkClient() {
const http = new XMLHttpRequest();
const host = getHost();
const unsafeClient = !this.safe_urls.includes(host);
try {
http.open('HEAD', `${location.protocol}//${host}/selfhosted`, false);
http.send();
this.props.setSettings({
...this.props.settings,
host,
unsafeClient,
selfhostedClient: http.status === 200,
});
} catch {
this.props.setSettings({
...this.props.settings,
host,
unsafeClient,
selfhostedClient: false,
});
}
}
componentDidMount() {
this.checkClient();
}
render() {
const { t } = this.props;
// If alert is hidden return null
if (!this.state.show) {
return null;
}
// Show selfhosted notice
else if (this.props.settings.selfhostedClient) {
return (
<div>
<Paper elevation={6} className='alertUnsafe'>
<Alert
severity='success'
sx={{ maxHeight: '120px' }}
action={
<Button color='success' onClick={() => this.setState({ show: false })}>
{t('Hide')}
</Button>
}
>
<AlertTitle>{t('You are self-hosting RoboSats')}</AlertTitle>
{t(
'RoboSats client is served from your own node granting you the strongest security and privacy.',
)}
</Alert>
</Paper>
</div>
);
}
// Show unsafe alert
else if (this.props.settings.unsafeClient) {
return (
<div>
<MediaQuery minWidth={800}>
<Paper elevation={6} className='alertUnsafe'>
<Alert
severity='warning'
sx={{ maxHeight: '100px' }}
action={<Button onClick={() => this.setState({ show: false })}>{t('Hide')}</Button>}
>
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
<Trans i18nKey='desktop_unsafe_alert'>
<a>
Some features are disabled for your protection (e.g. chat) and you will not be
able to complete a trade without them. To protect your privacy and fully enable
RoboSats, use{' '}
</a>
<Link href='https://www.torproject.org/download/' target='_blank'>
Tor Browser
</Link>
<a> and visit the </a>
<Link
href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion'
target='_blank'
>
Onion
</Link>
<a> site.</a>
</Trans>
</Alert>
</Paper>
</MediaQuery>
<MediaQuery maxWidth={799}>
<Paper elevation={6} className='alertUnsafe'>
<Alert severity='warning' sx={{ maxHeight: '120px' }}>
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
<Trans i18nKey='phone_unsafe_alert'>
<a>You will not be able to complete a trade. Use </a>
<Link href='https://www.torproject.org/download/' target='_blank'>
Tor Browser
</Link>
<a> and visit the </a>
<Link
href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion'
target='_blank'
>
Onion
</Link>{' '}
<a> site.</a>
</Trans>
<div style={{ width: '100%' }}></div>
<div align='center'>
<Button
className='hideAlertButton'
onClick={() => this.setState({ show: false })}
>
{t('Hide')}
</Button>
</div>
</Alert>
</Paper>
</MediaQuery>
</div>
);
}
}
}
export default withTranslation()(UnsafeAlert);

View File

@ -0,0 +1,136 @@
import React, { useState, useEffect, useContext } from 'react';
import { AppContext, AppContextProps } from '../contexts/AppContext';
import { useTranslation, Trans } from 'react-i18next';
import { Paper, Alert, AlertTitle, Button, Link } from '@mui/material';
import { getHost } from '../utils';
const UnsafeAlert = (): JSX.Element => {
const { settings, setSettings, windowSize } = useContext<AppContextProps>(AppContext);
const { t } = useTranslation();
const [show, setShow] = useState<boolean>(true);
// To do. Read from Coordinators Obj.
const safe_urls = [
'robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion',
'robotestagw3dcxmd66r4rgksb4nmmr43fh77bzn2ia2eucduyeafnyd.onion',
'robodevs7ixniseezbv7uryxhamtz3hvcelzfwpx3rvoipttjomrmpqd.onion',
'robosats.i2p',
'r7r4sckft6ptmk4r2jajiuqbowqyxiwsle4iyg4fijtoordc6z7a.b32.i2p',
];
const checkClient = () => {
const http = new XMLHttpRequest();
const host = getHost();
const unsafeClient = !safe_urls.includes(host);
try {
http.open('HEAD', `${location.protocol}//${host}/selfhosted`, false);
http.send();
setSettings({
...settings,
host,
unsafeClient,
selfhostedClient: http.status === 200,
});
} catch {
setSettings({
...settings,
host,
unsafeClient,
selfhostedClient: false,
});
}
};
useEffect(() => {
checkClient();
}, []);
// If alert is hidden return null
if (!show) {
return <></>;
}
// Show selfhosted notice
else if (settings.selfhostedClient) {
return (
<div>
<Paper elevation={6} className='unsafeAlert'>
<Alert
severity='success'
sx={{ maxHeight: '8em' }}
action={
<Button color='success' onClick={() => setShow(false)}>
{t('Hide')}
</Button>
}
>
<AlertTitle>{t('You are self-hosting RoboSats')}</AlertTitle>
{t(
'RoboSats client is served from your own node granting you the strongest security and privacy.',
)}
</Alert>
</Paper>
</div>
);
}
// Show unsafe alert
else if (settings.unsafeClient) {
return (
<Paper elevation={6} className='unsafeAlert'>
{windowSize.width > 57 ? (
<Alert
severity='warning'
sx={{ maxHeight: '7em' }}
action={<Button onClick={() => setShow(false)}>{t('Hide')}</Button>}
>
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
<Trans i18nKey='desktop_unsafe_alert'>
<a>
Some features are disabled for your protection (e.g. chat) and you will not be able
to complete a trade without them. To protect your privacy and fully enable RoboSats,
use{' '}
</a>
<Link href='https://www.torproject.org/download/' target='_blank'>
Tor Browser
</Link>
<a> and visit the </a>
<Link
href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion'
target='_blank'
>
Onion
</Link>
<a> site.</a>
</Trans>
</Alert>
) : (
<Alert severity='warning' sx={{ maxHeight: '8em' }}>
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
<Trans i18nKey='phone_unsafe_alert'>
<a>You will not be able to complete a trade. Use </a>
<Link href='https://www.torproject.org/download/' target='_blank'>
Tor Browser
</Link>
<a> and visit the </a>
<Link
href='http://robosats6tkf3eva7x2voqso3a5wcorsnw34jveyxfqi2fu7oyheasid.onion'
target='_blank'
>
Onion
</Link>{' '}
<a> site.</a>
</Trans>
<div style={{ display: 'flex', justifyContent: 'center', width: '100%' }}>
<Button className='hideAlertButton' onClick={() => setShow(false)}>
{t('Hide')}
</Button>
</div>
</Alert>
)}
</Paper>
);
}
};
export default UnsafeAlert;

View File

@ -401,7 +401,7 @@ export const AppContextProvider = ({
}
setBadRequest('');
let requestBody = {};
const requestBody = {};
if (action == 'login' || action == 'refresh') {
requestBody.token_sha256 = sha256(newToken ?? oldRobot.token);
} else if (action == 'generate' && newToken != null) {
@ -459,7 +459,7 @@ export const AppContextProvider = ({
shannonEntropy: data.token_shannon_entropy,
pubKey: data.public_key,
encPrivKey: data.encrypted_private_key,
copiedToken: data.found ? true : false,
copiedToken: !!data.found,
};
setRobot(newRobot);
garage.updateRobot(newRobot, targetSlot);

View File

@ -16,8 +16,9 @@ class Garage {
} else {
this.slots = [emptySlot];
}
this.setGarage = initialState?.setGarage || (() => {});
this.setGarage = initialState?.setGarage != null || (() => {});
}
slots: Slot[] = [emptySlot];
setGarage: (state: Garage) => void = () => {};

View File

@ -1,6 +1,6 @@
class Robot {
constructor(garageRobot?: Robot) {
if (garageRobot) {
if (garageRobot != null) {
this.token = garageRobot?.token ?? undefined;
this.pubKey = garageRobot?.pubKey ?? undefined;
this.encPrivKey = garageRobot?.encPrivKey ?? undefined;

View File

@ -51,7 +51,7 @@ class BaseSettings {
public coordinator: Coordinator | undefined = undefined;
public host?: string;
public unsafeClient: boolean = false;
public hostedClient: boolean = false;
public selfhostedClient: boolean = false;
}
export default BaseSettings;

View File

@ -46,16 +46,12 @@ body {
}
}
.alertUnsafe {
.unsafeAlert {
position: absolute;
width: 100%;
z-index: 9999;
}
.hideAlertButton {
position: fixed;
}
/* No arrows on numeric inputs */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {