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

✨feat(lld): UI of inscriptions table for ordis #7745

Merged
merged 1 commit into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/clever-cups-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ledger-live-desktop": patch
---

LLD ORDINALS add dummy table to display inscriptions inside BTC account screen.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React from "react";
import { Account } from "@ledgerhq/types-live";
import { Box, Flex } from "@ledgerhq/react-ui";
import { useInscriptionsModel } from "./useInscriptionsModel";
import TableContainer from "~/renderer/components/TableContainer";
import TableHeader from "LLD/features/Collectibles/components/Collection/TableHeader";
import { OrdinalsRowProps, TableHeaderTitleKey } from "LLD/features/Collectibles/types/Collection";
import TableRow from "LLD/features/Collectibles/components/Collection/TableRow";
import ShowMore from "LLD/features/Collectibles/components/Collection/ShowMore";
import { MediaProps } from "LLD/features/Collectibles/types/Media";

type ViewProps = ReturnType<typeof useInscriptionsModel>;

type Props = {
account: Account;
};

export type InscriptionsItemProps = {
isLoading: boolean;
tokenName: string;
collectionName: string;
tokenIcons: OrdinalsRowProps["tokenIcons"];
media: MediaProps;
onClick: () => void;
};

const Item: React.FC<InscriptionsItemProps> = ({
isLoading,
tokenName,
collectionName,
tokenIcons,
media,
onClick,
}) => {
return (
<TableRow
isLoading={isLoading}
tokenName={tokenName}
collectionName={collectionName}
tokenIcons={tokenIcons}
media={media}
onClick={onClick}
/>
);
};

function View({ displayedObjects, displayShowMore, onShowMore }: ViewProps) {
return (
<Box>
<TableContainer id="oridinals-inscriptions">
<TableHeader titleKey={TableHeaderTitleKey.Inscriptions} />
{/** titlekey doesn't need to be translated so we keep it hard coded */}
{displayedObjects ? (
displayedObjects.map((item, index) => (
<Item
key={index}
isLoading={item.isLoading}
tokenName={item.tokenName}
collectionName={item.collectionName}
tokenIcons={item.tokenIcons}
media={item.media}
onClick={item.onClick}
/>
))
) : (
<Flex justifyContent={"center"} my={12}>
{"NOTHING TO SHOW"}
</Flex>
)}
{displayShowMore && <ShowMore onShowMore={onShowMore} />}
</TableContainer>
</Box>
);
}

const Inscriptions: React.FC<Props> = ({ account }: Props) => {
return <View {...useInscriptionsModel({ account })} />;
};

export default Inscriptions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useEffect, useMemo, useState } from "react";
import { Account } from "@ledgerhq/types-live";
import { InscriptionsItemProps } from "./index";
import { mockedItems as InscriptionsMocked } from "LLD/features/Collectibles/__integration__/mockedInscriptions";
type Props = {
account: Account;
};

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

const mockedItems: InscriptionsItemProps[] = useMemo(() => [...InscriptionsMocked], []);

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

const onShowMore = () => {
setDisplayedObjects(prevDisplayedObjects => {
const newDisplayedObjects = [
...prevDisplayedObjects,
...mockedItems.slice(prevDisplayedObjects.length, prevDisplayedObjects.length + 3),
];
if (newDisplayedObjects.length === mockedItems.length) setDisplayShowMore(false);
return newDisplayedObjects;
});
};

return { account, displayedObjects, displayShowMore, onShowMore };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from "react";
import { Account } from "@ledgerhq/types-live";
import Inscriptions from "../../components/Inscriptions";

type Props = {
account: Account;
};

const OrdinalsAccount: React.FC<Props> = ({ account }) => {
return <Inscriptions account={account} />;
// here we will add the rare sats table
};

export default OrdinalsAccount;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Icons } from "@ledgerhq/react-ui";
import { InscriptionsItemProps } from "../Ordinals/components/Inscriptions";

export const mockedItems: InscriptionsItemProps[] = [
{
isLoading: false,
tokenName: "NodeMonke#5673",
collectionName: "NodeMonkes",
tokenIcons: [Icons.OrdinalsAlpha, Icons.OrdinalsPaliblockPalindrome],
media: {
uri: "https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2Ff976d219206858d782cccd90d25882cc77cafd3d6c159728f0d3407e25961ab0i0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252Ff976d219206858d782cccd90d25882cc77cafd3d6c159728f0d3407e25961ab0i0.png&w=1920&q=75",
previewUri:
"https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2Ff976d219206858d782cccd90d25882cc77cafd3d6c159728f0d3407e25961ab0i0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252Ff976d219206858d782cccd90d25882cc77cafd3d6c159728f0d3407e25961ab0i0.png&w=1920&q=75",
mediaType: "image",
isLoading: false,
useFallback: true,
contentType: "image",
},
onClick: () => console.log("clicked"),
},
{
isLoading: false,
tokenName: "NodeMonke#5673#22",
collectionName: "NodeMonkes#2",
tokenIcons: [Icons.OrdinalsAlpha, Icons.OrdinalsPaliblockPalindrome],
media: {
uri: "https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
previewUri:
"https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
mediaType: "image",
isLoading: false,
useFallback: true,
contentType: "image",
},
onClick: () => console.log("clicked"),
},
{
isLoading: false,
tokenName: "NodeMonke#5673#33",
collectionName: "NodeMonkes#2",
tokenIcons: [],
media: {
uri: "https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
previewUri:
"https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
mediaType: "image",
isLoading: false,
useFallback: true,
contentType: "image",
},
onClick: () => console.log("clicked"),
},
{
isLoading: false,
tokenName: "NodeMonke#5673#44",
collectionName: "NodeMonkes#2",
tokenIcons: [Icons.OrdinalsBlackLegendary],
media: {
uri: "https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
previewUri:
"https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
mediaType: "image",
isLoading: false,
useFallback: true,
contentType: "image",
},
onClick: () => console.log("clicked"),
},
{
isLoading: false,
tokenName: "NodeMonke#5673#55",
collectionName: "NodeMonkes#2",
tokenIcons: [
Icons.OrdinalsBlock9450X,
Icons.OrdinalsPaliblockPalindrome,
Icons.OrdinalsBlock9,
Icons.OrdinalsHitman,
],
media: {
uri: "https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
previewUri:
"https://www.cryptoslam.io/_next/image?url=https%3A%2F%2Fd6rvidx1ucs57.cloudfront.net%2Fcryptoslam-token-images.s3.amazonaws.com%2FBitcoin%2Fnodemonkes%2Fimage%2F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png%3Fd%3D354%26u%3Dhttps%253A%252F%252Fcryptoslam-token-images.s3.amazonaws.com%252FBitcoin%252Fnodemonkes%252Fimage%252F33199e5e35a90b516d274e8c076ca205436db00a36bc5a99d2f0e26110ca7abai0.png&w=1920&q=75",
mediaType: "image",
isLoading: false,
useFallback: true,
contentType: "image",
},
onClick: () => console.log("clicked"),
},
];
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import React from "react";
import { Skeleton } from "../../Skeleton";
import { Text } from "@ledgerhq/react-ui";
import { Flex, Text } from "@ledgerhq/react-ui";

type Props = {
tokenName: string | string[];
isLoading: boolean;
collectionName?: string;
};

const TokenTitle: React.FC<Props> = ({ tokenName, isLoading }) => {
const TokenTitle: React.FC<Props> = ({ tokenName, isLoading, collectionName }) => {
return (
<Skeleton width={136} minHeight={24} barHeight={10} show={isLoading}>
<Text ff="Inter|SemiBold" color="palette.text.shade100" fontSize={4}>
{tokenName}
</Text>
<Flex flexDirection="column" alignItems="flex-start">
<Text ff="Inter|SemiBold" color="palette.text.shade100" fontSize={4}>
{tokenName}
</Text>
<Text ff="Inter|SemiBold" color={"opacityDefault.c50"} fontSize={3}>
{collectionName}
</Text>
</Flex>
</Skeleton>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { Media, Skeleton } from "../../index";
import { Box, Text } from "@ledgerhq/react-ui";
import { Box, Flex, Text } from "@ledgerhq/react-ui";
import { rgba } from "~/renderer/styles/helpers";
import styled from "styled-components";
import {
Expand All @@ -25,6 +25,13 @@ const Container = styled(Box)`
}
`;

const SatsIconContainer = styled(Flex)`
border-radius: 8px;
background: ${p => p.theme.colors.opacityDefault.c05};
border: 1px solid ${p => p.theme.colors.opacityDefault.c10};
padding: 8px;
`;

Comment on lines +28 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You maybe should put this outside of TableRow as it's specific to Stats ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I've changed that in feat/LIVE-12479_b. There will be a dedicated component

const TableRow: React.FC<Props> = props => {
const mediaBox = () => {
return (
Expand All @@ -37,14 +44,28 @@ const TableRow: React.FC<Props> = props => {

const nftCount = () => {
return (
<Skeleton width={42} minHeight={24} barHeight={10} show={props.isLoading}>
<>
{isNFTRow(props) && (
<Text ff="Inter|SemiBold" color="palette.text.shade100" fontSize={4} textAlign="right">
{props.numberOfNfts || 0}
</Text>
<Skeleton width={42} minHeight={24} barHeight={10} show={props.isLoading}>
<Text ff="Inter|SemiBold" color="palette.text.shade100" fontSize={4} textAlign="right">
{props.numberOfNfts || 0}
</Text>
</Skeleton>
)}
{isOrdinalsRow(props) && null}
</Skeleton>
{isOrdinalsRow(props) && props.tokenIcons.length != 0 && (
<SatsIconContainer
p={"8px"}
alignItems={"center"}
justifyContent={"center"}
flexDirection={"row"}
columnGap={"12px"}
>
{props.tokenIcons?.map((Icon, index) => (
<Icon key={index} size={"XS"} color={"neutral.c100"} />
))}
</SatsIconContainer>
)}
</>
);
};

Expand All @@ -54,12 +75,17 @@ const TableRow: React.FC<Props> = props => {
justifyContent="center"
px={4}
py={3}
maxHeight={64}
display={"flex"}
onClick={props.onClick}
>
{mediaBox()}
<Box ml={3} flex={1}>
<TokenTitle tokenName={props.tokenName} isLoading={props.isLoading} />
<TokenTitle
tokenName={props.tokenName}
isLoading={props.isLoading}
collectionName={isOrdinalsRow(props) ? props.collectionName : undefined}
/>
</Box>
{nftCount()}
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ export type NftRowProps = {
onClick: () => void;
};

export interface IconProps {
size: "S" | "XS" | "M" | "L" | "XL" | undefined;
color: string;
style?: React.CSSProperties;
}

export type OrdinalsRowProps = {
media: MediaProps;
tokenName: string;
collectionName: string;
tokenIcons: string[];
tokenIcons: Array<({ size, color, style }: IconProps) => JSX.Element>;
onClick: () => void;
};

export type RareSatsRowProps = {
tokenIcons: string[];
tokenIcons: Array<({ size, color, style }: IconProps) => JSX.Element>;
tokenName: string[];
numberOfSats: number[];
yearOfCreation: number[];
Expand All @@ -35,6 +41,7 @@ export type TableHeaderActionsProps = {

export enum TableHeaderTitleKey {
NFTCollections = "NFT.collections.title",
Inscriptions = "Inscriptions",
LucasWerey marked this conversation as resolved.
Show resolved Hide resolved
}

export type TableHeaderProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from "../types/Collection";

export function isNFTRow(props: Props): props is Props & NftRowProps {
return "media" in props;
return "media" in props && !("collectionName" in props);
}

export function isOrdinalsRow(props: Props): props is Props & OrdinalsRowProps {
Expand Down
Loading
Loading