Skip to content

Commit

Permalink
Merge pull request #1380 from RoboSats/android-notification-system
Browse files Browse the repository at this point in the history
Android notification system
  • Loading branch information
KoalaSat authored Sep 6, 2024
2 parents 5244b2d + cc63b4d commit e0bd103
Show file tree
Hide file tree
Showing 27 changed files with 712 additions and 263 deletions.
6 changes: 5 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ const App = (): JSX.Element => {
<GarageContextProvider>
<FederationContextProvider>
<CssBaseline />
{(window.NativeRobosats === undefined && window.RobosatsClient === undefined )? <HostAlert /> : <TorConnectionBadge />}
{window.NativeRobosats === undefined && window.RobosatsClient === undefined ? (
<HostAlert />
) : (
<TorConnectionBadge />
)}
<Main />
</FederationContextProvider>
</GarageContextProvider>
Expand Down
96 changes: 8 additions & 88 deletions frontend/src/basic/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import React, { useContext } from 'react';
import { MemoryRouter,HashRouter ,BrowserRouter, Routes, Route } from 'react-router-dom';
import { Box, Slide, Typography, styled } from '@mui/material';
import { MemoryRouter, HashRouter, BrowserRouter } from 'react-router-dom';
import { Box, Typography, styled } from '@mui/material';
import { type UseAppStoreType, AppContext, closeAll } from '../contexts/AppContext';

import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage, NavBar, MainDialogs } from './';
import { NavBar, MainDialogs } from './';
import RobotAvatar from '../components/RobotAvatar';
import Notifications from '../components/Notifications';

import { useTranslation } from 'react-i18next';
import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext';
import Routes from './Routes';

function getRouter() {
const getRouter = (): any => {
if (window.NativeRobosats === undefined && window.RobosatsClient === undefined) {
return BrowserRouter;
} else if (window.RobosatsClient === 'desktop-app') {
return HashRouter;
} else {
return MemoryRouter;
}
}
};
const Router = getRouter();

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

const Main: React.FC = () => {
const { t } = useTranslation();
const { settings, page, slideDirection, setOpen, windowSize, navbarHeight } =
const { settings, page, setOpen, windowSize, navbarHeight } =
useContext<UseAppStoreType>(AppContext);
const { garage } = useContext<UseGarageStoreType>(GarageContext);

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

<MainBox navbarHeight={navbarHeight}>

<Routes>
{['/robot/:token?', '/', ''].map((path, index) => {
return (
<Route
path={path}
element={
<Slide
direction={page === 'robot' ? slideDirection.in : slideDirection.out}
in={page === 'robot'}
appear={slideDirection.in !== undefined}
>
<div>
<RobotPage />
</div>
</Slide>
}
key={index}
/>
);
})}

<Route
path={'/offers'}
element={
<Slide
direction={page === 'offers' ? slideDirection.in : slideDirection.out}
in={page === 'offers'}
appear={slideDirection.in !== undefined}
>
<div>
<BookPage />
</div>
</Slide>
}
/>

<Route
path='/create'
element={
<Slide
direction={page === 'create' ? slideDirection.in : slideDirection.out}
in={page === 'create'}
appear={slideDirection.in !== undefined}
>
<div>
<MakerPage />
</div>
</Slide>
}
/>

<Route
path='/order/:shortAlias/:orderId'
element={
<Slide
direction={page === 'order' ? slideDirection.in : slideDirection.out}
in={page === 'order'}
appear={slideDirection.in !== undefined}
>
<div>
<OrderPage />
</div>
</Slide>
}
/>

<Route
path='/settings'
element={
<Slide
direction={page === 'settings' ? slideDirection.in : slideDirection.out}
in={page === 'settings'}
appear={slideDirection.in !== undefined}
>
<div>
<SettingsPage />
</div>
</Slide>
}
/>
</Routes>
<Routes />
</MainBox>
<NavBar />
<MainDialogs />
Expand Down
114 changes: 114 additions & 0 deletions frontend/src/basic/Routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React, { useContext, useEffect } from 'react';
import { Routes as DomRoutes, Route, useNavigate } from 'react-router-dom';
import { Slide } from '@mui/material';
import { type UseAppStoreType, AppContext } from '../contexts/AppContext';

import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage } from '.';
import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext';

const Routes: React.FC = () => {
const navigate = useNavigate();
const { garage } = useContext<UseGarageStoreType>(GarageContext);
const { page, slideDirection } = useContext<UseAppStoreType>(AppContext);

useEffect(() => {
window.addEventListener('navigateToPage', (event) => {
console.log('navigateToPage', JSON.stringify(event));
const orderId: string = event?.detail?.order_id;
const coordinator: string = event?.detail?.coordinator;
if (orderId && coordinator) {
const slot = garage.getSlotByOrder(coordinator, orderId);
if (slot?.token) {
garage.setCurrentSlot(slot?.token);
navigate(`/order/${coordinator}/${orderId}`);
}
}
});
}, []);

return (
<DomRoutes>
{['/robot/:token?', '/', ''].map((path, index) => {
return (
<Route
path={path}
element={
<Slide
direction={page === 'robot' ? slideDirection.in : slideDirection.out}
in={page === 'robot'}
appear={slideDirection.in !== undefined}
>
<div>
<RobotPage />
</div>
</Slide>
}
key={index}
/>
);
})}

<Route
path={'/offers'}
element={
<Slide
direction={page === 'offers' ? slideDirection.in : slideDirection.out}
in={page === 'offers'}
appear={slideDirection.in !== undefined}
>
<div>
<BookPage />
</div>
</Slide>
}
/>

<Route
path='/create'
element={
<Slide
direction={page === 'create' ? slideDirection.in : slideDirection.out}
in={page === 'create'}
appear={slideDirection.in !== undefined}
>
<div>
<MakerPage />
</div>
</Slide>
}
/>

<Route
path='/order/:shortAlias/:orderId'
element={
<Slide
direction={page === 'order' ? slideDirection.in : slideDirection.out}
in={page === 'order'}
appear={slideDirection.in !== undefined}
>
<div>
<OrderPage />
</div>
</Slide>
}
/>

<Route
path='/settings'
element={
<Slide
direction={page === 'settings' ? slideDirection.in : slideDirection.out}
in={page === 'settings'}
appear={slideDirection.in !== undefined}
>
<div>
<SettingsPage />
</div>
</Slide>
}
/>
</DomRoutes>
);
};

export default Routes;
4 changes: 2 additions & 2 deletions frontend/src/components/OrderDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ const OrderDetails = ({

const isBuyer = (order.type === 0 && order.is_maker) || (order.type === 1 && !order.is_maker);
const tradeFee = order.is_maker
? (coordinator.info?.maker_fee ?? 0)
: (coordinator.info?.taker_fee ?? 0);
? coordinator.info?.maker_fee ?? 0
: coordinator.info?.taker_fee ?? 0;
const defaultRoutingBudget = 0.001;
const btc_now = order.satoshis_now / 100000000;
const rate = Number(order.max_amount ?? order.amount) / btc_now;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const audioPath =
window.NativeRobosats === undefined
? '/static/assets/sounds'
: 'file:///android_asset/Web.bundle/assets/sounds';

const EncryptedTurtleChat: React.FC<Props> = ({
order,
userNick,
Expand Down
15 changes: 4 additions & 11 deletions frontend/src/contexts/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,13 @@ const makeTheme = function (settings: Settings): Theme {
};

const getHostUrl = (network = 'mainnet'): string => {
let host = '';
let protocol = '';
if(isDesktopRoboSats){
host = defaultFederation.exp[network].onion;
protocol = 'http:';
}
else if (window.NativeRobosats === undefined) {
let host = defaultFederation.exp[network].onion;
let protocol = 'http:';
if (window.NativeRobosats === undefined) {
host = getHost();
protocol = location.protocol;
} else {
host = defaultFederation.exp[network].onion;
protocol = 'http:';
}
const hostUrl = `${host}`;
const hostUrl = `${protocol}//${host}`;
return hostUrl;
};

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/models/Federation.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
defaultExchange,
} from '.';
import defaultFederation from '../../static/federation.json';
import { systemClient } from '../services/System';
import { getHost } from '../utils';
import { coordinatorDefaultValues } from './Coordinator.model';
import { updateExchangeInfo } from './Exchange.model';
Expand Down Expand Up @@ -105,9 +106,12 @@ export class Federation {
};

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

update = async (): Promise<void> => {
Expand Down
17 changes: 16 additions & 1 deletion frontend/src/models/Garage.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class Garage {
// Slots
getSlot: (token?: string) => Slot | null = (token) => {
const currentToken = token ?? this.currentSlot;
return currentToken ? (this.slots[currentToken] ?? null) : null;
return currentToken ? this.slots[currentToken] ?? null : null;
};

deleteSlot: (token?: string) => void = (token) => {
Expand All @@ -104,16 +104,30 @@ class Garage {
const slot = this.getSlot(token);
if (attributes) {
if (attributes.copiedToken !== undefined) slot?.setCopiedToken(attributes.copiedToken);
this.save();
this.triggerHook('onRobotUpdate');
}
return slot;
};

setCurrentSlot: (currentSlot: string) => void = (currentSlot) => {
this.currentSlot = currentSlot;
this.save();
this.triggerHook('onRobotUpdate');
};

getSlotByOrder: (coordinator: string, orderID: number) => Slot | null = (
coordinator,
orderID,
) => {
return (
Object.values(this.slots).find((slot) => {
const robot = slot.getRobot(coordinator);
return slot.activeShortAlias === coordinator && robot?.activeOrderId === orderID;
}) ?? null
);
};

// Robots
createRobot: (token: string, shortAliases: string[], attributes: Record<any, any>) => void = (
token,
Expand Down Expand Up @@ -174,6 +188,7 @@ class Garage {
Object.values(this.slots).forEach((slot) => {
slot.syncCoordinator(coordinator, this);
});
this.save();
};
}

Expand Down
8 changes: 7 additions & 1 deletion frontend/src/services/Native/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ export interface NativeWebViewMessageHttp {
export interface NativeWebViewMessageSystem {
id?: number;
category: 'system';
type: 'init' | 'torStatus' | 'copyToClipboardString' | 'setCookie' | 'deleteCookie';
type:
| 'init'
| 'torStatus'
| 'copyToClipboardString'
| 'setCookie'
| 'deleteCookie'
| 'navigateToPage';
key?: string;
detail?: string;
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/services/Native/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class NativeRobosats {
if (message.key !== undefined) {
this.cookies[message.key] = String(message.detail);
}
} else if (message.type === 'navigateToPage') {
window.dispatchEvent(new CustomEvent('navigateToPage', { detail: message?.detail }));
}
};

Expand Down
Loading

0 comments on commit e0bd103

Please sign in to comment.