Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Us 120 receive page #416

Merged
merged 12 commits into from
Apr 7, 2024
Merged
22 changes: 15 additions & 7 deletions src/_dev/hotReloadObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@ const HOTRELOAD_TAB_URL = browser.runtime.getURL("hotreload.html");
initHotReloadTab().catch(console.error);

async function initHotReloadTab() {
const existing = await browser.tabs.query({ url: `${HOTRELOAD_TAB_URL}**` });

if (existing.length === 0) {
await browser.tabs.create({
url: HOTRELOAD_TAB_URL,
active: false,
index: 0,
try {
const existing = await browser.tabs.query({
url: `${HOTRELOAD_TAB_URL}**`,
});

if (existing.length > 0) {
await browser.tabs.remove(existing.map((t) => t.id!));
}
} catch (err) {
console.warn(err);
}

await browser.tabs.create({
url: HOTRELOAD_TAB_URL,
active: false,
index: 0,
});
}
6 changes: 6 additions & 0 deletions src/app/atoms/nav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ export const tokenSlugAtom = atomWithURLHash<string | null>("token", null);
export const activityModalAtom = atomWithURLHash("activityOpened", false);

export const chainIdUrlAtom = atomWithURLHash<number | null>("chainid", null);

export const receiveModalAtom = atomWithURLHash("receiveOpened", false);
export const receiveTokenAtom = atomWithURLHash<string | null>(
"receiveToken",
null,
);
2 changes: 2 additions & 0 deletions src/app/components/MainApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ContactsDialog from "./blocks/ContactsDialog";
import AddAccountModal from "./blocks/AddAccountModal";
import ActivityModal from "./blocks/activity/ActivityModal";
import AddFundsOnRampModal from "./blocks/AddFundsOnRampModal";
import ReceivePopup from "./blocks/ReceiveModal";
// import AuthSignatureModal from "./blocks/AuthSignatureModal";

const MainApp: FC = () => (
Expand All @@ -36,6 +37,7 @@ const Modals: FC = () => {
<ContactsDialog />
<AddAccountModal />
<ActivityModal />
<ReceivePopup />
<AddFundsOnRampModal />
{/* <AuthSignatureModal /> */}
</>
Expand Down
8 changes: 7 additions & 1 deletion src/app/components/PopupApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Unlock from "./screens/Unlock";
import Popup from "./screens/Popup";
import Dialog from "./blocks/Dialog";
import ActivityModal from "./blocks/activity/ActivityModal";
import ReceivePopup from "./blocks/ReceiveModal";

const PopupApp: FC = () => (
<BaseProvider>
Expand All @@ -37,7 +38,12 @@ const PopupModals: FC = () => {
return (
<>
<Dialog small />
{!locked && <ActivityModal />}
{!locked && (
<>
<ActivityModal />
<ReceivePopup />
</>
)}
</>
);
};
Expand Down
71 changes: 71 additions & 0 deletions src/app/components/blocks/ReceiveModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { FC, useCallback } from "react";
import classNames from "clsx";
import { useAtom, useSetAtom } from "jotai";
import { isPopup } from "lib/ext/view";

import { AccountAsset } from "core/types";

import { receiveModalAtom, receiveTokenAtom } from "app/atoms";
import { useAccountToken } from "app/hooks";
import ShareAddress from "../screens/receiveTabs/ShareAddress";
import SecondaryModal, {
SecondaryModalProps,
} from "../elements/SecondaryModal";
import AssetLogo from "../elements/AssetLogo";

type ReceiveModalProps = Pick<SecondaryModalProps, "open" | "onOpenChange">;

const ReceiveModal: FC<ReceiveModalProps> = (props) => {
const isPopupMode = isPopup();
const setReceiveToken = useSetAtom(receiveTokenAtom);
const [receiveOpened, setReceiveOpened] = useAtom(receiveModalAtom);

const handleOpenChange = useCallback(
(open: boolean) => {
setReceiveOpened([open, "replace"]);
setReceiveToken([null, "replace"]);
},
[setReceiveOpened, setReceiveToken],
);

return (
<SecondaryModal
{...props}
header={
<p className="flex w-full justify-center items-center">
Receive{" "}
{receiveOpened && <TokenDetails key={String(receiveOpened)} />}
</p>
}
small
open={receiveOpened}
onOpenChange={handleOpenChange}
className={classNames("", !isPopupMode ? "max-w-[30rem]" : "")}
headerClassName={classNames(
"!m-0 !w-full",
isPopupMode ? "!text-lg" : "!text-[1.5rem]",
)}
>
<ShareAddress
className={classNames(isPopupMode ? "mt-4" : "mt-8")}
title="Wallet address"
labelClassName="pl-0"
walletNameDisplayed
/>
</SecondaryModal>
);
};

export default ReceiveModal;

const TokenDetails = () => {
const [tokenSlug] = useAtom(receiveTokenAtom);
const currentToken = useAccountToken(tokenSlug ?? "") as AccountAsset;

return currentToken ? (
<>
<AssetLogo asset={currentToken} className="mx-2 h-6 w-6" />
{currentToken.symbol}
</>
) : null;
};
20 changes: 16 additions & 4 deletions src/app/components/blocks/Sidebar.Links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import { ReactComponent as SwapIcon } from "app/icons/SwapIcon.svg";
// import { ReactComponent as AppsIcon } from "app/icons/Apps.svg";
import { ReactComponent as ContactsIcon } from "app/icons/Contacts.svg";
import { ReactComponent as WalletsIcon } from "app/icons/Wallets.svg";
import { ReactComponent as BuyIcon } from "app/icons/Buy-page.svg";
import { ReactComponent as SettingsIcon } from "app/icons/Settings.svg";
import { ReactComponent as SupportIcon } from "app/icons/Support.svg";
import { ReactComponent as ActivityIcon } from "app/icons/ActivityIcon.svg";
import { ReactComponent as RewardsIcon } from "app/icons/Rewards.svg";
import * as SupportAlert from "app/components/elements/SupportAlert";
import { useDialog } from "app/hooks/dialog";
import { activityModalAtom } from "app/atoms";
import { activityModalAtom, receiveModalAtom } from "app/atoms";
import { useActivityBadge, useSwapBadge, useAccounts } from "app/hooks";

const useSidebarLinks = () => {
const { alert } = useDialog();
const setActivityOpened = useSetAtom(activityModalAtom);
const setReceiveOpened = useSetAtom(receiveModalAtom);
const activityBadgeAmount = useActivityBadge();
const { currentAccount } = useAccounts();

Expand All @@ -45,9 +47,14 @@ const useSidebarLinks = () => {
Icon: SendIcon,
},
{
route: Page.Receive,
label: "Buy",
label: "Receive",
Icon: ReceiveIcon,
action: () => setReceiveOpened([true, "replace"]),
},
{
route: Page.Buy,
label: "Buy",
Icon: BuyIcon,
},
{
route: Page.Swap,
Expand All @@ -67,7 +74,12 @@ const useSidebarLinks = () => {
// soon: true,
// },
];
}, [activityBadgeAmount, swapBadgeAmount, setActivityOpened]);
}, [
activityBadgeAmount,
swapBadgeAmount,
setActivityOpened,
setReceiveOpened,
]);

const NavLinksSecondary = useMemo(() => {
return [
Expand Down
26 changes: 18 additions & 8 deletions src/app/components/blocks/overview/AssetInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import { ReactComponent as WalletExplorerIcon } from "app/icons/external-link.sv
import { ReactComponent as CoinGeckoIcon } from "app/icons/coingecko.svg";
import { ReactComponent as SwapIcon } from "app/icons/swap.svg";
import { ReactComponent as SendIcon } from "app/icons/send-action.svg";
import { ReactComponent as BuyIcon } from "app/icons/buy-action.svg";
import { ReactComponent as ReceiveIcon } from "app/icons/buy-action.svg";
import { ReactComponent as BuyIcon } from "app/icons/plus-rounded.svg";
import { ReactComponent as EyeIcon } from "app/icons/eye.svg";

import TokenActivity from "./TokenActivity";
Expand Down Expand Up @@ -223,38 +224,47 @@ const AssetInfo: FC = () => {
/>
</div>
</div>
<div className="mt-6 grid grid-cols-3 gap-2">
<div className="mt-6 grid grid-cols-4 gap-2">
<Button
to={{ page: Page.Transfer }}
merge={["token"]}
theme="secondary"
className="grow !py-2 !min-w-0"
className="grow !py-2 !min-w-0 text-sm"
>
<SendIcon className="w-6 h-auto mr-2" />
<SendIcon className="w-4 h-auto mr-2" />
Send
</Button>
<Button
to={{ receiveOpened: true, receiveToken: tokenSlug }}
merge={["token"]}
theme="secondary"
className="grow !py-2 !min-w-0 text-sm"
>
<ReceiveIcon className="w-4 h-auto mr-2" />
Receive
</Button>
<Button
to={{
onRampOpened: true,
token: tokenSlug,
}}
merge
theme="secondary"
className="grow !py-2 !min-w-0"
className="grow !py-2 !min-w-0 text-sm"
disabled={!showBuyButton}
title={showBuyButton ? undefined : "Coming soon"}
>
<BuyIcon className="w-6 h-auto mr-2" />
<BuyIcon className="w-4 h-auto mr-2" />
Buy
</Button>
<Button
to={{ page: Page.Swap }}
merge={["token"]}
theme="secondary"
className="grow !py-2"
className="grow !py-2 !min-w-0 text-sm"
title={`Swap ${symbol}`}
>
<SwapIcon className="w-6 h-auto mr-2" />
<SwapIcon className="w-4 h-auto mr-2" />
Swap
</Button>
</div>
Expand Down
30 changes: 28 additions & 2 deletions src/app/components/blocks/popup/AssetCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ import {
import { ReactComponent as ExpandIcon } from "app/icons/expand.svg";
import { ReactComponent as SwapIcon } from "app/icons/swap.svg";
import { ReactComponent as SendIcon } from "app/icons/send-action.svg";
import { ReactComponent as BuyIcon } from "app/icons/buy-action.svg";
import { ReactComponent as CheckIcon } from "app/icons/check.svg";
import { ReactComponent as WalletExplorerIcon } from "app/icons/external-link.svg";
import { ReactComponent as CoinGeckoIcon } from "app/icons/coingecko.svg";
import { ReactComponent as SuccessIcon } from "app/icons/success.svg";
import { ReactComponent as CopyIcon } from "app/icons/copy.svg";
import { ReactComponent as EyeIcon } from "app/icons/eye.svg";
import { ReactComponent as ReceiveIcon } from "app/icons/buy-action.svg";
import { ReactComponent as BuyIcon } from "app/icons/plus-rounded.svg";

import FiatAmount from "app/components/elements/FiatAmount";
import AssetLogo from "app/components/elements/AssetLogo";
Expand All @@ -51,6 +52,7 @@ import PriceChange from "app/components/elements/PriceChange";
import IconedButton from "app/components/elements/IconedButton";

import PopupModal from "./PopupModal";
import { navigate } from "lib/navigation";

type AssetCardProps = {
asset: AccountAsset;
Expand Down Expand Up @@ -178,6 +180,13 @@ const AssetCard = memo(
<ChainIdProvider chainId={asset.chainId}>
<AssetModal
open={openModal}
onReceive={() => {
navigate((s) => ({
...s,
receiveOpened: true,
receiveToken: asset.tokenSlug,
}));
}}
onClose={() => setModalOpen(false)}
asset={asset}
/>
Expand Down Expand Up @@ -217,11 +226,17 @@ const PopoverButton: FC<PopoverButton> = ({ Icon, children, ...rest }) => (

interface IAssetModalProps {
open: boolean;
onReceive: () => void;
onClose: () => void;
asset: AccountAsset;
}

const AssetModal: FC<IAssetModalProps> = ({ open, asset, onClose }) => {
const AssetModal: FC<IAssetModalProps> = ({
open,
onReceive,
asset,
onClose,
}) => {
const {
balanceUSD,
name,
Expand Down Expand Up @@ -323,6 +338,17 @@ const AssetModal: FC<IAssetModalProps> = ({ open, asset, onClose }) => {
}
Icon={SendIcon}
/>
<Button
theme="clean"
className="!p-0"
innerClassName="flex flex-col"
onClick={onReceive}
>
<div className="mb-1 py-[0.78125rem] px-[0.8125rem] bg-[#373B45] rounded-full">
<ReceiveIcon />
</div>
<span className="text-xs font-medium">Receive</span>
</Button>
<DeepLinkButton
text="Buy"
onClick={() =>
Expand Down
17 changes: 15 additions & 2 deletions src/app/components/elements/AddressField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,22 @@ import { ReactComponent as CopyIcon } from "app/icons/copy.svg";

export type AddressFieldProps = LongTextFieldProps & {
setFromClipboard?: (value: string) => void;
hideLabel?: boolean;
labelClassName?: string;
};

const AddressField = forwardRef<HTMLTextAreaElement, AddressFieldProps>(
({ label = "Recipient", setFromClipboard, className, ...rest }, ref) => {
(
{
label = "Recipient",
setFromClipboard,
className,
hideLabel,
labelClassName,
...rest
},
ref,
) => {
const { paste, pasted } = usePasteFromClipboard(setFromClipboard);
const { copy, copied } = useCopyToClipboard(
rest.value ?? rest.defaultValue,
Expand All @@ -23,9 +35,10 @@ const AddressField = forwardRef<HTMLTextAreaElement, AddressFieldProps>(
return (
<LongTextField
ref={ref}
label={label}
label={!hideLabel ? label : undefined}
placeholder="0x0000000000000000000000000000000000000000"
textareaClassName="!h-20"
labelClassName={labelClassName}
maxLength={42}
actions={
<Button
Expand Down
Loading
Loading