Skip to content

Commit 7181deb

Browse files
Refactor contexts and models (#921)
* Add SVG icons for map pins * Add federation basis and new coordinator form (#793) * Add new coordinator entry issue form * Add Federation basis * Fix eslint errors from F2F and fix languages * Redo eslint @typescript-eslint/strict-boolean-expressions * Robot Page working * Contexts Working * Garage Working * CurrentOrder working * Federation model working --------- Co-authored-by: Reckless_Satoshi <reckless.satoshi@protonmail.com> Co-authored-by: Reckless_Satoshi <90936742+Reckless-Satoshi@users.noreply.github.com>
1 parent 260c4ce commit 7181deb

File tree

195 files changed

+9406
-4973
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+9406
-4973
lines changed

.github/workflows/js-linter.yml

+3-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
- main
99
paths:
1010
- frontend
11-
pull_request:
11+
pull_request_target:
1212
branches:
1313
- main
1414
paths:
@@ -41,7 +41,5 @@ jobs:
4141
with:
4242
prettier: true
4343
prettier_dir: frontend
44-
45-
## Disabled due to error
46-
# eslint: true
47-
# eslint_dir: frontend
44+
eslint: true
45+
eslint_dir: frontend

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ services:
6161
volumes:
6262
- ./nodeapp/:/usr/src/robosats/
6363
- ./nodeapp/nginx.conf:/etc/nginx/nginx.conf
64+
- ./nodeapp/coordinators/:/etc/nginx/conf.d/
6465
- ./frontend/static:/usr/src/robosats/static
6566

6667
clean-orders:

federation.md

+6
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,15 @@ Each RoboSats coordinator has a profile in the RoboSats app. The profile contain
9292
- Large Limits - Can host orders with large limits.
9393
- DevFund donator - Donates to the DevFund the default amount or more.
9494

95+
<<<<<<< HEAD
9596
Some of these badges can be objectively measured and awarded. Other badges rely on the subjectivity of the development team. These will be generously awarded and only taken away after a warning.
9697

9798
We also envision more badges in the future, for example milestones by number of trades coordinated (200, 1K, 5K, 25K, 100K, etc).
99+
=======
100+
Some of these badges can be objectively measured and therefore awarded. Others badges rely on the subjectivity by the development team. These will be generously awarded and only taken away after a warning.
101+
102+
We also envision more badges in the future. For example milestones of number of trades coordinated (200, 1K, 5K, 25K, 100K, etc).
103+
>>>>>>> 2254fa60 (Add federation basis and new coordinator form (#793))
98104
99105
## Timeline
100106

frontend/.eslintrc.json

+11-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,21 @@
1919
"sourceType": "module",
2020
"project": "./tsconfig.json"
2121
},
22+
"ignorePatterns": ["index.js", "**/PaymentMethods/Icons/code/code.js"],
2223
"plugins": ["react", "react-hooks", "@typescript-eslint", "prettier"],
2324
"rules": {
2425
"react-hooks/rules-of-hooks": "error",
25-
"react-hooks/exhaustive-deps": "warn",
26+
"react-hooks/exhaustive-deps": "off",
2627
"react/prop-types": "off",
27-
"react/react-in-jsx-scope": "off"
28+
"react/react-in-jsx-scope": "off",
29+
"@typescript-eslint/naming-convention": [
30+
"error",
31+
{
32+
"selector": "variableLike",
33+
"format": ["camelCase", "snake_case", "PascalCase", "UPPER_CASE"],
34+
"leadingUnderscore": "allow"
35+
}
36+
]
2837
},
2938
"settings": {
3039
"import/resolver": {

frontend/src/App.tsx

+18-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { StrictMode, Suspense } from 'react';
1+
import React, { StrictMode, Suspense, useState } from 'react';
22
import ReactDOM from 'react-dom/client';
33
import Main from './basic/Main';
44
import { CssBaseline, ThemeProvider } from '@mui/material';
@@ -11,20 +11,29 @@ import i18n from './i18n/Web';
1111

1212
import { systemClient } from './services/System';
1313
import ErrorBoundary from './components/ErrorBoundary';
14+
import { GarageContext, useGarageStore } from './contexts/GarageContext';
15+
import { FederationContext, useFederationStore } from './contexts/FederationContext';
1416

1517
const App = (): JSX.Element => {
16-
const store = useAppStore();
18+
const appStore = useAppStore();
19+
const garageStore = useGarageStore();
20+
const federationStore = useFederationStore();
21+
1722
return (
1823
<StrictMode>
1924
<ErrorBoundary>
2025
<Suspense fallback='loading'>
2126
<I18nextProvider i18n={i18n}>
22-
<AppContext.Provider value={store}>
23-
<ThemeProvider theme={store.theme}>
24-
<CssBaseline />
25-
{window.NativeRobosats === undefined ? <HostAlert /> : <TorConnectionBadge />}
26-
<Main />
27-
</ThemeProvider>
27+
<AppContext.Provider value={appStore}>
28+
<GarageContext.Provider value={garageStore}>
29+
<FederationContext.Provider value={federationStore}>
30+
<ThemeProvider theme={appStore.theme}>
31+
<CssBaseline />
32+
{window.NativeRobosats === undefined ? <HostAlert /> : <TorConnectionBadge />}
33+
<Main />
34+
</ThemeProvider>
35+
</FederationContext.Provider>
36+
</GarageContext.Provider>
2837
</AppContext.Provider>
2938
</I18nextProvider>
3039
</Suspense>
@@ -33,7 +42,7 @@ const App = (): JSX.Element => {
3342
);
3443
};
3544

36-
const loadApp = () => {
45+
const loadApp = (): void => {
3746
// waits until the environment is ready for the Android WebView app
3847
if (systemClient.loading) {
3948
setTimeout(loadApp, 200);

frontend/src/basic/BookPage/index.tsx

+33-22
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ import BookTable from '../../components/BookTable';
1212
import { BarChart, FormatListBulleted, Map } from '@mui/icons-material';
1313
import { AppContext, type UseAppStoreType } from '../../contexts/AppContext';
1414
import MapChart from '../../components/Charts/MapChart';
15+
import { FederationContext, UseFederationStoreType } from '../../contexts/FederationContext';
16+
import { GarageContext, UseGarageStoreType } from '../../contexts/GarageContext';
1517

1618
const BookPage = (): JSX.Element => {
17-
const { robot, fetchBook, windowSize, setDelay, setOrder } =
18-
useContext<UseAppStoreType>(AppContext);
19+
const { windowSize } = useContext<UseAppStoreType>(AppContext);
20+
const { setDelay } = useContext<UseFederationStoreType>(FederationContext);
21+
const { garage, clearOrder } = useContext<UseGarageStoreType>(GarageContext);
1922
const { t } = useTranslation();
2023
const navigate = useNavigate();
2124
const [view, setView] = useState<'list' | 'depth' | 'map'>('list');
@@ -27,25 +30,17 @@ const BookPage = (): JSX.Element => {
2730
const maxBookTableWidth = 85;
2831
const chartWidthEm = width - maxBookTableWidth;
2932

30-
useEffect(() => {
31-
fetchBook();
32-
}, []);
33-
34-
const onViewOrder = function () {
35-
setOrder(undefined);
36-
setDelay(10000);
37-
};
38-
39-
const onOrderClicked = function (id: number) {
40-
if (robot.avatarLoaded) {
41-
navigate('/order/' + id);
42-
onViewOrder();
33+
const onOrderClicked = function (id: number, shortAlias: string): void {
34+
if (garage.getRobot().avatarLoaded) {
35+
clearOrder();
36+
setDelay(10000);
37+
navigate(`/order/${shortAlias}/${id}`);
4338
} else {
4439
setOpenNoRobot(true);
4540
}
4641
};
4742

48-
const NavButtons = function () {
43+
const NavButtons = function (): JSX.Element {
4944
return (
5045
<ButtonGroup variant='contained' color='inherit'>
5146
<Button
@@ -60,13 +55,25 @@ const BookPage = (): JSX.Element => {
6055
<></>
6156
) : (
6257
<>
63-
<Button onClick={() => setView('list')}>
58+
<Button
59+
onClick={() => {
60+
setView('list');
61+
}}
62+
>
6463
<FormatListBulleted /> {t('List')}
6564
</Button>
66-
<Button onClick={() => setView('depth')}>
65+
<Button
66+
onClick={() => {
67+
setView('depth');
68+
}}
69+
>
6770
<BarChart /> {t('Chart')}
6871
</Button>
69-
<Button onClick={() => setView('map')}>
72+
<Button
73+
onClick={() => {
74+
setView('map');
75+
}}
76+
>
7077
<Map /> {t('Map')}
7178
</Button>
7279
</>
@@ -82,7 +89,9 @@ const BookPage = (): JSX.Element => {
8289
onClose={() => {
8390
setOpenNoRobot(false);
8491
}}
85-
onClickGenerateRobot={() => navigate('/robot')}
92+
onClickGenerateRobot={() => {
93+
navigate('/robot');
94+
}}
8695
/>
8796
{openMaker ? (
8897
<Dialog
@@ -94,9 +103,11 @@ const BookPage = (): JSX.Element => {
94103
<Box sx={{ maxWidth: '18em', padding: '0.5em' }}>
95104
<MakerForm
96105
onOrderCreated={(id) => {
97-
navigate('/order/' + id);
106+
navigate(`/order/${id}`);
107+
}}
108+
onClickGenerateRobot={() => {
109+
navigate('/robot');
98110
}}
99-
onClickGenerateRobot={() => navigate('/robot')}
100111
/>
101112
</Box>
102113
</Dialog>

frontend/src/basic/Main.tsx

+28-41
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
import React, { useContext } from 'react';
1+
import React, { useContext, useEffect, useState } from 'react';
22
import { MemoryRouter, BrowserRouter, Routes, Route } from 'react-router-dom';
33
import { Box, Slide, Typography, styled } from '@mui/material';
4+
import { type UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';
45

5-
import RobotPage from './RobotPage';
6-
import MakerPage from './MakerPage';
7-
import BookPage from './BookPage';
8-
import OrderPage from './OrderPage';
9-
import SettingsPage from './SettingsPage';
10-
import NavBar from './NavBar';
11-
import MainDialogs from './MainDialogs';
12-
6+
import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage, NavBar, MainDialogs } from './';
137
import RobotAvatar from '../components/RobotAvatar';
8+
import Notifications from '../components/Notifications';
149

1510
import { useTranslation } from 'react-i18next';
16-
import Notifications from '../components/Notifications';
17-
import { type UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';
11+
import { FederationContext, UseFederationStoreType } from '../contexts/FederationContext';
12+
import { GarageContext, UseGarageStoreType } from '../contexts/GarageContext';
1813

1914
const Router = window.NativeRobosats === undefined ? BrowserRouter : MemoryRouter;
2015

@@ -35,39 +30,31 @@ const MainBox = styled(Box)<MainBoxProps>((props) => ({
3530

3631
const Main: React.FC = () => {
3732
const { t } = useTranslation();
38-
const {
39-
settings,
40-
robot,
41-
setRobot,
42-
baseUrl,
43-
order,
44-
page,
45-
slideDirection,
46-
setOpen,
47-
windowSize,
48-
navbarHeight,
49-
} = useContext<UseAppStoreType>(AppContext);
33+
const { settings, page, slideDirection, setOpen, windowSize, navbarHeight, hostUrl, origin } =
34+
useContext<UseAppStoreType>(AppContext);
35+
const { federation, sortedCoordinators } = useContext<UseFederationStoreType>(FederationContext);
36+
const { garage } = useContext<UseGarageStoreType>(GarageContext);
37+
const [avatarBaseUrl, setAvatarBaseUrl] = useState<string>(hostUrl);
38+
39+
useEffect(() => {
40+
setAvatarBaseUrl(federation.getCoordinator(sortedCoordinators[0]).getBaseUrl());
41+
}, [settings.network, settings.selfhostedClient, federation, sortedCoordinators]);
5042

5143
return (
5244
<Router>
5345
<RobotAvatar
5446
style={{ display: 'none' }}
55-
nickname={robot.nickname}
56-
baseUrl={baseUrl}
57-
onLoad={() => {
58-
setRobot((robot) => {
59-
return { ...robot, avatarLoaded: true };
60-
});
61-
}}
47+
nickname={garage.getRobot().nickname}
48+
baseUrl={federation.getCoordinator(sortedCoordinators[0]).getBaseUrl()}
49+
onLoad={() => garage.updateRobot({ avatarLoaded: true })}
6250
/>
6351
<Notifications
64-
order={order}
6552
page={page}
6653
openProfile={() => {
6754
setOpen({ ...closeAll, profile: true });
6855
}}
69-
rewards={robot.earnedRewards}
70-
windowWidth={windowSize.width}
56+
rewards={garage.getRobot().earnedRewards}
57+
windowWidth={windowSize?.width}
7158
/>
7259
{settings.network === 'testnet' ? (
7360
<TestnetTypography color='secondary' align='center'>
@@ -87,10 +74,10 @@ const Main: React.FC = () => {
8774
<Slide
8875
direction={page === 'robot' ? slideDirection.in : slideDirection.out}
8976
in={page === 'robot'}
90-
appear={slideDirection.in != undefined}
77+
appear={slideDirection.in !== undefined}
9178
>
9279
<div>
93-
<RobotPage />
80+
<RobotPage avatarBaseUrl={avatarBaseUrl} />
9481
</div>
9582
</Slide>
9683
}
@@ -105,7 +92,7 @@ const Main: React.FC = () => {
10592
<Slide
10693
direction={page === 'offers' ? slideDirection.in : slideDirection.out}
10794
in={page === 'offers'}
108-
appear={slideDirection.in != undefined}
95+
appear={slideDirection.in !== undefined}
10996
>
11097
<div>
11198
<BookPage />
@@ -120,7 +107,7 @@ const Main: React.FC = () => {
120107
<Slide
121108
direction={page === 'create' ? slideDirection.in : slideDirection.out}
122109
in={page === 'create'}
123-
appear={slideDirection.in != undefined}
110+
appear={slideDirection.in !== undefined}
124111
>
125112
<div>
126113
<MakerPage />
@@ -130,12 +117,12 @@ const Main: React.FC = () => {
130117
/>
131118

132119
<Route
133-
path='/order/:orderId'
120+
path='/order/:shortAlias/:orderId'
134121
element={
135122
<Slide
136123
direction={page === 'order' ? slideDirection.in : slideDirection.out}
137124
in={page === 'order'}
138-
appear={slideDirection.in != undefined}
125+
appear={slideDirection.in !== undefined}
139126
>
140127
<div>
141128
<OrderPage />
@@ -150,7 +137,7 @@ const Main: React.FC = () => {
150137
<Slide
151138
direction={page === 'settings' ? slideDirection.in : slideDirection.out}
152139
in={page === 'settings'}
153-
appear={slideDirection.in != undefined}
140+
appear={slideDirection.in !== undefined}
154141
>
155142
<div>
156143
<SettingsPage />
@@ -160,7 +147,7 @@ const Main: React.FC = () => {
160147
/>
161148
</Routes>
162149
</MainBox>
163-
<NavBar width={windowSize.width} height={navbarHeight} />
150+
<NavBar />
164151
<MainDialogs />
165152
</Router>
166153
);

0 commit comments

Comments
 (0)