Skip to content

Commit

Permalink
✨(lld): add detaildrawer for inscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasWerey committed Sep 25, 2024
1 parent 4cfc118 commit 5b4d288
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changeset/dry-otters-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"ledger-live-desktop": patch
"@ledgerhq/live-nft": patch
---

Add detail drawers for inscriptions of ordinals protocol
Original file line number Diff line number Diff line change
@@ -1,18 +1,66 @@
import React from "react";
import { SideDrawer } from "~/renderer/components/SideDrawer";
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import { DetailDrawer } from "LLD/features/Collectibles/components";
import { CollectibleTypeEnum } from "LLD/features/Collectibles/types/enum/Collectibles";
import { Flex, Icons, Text } from "@ledgerhq/react-ui";
import Button from "~/renderer/components/Button";
import useInscriptionDetailDrawer from "./useInscriptionDetailDrawer";
import { t } from "i18next";

type ViewProps = ReturnType<typeof useInscriptionDetailDrawer> & {
onClose: () => void;
};

type Props = {
inscription: SimpleHashNft;
onClose: () => void;
isLoading: boolean;
};
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>
);

const View: React.FC<ViewProps> = ({ data, onClose }) => (
<DetailDrawer
collectibleType={CollectibleTypeEnum.NFT}
areFieldsLoading={data.areFieldsLoading}
collectibleName={data.collectibleName}
contentType={data.contentType}
collectionName={data.collectionName}
details={data.details}
previewUri={data.previewUri}
originalUri={data.originalUri}
isPanAndZoomOpen={data.isPanAndZoomOpen}
mediaType={data.mediaType}
tags={data.tags}
useFallback={data.useFallback}
tokenId={data.tokenId}
isOpened={true}
closeCollectiblesPanAndZoom={data.closeCollectiblesPanAndZoom}
handleRequestClose={onClose}
openCollectiblesPanAndZoom={data.openCollectiblesPanAndZoom}
setUseFallback={data.setUseFallback}
>
<DetailDrawer.Actions>
<Flex>
<Button
outlineGrey
style={{ flex: 1, justifyContent: "center" }}
my={4}
onClick={() => console.log("hide " + data.collectibleName + " clicked")}
center
>
<Flex columnGap={1}>
<Icons.Eye color="neutral.c100" />
<Text variant="bodyLineHeight" fontWeight="600" fontSize={14} color="neutral.c100">
{t("ordinals.inscriptions.detailsDrawer.hide")}
</Text>
</Flex>
</Button>
</Flex>
</DetailDrawer.Actions>
</DetailDrawer>
);

const InscriptionDetailDrawer = ({ inscription, isLoading, onClose }: Props) => {
return <View onClose={onClose} {...useInscriptionDetailDrawer({ isLoading, inscription })} />;
};

export default InscriptionDetailsDrawer;
export default InscriptionDetailDrawer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";
import useCollectibles from "LLD/features/Collectibles/hooks/useCollectibles";
import { useState } from "react";
import { createDetails } from "LLD/features/Collectibles/utils/createInscriptionDetailsArrays";
import { useCalendarFormatted } from "~/renderer/hooks/useDateFormatter";
import { Tag } from "LLD/features/Collectibles/types/DetailDrawer";

type Props = {
isLoading: boolean;
inscription: SimpleHashNft;
};

const useInscriptionDetailDrawer = ({ isLoading, inscription }: Props) => {
const [useFallback, setUseFallback] = useState(false);
const imageUri =
inscription.video_url || inscription.previews?.image_large_url || inscription.image_url;

const isVideo = !!inscription.video_url;

const contentType = isVideo ? "video" : imageUri ? "image" : "";

const { isPanAndZoomOpen, openCollectiblesPanAndZoom, closeCollectiblesPanAndZoom } =
useCollectibles();

const createdDateFromTimestamp = new Date(inscription.first_created?.timestamp || 0);
const formattedCreatedDate = useCalendarFormatted(createdDateFromTimestamp);
const createdDate = createdDateFromTimestamp === new Date(0) ? "" : formattedCreatedDate;
const details = createDetails(inscription, createdDate);

const tags: Tag[] =
inscription.extra_metadata?.attributes?.map(attr => ({
key: attr.trait_type,
value: attr.value,
})) || [];

const data = {
areFieldsLoading: isLoading,
collectibleName: inscription.name || inscription.contract.name || "",
contentType,
collectionName: inscription.collection.name || "",
details: details,
previewUri: imageUri,
originalUri: imageUri,
isPanAndZoomOpen,
mediaType: inscription.video_properties?.mime_type || "image",
tags: tags,
useFallback: useFallback,
tokenId: inscription.nft_id,
isOpened: true,
closeCollectiblesPanAndZoom,
openCollectiblesPanAndZoom,
setUseFallback: setUseFallback,
};

return { inscription, data };
};

export default useInscriptionDetailDrawer;
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ const View: React.FC<ViewProps> = ({
<RareSats rareSats={rareSats} onReceive={onReceive} {...rest} />
<DiscoveryDrawer isOpen={isDrawerOpen} onClose={handleDrawerClose} />
{selectedInscription && (
<InscriptionDetailsDrawer inscription={selectedInscription} onClose={onDetailsDrawerClose} />
<InscriptionDetailsDrawer
inscription={selectedInscription}
onClose={onDetailsDrawerClose}
isLoading={rest.isLoading}
/>
)}
</Flex>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,28 @@ describe("displayBitcoinPage", () => {
await user.hover(screen.getByTestId(/raresaticon-jpeg-0/i));
await waitFor(() => expect(screen.getByText(/journey into the past with jpeg/i)).toBeVisible());
});

it("should open discovery drawer when it is the first time feature is activated", async () => {
const { user } = render(<BitcoinPage />);

await waitFor(() => expect(screen.getByText(/discover ordinals/i)).toBeVisible());
await user.click(screen.getByText(/learn more/i));
expect(openURL).toHaveBeenCalledWith("https://www.ledger.com/academy/bitcoin-ordinals");
});

it("should open inscription detail drawer", async () => {
const { user } = render(<BitcoinPage />, {
initialState: {
settings: {
hasSeenOrdinalsDiscoveryDrawer: true,
},
},
});

await waitFor(() => expect(screen.getByText(/inscription #63691311/i)).toBeVisible());
await user.click(screen.getByText(/inscription #63691311/i));
await expect(screen.getByText(/hide/i)).toBeVisible();
// sat name
await expect(screen.getByText(/gnqupvpiwdm/i)).toBeVisible();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { DetailsArray } from "LLD/features/Collectibles/types/DetailDrawer";
import { SimpleHashNft } from "@ledgerhq/live-nft/api/types";

export function createDetails(inscription: SimpleHashNft, createdDate: string): DetailsArray {
return [
...(inscription.collection.description
? [
{
key: "Description",
title: "ordinals.inscriptions.detailsDrawer.description",
value: inscription.collection.description,
},
]
: []),
...(inscription.collection.name
? [
{
key: "Collection Name",
title: "ordinals.inscriptions.detailsDrawer.collectionName",
value: inscription.collection.name,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.sat_rarity
? [
{
key: "Satribute",
title: "ordinals.inscriptions.detailsDrawer.satribute",
value: inscription.extra_metadata.ordinal_details.sat_rarity,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.inscription_id
? [
{
key: "InscriptionID",
title: "ordinals.inscriptions.detailsDrawer.inscriptionId",
value: inscription.extra_metadata.ordinal_details.inscription_id,
isCopyable: true,
isHash:
inscription.extra_metadata.ordinal_details.inscription_id.length >= 4 ? true : false,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.inscription_number
? [
{
key: "InscriptionNumber",
title: "ordinals.inscriptions.detailsDrawer.inscriptionNumber",
isCopyable: true,
value: String(inscription.extra_metadata.ordinal_details.inscription_number),
},
]
: []),
...(inscription.first_created?.minted_to
? [
{
key: "MintedTo",
title: "ordinals.inscriptions.detailsDrawer.mintedTo",
value: inscription.first_created.minted_to,
isCopyable: true,
isHash: inscription.first_created.minted_to.length >= 4 ? true : false,
},
]
: []),
...(inscription.first_created?.transaction
? [
{
key: "GenesisTx",
title: "ordinals.inscriptions.detailsDrawer.genesisTx",
value: inscription.first_created.transaction,
isCopyable: true,
isHash: inscription.first_created.minted_to.length >= 4 ? true : false,
},
]
: []),
...(inscription.first_created?.block_number
? [
{
key: "BlockNumber",
title: "ordinals.inscriptions.detailsDrawer.blockNumber",
value: String(inscription.first_created.block_number),
isCopyable: true,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.content_type
? [
{
key: "ContentType",
title: "ordinals.inscriptions.detailsDrawer.contentType",
value: inscription.extra_metadata?.ordinal_details?.content_type,
},
]
: []),
...(inscription.first_created?.timestamp
? [
{
key: "CreatedDate",
title: "ordinals.inscriptions.detailsDrawer.createdDate",
value: createdDate,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.sat_number
? [
{
key: "SatNumber",
title: "ordinals.inscriptions.detailsDrawer.satNumber",
value: String(inscription.extra_metadata.ordinal_details.sat_number),
isCopyable: true,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.sat_name
? [
{
key: "SatName",
title: "ordinals.inscriptions.detailsDrawer.satName",
value: inscription.extra_metadata.ordinal_details.sat_name,
isCopyable: true,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.location
? [
{
key: "Location",
title: "ordinals.inscriptions.detailsDrawer.location",
value: inscription.extra_metadata.ordinal_details.location,
isCopyable: true,
isHash: inscription.extra_metadata.ordinal_details.location.length >= 4 ? true : false,
},
]
: []),
...(inscription.extra_metadata?.ordinal_details?.output_value
? [
{
key: "OutputValue",
title: "ordinals.inscriptions.detailsDrawer.outputValue",
value: String(inscription.extra_metadata.ordinal_details.output_value),
},
]
: []),
];
}
17 changes: 17 additions & 0 deletions apps/ledger-live-desktop/static/i18n/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -6602,6 +6602,23 @@
"description": "Do you know that you may own valuable rare sats and inscriptions?",
"learnMore": "Learn more",
"viewCoinControl": "View coin control"
},
"detailsDrawer": {
"description": "Description",
"collectionName": "Collection Name",
"inscriptionId": "Inscription ID",
"inscriptionNumber": "Inscription number",
"mintedTo": "Minted to",
"genesisTx": "Genesis transaction",
"blockNumber": "Block Number",
"contentType": "Content type",
"createdDate": "Created date",
"satribute": "Satribute",
"satNumber": "Sat number",
"satName": "Sat name",
"location": "Location",
"outputValue": "Output value",
"hide": "Hide"
}
},
"rareSats": {
Expand Down
Loading

0 comments on commit 5b4d288

Please sign in to comment.