mirror of
https://github.com/RoboSats/robosats.git
synced 2025-09-13 00:56:22 +00:00
New mobile views
This commit is contained in:
@ -16,7 +16,7 @@ import { type PublicOrder } from '../../models';
|
||||
import GoToOrder from '../../components/Dialogs/GoToOrder';
|
||||
|
||||
const BookPage = (): React.JSX.Element => {
|
||||
const { windowSize } = useContext<UseAppStoreType>(AppContext);
|
||||
const { windowSize, navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { federation } = useContext<UseFederationStoreType>(FederationContext);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
@ -43,7 +43,7 @@ const BookPage = (): React.JSX.Element => {
|
||||
setOpenVisitThirdParty(true);
|
||||
}
|
||||
} else {
|
||||
navigate(`/order/${shortAlias}/${id}`);
|
||||
navigateToPage(`order/${shortAlias}/${id}`, navigate);
|
||||
}
|
||||
};
|
||||
|
||||
@ -97,7 +97,13 @@ const BookPage = (): React.JSX.Element => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container direction='column' alignItems='center' spacing={1} sx={{ minWidth: 400 }}>
|
||||
<Grid
|
||||
container
|
||||
direction='column'
|
||||
alignItems='center'
|
||||
spacing={1}
|
||||
sx={{ minWidth: 400, marginTop: 2.5 }}
|
||||
>
|
||||
<GoToOrder
|
||||
open={goToOrder}
|
||||
onClose={() => {
|
||||
@ -151,19 +157,19 @@ const BookPage = (): React.JSX.Element => {
|
||||
) : view === 'depth' ? (
|
||||
<DepthChart
|
||||
maxWidth={windowSize.width * 0.8} // EM units
|
||||
maxHeight={windowSize.height * 0.72} // EM units
|
||||
maxHeight={windowSize.height * 0.68} // EM units
|
||||
onOrderClicked={onOrderClicked}
|
||||
/>
|
||||
) : view === 'map' ? (
|
||||
<MapChart
|
||||
maxWidth={windowSize.width * 0.8} // M units
|
||||
maxHeight={windowSize.height * 0.72} // EM units
|
||||
maxHeight={windowSize.height * 0.68} // EM units
|
||||
onOrderClicked={onOrderClicked}
|
||||
/>
|
||||
) : (
|
||||
<BookTable
|
||||
maxWidth={windowSize.width * 0.8} // EM units
|
||||
maxHeight={windowSize.height * 0.72} // EM units
|
||||
maxHeight={windowSize.height * 0.68} // EM units
|
||||
fullWidth={windowSize.width} // EM units
|
||||
fullHeight={windowSize.height} // EM units
|
||||
defaultFullscreen={false}
|
||||
|
||||
@ -15,7 +15,7 @@ import VisitThirdParty from '../../components/Dialogs/VisitThirdParty';
|
||||
import { type PublicOrder } from '../../models';
|
||||
|
||||
const MakerPage = (): React.JSX.Element => {
|
||||
const { fav, windowSize, navbarHeight } = useContext<UseAppStoreType>(AppContext);
|
||||
const { fav, windowSize, navbarHeight, navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { federation } = useContext<UseFederationStoreType>(FederationContext);
|
||||
const { garage, maker } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const { t } = useTranslation();
|
||||
@ -68,7 +68,7 @@ const MakerPage = (): React.JSX.Element => {
|
||||
}
|
||||
} else {
|
||||
if (garage.getSlot()?.hashId) {
|
||||
navigate(`/order/${shortAlias}/${id}`);
|
||||
navigateToPage(`order/${shortAlias}/${id}`, navigate);
|
||||
} else {
|
||||
setClickedOrder({ id, shortAlias });
|
||||
setOpenNoRobot(true);
|
||||
@ -96,7 +96,8 @@ const MakerPage = (): React.JSX.Element => {
|
||||
.createRobot(federation, token)
|
||||
.then(() => {
|
||||
setOpenNoRobot(true);
|
||||
if (clickedOrder) navigate(`/order/${clickedOrder?.shortAlias}/${clickedOrder?.id}`);
|
||||
if (clickedOrder)
|
||||
navigateToPage(`order/${clickedOrder?.shortAlias}/${clickedOrder?.id}`, navigate);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
|
||||
@ -25,8 +25,14 @@ import { type UseGarageStoreType, GarageContext } from '../../contexts/GarageCon
|
||||
import { genBase62Token } from '../../utils';
|
||||
|
||||
const OrderPage = (): React.JSX.Element => {
|
||||
const { windowSize, setOpen, acknowledgedWarning, setAcknowledgedWarning, navbarHeight } =
|
||||
useContext<UseAppStoreType>(AppContext);
|
||||
const {
|
||||
windowSize,
|
||||
setOpen,
|
||||
acknowledgedWarning,
|
||||
setAcknowledgedWarning,
|
||||
navbarHeight,
|
||||
navigateToPage,
|
||||
} = useContext<UseAppStoreType>(AppContext);
|
||||
const { federation } = useContext<UseFederationStoreType>(FederationContext);
|
||||
const { garage } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const { t } = useTranslation();
|
||||
@ -100,7 +106,7 @@ const OrderPage = (): React.JSX.Element => {
|
||||
};
|
||||
|
||||
const startAgain = (): void => {
|
||||
navigate('/garage');
|
||||
navigateToPage('order', navigate);
|
||||
};
|
||||
|
||||
const orderDetailsSpace = currentOrder ? (
|
||||
|
||||
@ -1,20 +1,15 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { Routes as DomRoutes, Route, useNavigate } from 'react-router-dom';
|
||||
import { Slide, type SlideProps } from '@mui/material';
|
||||
import { Fade } from '@mui/material';
|
||||
import { type UseAppStoreType, AppContext, Page } from '../contexts/AppContext';
|
||||
|
||||
import { RobotPage, MakerPage, BookPage, OrderPage, SettingsPage } from '.';
|
||||
import { GarageContext, type UseGarageStoreType } from '../contexts/GarageContext';
|
||||
|
||||
// Define the page order for carousel effect
|
||||
const pageOrder: Page[] = ['garage', 'offers', 'create', 'order', 'settings'];
|
||||
|
||||
const Routes: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const { garage } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const { page, navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const [prevPage, setPrevPage] = useState<Page>('none');
|
||||
const [slideDirection, setSlideDirection] = useState<SlideProps['direction']>('left');
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('navigateToPage', (event) => {
|
||||
@ -24,7 +19,7 @@ const Routes: React.FC = () => {
|
||||
const slot = garage.getSlotByOrder(coordinator, parseInt(orderId, 10));
|
||||
if (slot?.token) {
|
||||
garage.setCurrentSlot(slot?.token);
|
||||
navigate(`/order/${coordinator}/${orderId}`);
|
||||
navigateToPage(`order/${coordinator}/${orderId}`, navigate);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -35,37 +30,9 @@ const Routes: React.FC = () => {
|
||||
const pathPage: Page | string = location.pathname.split('/')[1];
|
||||
if (pathPage === 'index.html') {
|
||||
navigateToPage('garage', navigate);
|
||||
} else {
|
||||
navigateToPage(pathPage as Page, navigate);
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
// Determine slide direction based on page order (carousel effect)
|
||||
useEffect(() => {
|
||||
if (prevPage === 'none' || page === prevPage) {
|
||||
// Initial load or same page, default direction
|
||||
setSlideDirection('left');
|
||||
} else {
|
||||
const prevIndex = pageOrder.indexOf(prevPage);
|
||||
const currentIndex = pageOrder.indexOf(page);
|
||||
|
||||
// If moving forward in the carousel (or wrapping from end to start)
|
||||
if (currentIndex > prevIndex || (prevIndex === pageOrder.length - 1 && currentIndex === 0)) {
|
||||
setSlideDirection('left'); // New page comes from right
|
||||
}
|
||||
// If moving backward in the carousel (or wrapping from start to end)
|
||||
else if (
|
||||
currentIndex < prevIndex ||
|
||||
(prevIndex === 0 && currentIndex === pageOrder.length - 1)
|
||||
) {
|
||||
setSlideDirection('right'); // New page comes from left
|
||||
}
|
||||
}
|
||||
|
||||
// Update previous page after determining direction
|
||||
setPrevPage(page);
|
||||
}, [page]);
|
||||
|
||||
return (
|
||||
<DomRoutes>
|
||||
{['/garage/:token?', '/garage', '/', ''].map((path, index) => {
|
||||
@ -73,11 +40,11 @@ const Routes: React.FC = () => {
|
||||
<Route
|
||||
path={path}
|
||||
element={
|
||||
<Slide in={page === 'garage'} direction={slideDirection} appear>
|
||||
<Fade in={page === 'garage'} appear>
|
||||
<div>
|
||||
<RobotPage />
|
||||
</div>
|
||||
</Slide>
|
||||
</Fade>
|
||||
}
|
||||
key={index}
|
||||
/>
|
||||
@ -87,44 +54,44 @@ const Routes: React.FC = () => {
|
||||
<Route
|
||||
path={'/offers'}
|
||||
element={
|
||||
<Slide in={page === 'offers'} direction={slideDirection} appear>
|
||||
<Fade in={page === 'offers'} appear>
|
||||
<div>
|
||||
<BookPage />
|
||||
</div>
|
||||
</Slide>
|
||||
</Fade>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path='/create'
|
||||
element={
|
||||
<Slide in={page === 'create'} direction={slideDirection} appear>
|
||||
<Fade in={page === 'create'} appear>
|
||||
<div>
|
||||
<MakerPage />
|
||||
</div>
|
||||
</Slide>
|
||||
</Fade>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path='/order/:shortAlias/:orderId'
|
||||
element={
|
||||
<Slide in={page === 'order'} direction={slideDirection} appear>
|
||||
<Fade in={page === 'order'} appear>
|
||||
<div>
|
||||
<OrderPage />
|
||||
</div>
|
||||
</Slide>
|
||||
</Fade>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path='/settings'
|
||||
element={
|
||||
<Slide in={page === 'settings'} direction={slideDirection} appear>
|
||||
<Fade in={page === 'settings'} appear>
|
||||
<div>
|
||||
<SettingsPage />
|
||||
</div>
|
||||
</Slide>
|
||||
</Fade>
|
||||
}
|
||||
/>
|
||||
</DomRoutes>
|
||||
|
||||
@ -32,8 +32,8 @@ const BookControl = ({
|
||||
const theme = useTheme();
|
||||
|
||||
const [orderType, setOrderType] = useState<string>('any');
|
||||
const [small, medium, large] = useMemo(() => {
|
||||
const small = fav.mode === 'fiat' ? 16 : 7.5;
|
||||
const [_small, medium, large] = useMemo(() => {
|
||||
const small = 16;
|
||||
const medium = small + 13;
|
||||
const large = medium + (t('and use').length + t('pay with').length) * 0.6 + 5;
|
||||
return [small, medium, large];
|
||||
@ -270,21 +270,21 @@ const BookControl = ({
|
||||
tagProps={{ sx: { height: '1.8em' } }}
|
||||
listBoxProps={{ sx: { width: '13em' } }}
|
||||
onAutocompleteChange={setPaymentMethods}
|
||||
value={paymentMethod}
|
||||
paymentMethods={paymentMethod}
|
||||
paymentMethodsText={paymentMethod.join(' ')}
|
||||
optionsType={fav.currency === 1000 ? 'swap' : 'fiat'}
|
||||
error={false}
|
||||
helperText={''}
|
||||
label={fav.currency === 1000 ? t('DESTINATION') : t('METHOD')}
|
||||
tooltipTitle=''
|
||||
addNewButtonText=''
|
||||
isFilter={true}
|
||||
multiple={true}
|
||||
optionsDisplayLimit={1}
|
||||
listHeaderText={''}
|
||||
/>
|
||||
</Grid>
|
||||
) : null}
|
||||
|
||||
{width > small && width <= medium ? (
|
||||
{width <= medium ? (
|
||||
<Grid item>
|
||||
<Select
|
||||
sx={{
|
||||
@ -300,21 +300,27 @@ const BookControl = ({
|
||||
size='small'
|
||||
label={t('Select Payment Method')}
|
||||
required={true}
|
||||
renderValue={(value) =>
|
||||
value === 'ANY' ? (
|
||||
<CheckBoxOutlineBlankIcon style={{ position: 'relative', top: '0.1em' }} />
|
||||
) : (
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<PaymentIcon width={22} height={22} icon={value.icon} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
renderValue={(value) => {
|
||||
if (value === 'ANY') {
|
||||
return (
|
||||
<CheckBoxOutlineBlankIcon style={{ position: 'relative', top: '0.1em' }} />
|
||||
);
|
||||
} else {
|
||||
const methods = fav.currency === 1000 ? swapMethods : fiatMethods;
|
||||
const method = methods.find((m) => m.name === value);
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<PaymentIcon width={22} height={22} icon={method.icon} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}}
|
||||
inputProps={{
|
||||
style: { textAlign: 'center' },
|
||||
}}
|
||||
value={paymentMethod[0] ?? 'ANY'}
|
||||
onChange={(e) => {
|
||||
setPaymentMethods(e.target.value === 'ANY' ? [] : [e.target.value]);
|
||||
setPaymentMethods(e.target.value === 'ANY' ? [] : [e.target.value.name]);
|
||||
}}
|
||||
>
|
||||
<MenuItem value={'ANY'}>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Dialog,
|
||||
@ -12,6 +12,7 @@ import {
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
@ -22,6 +23,7 @@ const GoToOrder = ({ open, onClose }: Props): React.JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const { navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const [orderUrl, setOrderUrl] = useState<string>();
|
||||
const [error, setError] = useState<boolean>(false);
|
||||
|
||||
@ -32,7 +34,7 @@ const GoToOrder = ({ open, onClose }: Props): React.JSX.Element => {
|
||||
if (match) {
|
||||
const coordinator = match[2];
|
||||
const orderId = match[3];
|
||||
navigate(`/order/${coordinator}/${orderId}`);
|
||||
navigateToPage(`order/${coordinator}/${orderId}`, navigate);
|
||||
} else {
|
||||
setError(true);
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ const NoRobotDialog = ({
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate('/garage');
|
||||
navigate('garage');
|
||||
}}
|
||||
>
|
||||
<Key /> <div style={{ width: '0.5em' }} />
|
||||
|
||||
@ -268,7 +268,7 @@ interface AutocompletePaymentsProps {
|
||||
paymentMethods: string[];
|
||||
paymentMethodsText: string;
|
||||
optionsType: 'fiat' | 'swap';
|
||||
setHasCustomPaymentMethod: (value: boolean) => void;
|
||||
setHasCustomPaymentMethod?: (value: boolean) => void;
|
||||
onAutocompleteChange: (value: string[]) => void;
|
||||
tooltipTitle: string;
|
||||
labelProps: MUIStyledCommonProps;
|
||||
|
||||
@ -60,7 +60,7 @@ const MakerForm = ({
|
||||
onReset = () => {},
|
||||
submitButtonLabel = 'Create Order',
|
||||
}: MakerFormProps): React.JSX.Element => {
|
||||
const { fav, setFav, settings } = useContext<UseAppStoreType>(AppContext);
|
||||
const { fav, setFav, settings, navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { federation, federationUpdatedAt } = useContext<UseFederationStoreType>(FederationContext);
|
||||
const { maker, setMaker, garage } = useContext<UseGarageStoreType>(GarageContext);
|
||||
|
||||
@ -258,7 +258,7 @@ const MakerForm = ({
|
||||
.makeOrder(federation, orderAttributes)
|
||||
.then((order: Order) => {
|
||||
if (order.id) {
|
||||
navigate(`/order/${order.shortAlias}/${order.id}`);
|
||||
navigateToPage(`order/${order.shortAlias}/${order.id}`, navigate);
|
||||
} else if (order?.bad_request) {
|
||||
setBadRequest(order?.bad_request);
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Close from '@mui/icons-material/Close';
|
||||
import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageContext';
|
||||
import { Page } from '../../contexts/AppContext';
|
||||
import { AppContext, Page, UseAppStoreType } from '../../contexts/AppContext';
|
||||
import getSettings from '../../utils/settings';
|
||||
|
||||
interface NotificationsProps {
|
||||
@ -70,6 +70,7 @@ const Notifications = ({
|
||||
}: NotificationsProps): React.JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { garage, slotUpdatedAt } = useContext<UseGarageStoreType>(GarageContext);
|
||||
|
||||
const [message, setMessage] = useState<NotificationMessage>(emptyNotificationMessage);
|
||||
@ -86,7 +87,7 @@ const Notifications = ({
|
||||
const basePageTitle = t('RoboSats - Simple and Private Bitcoin Exchange');
|
||||
|
||||
const moveToOrderPage = function (): void {
|
||||
navigate(`/order/${String(garage.getSlot()?.activeOrder?.id)}`);
|
||||
navigateToPage(`order/${String(garage.getSlot()?.activeOrder?.id)}`, navigate);
|
||||
setShow(false);
|
||||
};
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ import { GarageContext, type UseGarageStoreType } from '../../contexts/GarageCon
|
||||
import { type UseFederationStoreType, FederationContext } from '../../contexts/FederationContext';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { sha256 } from 'js-sha256';
|
||||
import { UseAppStoreType, AppContext } from '../../contexts/AppContext';
|
||||
|
||||
interface TakeButtonProps {
|
||||
currentOrder: Order;
|
||||
@ -53,6 +54,7 @@ const TakeButton = ({
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const { navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { garage, slotUpdatedAt } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const { federation } = useContext<UseFederationStoreType>(FederationContext);
|
||||
|
||||
@ -334,7 +336,7 @@ const TakeButton = ({
|
||||
} else {
|
||||
setBadRequest('');
|
||||
setCurrentOrder(order);
|
||||
navigate(`/order/${order.shortAlias}/${order.id}`);
|
||||
navigateToPage(`order/${order.shortAlias}/${order.id}`, navigate);
|
||||
}
|
||||
setLoadingTake(false);
|
||||
})
|
||||
|
||||
@ -149,7 +149,7 @@ const RobotInfo: React.FC<Props> = ({ coordinator, onClose, disabled }: Props) =
|
||||
) : robot?.lastOrderId ? (
|
||||
<ListItemButton
|
||||
onClick={() => {
|
||||
navigate(`/order/${String(coordinator.shortAlias)}/${String(robot?.lastOrderId)}`);
|
||||
navigate(`order/${String(coordinator.shortAlias)}/${String(robot?.lastOrderId)}`);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
|
||||
@ -114,7 +114,7 @@ interface Contract {
|
||||
|
||||
const TradeBox = ({ currentOrder, onStartAgain }: TradeBoxProps): React.JSX.Element => {
|
||||
const { garage, slotUpdatedAt } = useContext<UseGarageStoreType>(GarageContext);
|
||||
const { settings } = useContext<UseAppStoreType>(AppContext);
|
||||
const { settings, navigateToPage } = useContext<UseAppStoreType>(AppContext);
|
||||
const { federation } = useContext<UseFederationStoreType>(FederationContext);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
@ -175,7 +175,8 @@ const TradeBox = ({ currentOrder, onStartAgain }: TradeBoxProps): React.JSX.Elem
|
||||
shortAlias: newOrder.shortAlias,
|
||||
};
|
||||
void slot.makeOrder(federation, orderAttributes).then((order: Order) => {
|
||||
if (order?.id) navigate(`/order/${String(order?.shortAlias)}/${String(order.id)}`);
|
||||
if (order?.id)
|
||||
navigateToPage(`order/${String(order?.shortAlias)}/${String(order.id)}`, navigate);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -66,7 +66,7 @@ export interface UseAppStoreType {
|
||||
settings: Settings;
|
||||
setSettings: Dispatch<SetStateAction<Settings>>;
|
||||
page: Page;
|
||||
navigateToPage: (newPage: Page, navigate: NavigateFunction) => void;
|
||||
navigateToPage: (newPage: Page | string, navigate: NavigateFunction) => void;
|
||||
navbarHeight: number;
|
||||
open: OpenDialogs;
|
||||
setOpen: Dispatch<SetStateAction<OpenDialogs>>;
|
||||
@ -140,11 +140,10 @@ export const AppContextProvider = ({ children }: AppContextProviderProps): React
|
||||
newPage,
|
||||
navigate,
|
||||
) => {
|
||||
if (isPage(newPage)) {
|
||||
setPage(newPage);
|
||||
setTimeout(() => {
|
||||
navigate(`/${newPage}`);
|
||||
}, theme.transitions.duration.leavingScreen);
|
||||
const pathPage: Page | string = newPage.split('/')[0];
|
||||
if (isPage(pathPage)) {
|
||||
setPage(pathPage);
|
||||
navigate(`/${newPage}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user