Skip to content

Commit

Permalink
✨(lld): add empty message and dummy drawer for ordis (#7881)
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasWerey authored Sep 25, 2024
1 parent ec06a5c commit c55d0b3
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 44 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-clouds-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ledger-live-desktop": patch
---

Add ui for empty rare sats and inscriptions. Add error message from Error when inscriptions / rare sats can't load. Add dumy drawer for inscriptions
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import React from "react";
import { Flex, Icons, Text } from "@ledgerhq/react-ui";
import { useTranslation } from "react-i18next";

const Error: React.FC = () => {
type Props = {
error: Error;
};

const Error: React.FC<Props> = ({ error }) => {
const { t } = useTranslation();

return (
<Flex justifyContent="center" my={4} columnGap={2}>
<Flex my={4} ml={4} alignItems={"center"} columnGap={2}>
<Icons.Warning size="S" color="error.c60" />
<Text color="error.c60">{t("crash.title")}</Text>
<Text fontSize={12} alignSelf={"flex-end"} color="error.c40">{`(${error?.message})`}</Text>
</Flex>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react";
import { SideDrawer } from "~/renderer/components/SideDrawer";
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";

type Props = {
inscription: SimpleHashNft;
onClose: () => void;
};
const InscriptionDetailsDrawer: React.FC<Props> = ({ inscription, onClose }) => {
// will be replaced by DetailsDrawer from collectibles
return (
<SideDrawer direction={"left"} isOpen={!!inscription} onRequestClose={onClose}>
{inscription.name || inscription.contract.name}
</SideDrawer>
);
};

export default InscriptionDetailsDrawer;
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ function matchCorrespondingIcon(
});
}

export function getInscriptionsData(inscriptions: SimpleHashNft[]) {
export function getInscriptionsData(
inscriptions: SimpleHashNft[],
onInscriptionClick: (inscription: SimpleHashNft) => void,
) {
const inscriptionsWithIcons = matchCorrespondingIcon(inscriptions);
return inscriptionsWithIcons.map(item => ({
tokenName: item.name || item.contract.name || "",
Expand All @@ -39,9 +42,6 @@ export function getInscriptionsData(inscriptions: SimpleHashNft[]) {
contentType: item.extra_metadata?.ordinal_details?.content_type,
mediaType: "image",
},
onClick: () => {
console.log(`you clicked on : \x1b[32m${item.name}\x1b[0m inscription`);
},
// it does nothing for now but it will be used for the next PR with the drawer
onClick: () => onInscriptionClick(item),
}));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { Box, Flex } from "@ledgerhq/react-ui";
import { Box, Flex, Icons } from "@ledgerhq/react-ui";
import { useInscriptionsModel } from "./useInscriptionsModel";
import TableContainer from "~/renderer/components/TableContainer";
import TableHeader from "LLD/features/Collectibles/components/Collection/TableHeader";
Expand All @@ -9,31 +9,47 @@ import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import Loader from "../Loader";
import Error from "../Error";
import Item from "./Item";
import EmptyCollection from "LLD/features/Collectibles/components/Collection/EmptyCollection";
import { CollectibleTypeEnum } from "../../../types/enum/Collectibles";
import Button from "~/renderer/components/Button";
import { useTranslation } from "react-i18next";

type ViewProps = ReturnType<typeof useInscriptionsModel> & { isLoading: boolean; isError: boolean };
type ViewProps = ReturnType<typeof useInscriptionsModel> & {
isLoading: boolean;
isError: boolean;
error: Error | null;
onReceive: () => void;
};

type Props = {
inscriptions: SimpleHashNft[];
isLoading: boolean;
isError: boolean;
error: Error | null;
onReceive: () => void;
onInscriptionClick: (inscription: SimpleHashNft) => void;
};

const View: React.FC<ViewProps> = ({
displayShowMore,
isLoading,
isError,
inscriptions,
error,
onShowMore,
onReceive,
}) => {
const { t } = useTranslation();
const hasInscriptions = inscriptions.length > 0 && !isError;
const nothingToShow = !hasInscriptions && !isLoading && !isError;
const hasError = isError && error;

return (
<Box>
<TableContainer id="ordinals-inscriptions">
<TableHeader titleKey={TableHeaderTitleKey.Inscriptions} />
{isLoading && <Loader />}
{isError && <Error />}
{hasError && <Error error={error} />}
{hasInscriptions &&
inscriptions.map((item, index) => (
<Item
Expand All @@ -48,18 +64,36 @@ const View: React.FC<ViewProps> = ({
/>
))}
{nothingToShow && (
<Flex justifyContent="center" my={4}>
{"NOTHING TO SHOW WAITING FOR DESIGN"}
</Flex>
<EmptyCollection collectionType={CollectibleTypeEnum.Inscriptions}>
<Button small primary onClick={onReceive} icon>
<Flex alignItems={"center"}>
<Icons.ArrowDown size="XS" />
<Box>{t("ordinals.inscriptions.receive")}</Box>
</Flex>
</Button>
</EmptyCollection>
)}
{displayShowMore && !isError && <ShowMore onShowMore={onShowMore} isInscriptions />}
</TableContainer>
</Box>
);
};

const Inscriptions: React.FC<Props> = ({ inscriptions, isLoading, isError }) => (
<View isLoading={isLoading} isError={isError} {...useInscriptionsModel({ inscriptions })} />
const Inscriptions: React.FC<Props> = ({
inscriptions,
isLoading,
isError,
error,
onReceive,
onInscriptionClick,
}) => (
<View
isLoading={isLoading}
isError={isError}
error={error}
onReceive={onReceive}
{...useInscriptionsModel({ inscriptions, onInscriptionClick })}
/>
);

export default Inscriptions;
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,28 @@ import { InscriptionsItemProps } from "LLD/features/Collectibles/types/Inscripti

type Props = {
inscriptions: SimpleHashNft[];
onInscriptionClick: (inscription: SimpleHashNft) => void;
};

export const useInscriptionsModel = ({ inscriptions }: Props) => {
const [displayShowMore, setDisplayShowMore] = useState(false);
const [displayedObjects, setDisplayedObjects] = useState<InscriptionsItemProps[]>([]);

export const useInscriptionsModel = ({ inscriptions, onInscriptionClick }: Props) => {
const items: InscriptionsItemProps[] = useMemo(
() => getInscriptionsData(inscriptions),
[inscriptions],
() => getInscriptionsData(inscriptions, onInscriptionClick),
[inscriptions, onInscriptionClick],
);

const initialDisplayedObjects = items.slice(0, 3);
const initialDisplayShowMore = items.length > 3;

const [displayShowMore, setDisplayShowMore] = useState(initialDisplayShowMore);
const [displayedObjects, setDisplayedObjects] =
useState<InscriptionsItemProps[]>(initialDisplayedObjects);

useEffect(() => {
if (items.length > 3) setDisplayShowMore(true);
setDisplayedObjects(items.slice(0, 3));
}, [items]);
if (displayedObjects.length === 0) {
if (items.length > 3) setDisplayShowMore(true);
setDisplayedObjects(items.slice(0, 3));
}
}, [items, displayedObjects.length]);

const onShowMore = () => {
setDisplayedObjects(prevDisplayedObjects => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,46 @@ import TableContainer from "~/renderer/components/TableContainer";
import TableHeader from "LLD/features/Collectibles/components/Collection/TableHeader";
import Item from "./Item";
import { TableHeaderTitleKey } from "LLD/features/Collectibles/types/Collection";
import { Box, Flex } from "@ledgerhq/react-ui";
import { Box, Flex, Icons } from "@ledgerhq/react-ui";
import { TableHeader as TableHeaderContainer } from "./TableHeader";
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import Loader from "../Loader";
import Error from "../Error";
import EmptyCollection from "../../../components/Collection/EmptyCollection";
import { CollectibleTypeEnum } from "../../../types/enum/Collectibles";
import Button from "~/renderer/components/Button";
import { useTranslation } from "react-i18next";

type ViewProps = ReturnType<typeof useRareSatsModel> & {
isLoading: boolean;
isError: boolean;
isFetched: boolean;
error: Error | null;
onReceive: () => void;
};

type Props = {
rareSats: SimpleHashNft[];
isLoading: boolean;
isError: boolean;
isFetched: boolean;
error: Error | null;
onReceive: () => void;
};

function View({ rareSats, isLoading, isError, isFetched }: ViewProps) {
const isLoaded = isFetched;
function View({ rareSats, isLoading, isError, isFetched, error, onReceive }: ViewProps) {
const { t } = useTranslation();
const isLoaded = isFetched && !isError && !isLoading;
const hasRareSats = Object.values(rareSats).length > 0;
const dataReady = isLoaded && hasRareSats;
const hasError = isError && error;

return (
<Box>
<TableContainer id="oridinals-raresats">
<TableHeader titleKey={TableHeaderTitleKey.RareSats} />
{isLoading && <Loader />}
{isError && <Error />}
{hasError && <Error error={error} />}
{dataReady && <TableHeaderContainer />}
<Flex flexDirection="column">
{dataReady &&
Expand All @@ -45,22 +55,29 @@ function View({ rareSats, isLoading, isError, isFetched }: ViewProps) {
</Flex>
))}
{isLoaded && !hasRareSats && (
<Flex justifyContent="center" my={4}>
{"NOTHING TO SHOW WAITING FOR DESIGN"}
</Flex>
<EmptyCollection collectionType={CollectibleTypeEnum.RareSat}>
<Button small primary onClick={onReceive} icon>
<Flex alignItems={"center"}>
<Icons.ArrowDown size="XS" />
<Box>{t("ordinals.rareSats.receive")}</Box>
</Flex>
</Button>
</EmptyCollection>
)}
</Flex>
</TableContainer>
</Box>
);
}

const RareSats = ({ rareSats, isLoading, isError, isFetched }: Props) => {
const RareSats = ({ rareSats, isLoading, isError, isFetched, error, onReceive }: Props) => {
return (
<View
isFetched={isFetched}
isLoading={isLoading}
isError={isError}
error={error}
onReceive={onReceive}
{...useRareSatsModel({ rareSats })}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import RareSats from "../../components/RareSats";
import DiscoveryDrawer from "../../components/Inscriptions/DiscoveryDrawer";
import { BitcoinAccount } from "@ledgerhq/coin-bitcoin/lib/types";
import { useBitcoinAccountModel } from "./useBitcoinAccountModel";
import InscriptionDetailsDrawer from "../../components/Inscriptions/DetailsDrawer";

type ViewProps = ReturnType<typeof useBitcoinAccountModel>;

Expand All @@ -17,12 +18,24 @@ const View: React.FC<ViewProps> = ({
rest,
rareSats,
isDrawerOpen,
selectedInscription,
handleDrawerClose,
onReceive,
onInscriptionClick,
onDetailsDrawerClose,
}) => (
<Flex mb={50} width="100%" flexDirection="column" rowGap={40}>
<Inscriptions inscriptions={inscriptions} {...rest} />
<RareSats rareSats={rareSats} {...rest} />
<Inscriptions
inscriptions={inscriptions}
onReceive={onReceive}
onInscriptionClick={onInscriptionClick}
{...rest}
/>
<RareSats rareSats={rareSats} onReceive={onReceive} {...rest} />
<DiscoveryDrawer isOpen={isDrawerOpen} onClose={handleDrawerClose} />
{selectedInscription && (
<InscriptionDetailsDrawer inscription={selectedInscription} onClose={onDetailsDrawerClose} />
)}
</Flex>
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { BitcoinAccount } from "@ledgerhq/coin-bitcoin/lib/types";
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import useFetchOrdinals from "LLD/features/Collectibles/hooks/useFetchOrdinals";
import { useState, useEffect } from "react";
import { useState, useEffect, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { openModal } from "~/renderer/actions/modals";
import { setHasSeenOrdinalsDiscoveryDrawer } from "~/renderer/actions/settings";
import { hasSeenOrdinalsDiscoveryDrawerSelector } from "~/renderer/reducers/settings";

Expand All @@ -12,6 +14,7 @@ interface Props {
export const useBitcoinAccountModel = ({ account }: Props) => {
const dispatch = useDispatch();
const hasSeenDiscoveryDrawer = useSelector(hasSeenOrdinalsDiscoveryDrawerSelector);
const [selectedInscription, setSelectedInscription] = useState<SimpleHashNft | null>(null);

const { rareSats, inscriptions, ...rest } = useFetchOrdinals({ account });

Expand All @@ -28,5 +31,28 @@ export const useBitcoinAccountModel = ({ account }: Props) => {
dispatch(setHasSeenOrdinalsDiscoveryDrawer(true));
};

return { rareSats, inscriptions, rest, isDrawerOpen, handleDrawerClose };
const onReceive = useCallback(() => {
dispatch(
openModal("MODAL_RECEIVE", {
account,
receiveOrdinalMode: true,
}),
);
}, [dispatch, account]);

const onInscriptionClick = (inscription: SimpleHashNft) => setSelectedInscription(inscription);

const onDetailsDrawerClose = () => setSelectedInscription(null);

return {
rareSats,
inscriptions,
rest,
isDrawerOpen,
selectedInscription,
onReceive,
handleDrawerClose,
onInscriptionClick,
onDetailsDrawerClose,
};
};
Loading

0 comments on commit c55d0b3

Please sign in to comment.