Skip to content

Commit e0bd103

Browse files
authored
Merge pull request #1380 from RoboSats/android-notification-system
Android notification system
2 parents 5244b2d + cc63b4d commit e0bd103

File tree

27 files changed

+712
-263
lines changed

27 files changed

+712
-263
lines changed

frontend/src/App.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ const App = (): JSX.Element => {
2424
<GarageContextProvider>
2525
<FederationContextProvider>
2626
<CssBaseline />
27-
{(window.NativeRobosats === undefined && window.RobosatsClient === undefined )? <HostAlert /> : <TorConnectionBadge />}
27+
{window.NativeRobosats === undefined && window.RobosatsClient === undefined ? (
28+
<HostAlert />
29+
) : (
30+
<TorConnectionBadge />
31+
)}
2832
<Main />
2933
</FederationContextProvider>
3034
</GarageContextProvider>

frontend/src/basic/Main.tsx

+8-88
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
import React, { useContext } from 'react';
2-
import { MemoryRouter,HashRouter ,BrowserRouter, Routes, Route } from 'react-router-dom';
3-
import { Box, Slide, Typography, styled } from '@mui/material';
2+
import { MemoryRouter, HashRouter, BrowserRouter } from 'react-router-dom';
3+
import { Box, Typography, styled } from '@mui/material';
44
import { type UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';
55

6-
import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage, NavBar, MainDialogs } from './';
6+
import { NavBar, MainDialogs } from './';
77
import RobotAvatar from '../components/RobotAvatar';
88
import Notifications from '../components/Notifications';
99

1010
import { useTranslation } from 'react-i18next';
1111
import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext';
12+
import Routes from './Routes';
1213

13-
function getRouter() {
14+
const getRouter = (): any => {
1415
if (window.NativeRobosats === undefined && window.RobosatsClient === undefined) {
1516
return BrowserRouter;
1617
} else if (window.RobosatsClient === 'desktop-app') {
1718
return HashRouter;
1819
} else {
1920
return MemoryRouter;
2021
}
21-
}
22+
};
2223
const Router = getRouter();
2324

2425
const TestnetTypography = styled(Typography)({
@@ -38,7 +39,7 @@ const MainBox = styled(Box)<MainBoxProps>((props) => ({
3839

3940
const Main: React.FC = () => {
4041
const { t } = useTranslation();
41-
const { settings, page, slideDirection, setOpen, windowSize, navbarHeight } =
42+
const { settings, page, setOpen, windowSize, navbarHeight } =
4243
useContext<UseAppStoreType>(AppContext);
4344
const { garage } = useContext<UseGarageStoreType>(GarageContext);
4445

@@ -62,88 +63,7 @@ const Main: React.FC = () => {
6263
)}
6364

6465
<MainBox navbarHeight={navbarHeight}>
65-
66-
<Routes>
67-
{['/robot/:token?', '/', ''].map((path, index) => {
68-
return (
69-
<Route
70-
path={path}
71-
element={
72-
<Slide
73-
direction={page === 'robot' ? slideDirection.in : slideDirection.out}
74-
in={page === 'robot'}
75-
appear={slideDirection.in !== undefined}
76-
>
77-
<div>
78-
<RobotPage />
79-
</div>
80-
</Slide>
81-
}
82-
key={index}
83-
/>
84-
);
85-
})}
86-
87-
<Route
88-
path={'/offers'}
89-
element={
90-
<Slide
91-
direction={page === 'offers' ? slideDirection.in : slideDirection.out}
92-
in={page === 'offers'}
93-
appear={slideDirection.in !== undefined}
94-
>
95-
<div>
96-
<BookPage />
97-
</div>
98-
</Slide>
99-
}
100-
/>
101-
102-
<Route
103-
path='/create'
104-
element={
105-
<Slide
106-
direction={page === 'create' ? slideDirection.in : slideDirection.out}
107-
in={page === 'create'}
108-
appear={slideDirection.in !== undefined}
109-
>
110-
<div>
111-
<MakerPage />
112-
</div>
113-
</Slide>
114-
}
115-
/>
116-
117-
<Route
118-
path='/order/:shortAlias/:orderId'
119-
element={
120-
<Slide
121-
direction={page === 'order' ? slideDirection.in : slideDirection.out}
122-
in={page === 'order'}
123-
appear={slideDirection.in !== undefined}
124-
>
125-
<div>
126-
<OrderPage />
127-
</div>
128-
</Slide>
129-
}
130-
/>
131-
132-
<Route
133-
path='/settings'
134-
element={
135-
<Slide
136-
direction={page === 'settings' ? slideDirection.in : slideDirection.out}
137-
in={page === 'settings'}
138-
appear={slideDirection.in !== undefined}
139-
>
140-
<div>
141-
<SettingsPage />
142-
</div>
143-
</Slide>
144-
}
145-
/>
146-
</Routes>
66+
<Routes />
14767
</MainBox>
14868
<NavBar />
14969
<MainDialogs />

frontend/src/basic/Routes.tsx

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import React, { useContext, useEffect } from 'react';
2+
import { Routes as DomRoutes, Route, useNavigate } from 'react-router-dom';
3+
import { Slide } from '@mui/material';
4+
import { type UseAppStoreType, AppContext } from '../contexts/AppContext';
5+
6+
import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage } from '.';
7+
import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext';
8+
9+
const Routes: React.FC = () => {
10+
const navigate = useNavigate();
11+
const { garage } = useContext<UseGarageStoreType>(GarageContext);
12+
const { page, slideDirection } = useContext<UseAppStoreType>(AppContext);
13+
14+
useEffect(() => {
15+
window.addEventListener('navigateToPage', (event) => {
16+
console.log('navigateToPage', JSON.stringify(event));
17+
const orderId: string = event?.detail?.order_id;
18+
const coordinator: string = event?.detail?.coordinator;
19+
if (orderId && coordinator) {
20+
const slot = garage.getSlotByOrder(coordinator, orderId);
21+
if (slot?.token) {
22+
garage.setCurrentSlot(slot?.token);
23+
navigate(`/order/${coordinator}/${orderId}`);
24+
}
25+
}
26+
});
27+
}, []);
28+
29+
return (
30+
<DomRoutes>
31+
{['/robot/:token?', '/', ''].map((path, index) => {
32+
return (
33+
<Route
34+
path={path}
35+
element={
36+
<Slide
37+
direction={page === 'robot' ? slideDirection.in : slideDirection.out}
38+
in={page === 'robot'}
39+
appear={slideDirection.in !== undefined}
40+
>
41+
<div>
42+
<RobotPage />
43+
</div>
44+
</Slide>
45+
}
46+
key={index}
47+
/>
48+
);
49+
})}
50+
51+
<Route
52+
path={'/offers'}
53+
element={
54+
<Slide
55+
direction={page === 'offers' ? slideDirection.in : slideDirection.out}
56+
in={page === 'offers'}
57+
appear={slideDirection.in !== undefined}
58+
>
59+
<div>
60+
<BookPage />
61+
</div>
62+
</Slide>
63+
}
64+
/>
65+
66+
<Route
67+
path='/create'
68+
element={
69+
<Slide
70+
direction={page === 'create' ? slideDirection.in : slideDirection.out}
71+
in={page === 'create'}
72+
appear={slideDirection.in !== undefined}
73+
>
74+
<div>
75+
<MakerPage />
76+
</div>
77+
</Slide>
78+
}
79+
/>
80+
81+
<Route
82+
path='/order/:shortAlias/:orderId'
83+
element={
84+
<Slide
85+
direction={page === 'order' ? slideDirection.in : slideDirection.out}
86+
in={page === 'order'}
87+
appear={slideDirection.in !== undefined}
88+
>
89+
<div>
90+
<OrderPage />
91+
</div>
92+
</Slide>
93+
}
94+
/>
95+
96+
<Route
97+
path='/settings'
98+
element={
99+
<Slide
100+
direction={page === 'settings' ? slideDirection.in : slideDirection.out}
101+
in={page === 'settings'}
102+
appear={slideDirection.in !== undefined}
103+
>
104+
<div>
105+
<SettingsPage />
106+
</div>
107+
</Slide>
108+
}
109+
/>
110+
</DomRoutes>
111+
);
112+
};
113+
114+
export default Routes;

frontend/src/components/OrderDetails/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ const OrderDetails = ({
174174

175175
const isBuyer = (order.type === 0 && order.is_maker) || (order.type === 1 && !order.is_maker);
176176
const tradeFee = order.is_maker
177-
? (coordinator.info?.maker_fee ?? 0)
178-
: (coordinator.info?.taker_fee ?? 0);
177+
? coordinator.info?.maker_fee ?? 0
178+
: coordinator.info?.taker_fee ?? 0;
179179
const defaultRoutingBudget = 0.001;
180180
const btc_now = order.satoshis_now / 100000000;
181181
const rate = Number(order.max_amount ?? order.amount) / btc_now;

frontend/src/components/TradeBox/EncryptedChat/EncryptedTurtleChat/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const audioPath =
3939
window.NativeRobosats === undefined
4040
? '/static/assets/sounds'
4141
: 'file:///android_asset/Web.bundle/assets/sounds';
42-
42+
4343
const EncryptedTurtleChat: React.FC<Props> = ({
4444
order,
4545
userNick,

frontend/src/contexts/AppContext.tsx

+4-11
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,13 @@ const makeTheme = function (settings: Settings): Theme {
7676
};
7777

7878
const getHostUrl = (network = 'mainnet'): string => {
79-
let host = '';
80-
let protocol = '';
81-
if(isDesktopRoboSats){
82-
host = defaultFederation.exp[network].onion;
83-
protocol = 'http:';
84-
}
85-
else if (window.NativeRobosats === undefined) {
79+
let host = defaultFederation.exp[network].onion;
80+
let protocol = 'http:';
81+
if (window.NativeRobosats === undefined) {
8682
host = getHost();
8783
protocol = location.protocol;
88-
} else {
89-
host = defaultFederation.exp[network].onion;
90-
protocol = 'http:';
9184
}
92-
const hostUrl = `${host}`;
85+
const hostUrl = `${protocol}//${host}`;
9386
return hostUrl;
9487
};
9588

frontend/src/models/Federation.model.ts

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
defaultExchange,
99
} from '.';
1010
import defaultFederation from '../../static/federation.json';
11+
import { systemClient } from '../services/System';
1112
import { getHost } from '../utils';
1213
import { coordinatorDefaultValues } from './Coordinator.model';
1314
import { updateExchangeInfo } from './Exchange.model';
@@ -105,9 +106,12 @@ export class Federation {
105106
};
106107

107108
updateUrl = async (origin: Origin, settings: Settings, hostUrl: string): Promise<void> => {
109+
const federationUrls = {};
108110
for (const coor of Object.values(this.coordinators)) {
109111
coor.updateUrl(origin, settings, hostUrl);
112+
federationUrls[coor.shortAlias] = coor.url;
110113
}
114+
systemClient.setCookie('federation', JSON.stringify(federationUrls));
111115
};
112116

113117
update = async (): Promise<void> => {

frontend/src/models/Garage.model.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class Garage {
8383
// Slots
8484
getSlot: (token?: string) => Slot | null = (token) => {
8585
const currentToken = token ?? this.currentSlot;
86-
return currentToken ? (this.slots[currentToken] ?? null) : null;
86+
return currentToken ? this.slots[currentToken] ?? null : null;
8787
};
8888

8989
deleteSlot: (token?: string) => void = (token) => {
@@ -104,16 +104,30 @@ class Garage {
104104
const slot = this.getSlot(token);
105105
if (attributes) {
106106
if (attributes.copiedToken !== undefined) slot?.setCopiedToken(attributes.copiedToken);
107+
this.save();
107108
this.triggerHook('onRobotUpdate');
108109
}
109110
return slot;
110111
};
111112

112113
setCurrentSlot: (currentSlot: string) => void = (currentSlot) => {
113114
this.currentSlot = currentSlot;
115+
this.save();
114116
this.triggerHook('onRobotUpdate');
115117
};
116118

119+
getSlotByOrder: (coordinator: string, orderID: number) => Slot | null = (
120+
coordinator,
121+
orderID,
122+
) => {
123+
return (
124+
Object.values(this.slots).find((slot) => {
125+
const robot = slot.getRobot(coordinator);
126+
return slot.activeShortAlias === coordinator && robot?.activeOrderId === orderID;
127+
}) ?? null
128+
);
129+
};
130+
117131
// Robots
118132
createRobot: (token: string, shortAliases: string[], attributes: Record<any, any>) => void = (
119133
token,
@@ -174,6 +188,7 @@ class Garage {
174188
Object.values(this.slots).forEach((slot) => {
175189
slot.syncCoordinator(coordinator, this);
176190
});
191+
this.save();
177192
};
178193
}
179194

frontend/src/services/Native/index.d.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ export interface NativeWebViewMessageHttp {
2626
export interface NativeWebViewMessageSystem {
2727
id?: number;
2828
category: 'system';
29-
type: 'init' | 'torStatus' | 'copyToClipboardString' | 'setCookie' | 'deleteCookie';
29+
type:
30+
| 'init'
31+
| 'torStatus'
32+
| 'copyToClipboardString'
33+
| 'setCookie'
34+
| 'deleteCookie'
35+
| 'navigateToPage';
3036
key?: string;
3137
detail?: string;
3238
}

frontend/src/services/Native/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class NativeRobosats {
4545
if (message.key !== undefined) {
4646
this.cookies[message.key] = String(message.detail);
4747
}
48+
} else if (message.type === 'navigateToPage') {
49+
window.dispatchEvent(new CustomEvent('navigateToPage', { detail: message?.detail }));
4850
}
4951
};
5052

0 commit comments

Comments
 (0)