mirror of
https://github.com/RoboSats/robosats.git
synced 2025-01-19 04:31:35 +00:00
Refactor context (#427)
* Move AppContext to top level * Refactor context
This commit is contained in:
parent
e3b7f1f268
commit
28ef253020
@ -1,9 +1,8 @@
|
||||
import React, { Suspense, useState, useEffect } from 'react';
|
||||
import React, { StrictMode, Suspense } from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import Main from './basic/Main';
|
||||
import { CssBaseline } from '@mui/material';
|
||||
import { AppContextProvider } from './contexts/AppContext';
|
||||
import { ThemeProvider, createTheme, Theme } from '@mui/material/styles';
|
||||
import { CssBaseline, ThemeProvider } from '@mui/material';
|
||||
import { AppContext, useAppStore } from './contexts/AppContext';
|
||||
import UnsafeAlert from './components/UnsafeAlert';
|
||||
import TorConnectionBadge from './components/TorConnection';
|
||||
|
||||
@ -11,53 +10,31 @@ import { I18nextProvider } from 'react-i18next';
|
||||
import i18n from './i18n/Web';
|
||||
|
||||
import { systemClient } from './services/System';
|
||||
import { Settings } from './models';
|
||||
import ErrorBoundary from './components/ErrorBoundary';
|
||||
|
||||
const makeTheme = function (settings: Settings) {
|
||||
const theme: Theme = createTheme({
|
||||
palette: {
|
||||
mode: settings.mode,
|
||||
background: {
|
||||
default: settings.mode === 'dark' ? '#070707' : '#fff',
|
||||
},
|
||||
},
|
||||
typography: { fontSize: settings.fontSize },
|
||||
});
|
||||
|
||||
return theme;
|
||||
};
|
||||
|
||||
const App = (): JSX.Element => {
|
||||
const [theme, setTheme] = useState<Theme>(makeTheme(new Settings()));
|
||||
const [settings, setSettings] = useState<Settings>(new Settings());
|
||||
|
||||
useEffect(() => {
|
||||
setTheme(makeTheme(settings));
|
||||
}, [settings.fontSize, settings.mode]);
|
||||
|
||||
useEffect(() => {
|
||||
i18n.changeLanguage(settings.language);
|
||||
}, []);
|
||||
|
||||
const store = useAppStore();
|
||||
return (
|
||||
<StrictMode>
|
||||
<ErrorBoundary>
|
||||
<Suspense fallback='loading language'>
|
||||
<Suspense fallback='loading'>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<AppContextProvider settings={settings} setSettings={setSettings}>
|
||||
<AppContext.Provider value={store}>
|
||||
<ThemeProvider theme={store.theme}>
|
||||
<CssBaseline />
|
||||
{window.NativeRobosats === undefined ? <UnsafeAlert /> : <TorConnectionBadge />}
|
||||
<Main />
|
||||
</AppContextProvider>
|
||||
</ThemeProvider>
|
||||
</AppContext.Provider>
|
||||
</I18nextProvider>
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</StrictMode>
|
||||
);
|
||||
};
|
||||
|
||||
const loadApp = () => {
|
||||
// waits until the environment is ready for the Android WebView app
|
||||
if (systemClient.loading) {
|
||||
setTimeout(loadApp, 200);
|
||||
} else {
|
||||
|
@ -10,7 +10,7 @@ import BookTable from '../../components/BookTable';
|
||||
|
||||
// Icons
|
||||
import { BarChart, FormatListBulleted } from '@mui/icons-material';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
const BookPage = (): JSX.Element => {
|
||||
const {
|
||||
@ -24,7 +24,7 @@ const BookPage = (): JSX.Element => {
|
||||
book,
|
||||
setDelay,
|
||||
setOrder,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [view, setView] = useState<'list' | 'depth'>('list');
|
||||
|
@ -14,7 +14,7 @@ import RobotAvatar from '../components/RobotAvatar';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Notifications from '../components/Notifications';
|
||||
import { AppContextProps, AppContext } from '../contexts/AppContext';
|
||||
import { UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';
|
||||
|
||||
const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter;
|
||||
|
||||
@ -29,11 +29,10 @@ const Main = (): JSX.Element => {
|
||||
page,
|
||||
setPage,
|
||||
slideDirection,
|
||||
closeAll,
|
||||
setOpen,
|
||||
windowSize,
|
||||
navbarHeight,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
|
||||
return (
|
||||
<Router>
|
||||
@ -41,7 +40,11 @@ const Main = (): JSX.Element => {
|
||||
style={{ display: 'none' }}
|
||||
nickname={robot.nickname}
|
||||
baseUrl={baseUrl}
|
||||
onLoad={() => setRobot({ ...robot, avatarLoaded: true })}
|
||||
onLoad={() =>
|
||||
setRobot((robot) => {
|
||||
return { ...robot, avatarLoaded: true };
|
||||
})
|
||||
}
|
||||
/>
|
||||
<Notifications
|
||||
order={order}
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
UpdateClientDialog,
|
||||
} from '../../components/Dialogs';
|
||||
import { pn } from '../../utils';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType, closeAll } from '../../contexts/AppContext';
|
||||
|
||||
export interface OpenDialogs {
|
||||
more: boolean;
|
||||
@ -23,18 +23,8 @@ export interface OpenDialogs {
|
||||
}
|
||||
|
||||
const MainDialogs = (): JSX.Element => {
|
||||
const {
|
||||
open,
|
||||
setOpen,
|
||||
info,
|
||||
limits,
|
||||
closeAll,
|
||||
robot,
|
||||
setRobot,
|
||||
setPage,
|
||||
setCurrentOrder,
|
||||
baseUrl,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
const { open, setOpen, info, limits, robot, setRobot, setPage, setCurrentOrder, baseUrl } =
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
|
||||
const [maxAmount, setMaxAmount] = useState<string>('...loading...');
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { filterOrders } from '../../utils';
|
||||
import MakerForm from '../../components/MakerForm';
|
||||
import BookTable from '../../components/BookTable';
|
||||
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
import { NoRobotDialog } from '../../components/Dialogs';
|
||||
|
||||
const MakerPage = (): JSX.Element => {
|
||||
@ -24,7 +24,7 @@ const MakerPage = (): JSX.Element => {
|
||||
setPage,
|
||||
setOrder,
|
||||
setDelay,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
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 { closeAll } from '../../contexts/AppContext';
|
||||
import { OpenDialogs } from '../MainDialogs';
|
||||
|
||||
import { BubbleChart, Info, People, PriceChange, School } from '@mui/icons-material';
|
||||
@ -22,11 +22,10 @@ const StyledTooltip = styled(({ className, ...props }: TooltipProps) => (
|
||||
interface MoreTooltipProps {
|
||||
open: OpenDialogs;
|
||||
setOpen: (state: OpenDialogs) => void;
|
||||
closeAll: OpenDialogs;
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
const MoreTooltip = ({ open, setOpen, closeAll, children }: MoreTooltipProps): JSX.Element => {
|
||||
const MoreTooltip = ({ open, setOpen, children }: MoreTooltipProps): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
return (
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
MoreHoriz,
|
||||
} from '@mui/icons-material';
|
||||
import RobotAvatar from '../../components/RobotAvatar';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType, closeAll } from '../../contexts/AppContext';
|
||||
|
||||
interface NavBarProps {
|
||||
width: number;
|
||||
@ -31,10 +31,9 @@ const NavBar = ({ width, height }: NavBarProps): JSX.Element => {
|
||||
setSlideDirection,
|
||||
open,
|
||||
setOpen,
|
||||
closeAll,
|
||||
currentOrder,
|
||||
baseUrl,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
@ -7,7 +7,7 @@ import TradeBox from '../../components/TradeBox';
|
||||
import OrderDetails from '../../components/OrderDetails';
|
||||
|
||||
import { apiClient } from '../../services/api';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
const OrderPage = (): JSX.Element => {
|
||||
const {
|
||||
@ -23,7 +23,7 @@ const OrderPage = (): JSX.Element => {
|
||||
setPage,
|
||||
baseUrl,
|
||||
navbarHeight,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
|
@ -18,7 +18,7 @@ import RobotAvatar from '../../components/RobotAvatar';
|
||||
import TokenInput from './TokenInput';
|
||||
import { Page } from '../NavBar';
|
||||
import { Slot, Robot } from '../../models';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
import { genBase62Token } from '../../utils';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
|
||||
@ -53,7 +53,7 @@ const RobotProfile = ({
|
||||
width,
|
||||
}: RobotProfileProps): JSX.Element => {
|
||||
const { currentSlot, garage, setCurrentSlot, windowSize } =
|
||||
useContext<AppContextProps>(AppContext);
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
|
@ -8,7 +8,6 @@ import { systemClient } from '../../services/System';
|
||||
interface TokenInputProps {
|
||||
robot: Robot;
|
||||
editable?: boolean;
|
||||
showDownload?: boolean;
|
||||
fullWidth?: boolean;
|
||||
loading?: boolean;
|
||||
setRobot: (state: Robot) => void;
|
||||
@ -42,16 +41,6 @@ const TokenInput = ({
|
||||
setShowCopied(false);
|
||||
}, [inputToken]);
|
||||
|
||||
const createJsonFile = () => {
|
||||
return {
|
||||
token: robot.token,
|
||||
token_shannon_entropy: robot.shannonEntropy,
|
||||
token_bit_entropy: robot.bitsEntropy,
|
||||
public_key: robot.pubKey,
|
||||
encrypted_private_key: robot.encPrivKey,
|
||||
};
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <LinearProgress sx={{ height: '0.8em' }} />;
|
||||
} else {
|
||||
@ -84,7 +73,9 @@ const TokenInput = ({
|
||||
systemClient.copyToClipboard(inputToken);
|
||||
setShowCopied(true);
|
||||
setTimeout(() => setShowCopied(false), 1000);
|
||||
setRobot({ ...robot, copiedToken: true });
|
||||
setRobot((robot) => {
|
||||
return { ...robot, copiedToken: true };
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ContentCopy sx={{ width: '1em', height: '1em' }} />
|
||||
|
@ -13,18 +13,17 @@ import {
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { Robot } from '../../models';
|
||||
import { apiClient } from '../../services/api';
|
||||
import Onboarding from './Onboarding';
|
||||
import Welcome from './Welcome';
|
||||
import RobotProfile from './RobotProfile';
|
||||
import Recovery from './Recovery';
|
||||
import { TorIcon } from '../../components/Icons';
|
||||
import { genKey } from '../../pgp';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
const RobotPage = (): JSX.Element => {
|
||||
const { robot, setRobot, setPage, setCurrentOrder, fetchRobot, torStatus, windowSize, baseUrl } =
|
||||
useContext<AppContextProps>(AppContext);
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const params = useParams();
|
||||
const refCode = params.refCode;
|
||||
@ -138,7 +137,7 @@ const RobotPage = (): JSX.Element => {
|
||||
<Onboarding
|
||||
setView={setView}
|
||||
robot={robot}
|
||||
setRobot={() => null}
|
||||
setRobot={setRobot}
|
||||
badRequest={badRequest}
|
||||
inputToken={inputToken}
|
||||
setInputToken={setInputToken}
|
||||
@ -152,7 +151,7 @@ const RobotPage = (): JSX.Element => {
|
||||
<RobotProfile
|
||||
setView={setView}
|
||||
robot={robot}
|
||||
setRobot={() => null}
|
||||
setRobot={setRobot}
|
||||
setCurrentOrder={setCurrentOrder}
|
||||
badRequest={badRequest}
|
||||
getGenerateRobot={getGenerateRobot}
|
||||
@ -170,7 +169,7 @@ const RobotPage = (): JSX.Element => {
|
||||
<Recovery
|
||||
setView={setView}
|
||||
robot={robot}
|
||||
setRobot={() => null}
|
||||
setRobot={setRobot}
|
||||
badRequest={badRequest}
|
||||
inputToken={inputToken}
|
||||
setInputToken={setInputToken}
|
||||
|
@ -1,13 +1,10 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Grid, Paper, useTheme } from '@mui/material';
|
||||
import { Grid, Paper } from '@mui/material';
|
||||
import SettingsForm from '../../components/SettingsForm';
|
||||
import { AppContextProps, AppContext } from '../../contexts/AppContext';
|
||||
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
|
||||
|
||||
const SettingsPage = (): JSX.Element => {
|
||||
const { windowSize, navbarHeight } = useContext<AppContextProps>(AppContext);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const { windowSize, navbarHeight } = useContext<UseAppStoreType>(AppContext);
|
||||
const maxHeight = (windowSize.height - navbarHeight) * 0.85 - 3;
|
||||
|
||||
return (
|
||||
|
@ -32,7 +32,7 @@ import RobotAvatar from '../RobotAvatar';
|
||||
|
||||
// Icons
|
||||
import { Fullscreen, FullscreenExit, Refresh } from '@mui/icons-material';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
interface BookTableProps {
|
||||
orderList?: PublicOrder[];
|
||||
@ -63,7 +63,7 @@ const BookTable = ({
|
||||
showNoResults = true,
|
||||
onOrderClicked = () => null,
|
||||
}: BookTableProps): JSX.Element => {
|
||||
const { book, fetchBook, fav, setFav, baseUrl } = useContext<AppContextProps>(AppContext);
|
||||
const { book, fetchBook, fav, setFav, baseUrl } = useContext<UseAppStoreType>(AppContext);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
@ -26,7 +26,7 @@ import { amountToString, matchMedian, statusBadgeColor } from '../../../utils';
|
||||
import currencyDict from '../../../../static/assets/currencies.json';
|
||||
import { PaymentStringAsIcons } from '../../PaymentMethods';
|
||||
import getNivoScheme from '../NivoScheme';
|
||||
import { AppContextProps, AppContext } from '../../../contexts/AppContext';
|
||||
import { UseAppStoreType, AppContext } from '../../../contexts/AppContext';
|
||||
|
||||
interface DepthChartProps {
|
||||
maxWidth: number;
|
||||
@ -43,7 +43,7 @@ const DepthChart: React.FC<DepthChartProps> = ({
|
||||
elevation = 6,
|
||||
onOrderClicked = () => null,
|
||||
}) => {
|
||||
const { book, fav, info, limits, baseUrl } = useContext<AppContextProps>(AppContext);
|
||||
const { book, fav, info, limits, baseUrl } = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const [enrichedOrders, setEnrichedOrders] = useState<Order[]>([]);
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
Button,
|
||||
} from '@mui/material';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
@ -17,7 +17,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const NoRobotDialog = ({ open, onClose }: Props): JSX.Element => {
|
||||
const { setPage } = useContext<AppContextProps>(AppContext);
|
||||
const { setPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { systemClient } from '../../services/System';
|
||||
import ContentCopy from '@mui/icons-material/ContentCopy';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
@ -24,7 +24,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const StoreTokenDialog = ({ open, onClose, onClickBack, onClickDone }: Props): JSX.Element => {
|
||||
const { robot } = useContext<AppContextProps>(AppContext);
|
||||
const { robot } = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
|
@ -12,6 +12,8 @@ interface ErrorBoundaryState {
|
||||
}
|
||||
|
||||
export default class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
||||
// In case the app crashes this component will restart it in 10 seconds
|
||||
// It will also print an obnoxious error message (useful for end users to grab a screenshot and report)
|
||||
constructor(props: ErrorBoundaryProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -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, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
interface MakerFormProps {
|
||||
disableRequest?: boolean;
|
||||
@ -64,7 +64,7 @@ const MakerForm = ({
|
||||
hasRobot = true,
|
||||
}: MakerFormProps): JSX.Element => {
|
||||
const { fav, setFav, limits, fetchLimits, info, maker, setMaker, setPage, baseUrl } =
|
||||
useContext<AppContextProps>(AppContext);
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
|
@ -22,7 +22,6 @@ import { apiClient } from '../../services/api';
|
||||
|
||||
import { Order } from '../../models';
|
||||
import { ConfirmationDialog } from '../Dialogs';
|
||||
import { Page } from '../../basic/NavBar';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
|
||||
interface TakeButtonProps {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AppContextProps, AppContext } from '../../contexts/AppContext';
|
||||
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
|
||||
import {
|
||||
Grid,
|
||||
Paper,
|
||||
@ -35,7 +35,7 @@ interface SettingsFormProps {
|
||||
}
|
||||
|
||||
const SettingsForm = ({ dense = false, showNetwork = false }: SettingsFormProps): JSX.Element => {
|
||||
const { fav, setFav, settings, setSettings } = useContext<AppContextProps>(AppContext);
|
||||
const { fav, setFav, settings, setSettings } = useContext<UseAppStoreType>(AppContext);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const fontSizes = [
|
||||
|
@ -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, AppContextProps } from '../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../contexts/AppContext';
|
||||
|
||||
interface TorIndicatorProps {
|
||||
color: 'inherit' | 'error' | 'warning' | 'success' | 'primary' | 'secondary' | 'info' | undefined;
|
||||
@ -55,7 +55,7 @@ const TorIndicator = ({
|
||||
};
|
||||
|
||||
const TorConnectionBadge = (): JSX.Element => {
|
||||
const { torStatus } = useContext<AppContextProps>(AppContext);
|
||||
const { torStatus } = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (window?.NativeRobosats == null) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import { AppContext, AppContextProps } from '../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } 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 { windowSize } = useContext<AppContextProps>(AppContext);
|
||||
const { windowSize } = useContext<UseAppStoreType>(AppContext);
|
||||
const { t } = useTranslation();
|
||||
const [show, setShow] = useState<boolean>(true);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { createContext, useEffect, useState } from 'react';
|
||||
import { Page } from '../basic/NavBar';
|
||||
import { OpenDialogs } from '../basic/MainDialogs';
|
||||
|
||||
@ -23,7 +23,8 @@ import { checkVer, getHost, tokenStrength } from '../utils';
|
||||
import { sha256 } from 'js-sha256';
|
||||
|
||||
import defaultCoordinators from '../../static/federation.json';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { createTheme, Theme } from '@mui/material/styles';
|
||||
import i18n from '../i18n/Web';
|
||||
|
||||
const getWindowSize = function (fontSize: number) {
|
||||
// returns window size in EM units
|
||||
@ -72,61 +73,10 @@ export interface fetchRobotProps {
|
||||
|
||||
export type TorStatus = 'NOTINIT' | 'STARTING' | '"Done"' | 'DONE';
|
||||
|
||||
export interface AppContextProps {
|
||||
torStatus: TorStatus;
|
||||
federation: Coordinator[];
|
||||
setFederation: (state: Coordinator[]) => void;
|
||||
settings: Settings;
|
||||
setSettings: (state: Settings) => void;
|
||||
book: Book;
|
||||
info: Info;
|
||||
garage: Garage;
|
||||
setGarage: (state: Garage) => void;
|
||||
currentSlot: number;
|
||||
setCurrentSlot: (state: number) => void;
|
||||
setBook: (state: Book) => void;
|
||||
fetchBook: () => void;
|
||||
limits: { list: LimitList; loading: boolean };
|
||||
setLimits: (state: { list: LimitList; loading: boolean }) => void;
|
||||
fetchLimits: () => void;
|
||||
maker: Maker;
|
||||
setMaker: (state: Maker) => void;
|
||||
clearOrder: () => void;
|
||||
robot: Robot;
|
||||
setRobot: (state: Robot) => void;
|
||||
focusedCoordinator: number;
|
||||
setFocusedCoordinator: (state: number) => void;
|
||||
baseUrl: string;
|
||||
setBaseUrl: (state: string) => void;
|
||||
fav: Favorites;
|
||||
setFav: (state: Favorites) => void;
|
||||
order: Order | undefined;
|
||||
setOrder: (state: Order | undefined) => void;
|
||||
badOrder: string;
|
||||
setBadOrder: (state: string | undefined) => void;
|
||||
setDelay: (state: number) => void;
|
||||
page: Page;
|
||||
setPage: (state: Page) => void;
|
||||
slideDirection: SlideDirection;
|
||||
setSlideDirection: (state: SlideDirection) => void;
|
||||
currentOrder: number | undefined;
|
||||
setCurrentOrder: (state: number) => void;
|
||||
navbarHeight: number;
|
||||
closeAll: OpenDialogs;
|
||||
open: OpenDialogs;
|
||||
setOpen: (state: OpenDialogs) => void;
|
||||
windowSize: { width: number; height: number };
|
||||
clientVersion: {
|
||||
semver: Version;
|
||||
short: string;
|
||||
long: string;
|
||||
};
|
||||
}
|
||||
|
||||
const entryPage: Page | '' =
|
||||
window.NativeRobosats === undefined ? window.location.pathname.split('/')[1] : '';
|
||||
|
||||
const closeAll = {
|
||||
export const closeAll = {
|
||||
more: false,
|
||||
learn: false,
|
||||
community: false,
|
||||
@ -138,66 +88,40 @@ const closeAll = {
|
||||
profile: false,
|
||||
};
|
||||
|
||||
// export const initialState = {
|
||||
// federation: defaultFederation,
|
||||
// setFederation: () => null,
|
||||
// settings: new Settings(),
|
||||
// setSettings: () => null,
|
||||
// book: { orders: [], loading: true },
|
||||
// setBook: () => null,
|
||||
// fetchBook: () => null,
|
||||
// limits: {
|
||||
// list: [],
|
||||
// loading: true,
|
||||
// },
|
||||
// setLimits:() => null,
|
||||
// fetchLimits: ()=> null,
|
||||
// maker: defaultMaker,
|
||||
// setMaker: () => null,
|
||||
// clearOrder: () => null,
|
||||
// robot: new Robot(),
|
||||
// setRobot: () => null,
|
||||
// info: defaultExchange,
|
||||
// setExchange: () => null,
|
||||
// focusedCoordinator: 0,
|
||||
// setFocusedCoordinator: () => null,
|
||||
// baseUrl: '',
|
||||
// setBaseUrl: () => null,
|
||||
// fav: { type: null, currency: 0 },
|
||||
// setFav: () => null,
|
||||
// order: undefined,
|
||||
// setOrder: () => null,
|
||||
// badOrder: '',
|
||||
// setBadOrder: () => null,
|
||||
// setDelay: () => null,
|
||||
// page: entryPage == '' ? 'robot' : entryPage,
|
||||
// setPage: () => null,
|
||||
// slideDirection: {
|
||||
// in: undefined,
|
||||
// out: undefined,
|
||||
// },
|
||||
// setSlideDirection: () => null,
|
||||
// currentOrder: undefined,
|
||||
// setCurrentOrder: () => null,
|
||||
// navbarHeight: 2.5,
|
||||
// closeAll,
|
||||
// open: closeAll,
|
||||
// setOpen: () => null,
|
||||
// windowSize: getWindowSize(14),
|
||||
// }
|
||||
const makeTheme = function (settings: Settings) {
|
||||
const theme: Theme = createTheme({
|
||||
palette: {
|
||||
mode: settings.mode,
|
||||
background: {
|
||||
default: settings.mode === 'dark' ? '#070707' : '#fff',
|
||||
},
|
||||
},
|
||||
typography: { fontSize: settings.fontSize },
|
||||
});
|
||||
|
||||
export interface AppContextProviderProps {
|
||||
children: React.ReactNode;
|
||||
settings: Settings;
|
||||
setSettings: (state: Settings) => void;
|
||||
}
|
||||
return theme;
|
||||
};
|
||||
|
||||
export const AppContextProvider = ({
|
||||
children,
|
||||
settings,
|
||||
setSettings,
|
||||
}: AppContextProviderProps): JSX.Element => {
|
||||
const theme = useTheme();
|
||||
const initialSettings = new Settings();
|
||||
const initialTheme = makeTheme(initialSettings);
|
||||
const initialGarage = new Garage();
|
||||
const initialSlot = initialGarage.slots.length - 1;
|
||||
const initialRobot = new Robot(initialGarage.slots[initialSlot].robot);
|
||||
|
||||
export const useAppStore = () => {
|
||||
// State provided right at the top level of the app. A chaotic bucket of everything.
|
||||
// Contains app-wide state and functions. Triggers re-renders on the full tree often.
|
||||
|
||||
const [theme, setTheme] = useState<Theme>(initialTheme);
|
||||
const [settings, setSettings] = useState<Settings>(initialSettings);
|
||||
|
||||
useEffect(() => {
|
||||
setTheme(makeTheme(settings));
|
||||
}, [settings.fontSize, settings.mode]);
|
||||
|
||||
useEffect(() => {
|
||||
i18n.changeLanguage(settings.language);
|
||||
}, []);
|
||||
|
||||
// All app data structured
|
||||
const [torStatus, setTorStatus] = useState<TorStatus>('NOTINIT');
|
||||
@ -206,13 +130,9 @@ export const AppContextProvider = ({
|
||||
list: [],
|
||||
loading: true,
|
||||
});
|
||||
const [garage, setGarage] = useState<Garage>(() => {
|
||||
const initialState = { setGarage };
|
||||
const newGarage = new Garage(initialState);
|
||||
return newGarage;
|
||||
});
|
||||
const [currentSlot, setCurrentSlot] = useState<number>(garage.slots.length - 1);
|
||||
const [robot, setRobot] = useState<Robot>(new Robot(garage.slots[currentSlot].robot));
|
||||
const [garage, setGarage] = useState<Garage>(initialGarage);
|
||||
const [currentSlot, setCurrentSlot] = useState<number>(initialSlot);
|
||||
const [robot, setRobot] = useState<Robot>(initialRobot);
|
||||
const [maker, setMaker] = useState<Maker>(defaultMaker);
|
||||
const [info, setInfo] = useState<Info>(defaultInfo);
|
||||
const [coordinators, setCoordinators] = useState<Coordinator[]>(defaultCoordinators);
|
||||
@ -224,8 +144,6 @@ export const AppContextProvider = ({
|
||||
const [order, setOrder] = useState<Order | undefined>(undefined);
|
||||
const [badOrder, setBadOrder] = useState<string | undefined>(undefined);
|
||||
|
||||
const entryPage: Page | '' =
|
||||
window.NativeRobosats === undefined ? window.location.pathname.split('/')[1] : '';
|
||||
const [page, setPage] = useState<Page>(entryPage == '' ? 'robot' : entryPage);
|
||||
const [slideDirection, setSlideDirection] = useState<SlideDirection>({
|
||||
in: undefined,
|
||||
@ -234,16 +152,6 @@ export const AppContextProvider = ({
|
||||
const [currentOrder, setCurrentOrder] = useState<number | undefined>(undefined);
|
||||
|
||||
const navbarHeight = 2.5;
|
||||
const closeAll = {
|
||||
more: false,
|
||||
learn: false,
|
||||
community: false,
|
||||
info: false,
|
||||
coordinator: false,
|
||||
stats: false,
|
||||
update: false,
|
||||
profile: false,
|
||||
};
|
||||
const [open, setOpen] = useState<OpenDialogs>(closeAll);
|
||||
|
||||
const [windowSize, setWindowSize] = useState<{ width: number; height: number }>(
|
||||
@ -252,7 +160,7 @@ export const AppContextProvider = ({
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('torStatus', (event) => {
|
||||
// UX improv: delay the "Conencted" status by 10 secs to avoid long waits for first requests
|
||||
// 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);
|
||||
});
|
||||
}, []);
|
||||
@ -486,9 +394,8 @@ export const AppContextProvider = ({
|
||||
}
|
||||
}, [open.profile, baseUrl]);
|
||||
|
||||
return (
|
||||
<AppContext.Provider
|
||||
value={{
|
||||
return {
|
||||
theme,
|
||||
torStatus,
|
||||
settings,
|
||||
setSettings,
|
||||
@ -525,15 +432,12 @@ export const AppContextProvider = ({
|
||||
currentOrder,
|
||||
setCurrentOrder,
|
||||
navbarHeight,
|
||||
closeAll,
|
||||
open,
|
||||
setOpen,
|
||||
windowSize,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
export const AppContext = React.createContext();
|
||||
export type UseAppStoreType = ReturnType<typeof useAppStore>;
|
||||
|
||||
export const AppContext = createContext<UseAppStoreType | null>(null);
|
@ -10,22 +10,19 @@ const emptySlot: Slot = { robot: new Robot(), order: null };
|
||||
|
||||
class Garage {
|
||||
constructor(initialState?: Garage) {
|
||||
const slotsDump: string | undefined = systemClient.getItem('garage');
|
||||
const slotsDump: string = systemClient.getItem('garage');
|
||||
if (initialState?.slots === undefined && slotsDump != '') {
|
||||
this.slots = JSON.parse(slotsDump);
|
||||
console.log('Robot Garage was loaded from local storage');
|
||||
} else {
|
||||
this.slots = [emptySlot];
|
||||
}
|
||||
this.setGarage = initialState?.setGarage ?? (() => {});
|
||||
}
|
||||
|
||||
slots: Slot[] = [emptySlot];
|
||||
setGarage: (state: Garage) => void = () => {};
|
||||
|
||||
save = () => {
|
||||
systemClient.setItem('garage', JSON.stringify(this.slots));
|
||||
this.setGarage(new Garage(this));
|
||||
};
|
||||
|
||||
delete = () => {
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
import ToolBar from '../pro/ToolBar';
|
||||
import LandingDialog from '../pro/LandingDialog';
|
||||
|
||||
import { AppContext, AppContextProps } from '../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../contexts/AppContext';
|
||||
|
||||
// To Do. Add dotted grid when layout is not frozen
|
||||
// ${freeze ?
|
||||
@ -71,7 +71,7 @@ const Main = (): JSX.Element => {
|
||||
windowSize,
|
||||
badOrder,
|
||||
setBadOrder,
|
||||
} = useContext<AppContextProps>(AppContext);
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
|
||||
const theme = useTheme();
|
||||
const em: number = theme.typography.fontSize;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
import { Book, Favorites } from '../../models';
|
||||
import { Paper } from '@mui/material';
|
||||
@ -34,7 +34,7 @@ const BookWidget = React.forwardRef(
|
||||
}: BookWidgetProps,
|
||||
ref,
|
||||
) => {
|
||||
const { book, windowSize, fav } = useContext<AppContextProps>(AppContext);
|
||||
const { book, windowSize, fav } = useContext<UseAppStoreType>(AppContext);
|
||||
return React.useMemo(() => {
|
||||
return (
|
||||
<Paper elevation={3} style={{ width: '100%', height: '100%' }}>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
import { Paper, useTheme } from '@mui/material';
|
||||
import DepthChart from '../../components/Charts/DepthChart';
|
||||
|
||||
@ -27,7 +27,7 @@ const DepthChartWidget = React.forwardRef(
|
||||
ref,
|
||||
) => {
|
||||
const theme = useTheme();
|
||||
const { fav, book, limits } = useContext<AppContextProps>(AppContext);
|
||||
const { fav, book, limits } = useContext<UseAppStoreType>(AppContext);
|
||||
return React.useMemo(() => {
|
||||
return (
|
||||
<Paper elevation={3} style={{ width: '100%', height: '100%' }}>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { AppContext, AppContextProps } from '../../contexts/AppContext';
|
||||
import { AppContext, UseAppStoreType } from '../../contexts/AppContext';
|
||||
|
||||
import MakerForm from '../../components/MakerForm';
|
||||
import { LimitList, Maker, Favorites } from '../../models';
|
||||
@ -15,7 +15,7 @@ interface MakerWidgetProps {
|
||||
|
||||
const MakerWidget = React.forwardRef(
|
||||
({ style, className, onMouseDown, onMouseUp, onTouchEnd }: MakerWidgetProps, ref) => {
|
||||
const { maker, fav, limits } = useContext<AppContextProps>(AppContext);
|
||||
const { maker, fav, limits } = useContext<UseAppStoreType>(AppContext);
|
||||
return React.useMemo(() => {
|
||||
return (
|
||||
<Paper
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { AppContextProps, AppContext } from '../../contexts/AppContext';
|
||||
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
|
||||
import { Settings } from '../../models';
|
||||
import { Paper } from '@mui/material';
|
||||
import SettingsForm from '../../components/SettingsForm';
|
||||
@ -14,7 +14,7 @@ interface SettingsWidgetProps {
|
||||
|
||||
const SettingsWidget = React.forwardRef(
|
||||
({ style, className, onMouseDown, onMouseUp, onTouchEnd }: SettingsWidgetProps, ref) => {
|
||||
const { settings } = useContext<AppContextProps>(AppContext);
|
||||
const { settings } = useContext<UseAppStoreType>(AppContext);
|
||||
return React.useMemo(() => {
|
||||
return (
|
||||
<Paper
|
||||
|
Loading…
Reference in New Issue
Block a user