Small fixes, fix reconnecting websockets, fix rewards webln

This commit is contained in:
Reckless_Satoshi 2023-05-08 17:37:23 -07:00
parent 3b77a473f8
commit 0d180ee7c9
No known key found for this signature in database
GPG Key ID: 9C4585B561315571
84 changed files with 656 additions and 308 deletions

View File

@ -10,7 +10,7 @@ import BookTable from '../../components/BookTable';
// Icons
import { BarChart, FormatListBulleted } from '@mui/icons-material';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
const BookPage = (): JSX.Element => {
const { robot, fetchBook, windowSize, setDelay, setOrder } =
@ -47,13 +47,22 @@ const BookPage = (): JSX.Element => {
const NavButtons = function () {
return (
<ButtonGroup variant='contained' color='inherit'>
<Button color='primary' onClick={() => setOpenMaker(true)}>
<Button
color='primary'
onClick={() => {
setOpenMaker(true);
}}
>
{t('Create')}
</Button>
{doubleView ? (
<></>
) : (
<Button onClick={() => setView(view === 'depth' ? 'list' : 'depth')}>
<Button
onClick={() => {
setView(view === 'depth' ? 'list' : 'depth');
}}
>
{view == 'depth' ? (
<>
<FormatListBulleted /> {t('List')}
@ -71,9 +80,19 @@ const BookPage = (): JSX.Element => {
return (
<Grid container direction='column' alignItems='center' spacing={1} sx={{ minWidth: 400 }}>
<NoRobotDialog open={openNoRobot} onClose={() => setOpenNoRobot(false)} />
<NoRobotDialog
open={openNoRobot}
onClose={() => {
setOpenNoRobot(false);
}}
/>
{openMaker ? (
<Dialog open={openMaker} onClose={() => setOpenMaker(false)}>
<Dialog
open={openMaker}
onClose={() => {
setOpenMaker(false);
}}
>
<Box sx={{ maxWidth: '18em', padding: '0.5em' }}>
<MakerForm
onOrderCreated={(id) => {

View File

@ -14,7 +14,7 @@ import RobotAvatar from '../components/RobotAvatar';
import { useTranslation } from 'react-i18next';
import Notifications from '../components/Notifications';
import { UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';
import { type UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';
const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter;
@ -54,16 +54,18 @@ const Main: React.FC = () => {
style={{ display: 'none' }}
nickname={robot.nickname}
baseUrl={baseUrl}
onLoad={() =>
onLoad={() => {
setRobot((robot) => {
return { ...robot, avatarLoaded: true };
})
}
});
}}
/>
<Notifications
order={order}
page={page}
openProfile={() => setOpen({ ...closeAll, profile: true })}
openProfile={() => {
setOpen({ ...closeAll, profile: true });
}}
rewards={robot.earnedRewards}
windowWidth={windowSize.width}
/>

View File

@ -9,7 +9,7 @@ import {
UpdateClientDialog,
} from '../../components/Dialogs';
import { pn } from '../../utils';
import { AppContext, UseAppStoreType, closeAll } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType, closeAll } from '../../contexts/AppContext';
export interface OpenDialogs {
more: boolean;
@ -46,32 +46,49 @@ const MainDialogs = (): JSX.Element => {
open={open.update}
coordinatorVersion={info.coordinatorVersion}
clientVersion={info.clientVersion}
onClose={() => setOpen({ ...open, update: false })}
onClose={() => {
setOpen({ ...open, update: false });
}}
/>
<InfoDialog
open={open.info}
maxAmount={maxAmount}
onClose={() => setOpen({ ...open, info: false })}
onClose={() => {
setOpen({ ...open, info: false });
}}
/>
<LearnDialog
open={open.learn}
onClose={() => {
setOpen({ ...open, learn: false });
}}
/>
<LearnDialog open={open.learn} onClose={() => setOpen({ ...open, learn: false })} />
<CommunityDialog
open={open.community}
onClose={() => setOpen({ ...open, community: false })}
onClose={() => {
setOpen({ ...open, community: false });
}}
/>
<CoordinatorSummaryDialog
open={open.coordinator}
onClose={() => setOpen({ ...open, coordinator: false })}
onClose={() => {
setOpen({ ...open, coordinator: false });
}}
info={info}
/>
<StatsDialog
open={open.stats}
onClose={() => setOpen({ ...open, stats: false })}
onClose={() => {
setOpen({ ...open, stats: false });
}}
info={info}
/>
<ProfileDialog
open={open.profile}
baseUrl={baseUrl}
onClose={() => setOpen({ ...open, profile: false })}
onClose={() => {
setOpen({ ...open, profile: false });
}}
robot={robot}
setRobot={setRobot}
setCurrentOrder={setCurrentOrder}

View File

@ -8,7 +8,7 @@ import { filterOrders } from '../../utils';
import MakerForm from '../../components/MakerForm';
import BookTable from '../../components/BookTable';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { NoRobotDialog } from '../../components/Dialogs';
const MakerPage = (): JSX.Element => {
@ -64,7 +64,12 @@ const MakerPage = (): JSX.Element => {
return (
<Grid container direction='column' alignItems='center' spacing={1}>
<NoRobotDialog open={openNoRobot} onClose={() => setOpenNoRobot(false)} />
<NoRobotDialog
open={openNoRobot}
onClose={() => {
setOpenNoRobot(false);
}}
/>
<Grid item>
<Collapse in={matches.length > 0 && showMatches}>
<Grid container direction='column' alignItems='center' spacing={1}>
@ -102,8 +107,12 @@ const MakerPage = (): JSX.Element => {
}}
disableRequest={matches.length > 0 && !showMatches}
collapseAll={showMatches}
onSubmit={() => setShowMatches(matches.length > 0)}
onReset={() => setShowMatches(false)}
onSubmit={() => {
setShowMatches(matches.length > 0);
}}
onReset={() => {
setShowMatches(false);
}}
submitButtonLabel={matches.length > 0 && !showMatches ? 'Submit' : 'Create order'}
/>
</Paper>

View File

@ -1,9 +1,9 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useTheme, styled, Grid, IconButton } from '@mui/material';
import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip';
import Tooltip, { type TooltipProps, tooltipClasses } from '@mui/material/Tooltip';
import { closeAll } from '../../contexts/AppContext';
import { OpenDialogs } from '../MainDialogs';
import { type OpenDialogs } from '../MainDialogs';
import { BubbleChart, Info, People, PriceChange, School } from '@mui/icons-material';
@ -45,7 +45,9 @@ const MoreTooltip = ({ open, setOpen, children }: MoreTooltipProps): JSX.Element
sx={{
color: open.info ? theme.palette.primary.main : theme.palette.text.secondary,
}}
onClick={() => setOpen({ ...closeAll, info: !open.info })}
onClick={() => {
setOpen({ ...closeAll, info: !open.info });
}}
>
<Info />
</IconButton>
@ -58,7 +60,9 @@ const MoreTooltip = ({ open, setOpen, children }: MoreTooltipProps): JSX.Element
sx={{
color: open.learn ? theme.palette.primary.main : theme.palette.text.secondary,
}}
onClick={() => setOpen({ ...closeAll, learn: !open.learn })}
onClick={() => {
setOpen({ ...closeAll, learn: !open.learn });
}}
>
<School />
</IconButton>
@ -75,7 +79,9 @@ const MoreTooltip = ({ open, setOpen, children }: MoreTooltipProps): JSX.Element
sx={{
color: open.community ? theme.palette.primary.main : theme.palette.text.secondary,
}}
onClick={() => setOpen({ ...closeAll, community: !open.community })}
onClick={() => {
setOpen({ ...closeAll, community: !open.community });
}}
>
<People />
</IconButton>
@ -90,7 +96,9 @@ const MoreTooltip = ({ open, setOpen, children }: MoreTooltipProps): JSX.Element
? theme.palette.primary.main
: theme.palette.text.secondary,
}}
onClick={() => setOpen({ ...closeAll, coordinator: !open.coordinator })}
onClick={() => {
setOpen({ ...closeAll, coordinator: !open.coordinator });
}}
>
<PriceChange />
</IconButton>
@ -103,7 +111,9 @@ const MoreTooltip = ({ open, setOpen, children }: MoreTooltipProps): JSX.Element
sx={{
color: open.stats ? theme.palette.primary.main : theme.palette.text.secondary,
}}
onClick={() => setOpen({ ...closeAll, stats: !open.stats })}
onClick={() => {
setOpen({ ...closeAll, stats: !open.stats });
}}
>
<BubbleChart />
</IconButton>

View File

@ -4,7 +4,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
import { Tabs, Tab, Paper, useTheme } from '@mui/material';
import MoreTooltip from './MoreTooltip';
import { Page } from '.';
import { type Page } from '.';
import {
SettingsApplications,
@ -15,7 +15,7 @@ import {
MoreHoriz,
} from '@mui/icons-material';
import RobotAvatar from '../../components/RobotAvatar';
import { AppContext, UseAppStoreType, closeAll } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType, closeAll } from '../../contexts/AppContext';
interface NavBarProps {
width: number;
@ -76,10 +76,9 @@ const NavBar = ({ width, height }: NavBarProps): JSX.Element => {
handleSlideDirection(page, newPage);
setPage(newPage);
const param = newPage === 'order' ? currentOrder ?? '' : '';
setTimeout(
() => navigate(`/${newPage}/${param}`),
theme.transitions.duration.leavingScreen * 3,
);
setTimeout(() => {
navigate(`/${newPage}/${param}`);
}, theme.transitions.duration.leavingScreen * 3);
}
};
@ -104,7 +103,9 @@ const NavBar = ({ width, height }: NavBarProps): JSX.Element => {
sx={{ ...tabSx, minWidth: '2.5em', width: '2.5em', maxWidth: '4em' }}
value='none'
disabled={robot.nickname === null}
onClick={() => setOpen({ ...closeAll, profile: !open.profile })}
onClick={() => {
setOpen({ ...closeAll, profile: !open.profile });
}}
icon={
robot.nickname && robot.avatarLoaded ? (
<RobotAvatar

View File

@ -7,7 +7,7 @@ import TradeBox from '../../components/TradeBox';
import OrderDetails from '../../components/OrderDetails';
import { apiClient } from '../../services/api';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
const OrderPage = (): JSX.Element => {
const {
@ -70,7 +70,9 @@ const OrderPage = (): JSX.Element => {
}
};
const startAgain = () => navigate('/robot');
const startAgain = () => {
navigate('/robot');
};
return (
<Box>
@ -138,7 +140,9 @@ const OrderPage = (): JSX.Element => {
<Box sx={{ borderBottom: 1, borderColor: 'divider', width: '21em' }}>
<Tabs
value={tab}
onChange={(mouseEvent, value) => setTab(value)}
onChange={(mouseEvent, value) => {
setTab(value);
}}
variant='fullWidth'
>
<Tab label={t('Order')} value='order' />

View File

@ -15,7 +15,7 @@ import {
AccordionSummary,
AccordionDetails,
} from '@mui/material';
import { Robot } from '../../models';
import { type Robot } from '../../models';
import { Casino, Bolt, Check, Storefront, AddBox, School } from '@mui/icons-material';
import RobotAvatar from '../../components/RobotAvatar';
import TokenInput from './TokenInput';
@ -54,7 +54,9 @@ const Onboarding = ({
setGeneratedToken(true);
setInputToken(genBase62Token(36));
setLoading(true);
setTimeout(() => setLoading(false), 1000);
setTimeout(() => {
setLoading(false);
}, 1000);
};
return (
@ -209,7 +211,13 @@ const Onboarding = ({
) : null}
<Grid item>
<Collapse in={!!(robot.avatarLoaded && robot.nickname)}>
<Button onClick={() => setStep('3')} variant='contained' size='large'>
<Button
onClick={() => {
setStep('3');
}}
variant='contained'
size='large'
>
<Check />
{t('Continue')}
</Button>
@ -237,11 +245,21 @@ const Onboarding = ({
<Grid item>
<ButtonGroup variant='contained'>
<Button color='primary' onClick={() => navigate('/offers')}>
<Button
color='primary'
onClick={() => {
navigate('/offers');
}}
>
<Storefront /> <div style={{ width: '0.5em' }} />
{t('Offers')}
</Button>
<Button color='secondary' onClick={() => navigate('/create')}>
<Button
color='secondary'
onClick={() => {
navigate('/create');
}}
>
<AddBox /> <div style={{ width: '0.5em' }} />
{t('Create')}
</Button>
@ -273,7 +291,12 @@ const Onboarding = ({
</Button>
</Grid>
<Grid item sx={{ position: 'relative', top: '0.6em' }}>
<Button color='inherit' onClick={() => setView('profile')}>
<Button
color='inherit'
onClick={() => {
setView('profile');
}}
>
{t('See profile')}
</Button>
</Grid>

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Button, Grid, Typography } from '@mui/material';
import { Robot } from '../../models';
import { type Robot } from '../../models';
import TokenInput from './TokenInput';
import Key from '@mui/icons-material/Key';

View File

@ -16,8 +16,8 @@ import {
import { Bolt, Add, DeleteSweep, Logout, Download } from '@mui/icons-material';
import RobotAvatar from '../../components/RobotAvatar';
import TokenInput from './TokenInput';
import { Slot, Robot } from '../../models';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { type Slot, type Robot } from '../../models';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { genBase62Token } from '../../utils';
import { LoadingButton } from '@mui/lab';
@ -298,7 +298,12 @@ const RobotProfile = ({
{window.NativeRobosats === undefined ? (
<Grid item>
<Button color='primary' onClick={() => garage.download()}>
<Button
color='primary'
onClick={() => {
garage.download();
}}
>
<Download />
</Button>
</Grid>

View File

@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { IconButton, LinearProgress, TextField, Tooltip } from '@mui/material';
import { Robot } from '../../models';
import { type Robot } from '../../models';
import { ContentCopy } from '@mui/icons-material';
import { systemClient } from '../../services/System';
@ -57,7 +57,9 @@ const TokenInput = ({
variant={editable ? 'outlined' : 'filled'}
helperText={badToken}
size='medium'
onChange={(e) => setInputToken(e.target.value)}
onChange={(e) => {
setInputToken(e.target.value);
}}
onKeyPress={(e) => {
if (e.key === 'Enter') {
onPressEnter();
@ -72,7 +74,9 @@ const TokenInput = ({
onClick={() => {
systemClient.copyToClipboard(inputToken);
setShowCopied(true);
setTimeout(() => setShowCopied(false), 1000);
setTimeout(() => {
setShowCopied(false);
}, 1000);
setRobot((robot) => {
return { ...robot, copiedToken: true };
});

View File

@ -73,7 +73,9 @@ const Welcome = ({ setView, width, getGenerateRobot }: WelcomeProps): JSX.Elemen
size='large'
color='primary'
variant='contained'
onClick={() => setView('onboarding')}
onClick={() => {
setView('onboarding');
}}
>
<RocketLaunch />
<div style={{ width: '0.5em' }} />
@ -91,7 +93,9 @@ const Welcome = ({ setView, width, getGenerateRobot }: WelcomeProps): JSX.Elemen
size='small'
color='secondary'
variant='contained'
onClick={() => setView('recovery')}
onClick={() => {
setView('recovery');
}}
>
<Key /> <div style={{ width: '0.5em' }} />
{t('Recovery')}

View File

@ -19,7 +19,7 @@ import RobotProfile from './RobotProfile';
import Recovery from './Recovery';
import { TorIcon } from '../../components/Icons';
import { genKey } from '../../pgp';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { validateTokenEntropy } from '../../utils';
const RobotPage = (): JSX.Element => {

View File

@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import { Grid, Paper } from '@mui/material';
import SettingsForm from '../../components/SettingsForm';
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
import { type UseAppStoreType, AppContext } from '../../contexts/AppContext';
const SettingsPage = (): JSX.Element => {
const { windowSize, navbarHeight } = useContext<UseAppStoreType>(AppContext);

View File

@ -18,7 +18,7 @@ import { fiatMethods, swapMethods, PaymentIcon } from '../PaymentMethods';
import { FlagWithProps } from '../Icons';
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import { Favorites } from '../../models';
import { type Favorites } from '../../models';
import SwapCalls from '@mui/icons-material/SwapCalls';
interface BookControlProps {
@ -259,7 +259,9 @@ const BookControl = ({
style: { textAlign: 'center' },
}}
value={paymentMethod[0] ? paymentMethod[0] : 'ANY'}
onChange={(e) => setPaymentMethods(e.target.value == 'ANY' ? [] : [e.target.value])}
onChange={(e) => {
setPaymentMethods(e.target.value == 'ANY' ? [] : [e.target.value]);
}}
>
<MenuItem value={'ANY'}>
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>

View File

@ -14,17 +14,17 @@ import {
LinearProgress,
IconButton,
Tooltip,
LinearProgressProps,
type LinearProgressProps,
styled,
} from '@mui/material';
import {
DataGrid,
GridColumnVisibilityModel,
type GridColumnVisibilityModel,
GridPagination,
GridPaginationModel,
type GridPaginationModel,
} from '@mui/x-data-grid';
import currencyDict from '../../../static/assets/currencies.json';
import { PublicOrder } from '../../models';
import { type PublicOrder } from '../../models';
import { filterOrders, hexToRgb, statusBadgeColor, pn, amountToString } from '../../utils';
import BookControl from './BookControl';
@ -34,7 +34,7 @@ import RobotAvatar from '../RobotAvatar';
// Icons
import { Fullscreen, FullscreenExit, Refresh } from '@mui/icons-material';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
const ClickThroughDataGrid = styled(DataGrid)({
'& .MuiDataGrid-overlayWrapperInner': {
@ -609,7 +609,7 @@ const BookTable = ({
const filteredColumns = function (maxWidth: number) {
const useSmall = maxWidth < 70;
const selectedColumns: object[] = [];
let columnVisibilityModel: GridColumnVisibilityModel = {};
const columnVisibilityModel: GridColumnVisibilityModel = {};
let width: number = 0;
for (const [key, value] of Object.entries(columnSpecs)) {
@ -654,12 +654,20 @@ const BookTable = ({
<Grid item>
<Grid container alignItems='center' direction='row'>
<Grid item xs={6}>
<IconButton onClick={() => setFullscreen(!fullscreen)}>
<IconButton
onClick={() => {
setFullscreen(!fullscreen);
}}
>
{fullscreen ? <FullscreenExit /> : <Fullscreen />}
</IconButton>
</Grid>
<Grid item xs={6}>
<IconButton onClick={() => fetchBook()}>
<IconButton
onClick={() => {
fetchBook();
}}
>
<Refresh />
</IconButton>
</Grid>
@ -758,9 +766,9 @@ const BookTable = ({
loading={book.loading}
columns={columns}
columnVisibilityModel={columnVisibilityModel}
onColumnVisibilityModelChange={(newColumnVisibilityModel) =>
setColumnVisibilityModel(newColumnVisibilityModel)
}
onColumnVisibilityModelChange={(newColumnVisibilityModel) => {
setColumnVisibilityModel(newColumnVisibilityModel);
}}
hideFooter={!showFooter}
components={gridComponents}
componentsProps={{
@ -777,7 +785,9 @@ const BookTable = ({
onPaginationModelChange={(newPaginationModel) => {
setPaginationModel(newPaginationModel);
}}
onRowClick={(params: any) => onOrderClicked(params.row.id)}
onRowClick={(params: any) => {
onOrderClicked(params.row.id);
}}
/>
</Paper>
);
@ -795,9 +805,9 @@ const BookTable = ({
hideFooter={!showFooter}
components={gridComponents}
columnVisibilityModel={columnVisibilityModel}
onColumnVisibilityModelChange={(newColumnVisibilityModel) =>
setColumnVisibilityModel(newColumnVisibilityModel)
}
onColumnVisibilityModelChange={(newColumnVisibilityModel) => {
setColumnVisibilityModel(newColumnVisibilityModel);
}}
componentsProps={{
toolbar: {
width,
@ -812,7 +822,9 @@ const BookTable = ({
onPaginationModelChange={(newPaginationModel) => {
setPaginationModel(newPaginationModel);
}}
onRowClick={(params: any) => onOrderClicked(params.row.id)}
onRowClick={(params: any) => {
onOrderClicked(params.row.id);
}}
/>
</Paper>
</Dialog>

View File

@ -1,12 +1,12 @@
import React, { useEffect, useState, useContext } from 'react';
import {
ResponsiveLine,
Serie,
Datum,
PointTooltipProps,
PointMouseHandler,
Point,
CustomLayer,
type Serie,
type Datum,
type PointTooltipProps,
type PointMouseHandler,
type Point,
type CustomLayer,
} from '@nivo/line';
import {
Box,
@ -20,13 +20,13 @@ import {
} from '@mui/material';
import { AddCircleOutline, RemoveCircleOutline } from '@mui/icons-material';
import { useTranslation } from 'react-i18next';
import { PublicOrder, LimitList, Order } from '../../../models';
import { type PublicOrder, LimitList, type Order } from '../../../models';
import RobotAvatar from '../../RobotAvatar';
import { amountToString, matchMedian, statusBadgeColor } from '../../../utils';
import currencyDict from '../../../../static/assets/currencies.json';
import { PaymentStringAsIcons } from '../../PaymentMethods';
import getNivoScheme from '../NivoScheme';
import { UseAppStoreType, AppContext } from '../../../contexts/AppContext';
import { type UseAppStoreType, AppContext } from '../../../contexts/AppContext';
interface DepthChartProps {
maxWidth: number;
@ -316,7 +316,13 @@ const DepthChart: React.FC<DepthChartProps> = ({
alignItems='flex-start'
style={{ paddingLeft: '1em' }}
>
<Select variant='standard' value={xType} onChange={(e) => setXType(e.target.value)}>
<Select
variant='standard'
value={xType}
onChange={(e) => {
setXType(e.target.value);
}}
>
<MenuItem value={'premium'}>
<div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap' }}>
{t('Premium')}
@ -333,7 +339,11 @@ const DepthChart: React.FC<DepthChartProps> = ({
<Grid container direction='row' justifyContent='center' alignItems='center'>
<Grid container justifyContent='center' alignItems='center'>
<Grid item>
<IconButton onClick={() => setXRange(xRange + rangeSteps)}>
<IconButton
onClick={() => {
setXRange(xRange + rangeSteps);
}}
>
<RemoveCircleOutline />
</IconButton>
</Grid>
@ -345,7 +355,12 @@ const DepthChart: React.FC<DepthChartProps> = ({
</Box>
</Grid>
<Grid item>
<IconButton onClick={() => setXRange(xRange - rangeSteps)} disabled={xRange <= 1}>
<IconButton
onClick={() => {
setXRange(xRange - rangeSteps);
}}
disabled={xRange <= 1}
>
<AddCircleOutline />
</IconButton>
</Grid>

View File

@ -1,5 +1,5 @@
import { Theme as NivoTheme } from '@nivo/core';
import { Theme as MuiTheme } from '@mui/material/styles';
import { type Theme as NivoTheme } from '@nivo/core';
import { type Theme as MuiTheme } from '@mui/material/styles';
export const getNivoScheme: (theme: MuiTheme) => NivoTheme = (theme) => {
const lightMode = {

View File

@ -37,7 +37,11 @@ function CredentialTextfield(props) {
InputProps={{
endAdornment: (
<Tooltip disableHoverListener enterTouchDelay={0} title={props.copiedTitle}>
<IconButton onClick={() => systemClient.copyToClipboard(props.value)}>
<IconButton
onClick={() => {
systemClient.copyToClipboard(props.value);
}}
>
<ContentCopy />
</IconButton>
</Tooltip>
@ -144,14 +148,14 @@ const AuditPGPDialog = ({
size='small'
color='primary'
variant='contained'
onClick={() =>
onClick={() => {
saveAsJson('keys_' + orderId + '.json', {
own_public_key: own_pub_key,
peer_public_key: peer_pub_key,
encrypted_private_key: own_enc_priv_key,
passphrase,
})
}
});
}}
>
<div style={{ width: 26, height: 18 }}>
<ExportIcon sx={{ width: 18, height: 18 }} />
@ -176,7 +180,9 @@ const AuditPGPDialog = ({
size='small'
color='primary'
variant='contained'
onClick={() => saveAsJson('messages_' + orderId + '.json', messages)}
onClick={() => {
saveAsJson('messages_' + orderId + '.json', messages);
}}
>
<div style={{ width: 28, height: 20 }}>
<ExportIcon sx={{ width: 18, height: 18 }} />

View File

@ -23,7 +23,7 @@ import BookIcon from '@mui/icons-material/Book';
import LinkIcon from '@mui/icons-material/Link';
import { pn } from '../../utils';
import { Info } from '../../models';
import { type Info } from '../../models';
interface Props {
open: boolean;

View File

@ -13,7 +13,7 @@ import {
Grid,
} from '@mui/material';
import { NewTabIcon } from '../Icons';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
interface Props {
open: boolean;

View File

@ -33,10 +33,10 @@ import NumbersIcon from '@mui/icons-material/Numbers';
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import { UserNinjaIcon } from '../Icons';
import { getHost, getWebln } from '../../utils';
import { getWebln } from '../../utils';
import RobotAvatar from '../RobotAvatar';
import { apiClient } from '../../services/api';
import { Robot } from '../../models';
import { type Robot } from '../../models';
interface Props {
open: boolean;
@ -50,7 +50,6 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
const { t } = useTranslation();
const navigate = useNavigate();
const theme = useTheme();
const host = getHost();
const [rewardInvoice, setRewardInvoice] = useState<string>('');
const [showRewardsSpinner, setShowRewardsSpinner] = useState<boolean>(false);
@ -60,13 +59,20 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
const [weblnEnabled, setWeblnEnabled] = useState<boolean>(false);
const [openEnableTelegram, setOpenEnableTelegram] = useState<boolean>(false);
const handleWebln = async () => {
const webln = await getWebln()
.then(() => {
setWeblnEnabled(true);
})
.catch(() => {
setWeblnEnabled(false);
console.log('WebLN not available');
});
return webln;
};
useEffect(() => {
const handleWebln = async (order: Order) => {
const webln = await getWebln().catch(() => console.log('WebLN not available'));
return webln;
};
const webln = handleWebln();
setWeblnEnabled(webln !== undefined);
handleWebln();
}, []);
const handleWeblnInvoiceClicked = async (e: any) => {
@ -107,7 +113,9 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
const setStealthInvoice = (wantsStealth: boolean) => {
apiClient
.post(baseUrl, '/api/stealth/', { wantsStealth }, { tokenSHA256: robot.tokenSHA256 })
.then((data) => setRobot({ ...robot, stealthInvoices: data?.wantsStealth }));
.then((data) => {
setRobot({ ...robot, stealthInvoices: data?.wantsStealth });
});
};
return (
@ -213,7 +221,9 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
<EnableTelegramDialog
open={openEnableTelegram}
onClose={() => setOpenEnableTelegram(false)}
onClose={() => {
setOpenEnableTelegram(false);
}}
tgBotName={robot.tgBotName}
tgToken={robot.tgToken}
/>
@ -229,7 +239,12 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
<b>{t('Telegram enabled')}</b>
</Typography>
) : (
<Button color='primary' onClick={() => setOpenEnableTelegram(true)}>
<Button
color='primary'
onClick={() => {
setOpenEnableTelegram(true);
}}
>
{t('Enable Telegram Notifications')}
</Button>
)}
@ -256,7 +271,9 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
control={
<Switch
checked={robot.stealthInvoices}
onChange={() => setStealthInvoice(!robot.stealthInvoices)}
onChange={() => {
setStealthInvoice(!robot.stealthInvoices);
}}
/>
}
/>
@ -280,7 +297,9 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
<Grid item xs={3}>
<Button
disabled={robot.earnedRewards === 0}
onClick={() => setOpenClaimRewards(true)}
onClick={() => {
setOpenClaimRewards(true);
}}
variant='contained'
size='small'
>
@ -309,7 +328,9 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
<Grid item alignItems='stretch' style={{ display: 'flex', maxWidth: 80 }}>
<Button
sx={{ maxHeight: 38 }}
onClick={(e) => handleSubmitInvoiceClicked(e, rewardInvoice)}
onClick={(e) => {
handleSubmitInvoiceClicked(e, rewardInvoice);
}}
variant='contained'
color='primary'
size='small'
@ -319,12 +340,14 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
</Button>
</Grid>
</Grid>
{weblnEnabled && (
{weblnEnabled ? (
<Grid container style={{ display: 'flex', alignItems: 'stretch' }}>
<Grid item alignItems='stretch' style={{ display: 'flex', maxWidth: 240 }}>
<Button
sx={{ maxHeight: 38, minWidth: 230 }}
onClick={async (e) => await handleWeblnInvoiceClicked(e)}
onClick={async (e) => {
await handleWeblnInvoiceClicked(e);
}}
variant='contained'
color='primary'
size='small'
@ -334,6 +357,8 @@ const ProfileDialog = ({ open = false, baseUrl, onClose, robot, setRobot }: Prop
</Button>
</Grid>
</Grid>
) : (
<></>
)}
</form>
)}

View File

@ -25,7 +25,7 @@ import EqualizerIcon from '@mui/icons-material/Equalizer';
import { AmbossIcon, BitcoinSignIcon, RoboSatsNoTextIcon } from '../Icons';
import { pn } from '../../utils';
import { Info } from '../../models';
import { type Info } from '../../models';
interface Props {
open: boolean;

View File

@ -14,7 +14,7 @@ import {
} from '@mui/material';
import { systemClient } from '../../services/System';
import ContentCopy from '@mui/icons-material/ContentCopy';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
interface Props {
open: boolean;
@ -49,7 +49,11 @@ const StoreTokenDialog = ({ open, onClose, onClickBack, onClickDone }: Props): J
InputProps={{
endAdornment: (
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
<IconButton onClick={() => systemClient.copyToClipboard(robot.token)}>
<IconButton
onClick={() => {
systemClient.copyToClipboard(robot.token);
}}
>
<ContentCopy color='primary' />
</IconButton>
</Tooltip>

View File

@ -88,7 +88,12 @@ const UpdateClientDialog = ({
<Divider />
<ListItemButton component='a' onClick={() => location.reload(true)}>
<ListItemButton
component='a'
onClick={() => {
location.reload(true);
}}
>
<ListItemIcon>
<WebIcon color='primary' sx={{ height: 32, width: 32 }} />
</ListItemIcon>

View File

@ -29,6 +29,7 @@ export default class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBo
window.location.reload();
}, 30000);
}
render() {
if (this.state.hasError) {
return (

View File

@ -132,7 +132,9 @@ function AmountRange({
}}
value={currency == 0 ? 1 : currency}
renderValue={() => currencyCode}
onChange={(e) => handleCurrencyChange(e.target.value)}
onChange={(e) => {
handleCurrencyChange(e.target.value);
}}
>
{Object.entries(currencyDict).map(([key, value]) => (
<MenuItem key={key} value={parseInt(key)}>

View File

@ -226,9 +226,13 @@ export default function AutocompletePayments(props) {
value: props.value,
options: props.optionsType == 'fiat' ? fiatMethods : swapMethods,
getOptionLabel: (option) => option.name,
onInputChange: (e) => setVal(e ? (e.target.value ? e.target.value : '') : ''),
onInputChange: (e) => {
setVal(e ? (e.target.value ? e.target.value : '') : '');
},
onChange: (event, value) => props.onAutocompleteChange(value),
onClose: () => setVal(() => ''),
onClose: () => {
setVal(() => '');
},
});
const [val, setVal] = useState('');

View File

@ -25,7 +25,7 @@ import {
IconButton,
} from '@mui/material';
import { LimitList, defaultMaker } from '../../models';
import { type LimitList, defaultMaker } from '../../models';
import { LocalizationProvider, MobileTimePicker } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
@ -40,7 +40,7 @@ import { amountToString, computeSats, pn } from '../../utils';
import { SelfImprovement, Lock, HourglassTop, DeleteSweep, Edit } from '@mui/icons-material';
import { LoadingButton } from '@mui/lab';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
interface MakerFormProps {
disableRequest?: boolean;
@ -464,7 +464,9 @@ const MakerForm = ({
<Box>
<ConfirmationDialog
open={openDialogs}
onClose={() => setOpenDialogs(false)}
onClose={() => {
setOpenDialogs(false);
}}
onClickDone={handleCreateOrder}
hasRobot={robot.avatarLoaded}
/>
@ -531,7 +533,9 @@ const MakerForm = ({
<Checkbox
sx={{ position: 'relative', bottom: '0.3em' }}
checked={fav.mode == 'swap'}
onClick={() => handleCurrencyChange(fav.mode == 'swap' ? 1 : 1000)}
onClick={() => {
handleCurrencyChange(fav.mode == 'swap' ? 1 : 1000);
}}
/>
</FormControl>
</Grid>
@ -547,12 +551,12 @@ const MakerForm = ({
<Button
size={maker.advancedOptions ? 'small' : 'large'}
variant='contained'
onClick={() =>
onClick={() => {
setFav({
...fav,
type: 1,
})
}
});
}}
disableElevation={fav.type == 1}
sx={{
backgroundColor: fav.type == 1 ? 'primary.main' : 'background.paper',
@ -567,12 +571,12 @@ const MakerForm = ({
<Button
size={maker.advancedOptions ? 'small' : 'large'}
variant='contained'
onClick={() =>
onClick={() => {
setFav({
...fav,
type: 0,
})
}
});
}}
disableElevation={fav.type == 0}
color='secondary'
sx={{
@ -654,7 +658,9 @@ const MakerForm = ({
borderRadius: '4px',
},
}}
onChange={(e) => setMaker({ ...maker, amount: e.target.value })}
onChange={(e) => {
setMaker({ ...maker, amount: e.target.value });
}}
/>
</Tooltip>
{fav.mode === 'swap' && maker.amount != '' ? (
@ -677,7 +683,9 @@ const MakerForm = ({
style: { textAlign: 'center' },
}}
value={fav.currency == 0 ? 1 : fav.currency}
onChange={(e) => handleCurrencyChange(e.target.value)}
onChange={(e) => {
handleCurrencyChange(e.target.value);
}}
>
{Object.entries(currencyDict).map(([key, value]) => (
<MenuItem key={key} value={parseInt(key)}>
@ -946,7 +954,9 @@ const MakerForm = ({
]}
min={2}
max={15}
onChange={(e) => setMaker({ ...maker, bondSize: e.target.value })}
onChange={(e) => {
setMaker({ ...maker, bondSize: e.target.value });
}}
/>
</Grid>
</Grid>

View File

@ -5,14 +5,14 @@ import {
Alert,
useTheme,
IconButton,
TooltipProps,
type TooltipProps,
styled,
tooltipClasses,
} from '@mui/material';
import { useNavigate } from 'react-router-dom';
import { Order } from '../../models';
import { type Order } from '../../models';
import Close from '@mui/icons-material/Close';
import { Page } from '../../basic/NavBar';
import { type Page } from '../../basic/NavBar';
interface NotificationsProps {
order: Order | undefined;
@ -28,7 +28,7 @@ interface NotificationMessage {
onClick: () => void;
sound: HTMLAudioElement | undefined;
timeout: number;
pageTitle: String;
pageTitle: string;
}
const audio = {
@ -207,7 +207,9 @@ const Notifications = ({
if (message.title != '') {
setMessage(message);
setShow(true);
setTimeout(() => setShow(false), message.timeout);
setTimeout(() => {
setShow(false);
}, message.timeout);
if (message.sound != null) {
message.sound.play();
}

View File

@ -21,11 +21,11 @@ import Countdown from 'react-countdown';
import currencies from '../../../static/assets/currencies.json';
import { apiClient } from '../../services/api';
import { Order, Info } from '../../models';
import { type Order, type Info } from '../../models';
import { ConfirmationDialog } from '../Dialogs';
import { LoadingButton } from '@mui/lab';
import { computeSats } from '../../utils';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
interface TakeButtonProps {
order: Order;
@ -58,10 +58,10 @@ const TakeButton = ({ order, setOrder, baseUrl, info }: TakeButtonProps): JSX.El
const rate = order.amount ? order.amount / btc_now : order.max_amount / btc_now;
const amount = order.currency === 1000 ? Number(takeAmount) / 100000000 : Number(takeAmount);
const satoshis = computeSats({
amount: amount,
amount,
routingBudget: order.is_buyer ? defaultRoutingBudget : 0,
fee: tradeFee,
rate: rate,
rate,
});
return satoshis;
};
@ -74,7 +74,12 @@ const TakeButton = ({ order, setOrder, baseUrl, info }: TakeButtonProps): JSX.El
const InactiveMakerDialog = function () {
return (
<Dialog open={open.inactiveMaker} onClose={() => setOpen({ ...open, inactiveMaker: false })}>
<Dialog
open={open.inactiveMaker}
onClose={() => {
setOpen({ ...open, inactiveMaker: false });
}}
>
<DialogTitle>{t('The maker is away')}</DialogTitle>
<DialogContent>
<DialogContentText>
@ -84,10 +89,19 @@ const TakeButton = ({ order, setOrder, baseUrl, info }: TakeButtonProps): JSX.El
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(closeAll)} autoFocus>
<Button
onClick={() => {
setOpen(closeAll);
}}
autoFocus
>
{t('Go back')}
</Button>
<Button onClick={() => setOpen({ inactiveMaker: false, confirmation: true })}>
<Button
onClick={() => {
setOpen({ inactiveMaker: false, confirmation: true });
}}
>
{t('Sounds fine')}
</Button>
</DialogActions>
@ -313,7 +327,9 @@ const TakeButton = ({ order, setOrder, baseUrl, info }: TakeButtonProps): JSX.El
<ConfirmationDialog
open={open.confirmation}
onClose={() => setOpen({ ...open, confirmation: false })}
onClose={() => {
setOpen({ ...open, confirmation: false });
}}
onClickDone={() => {
takeOrder();
setLoadingTake(true);

View File

@ -16,7 +16,7 @@ import {
IconButton,
} from '@mui/material';
import Countdown, { CountdownRenderProps, zeroPad } from 'react-countdown';
import Countdown, { type CountdownRenderProps, zeroPad } from 'react-countdown';
import RobotAvatar from '../../components/RobotAvatar';
import currencies from '../../../static/assets/currencies.json';
@ -34,7 +34,7 @@ import { PaymentStringAsIcons } from '../../components/PaymentMethods';
import { FlagWithProps, SendReceiveIcon } from '../Icons';
import LinearDeterminate from './LinearDeterminate';
import { Order, Info } from '../../models';
import { type Order, type Info } from '../../models';
import { statusBadgeColor, pn, amountToString, computeSats } from '../../utils';
import TakeButton from './TakeButton';
@ -160,20 +160,20 @@ const OrderDetails = ({
amount: order.amount,
fee: -tradeFee,
routingBudget: defaultRoutingBudget,
rate: rate,
rate,
});
} else {
const min = computeSats({
amount: Number(order.min_amount),
fee: -tradeFee,
routingBudget: defaultRoutingBudget,
rate: rate,
rate,
});
const max = computeSats({
amount: Number(order.max_amount),
fee: -tradeFee,
routingBudget: defaultRoutingBudget,
rate: rate,
rate,
});
sats = `${min}-${max}`;
}
@ -190,18 +190,18 @@ const OrderDetails = ({
sats = computeSats({
amount: order.amount,
fee: tradeFee,
rate: rate,
rate,
});
} else {
const min = computeSats({
amount: order.min_amount,
fee: tradeFee,
rate: rate,
rate,
});
const max = computeSats({
amount: order.max_amount,
fee: tradeFee,
rate: rate,
rate,
});
sats = `${min}-${max}`;
}
@ -297,7 +297,11 @@ const OrderDetails = ({
secondary={order.amount ? 'Amount' : 'Amount Range'}
/>
<ListItemIcon>
<IconButton onClick={() => setShowSatsDetails(!showSatsDetails)}>
<IconButton
onClick={() => {
setShowSatsDetails(!showSatsDetails);
}}
>
{showSatsDetails ? <ExpandLess /> : <ExpandMore color='primary' />}
</IconButton>
</ListItemIcon>

View File

@ -105,7 +105,9 @@ const RobotAvatar: React.FC<Props> = ({
border: '0.3px solid #55555',
filter: 'dropShadow(0.5px 0.5px 0.5px #000000)',
...imageStyle,
onLoad: setTimeout(() => setActiveBackground(false), 1000),
onLoad: setTimeout(() => {
setActiveBackground(false);
}, 1000),
}}
/>
</div>

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Select, MenuItem, useTheme, Grid, Typography } from '@mui/material';
import Language from '../../models/Language.model';
import type Language from '../../models/Language.model';
import Flags from 'country-flag-icons/react/3x2';
import { CataloniaFlag, BasqueCountryFlag } from '../Icons';

View File

@ -1,6 +1,6 @@
import React, { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
import { type UseAppStoreType, AppContext } from '../../contexts/AppContext';
import {
Grid,
Paper,

View File

@ -2,7 +2,7 @@ import React, { useContext } from 'react';
import { Box, CircularProgress, Tooltip } from '@mui/material';
import { TorIcon } from './Icons';
import { useTranslation } from 'react-i18next';
import { AppContext, UseAppStoreType } from '../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../contexts/AppContext';
interface TorIndicatorProps {
color: 'inherit' | 'error' | 'warning' | 'success' | 'primary' | 'secondary' | 'info' | undefined;

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Tooltip } from '@mui/material';
import { Order } from '../../models';
import { type Order } from '../../models';
import { LoadingButton } from '@mui/lab';
interface CancelButtonProps {

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Alert } from '@mui/material';
import { Order } from '../../models';
import { type Order } from '../../models';
interface CollabCancelAlertProps {
order: Order;

View File

@ -12,7 +12,7 @@ import { LoadingButton } from '@mui/lab';
interface ConfirmCollabCancelDialogProps {
open: boolean;
loading: Boolean;
loading: boolean;
onClose: () => void;
onCollabCancelClick: () => void;
peerAskedCancel: boolean;

View File

@ -8,7 +8,7 @@ import {
DialogContentText,
Button,
} from '@mui/material';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import currencies from '../../../../static/assets/currencies.json';
import { pn } from '../../../utils';
import { LoadingButton } from '@mui/lab';

View File

@ -8,7 +8,7 @@ import {
DialogContentText,
Button,
} from '@mui/material';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import currencies from '../../../../static/assets/currencies.json';
import { pn } from '../../../utils';
import { LoadingButton } from '@mui/lab';

View File

@ -8,7 +8,7 @@ import {
DialogContentText,
Button,
} from '@mui/material';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import { LoadingButton } from '@mui/lab';
interface ConfirmUndoFiatSentDialogProps {
@ -30,7 +30,9 @@ export const ConfirmUndoFiatSentDialog = ({
useEffect(() => {
if (time > 0 && open) {
setTimeout(() => setTime(time - 1), 1000);
setTimeout(() => {
setTime(time - 1);
}, 1000);
}
}, [time, open]);

View File

@ -34,7 +34,14 @@ const ChatBottom: React.FC<Props> = ({ orderId, setAudit, audit, createJsonFile
enterNextDelay={2000}
title={t('Verify your privacy')}
>
<Button size='small' color='primary' variant='outlined' onClick={() => setAudit(!audit)}>
<Button
size='small'
color='primary'
variant='outlined'
onClick={() => {
setAudit(!audit);
}}
>
<KeyIcon sx={{ width: '0.8em', height: '0.8em' }} />
{t('Audit PGP')}{' '}
</Button>
@ -54,7 +61,9 @@ const ChatBottom: React.FC<Props> = ({ orderId, setAudit, audit, createJsonFile
size='small'
color='primary'
variant='outlined'
onClick={() => saveAsJson('complete_log_chat_' + orderId + '.json', createJsonFile())}
onClick={() => {
saveAsJson('complete_log_chat_' + orderId + '.json', createJsonFile());
}}
>
<div style={{ width: '1.4em', height: '1.4em' }}>
<ExportIcon sx={{ width: '0.8em', height: '0.8em' }} />
@ -68,7 +77,9 @@ const ChatBottom: React.FC<Props> = ({ orderId, setAudit, audit, createJsonFile
size='small'
color='primary'
variant='outlined'
onClick={() => systemClient.copyToClipboard(JSON.stringify(createJsonFile()))}
onClick={() => {
systemClient.copyToClipboard(JSON.stringify(createJsonFile()));
}}
>
<div style={{ width: '1.4em', height: '1.4em' }}>
<ExportIcon sx={{ width: '0.8em', height: '0.8em' }} />

View File

@ -53,7 +53,9 @@ const ChatHeader: React.FC<Props> = ({ connected, peerConnected, turtleMode, set
<IconButton
size='small'
color={turtleMode ? 'primary' : 'inherit'}
onClick={() => setTurtleMode(!turtleMode)}
onClick={() => {
setTurtleMode(!turtleMode);
}}
>
<WifiTetheringError />
</IconButton>

View File

@ -3,8 +3,8 @@ import { useTranslation } from 'react-i18next';
import { Button, Tooltip, TextField, Grid, Paper, Typography } from '@mui/material';
import { encryptMessage, decryptMessage } from '../../../../pgp';
import { AuditPGPDialog } from '../../../Dialogs';
import { websocketClient, WebsocketConnection } from '../../../../services/Websocket';
import { Robot } from '../../../../models';
import { websocketClient, type WebsocketConnection } from '../../../../services/Websocket';
import { type Robot } from '../../../../models';
// Icons
import CircularProgress from '@mui/material/CircularProgress';
@ -12,7 +12,7 @@ import KeyIcon from '@mui/icons-material/Key';
import { useTheme } from '@mui/system';
import MessageCard from '../MessageCard';
import ChatHeader from '../ChatHeader';
import { EncryptedChatMessage, ServerMessage } from '..';
import { type EncryptedChatMessage, type ServerMessage } from '..';
import ChatBottom from '../ChatBottom';
import { sha256 } from 'js-sha256';
@ -107,9 +107,15 @@ const EncryptedSocketChat: React.FC<Props> = ({
nick: userNick,
});
connection.onMessage((message) => setServerMessages((prev) => [...prev, message]));
connection.onClose(() => setConnected(false));
connection.onError(() => setConnected(false));
connection.onMessage((message) => {
setServerMessages((prev) => [...prev, message]);
});
connection.onClose(() => {
setConnected(false);
});
connection.onError(() => {
setConnected(false);
});
});
};
@ -230,7 +236,9 @@ const EncryptedSocketChat: React.FC<Props> = ({
});
}
})
.catch((error) => setError(error.toString()));
.catch((error) => {
setError(error.toString());
});
}
e.preventDefault();
};
@ -245,14 +253,18 @@ const EncryptedSocketChat: React.FC<Props> = ({
>
<AuditPGPDialog
open={audit}
onClose={() => setAudit(false)}
onClose={() => {
setAudit(false);
}}
orderId={Number(orderId)}
messages={messages}
own_pub_key={robot.pubKey || ''}
own_enc_priv_key={robot.encPrivKey || ''}
peer_pub_key={peerPubKey || 'Not received yet'}
passphrase={robot.token || ''}
onClickBack={() => setAudit(false)}
onClickBack={() => {
setAudit(false);
}}
/>
<Grid item>
<ChatHeader

View File

@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Button, TextField, Grid, Paper, Typography } from '@mui/material';
import { encryptMessage, decryptMessage } from '../../../../pgp';
import { AuditPGPDialog } from '../../../Dialogs';
import { Robot } from '../../../../models';
import { type Robot } from '../../../../models';
// Icons
import CircularProgress from '@mui/material/CircularProgress';
@ -11,7 +11,7 @@ import KeyIcon from '@mui/icons-material/Key';
import { useTheme } from '@mui/system';
import MessageCard from '../MessageCard';
import ChatHeader from '../ChatHeader';
import { EncryptedChatMessage, ServerMessage } from '..';
import { type EncryptedChatMessage, type ServerMessage } from '..';
import { apiClient } from '../../../../services/api';
import ChatBottom from '../ChatBottom';
@ -222,7 +222,9 @@ const EncryptedTurtleChat: React.FC<Props> = ({
setValue('');
});
})
.catch((error) => setError(error.toString()));
.catch((error) => {
setError(error.toString());
});
}
e.preventDefault();
};
@ -237,14 +239,18 @@ const EncryptedTurtleChat: React.FC<Props> = ({
>
<AuditPGPDialog
open={audit}
onClose={() => setAudit(false)}
onClose={() => {
setAudit(false);
}}
orderId={Number(orderId)}
messages={messages}
own_pub_key={robot.pubKey || ''}
own_enc_priv_key={robot.encPrivKey || ''}
peer_pub_key={peerPubKey || 'Not received yet'}
passphrase={robot.token || ''}
onClickBack={() => setAudit(false)}
onClickBack={() => {
setAudit(false);
}}
/>
<Grid item>

View File

@ -9,7 +9,7 @@ import CheckIcon from '@mui/icons-material/Check';
import CloseIcon from '@mui/icons-material/Close';
import ContentCopy from '@mui/icons-material/ContentCopy';
import VisibilityIcon from '@mui/icons-material/Visibility';
import { EncryptedChatMessage } from '..';
import { type EncryptedChatMessage } from '..';
interface Props {
message: EncryptedChatMessage;
@ -81,7 +81,9 @@ const MessageCard: React.FC<Props> = ({ message, isTaker, userConnected, baseUrl
<div style={{ width: '1.4em' }}>
<IconButton
sx={{ height: '1.2em', width: '1.2em', position: 'relative', right: '0.15em' }}
onClick={() => setShowPGP(!showPGP)}
onClick={() => {
setShowPGP(!showPGP);
}}
>
<VisibilityIcon
color={showPGP ? 'primary' : 'inherit'}
@ -97,11 +99,11 @@ const MessageCard: React.FC<Props> = ({ message, isTaker, userConnected, baseUrl
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
<IconButton
sx={{ height: '0.8em', width: '0.8em' }}
onClick={() =>
onClick={() => {
systemClient.copyToClipboard(
showPGP ? message.encryptedMessage : message.plainTextMessage,
)
}
);
}}
>
<ContentCopy
sx={{

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Robot } from '../../../models';
import { type Robot } from '../../../models';
import EncryptedSocketChat from './EncryptedSocketChat';
import EncryptedTurtleChat from './EncryptedTurtleChat';

View File

@ -52,7 +52,9 @@ export const DisputeStatementForm = ({
}}
multiline
rows={4}
onChange={(e) => setDispute({ ...dispute, statement: e.target.value })}
onChange={(e) => {
setDispute({ ...dispute, statement: e.target.value });
}}
/>
</Grid>
<Grid item>
@ -67,7 +69,9 @@ export const DisputeStatementForm = ({
control={
<Checkbox
checked={dispute.attachLogs}
onChange={() => setDispute({ ...dispute, attachLogs: !dispute.attachLogs })}
onChange={() => {
setDispute({ ...dispute, attachLogs: !dispute.attachLogs });
}}
/>
}
label={t('Attach chat logs')}

View File

@ -21,7 +21,7 @@ import {
FormHelperText,
} from '@mui/material';
import { Order, Settings } from '../../../models';
import { type Order, type Settings } from '../../../models';
import { decode } from 'light-bolt11-decoder';
import WalletsButton from '../WalletsButton';
import { LoadingButton } from '@mui/lab';
@ -195,7 +195,9 @@ export const LightningPayoutForm = ({
.catch(() => {
setLightning({ ...lightning, badLnproxy: 'Lnproxy server uncaught error' });
})
.finally(() => setLoadingLnproxy(false));
.finally(() => {
setLoadingLnproxy(false);
});
};
const handleAdvancedOptions = function (checked: boolean) {
@ -291,7 +293,9 @@ export const LightningPayoutForm = ({
<Switch
size='small'
checked={lightning.advancedOptions}
onChange={(e) => handleAdvancedOptions(e.target.checked)}
onChange={(e) => {
handleAdvancedOptions(e.target.checked);
}}
/>
<SelfImprovement sx={{ color: 'text.primary' }} />
</Grid>
@ -375,13 +379,13 @@ export const LightningPayoutForm = ({
>
<div>
<FormControlLabel
onChange={(e) =>
onChange={(e) => {
setLightning({
...lightning,
useLnproxy: e.target.checked,
invoice: e.target.checked ? '' : lightning.invoice,
})
}
});
}}
checked={lightning.useLnproxy}
control={<Checkbox />}
label={
@ -419,9 +423,9 @@ export const LightningPayoutForm = ({
label={t('Server')}
labelId='select-label'
value={lightning.lnproxyServer}
onChange={(e) =>
setLightning({ ...lightning, lnproxyServer: Number(e.target.value) })
}
onChange={(e) => {
setLightning({ ...lightning, lnproxyServer: Number(e.target.value) });
}}
>
{lnproxies.map((lnproxyServer, index) => (
<MenuItem key={index} value={index}>
@ -494,13 +498,13 @@ export const LightningPayoutForm = ({
<Tooltip disableHoverListener enterTouchDelay={0} title={t('Copied!')}>
<IconButton
sx={{ height: '0.5em' }}
onClick={() =>
onClick={() => {
systemClient.copyToClipboard(
lightning.useLnproxy
? String(lightning.lnproxyAmount)
: String(lightning.amount),
)
}
);
}}
>
<ContentCopy sx={{ width: '0.8em' }} />
</IconButton>
@ -523,9 +527,9 @@ export const LightningPayoutForm = ({
style: { textAlign: 'center' },
}}
variant='outlined'
onChange={(e) =>
setLightning({ ...lightning, lnproxyInvoice: e.target.value ?? '' })
}
onChange={(e) => {
setLightning({ ...lightning, lnproxyInvoice: e.target.value ?? '' });
}}
/>
) : (
<></>
@ -547,7 +551,9 @@ export const LightningPayoutForm = ({
multiline={!lightning.useLnproxy}
minRows={3}
maxRows={5}
onChange={(e) => setLightning({ ...lightning, invoice: e.target.value ?? '' })}
onChange={(e) => {
setLightning({ ...lightning, invoice: e.target.value ?? '' });
}}
/>
</Grid>
@ -572,7 +578,9 @@ export const LightningPayoutForm = ({
<LoadingButton
loading={loading}
disabled={lightning.invoice.length < 20 || lightning.badInvoice != ''}
onClick={() => onClickSubmit(lightning.invoice)}
onClick={() => {
onClickSubmit(lightning.invoice);
}}
variant='outlined'
color='primary'
>

View File

@ -1,7 +1,7 @@
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Grid, Typography, TextField, List, Divider, ListItemText, ListItem } from '@mui/material';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import { LoadingButton } from '@mui/lab';
import { pn } from '../../../utils';
@ -124,7 +124,9 @@ export const OnchainPayoutForm = ({
inputProps={{
style: { textAlign: 'center' },
}}
onChange={(e) => setOnchain({ ...onchain, address: e.target.value })}
onChange={(e) => {
setOnchain({ ...onchain, address: e.target.value });
}}
/>
</Grid>
<Grid item xs={5}>

View File

@ -3,9 +3,9 @@ import { useTranslation } from 'react-i18next';
import { Grid, Typography, Tooltip, Collapse, IconButton } from '@mui/material';
import currencies from '../../../../static/assets/currencies.json';
import { Order, Robot } from '../../../models';
import { type Order, type Robot } from '../../../models';
import { pn } from '../../../utils';
import EncryptedChat, { EncryptedChatMessage } from '../EncryptedChat';
import EncryptedChat, { type EncryptedChatMessage } from '../EncryptedChat';
import Countdown, { zeroPad } from 'react-countdown';
import { LoadingButton } from '@mui/lab';

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Grid, Typography } from '@mui/material';
import { DisputeForm, DisputeStatementForm } from '../Forms';
import { type DisputeForm, DisputeStatementForm } from '../Forms';
interface DisputePromptProps {
loading: boolean;

View File

@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { Grid, Typography } from '@mui/material';
import { LoadingButton } from '@mui/lab';
import { Order } from '../../../models';
import { type Order } from '../../../models';
interface ExpiredPromptProps {
order: Order;

View File

@ -3,11 +3,11 @@ import { useTranslation } from 'react-i18next';
import { Button, Box, Grid, Typography, TextField, Tooltip, useTheme } from '@mui/material';
import { ContentCopy } from '@mui/icons-material';
import QRCode from 'react-qr-code';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import { systemClient } from '../../../services/System';
import currencies from '../../../../static/assets/currencies.json';
import WalletsButton from '../WalletsButton';
import { AppContext, UseAppStoreType } from '../../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../../contexts/AppContext';
interface LockInvoicePromptProps {
order: Order;

View File

@ -4,10 +4,15 @@ import { Grid, Typography, ToggleButtonGroup, ToggleButton } from '@mui/material
import currencies from '../../../../static/assets/currencies.json';
import { Order, Settings } from '../../../models';
import { type Order, type Settings } from '../../../models';
import { pn } from '../../../utils';
import { Bolt, Link } from '@mui/icons-material';
import { LightningPayoutForm, LightningForm, OnchainPayoutForm, OnchainForm } from '../Forms';
import {
LightningPayoutForm,
type LightningForm,
OnchainPayoutForm,
type OnchainForm,
} from '../Forms';
interface PayoutPrompProps {
order: Order;
@ -71,7 +76,9 @@ export const PayoutPrompt = ({
size='small'
value={tab}
exclusive
onChange={(mouseEvent, value) => setTab(value == null ? tab : value)}
onChange={(mouseEvent, value) => {
setTab(value == null ? tab : value);
}}
>
<ToggleButton value='lightning'>
<div

View File

@ -14,7 +14,7 @@ import { LoadingButton } from '@mui/lab';
import currencies from '../../../../static/assets/currencies.json';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import { PauseCircle, Storefront, Percent } from '@mui/icons-material';
interface PublicWaitPrompProps {

View File

@ -1,10 +1,10 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Box, CircularProgress, Grid, Typography, useTheme } from '@mui/material';
import Countdown, { CountdownRenderProps, zeroPad } from 'react-countdown';
import Countdown, { type CountdownRenderProps, zeroPad } from 'react-countdown';
import { Order, Settings } from '../../../models';
import { LightningForm, LightningPayoutForm } from '../Forms';
import { type Order, type Settings } from '../../../models';
import { type LightningForm, LightningPayoutForm } from '../Forms';
interface RoutingFailedPromptProps {
order: Order;

View File

@ -18,7 +18,7 @@ import TradeSummary from '../TradeSummary';
import { Favorite, RocketLaunch, ContentCopy, Refresh } from '@mui/icons-material';
import { LoadingButton } from '@mui/lab';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import { systemClient } from '../../../services/System';
interface SuccessfulPromptProps {

View File

@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Typography, useTheme } from '@mui/material';
import { Order } from '../../../models';
import { type Order } from '../../../models';
import stepXofY from '../stepXofY';
interface TakerFoundPrompProps {

View File

@ -30,7 +30,7 @@ import {
Link,
} from '@mui/icons-material';
import { RoboSatsNoTextIcon, SendReceiveIcon, BitcoinIcon } from '../Icons';
import { TradeCoordinatorSummary, TradeRobotSummary } from '../../models/Order.model';
import { type TradeCoordinatorSummary, type TradeRobotSummary } from '../../models/Order.model';
import { systemClient } from '../../services/System';
interface Props {
@ -110,7 +110,13 @@ const TradeSummary = ({
}}
>
<ToggleButtonGroup size='small' value={buttonValue} exclusive>
<ToggleButton value={0} disableRipple={true} onClick={() => setButtonValue(0)}>
<ToggleButton
value={0}
disableRipple={true}
onClick={() => {
setButtonValue(0);
}}
>
<RobotAvatar
baseUrl={baseUrl}
style={{ height: '1.5em', width: '1.5em' }}
@ -120,10 +126,22 @@ const TradeSummary = ({
&nbsp;
{t('Maker')}
</ToggleButton>
<ToggleButton value={1} disableRipple={true} onClick={() => setButtonValue(1)}>
<ToggleButton
value={1}
disableRipple={true}
onClick={() => {
setButtonValue(1);
}}
>
<RoboSatsNoTextIcon />
</ToggleButton>
<ToggleButton value={2} disableRipple={true} onClick={() => setButtonValue(2)}>
<ToggleButton
value={2}
disableRipple={true}
onClick={() => {
setButtonValue(2);
}}
>
{t('Taker')}
&nbsp;
<RobotAvatar

View File

@ -39,15 +39,15 @@ import BondStatus from './BondStatus';
import CancelButton from './CancelButton';
import {
defaultLightning,
LightningForm,
type LightningForm,
defaultOnchain,
OnchainForm,
DisputeForm,
type OnchainForm,
type DisputeForm,
defaultDispute,
} from './Forms';
import { Order, Robot, Settings } from '../../models';
import { EncryptedChatMessage } from './EncryptedChat';
import { type Order, type Robot, type Settings } from '../../models';
import { type EncryptedChatMessage } from './EncryptedChat';
import CollabCancelAlert from './CollabCancelAlert';
import { Bolt } from '@mui/icons-material';
@ -259,7 +259,9 @@ const TradeBox = ({
};
const handleWebln = async (order: Order) => {
const webln = await getWebln().catch(() => console.log('WebLN not available'));
const webln = await getWebln().catch(() => {
console.log('WebLN not available');
});
// If Webln implements locked payments compatibility, this logic might be simplier
if (webln == undefined) {
return null;
@ -488,13 +490,21 @@ const TradeBox = ({
<ChatPrompt
order={order}
robot={robot}
onClickConfirmSent={() => setOpen({ ...open, confirmFiatSent: true })}
onClickUndoConfirmSent={() => setOpen({ ...open, confirmUndoFiatSent: true })}
onClickConfirmReceived={() => setOpen({ ...open, confirmFiatReceived: true })}
onClickConfirmSent={() => {
setOpen({ ...open, confirmFiatSent: true });
}}
onClickUndoConfirmSent={() => {
setOpen({ ...open, confirmUndoFiatSent: true });
}}
onClickConfirmReceived={() => {
setOpen({ ...open, confirmFiatReceived: true });
}}
loadingSent={loadingButtons.fiatSent}
loadingUndoSent={loadingButtons.undoFiatSent}
loadingReceived={loadingButtons.fiatReceived}
onClickDispute={() => setOpen({ ...open, confirmDispute: true })}
onClickDispute={() => {
setOpen({ ...open, confirmDispute: true });
}}
loadingDispute={loadingButtons.openDispute}
baseUrl={baseUrl}
messages={messages}
@ -668,23 +678,31 @@ const TradeBox = ({
<Box>
<WebLNDialog
open={open.webln}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
waitingWebln={waitingWebln}
isBuyer={order.is_buyer}
/>
<ConfirmDisputeDialog
open={open.confirmDispute}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
onAgreeClick={openDispute}
/>
<ConfirmCancelDialog
open={open.confirmCancel}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
onCancelClick={cancel}
/>
<ConfirmCollabCancelDialog
open={open.confirmCollabCancel}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
onCollabCancelClick={cancel}
loading={loadingButtons.cancel}
peerAskedCancel={order.pending_cancel}
@ -693,21 +711,27 @@ const TradeBox = ({
open={open.confirmFiatSent}
order={order}
loadingButton={loadingButtons.fiatSent}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
onConfirmClick={confirmFiatSent}
/>
<ConfirmUndoFiatSentDialog
open={open.confirmUndoFiatSent}
order={order}
loadingButton={loadingButtons.undoFiatSent}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
onConfirmClick={confirmUndoFiatSent}
/>
<ConfirmFiatReceivedDialog
open={open.confirmFiatReceived}
order={order}
loadingButton={loadingButtons.fiatReceived}
onClose={() => setOpen(closeAll)}
onClose={() => {
setOpen(closeAll);
}}
onConfirmClick={confirmFiatReceived}
/>
<CollabCancelAlert order={order} />
@ -745,8 +769,12 @@ const TradeBox = ({
<CancelButton
order={order}
onClickCancel={cancel}
openCancelDialog={() => setOpen({ ...closeAll, confirmCancel: true })}
openCollabCancelDialog={() => setOpen({ ...closeAll, confirmCollabCancel: true })}
openCancelDialog={() => {
setOpen({ ...closeAll, confirmCancel: true });
}}
openCollabCancelDialog={() => {
setOpen({ ...closeAll, confirmCollabCancel: true });
}}
loading={loadingButtons.cancel}
/>
</Grid>

View File

@ -1,4 +1,4 @@
import { Order } from '../../models';
import { type Order } from '../../models';
const stepXofY = function (order: Order): string {
// set y value

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, useContext } from 'react';
import { AppContext, UseAppStoreType } from '../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../contexts/AppContext';
import { useTranslation, Trans } from 'react-i18next';
import { Paper, Alert, AlertTitle, Button, Link } from '@mui/material';
import { getHost } from '../utils';
@ -57,7 +57,12 @@ const UnsafeAlert = (): JSX.Element => {
severity='success'
sx={{ maxHeight: '8em' }}
action={
<Button color='success' onClick={() => setShow(false)}>
<Button
color='success'
onClick={() => {
setShow(false);
}}
>
{t('Hide')}
</Button>
}
@ -80,7 +85,15 @@ const UnsafeAlert = (): JSX.Element => {
<Alert
severity='warning'
sx={{ maxHeight: '7em' }}
action={<Button onClick={() => setShow(false)}>{t('Hide')}</Button>}
action={
<Button
onClick={() => {
setShow(false);
}}
>
{t('Hide')}
</Button>
}
>
<AlertTitle>{t('You are not using RoboSats privately')}</AlertTitle>
<Trans i18nKey='desktop_unsafe_alert'>
@ -120,7 +133,12 @@ const UnsafeAlert = (): JSX.Element => {
<a> site.</a>
</Trans>
<div style={{ display: 'flex', justifyContent: 'center', width: '100%' }}>
<Button className='hideAlertButton' onClick={() => setShow(false)}>
<Button
className='hideAlertButton'
onClick={() => {
setShow(false);
}}
>
{t('Hide')}
</Button>
</div>

View File

@ -1,20 +1,20 @@
import React, { createContext, useEffect, useState } from 'react';
import { Page } from '../basic/NavBar';
import { OpenDialogs } from '../basic/MainDialogs';
import { type Page } from '../basic/NavBar';
import { type OpenDialogs } from '../basic/MainDialogs';
import {
Book,
LimitList,
Maker,
type Book,
type LimitList,
type Maker,
Robot,
Garage,
Info,
type Info,
Settings,
Favorites,
type Favorites,
defaultMaker,
defaultInfo,
Coordinator,
Order,
type Coordinator,
type Order,
} from '../models';
import { apiClient } from '../services/api';
@ -22,7 +22,7 @@ import { checkVer, getHost, hexToBase91, validateTokenEntropy } from '../utils';
import { sha256 } from 'js-sha256';
import defaultCoordinators from '../../static/federation.json';
import { createTheme, Theme } from '@mui/material/styles';
import { createTheme, type Theme } from '@mui/material/styles';
import i18n from '../i18n/Web';
import { systemClient } from '../services/System';
@ -163,7 +163,12 @@ export const useAppStore = () => {
useEffect(() => {
window.addEventListener('torStatus', (event) => {
// Trick to improve UX on Android webview: delay the "Connected to TOR" status by 5 secs to avoid long waits on the first request.
setTimeout(() => setTorStatus(event?.detail), event?.detail === '"Done"' ? 5000 : 0);
setTimeout(
() => {
setTorStatus(event?.detail);
},
event?.detail === '"Done"' ? 5000 : 0,
);
});
}, []);
@ -213,12 +218,12 @@ export const useAppStore = () => {
setBook((book) => {
return { ...book, loading: true };
});
apiClient.get(baseUrl, '/api/book/').then((data: any) =>
apiClient.get(baseUrl, '/api/book/').then((data: any) => {
setBook({
loading: false,
orders: data.not_found ? [] : data,
}),
);
});
});
};
const fetchLimits = async () => {
@ -272,7 +277,9 @@ export const useAppStore = () => {
useEffect(() => {
clearInterval(timer);
setTimer(setInterval(fetchOrder, delay));
return () => clearInterval(timer);
return () => {
clearInterval(timer);
};
}, [delay, currentOrder, page, badOrder]);
const orderReceived = function (data: any) {

View File

@ -1,4 +1,4 @@
import { Robot, Order } from '.';
import { Robot, type Order } from '.';
import { systemClient } from '../services/System';
import { saveAsJson } from '../utils';
export interface Slot {

View File

@ -6,8 +6,6 @@ export interface Limit {
max_bondless_amount: number;
}
export interface LimitList {
[currencyCode: string]: Limit;
}
export type LimitList = Record<string, Limit>;
export default Limit;

View File

@ -1,5 +1,5 @@
import React, { useEffect, useContext, useState } from 'react';
import GridLayout, { Layout } from 'react-grid-layout';
import GridLayout, { type Layout } from 'react-grid-layout';
import { Grid, styled, useTheme } from '@mui/material';
import {
@ -12,7 +12,7 @@ import {
import ToolBar from '../pro/ToolBar';
import LandingDialog from '../pro/LandingDialog';
import { AppContext, UseAppStoreType } from '../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../contexts/AppContext';
// To Do. Add dotted grid when layout is not frozen
// ${freeze ?
@ -83,7 +83,12 @@ const Main = (): JSX.Element => {
<Grid container direction='column' sx={{ width: `${windowSize.width}em` }}>
<Grid item>
<ToolBar height={`${toolbarHeight}em`} settings={settings} setSettings={setSettings} />
<LandingDialog open={openLanding} onClose={() => setOpenLanding(!openLanding)} />
<LandingDialog
open={openLanding}
onClose={() => {
setOpenLanding(!openLanding);
}}
/>
</Grid>
<Grid item>
@ -101,7 +106,9 @@ const Main = (): JSX.Element => {
isResizable={!settings.freezeViewports}
rowHeight={gridCellSize * em} // rows are 2em high
autoSize={true}
onLayoutChange={(layout: Layout) => setLayout(layout)}
onLayoutChange={(layout: Layout) => {
setLayout(layout);
}}
>
<div key='Maker'>
<MakerWidget />

View File

@ -2,7 +2,7 @@ import React from 'react';
import { Paper, Grid, IconButton, Tooltip, Typography } from '@mui/material';
import { Lock, LockOpen } from '@mui/icons-material';
import { useTranslation } from 'react-i18next';
import { Settings } from '../../models';
import { type Settings } from '../../models';
interface ToolBarProps {
settings: Settings;
@ -39,9 +39,9 @@ const ToolBar = ({ height = '3em', settings, setSettings }: ToolBarProps): JSX.E
enterNextDelay={2000}
>
<IconButton
onClick={() =>
setSettings({ ...settings, freezeViewports: !settings.freezeViewports })
}
onClick={() => {
setSettings({ ...settings, freezeViewports: !settings.freezeViewports });
}}
sx={{ position: 'fixed', right: '1em', top: '0em', color: 'text.secondary' }}
>
{settings.freezeViewports ? <Lock color='primary' /> : <LockOpen color='secondary' />}

View File

@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { Book, Favorites } from '../../models';
import { type Book, type Favorites } from '../../models';
import { Paper } from '@mui/material';
import BookTable from '../../components/BookTable';

View File

@ -1,5 +1,5 @@
import React, { useContext } from 'react';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import { Paper, useTheme } from '@mui/material';
import DepthChart from '../../components/Charts/DepthChart';

View File

@ -1,5 +1,5 @@
import React, { useContext } from 'react';
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
import MakerForm from '../../components/MakerForm';
import { LimitList, Maker, Favorites } from '../../models';

View File

@ -1,5 +1,5 @@
import React, { useContext } from 'react';
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
import { type UseAppStoreType, AppContext } from '../../contexts/AppContext';
import { Settings } from '../../models';
import { Paper } from '@mui/material';
import SettingsForm from '../../components/SettingsForm';

View File

@ -1,4 +1,4 @@
import NativeRobosats from './index';
import type NativeRobosats from './index';
declare global {
interface Window {

View File

@ -1,13 +1,17 @@
import { NativeRobosatsPromise, NativeWebViewMessage, NativeWebViewMessageSystem } from './index.d';
import {
type NativeRobosatsPromise,
type NativeWebViewMessage,
type NativeWebViewMessageSystem,
} from './index.d';
class NativeRobosats {
public torDaemonStatus = 'NOTINIT';
private messageCounter: number = 0;
private pendingMessages: { [id: number]: NativeRobosatsPromise } = {};
private pendingMessages: Record<number, NativeRobosatsPromise> = {};
public cookies: { [key: string]: string } = {};
public cookies: Record<string, string> = {};
public loadCookie = (cookie: { key: string; value: string }) => {
this.cookies[cookie.key] = cookie.value;
@ -44,7 +48,7 @@ class NativeRobosats {
}
};
public postMessage: (message: NativeWebViewMessage) => Promise<{ [key: string]: any }> = async (
public postMessage: (message: NativeWebViewMessage) => Promise<Record<string, any>> = async (
message,
) => {
this.messageCounter += 1;

View File

@ -1,4 +1,4 @@
import { SystemClient } from '..';
import { type SystemClient } from '..';
import NativeRobosats from '../../Native';
class SystemNativeClient implements SystemClient {

View File

@ -1,4 +1,4 @@
import { SystemClient } from '..';
import { type SystemClient } from '..';
class SystemWebClient implements SystemClient {
public loading = false;

View File

@ -1,12 +1,14 @@
import ReconnectingWebSocket from 'reconnecting-websocket';
import { WebsocketConnection } from '..';
import { type WebsocketConnection } from '..';
class WebsocketConnectionWeb implements WebsocketConnection {
constructor(path: string) {
this.rws = new ReconnectingWebSocket(path, [], {
WebSocket,
minReconnectionDelay: 15000,
connectionTimeout: 15000,
reconnectionDelayGrowFactor: 1.5,
maxRetries: 15,
reconnectionDelayGrowFactor: 2,
maxRetries: 4,
maxReconnectionDelay: 1000000,
});
}

View File

@ -1,4 +1,4 @@
import { WebsocketClient, WebsocketConnection } from '..';
import { type WebsocketClient, type WebsocketConnection } from '..';
import WebsocketConnectionWeb from '../WebsocketConnectionWeb';
class WebsocketWebClient implements WebsocketClient {

View File

@ -1,16 +1,16 @@
import { ApiClient, Auth } from '..';
import { type ApiClient, type Auth } from '..';
import { systemClient } from '../../System';
class ApiNativeClient implements ApiClient {
private assetsCache: { [path: string]: string } = {};
private assetsPromises: { [path: string]: Promise<string | undefined> } = {};
private assetsCache: Record<string, string> = {};
private assetsPromises: Record<string, Promise<string | undefined>> = {};
private readonly getHeaders: (auth?: Auth) => HeadersInit = (auth) => {
let headers = {
'Content-Type': 'application/json',
};
if (auth) {
if (auth != null) {
headers = {
...headers,
...{
@ -19,7 +19,7 @@ class ApiNativeClient implements ApiClient {
};
}
if (auth?.keys) {
if (auth?.keys != null) {
headers = {
...headers,
...{
@ -31,7 +31,7 @@ class ApiNativeClient implements ApiClient {
return headers;
};
private readonly parseResponse = (response: { [key: string]: any }): object => {
private readonly parseResponse = (response: Record<string, any>): object => {
if (response.headers['set-cookie']) {
response.headers['set-cookie'].forEach((cookie: string) => {
const keySplit: string[] = cookie.split('=');
@ -46,7 +46,9 @@ class ApiNativeClient implements ApiClient {
path,
body,
) => {
return await new Promise((res, _rej) => res({}));
return await new Promise((res, _rej) => {
res({});
});
};
public delete: (baseUrl: string, path: string, auth?: Auth) => Promise<object | undefined> =

View File

@ -1,4 +1,4 @@
import { ApiClient, Auth } from '..';
import { type ApiClient, type Auth } from '..';
import { systemClient } from '../../System';
class ApiWebClient implements ApiClient {
@ -7,7 +7,7 @@ class ApiWebClient implements ApiClient {
'Content-Type': 'application/json',
};
if (auth) {
if (auth != null) {
headers = {
...headers,
...{
@ -17,7 +17,7 @@ class ApiWebClient implements ApiClient {
}
// set cookies before sending the request
if (auth?.keys) {
if (auth?.keys != null) {
systemClient.setCookie('public_key', auth.keys.pubKey);
systemClient.setCookie('encrypted_private_key', auth.keys.encPrivKey);
}

View File

@ -1,4 +1,4 @@
import { PublicOrder, Favorites } from '../models';
import { type PublicOrder, type Favorites } from '../models';
interface AmountFilter {
amount: string;

View File

@ -2,7 +2,7 @@ import { Base91 } from 'base-ex';
export default function hexToBase85(hex: string): string {
const hexes = hex.match(/.{1,2}/g);
if (!hexes) return '';
if (hexes == null) return '';
const byteArray = hexes.map((byte) => parseInt(byte, 16));
const b91 = new Base91();
const base91string = b91.encode(new Uint8Array(byteArray));

View File

@ -1,4 +1,4 @@
import { requestProvider, WeblnProvider } from 'webln';
import { requestProvider, type WeblnProvider } from 'webln';
const getWebln = async (): Promise<WeblnProvider> => {
const resultPromise = new Promise<WeblnProvider>(async (resolve, reject) => {