Skip to content

Commit

Permalink
Added prompt window handling for old and new UI
Browse files Browse the repository at this point in the history
Added ConnectionRequest page
Updated styles
  • Loading branch information
Ivan-Mahda committed Oct 23, 2024
1 parent d5e242c commit 5846799
Show file tree
Hide file tree
Showing 28 changed files with 520 additions and 131 deletions.
14 changes: 11 additions & 3 deletions packages/browser-wallet/src/popup/pages/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useTranslation } from 'react-i18next';
import { absoluteRoutes } from '@popup/constants/routes';
import NavList from '@popup/shared/NavList';
import { useAtom } from 'jotai';
import { themeAtom } from '@popup/store/settings';
import { Theme } from '@shared/storage/types';
import { themeAtom, uiStyleAtom } from '@popup/store/settings';
import { Theme, UiStyle } from '@shared/storage/types';
import SunIcon from '@assets/svg/sun.svg';
import MoonIcon from '@assets/svg/moon.svg';
import { ToggleCheckbox } from '@popup/shared/Form/ToggleCheckbox';
Expand Down Expand Up @@ -34,6 +34,8 @@ function LightDarkModeToggle() {
export default function Settings() {
const { t } = useTranslation('settings');

const [, setUiStyle] = useAtom(uiStyleAtom);

return (
<div className="settings-page">
<NavList>
Expand Down Expand Up @@ -63,7 +65,13 @@ export default function Settings() {
{t('fullscreenWallet')}
</Button>
)}
<Link className="settings-page__link" to={`${routePrefix}/home`}>
<Link
className="settings-page__link"
to={`${routePrefix}/home`}
onClick={() => {
setUiStyle(UiStyle.WalletX);
}}
>
Wallet X
</Link>
<Link className="settings-page__link" to={absoluteRoutes.home.settings.about.path}>
Expand Down
6 changes: 6 additions & 0 deletions packages/browser-wallet/src/popup/popupX/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ export const relativeRoutes = {
},
},
},
prompt: {
path: 'prompt',
connectionRequest: {
path: 'connectionRequest',
},
},
};

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.external-request-layout-x {
height: calc(100% - 2.4rem);
overflow: hidden;
max-width: rem(1328px);
margin: auto;

&__main {
padding: rem(20px) rem(24px) 0 rem(24px);
margin: auto;
height: 100%;
max-width: rem(703px);
overflow: auto;

&::-webkit-scrollbar {
display: none;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { useMemo } from 'react';
import { Outlet } from 'react-router-dom';
import Toast from '@popup/shared/Toast/Toast';
import clsx from 'clsx';
import { Connection, Fullscreen } from '@popup/popupX/page-layouts/MainLayout/Header/components';
import FullscreenPromptLayout from '@popup/popupX/page-layouts/FullscreenPromptLayout';

function Header({ isScrolling }: { isScrolling: boolean }) {
return (
<div className={clsx('main-header', isScrolling && 'scroll-border')}>
<div className="main-header__top">
<Fullscreen />
<Connection hideConnection={false} />
</div>
</div>
);
}

export default function ExternalRequestLayout() {
const [scroll, setScroll] = React.useState(0);
const isScrolling = useMemo(() => scroll > 0, [!!scroll]);
return (
<FullscreenPromptLayout>
<Header isScrolling={isScrolling} />
<div className="external-request-layout-x">
<main
className={clsx('external-request-layout-x__main')}
onScroll={(e) => {
setScroll(e.currentTarget.scrollTop);
}}
>
<Outlet />
</main>
<Toast />
</div>
</FullscreenPromptLayout>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ExternalRequestLayout';
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { createContext, useRef, useCallback, useMemo, useState, ReactNode } from 'react';
import { useNavigate, To } from 'react-router-dom';
import { noOp } from 'wallet-common-helpers';

import { isSpawnedWindow } from '@popup/shared/window-helpers';

type OnCloseHandler = () => void;
type Unsubscribe = () => void;

type OnClose = (handler: OnCloseHandler) => Unsubscribe;
type WithClose = <A extends unknown[]>(action: (...args: A) => void) => (...args: A) => void;

type FullscreenPromptContext = {
onClose: OnClose;
/**
* Generate an action, that also closes the prompt.
*/
withClose: WithClose;
/**
*
*/
setReturnLocation: (location: To) => void;
};

const defaultContext: FullscreenPromptContext = {
onClose: () => noOp,
withClose: () => noOp,
setReturnLocation: noOp,
};

export const fullscreenPromptContext = createContext<FullscreenPromptContext>(defaultContext);

export default function FullscreenPromptLayout({ children }: { children: ReactNode }) {
const nav = useNavigate();
const [returnLocation, setReturnLocation] = useState<To>();

const closeHandler = useRef<OnCloseHandler>();
const close = useCallback(() => {
closeHandler?.current?.();

if (isSpawnedWindow) {
window.close();
} else if (returnLocation) {
nav(returnLocation);
} else {
// Go back
nav(-1);
}
}, [returnLocation]);

const withClose: WithClose = useCallback(
(action) =>
(...args) => {
action(...args);
close();
},
[close]
);

const onClose: OnClose = useCallback((handler) => {
closeHandler.current = handler;

return () => {
closeHandler.current = undefined;
};
}, []);

const contextValue: FullscreenPromptContext = useMemo(
() => ({ onClose, withClose, setReturnLocation }),
[onClose, withClose]
);

return <fullscreenPromptContext.Provider value={contextValue}>{children}</fullscreenPromptContext.Provider>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default, fullscreenPromptContext } from './FullscreenPromptLayout';
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
.fade-menu-bg {
position: absolute;
top: 0;
margin: rem(80px) auto 0 auto;
margin: rem(90px) auto 0 auto;
width: 100%;
max-width: rem(1328px);
height: calc(100% - rem(80px));
height: calc(100% - rem(90px));
z-index: 1;
backdrop-filter: blur(10px);
background: rgba($color-black, 0.9);
Expand Down Expand Up @@ -107,17 +107,15 @@
visibility: hidden;
}

&_button {
display: flex;
padding: unset;
border: unset;
background: unset;
cursor: pointer;
.button__icon.transparent {
&:hover:not(:disabled) {
opacity: 1;
}
}
}

&__menu-tiles {
padding: rem(24px);
padding: rem(14px) rem(24px) rem(24px) rem(24px);

.tablet & {
margin-top: rem(72px);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useEffect } from 'react';
import DotsNine from '@assets/svgX/dots-nine.svg';
import Close from '@assets/svgX/close.svg';
import clsx from 'clsx';
import Button from '@popup/popupX/shared/Button';

type Props = {
setMenuOpen: (open: boolean) => void;
Expand All @@ -21,15 +22,13 @@ export default function MenuButton({ setMenuOpen, menuOpen, hideMenu }: Props) {
}, [menuOpen]);
return (
<div className={clsx('main-header__menu', hideMenu && 'hidden')}>
<button
type="button"
className="main-header__menu_button"
<Button.Icon
className="transparent"
icon={menuOpen ? <Close /> : <DotsNine />}
onClick={() => {
setMenuOpen(!menuOpen);
}}
>
{menuOpen ? <Close /> : <DotsNine />}
</button>
/>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import Text from '@popup/popupX/shared/Text';
import { Link } from 'react-router-dom';
import { absoluteRoutes } from '@popup/popupX/constants/routes';
import { useTranslation } from 'react-i18next';
import { useAtom } from 'jotai';
import { uiStyleAtom } from '@popup/store/settings';
import { UiStyle } from '@shared/storage/types';

type MenuTilesProps = {
menuOpen: boolean;
Expand All @@ -22,6 +25,7 @@ type MenuTilesProps = {

export default function MenuTiles({ menuOpen, setMenuOpen }: MenuTilesProps) {
const { t } = useTranslation('x', { keyPrefix: 'header.menu' });
const [, setUiStyle] = useAtom(uiStyleAtom);
if (!menuOpen) return null;
return (
<div className="main-header__menu-tiles fade-menu-bg">
Expand Down Expand Up @@ -86,7 +90,12 @@ export default function MenuTiles({ menuOpen, setMenuOpen }: MenuTilesProps) {
<Text.Capture>{t('restore')}</Text.Capture>
</IconButton>
</Link>
<Link to="/account/tokens">
<Link
to="/account/tokens"
onClick={() => {
setUiStyle(UiStyle.Old);
}}
>
<IconButton className="main-header__menu-tiles_tile">
<Eye />
<Text.Capture>{t('oldUI')}</Text.Capture>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.connection-request-x {
.text__main {
color: $color-mineral-2;
}

.white {
color: $color-white;
}

.capture__main_small {
margin-top: rem(24px);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useContext, useEffect, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useAtom, useAtomValue } from 'jotai';
import Page from '@popup/popupX/shared/Page';
import Text from '@popup/popupX/shared/Text';
import Button from '@popup/popupX/shared/Button';
import { displayNameOrSplitAddress } from '@popup/shared/utils/account-helpers';
import { selectedCredentialAtom, storedAllowlistAtom } from '@popup/store/account';
import { fullscreenPromptContext } from '@popup/popupX/page-layouts/FullscreenPromptLayout';
import { handleAllowlistEntryUpdate } from '@popup/pages/Allowlist/util';
import { useUrlDisplay } from '@popup/popupX/shared/utils/helpers';

type Props = {
onAllow(): void;
onReject(): void;
};

export default function ConnectionRequest({ onAllow, onReject }: Props) {
const { t } = useTranslation('x', { keyPrefix: 'prompts.connectionRequestX' });
const [urlDisplay, url] = useUrlDisplay();
const { onClose, withClose } = useContext(fullscreenPromptContext);
const selectedAccount = useAtomValue(selectedCredentialAtom);
const [allowlistLoading, setAllowlist] = useAtom(storedAllowlistAtom);
const allowlist = allowlistLoading.value;
const [connectButtonDisabled, setConnectButtonDisabled] = useState<boolean>(false);

useEffect(() => onClose(onReject), [onClose, onReject]);

if (!selectedAccount || allowlistLoading.loading) {
return null;
}

async function connectAccount(account: string, urlString: string) {
await handleAllowlistEntryUpdate(urlString, allowlist, [account], setAllowlist);
}

return (
<Page className="connection-request-x">
<Page.Top heading={t('newConnection')} />
<Page.Main>
<Text.Main>
<Trans
ns="x"
i18nKey="prompts.connectionRequestX.connectTo"
components={{ 1: <span className="white" /> }}
values={{ dApp: urlDisplay, account: displayNameOrSplitAddress(selectedAccount) }}
/>
</Text.Main>
<Text.Capture>
<Trans
ns="x"
i18nKey="prompts.connectionRequestX.connectionDetails"
components={{ 1: <span className="white" /> }}
values={{ dApp: urlDisplay }}
/>
</Text.Capture>
</Page.Main>
<Page.Footer>
<Button.Main className="secondary" label={t('cancel')} onClick={withClose(onReject)} />
<Button.Main
label={t('connect')}
disabled={connectButtonDisabled}
onClick={() => {
setConnectButtonDisabled(true);
connectAccount(selectedAccount.address, new URL(url).origin).then(withClose(onAllow));
}}
/>
</Page.Footer>
</Page>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const t = {
newConnection: 'New connection',
connectTo: 'Connect {{ account }} to \n<1>{{dApp}}</1> ?',
connectionDetails:
'This will allow <1>{{dApp}}</1> to see your account address, public balance, transaction history, and suggest transactions to sign.\n\nYou should only connect your account to websites and services you trust.',
connect: 'Connect',
cancel: 'Cancel',
};

export default t;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ConnectionRequest';
Loading

0 comments on commit 5846799

Please sign in to comment.