Skip to content

Commit

Permalink
add Avatar component
Browse files Browse the repository at this point in the history
  • Loading branch information
notV4l committed Sep 9, 2024
1 parent 04e8cf2 commit d668649
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 34 deletions.
4 changes: 3 additions & 1 deletion packages/keychain/src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export function Menu({ onLogout }: { onLogout: () => void }) {
title={controller.username}
description={<CopyAddress address={controller.address} />}
>
<Content h="350px"></Content>
<Content h="350px">

</Content>
<Footer>
<Button w="full" onClick={onLogout}>
Log out
Expand Down
73 changes: 73 additions & 0 deletions packages/keychain/src/components/avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Box, Image, Spinner } from "@chakra-ui/react";

import { useConnection } from "hooks/connection";
import { PropsWithChildren, useEffect, useState } from "react";
import { byteArray, cairo, shortString } from "starknet";
import { selectors, VERSION } from "utils/selectors";
import Storage from "utils/storage";

const avatarAddress =
"0x56be7d500bd759ac4f96f786f15e9e4702c1ae0582091b20c90546e44ba42fc";

export const stringFromByteArray = (arr: string[]) => {
arr = arr.slice(1, -1);
while (arr.length > 0 && arr[arr.length - 1] === "0x0") {
arr = arr.slice(0, -1);
}

return arr.map((i) => shortString.decodeShortString(i)).join("");
};

export function Avatar({ children }: PropsWithChildren) {
const { controller } = useConnection();

const [image, setImage] = useState("");
const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
const avatarSelector = selectors[VERSION].avatar(controller.address);

const init = async () => {
const fromStorage = Storage.get(avatarSelector);
if (fromStorage && fromStorage !== "") {
setImage(fromStorage.image);
return;
}

setIsLoading(true);
try {
const tokenId = cairo.uint256(controller.address);
let metadataRaw = await controller.account.callContract({
contractAddress: avatarAddress,
entrypoint: "token_uri",
calldata: [tokenId.low, tokenId.high],
});

const metadataString = stringFromByteArray(metadataRaw);
const metadataJson = JSON.parse(metadataString);

Storage.set(avatarSelector, metadataJson);
setImage(metadataJson.image);
} catch (e) {
// console.log(e);
setImage("");
}
setIsLoading(false);
};

init();
}, [controller.address]);

return (
<Box width={"48px"} height={"48px"} display={"flex"} flexShrink={0} position={"relative"}>
{!isLoading && image !== "" ? (
<Image src={image} />
) : (
<>{children}</>
)}
{isLoading && (
<Spinner position={"absolute"} size="sm" top={"16px"} left={"16px"} />
)}
</Box>
);
}
71 changes: 38 additions & 33 deletions packages/keychain/src/components/layout/Container/Header/Banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
useColorMode,
Square,
HStack,

} from "@chakra-ui/react";
import { useControllerTheme } from "hooks/theme";
import { useMemo } from "react";
import { useLayoutVariant } from "../";
import { TOP_BAR_HEIGHT } from "./TopBar";
import { Avatar } from "components/avatar";

export type BannerProps = {
Icon?: React.ComponentType<IconProps>;
Expand Down Expand Up @@ -106,23 +108,24 @@ export function Banner({ Icon, icon, title, description }: BannerProps) {
/>

<HStack w="full" p={4} gap={4} minW={0}>
{!!Icon ? (
<Square size="44px" bg="solid.primary" borderRadius="md">
<Icon boxSize={8} />
</Square>
) : !!icon ? (
<Square size="44px" bg="solid.primary" borderRadius="md">
{icon}
</Square>
) : (
<Image
src={theme.icon}
boxSize="44px"
alt="Controller Icon"
borderRadius="md"
/>
)}

<Avatar>
{!!Icon ? (
<Square size="48px" bg="solid.primary" borderRadius="md">
<Icon boxSize={8} />
</Square>
) : !!icon ? (
<Square size="48px" bg="solid.primary" borderRadius="md">
{icon}
</Square>
) : (
<Image
src={theme.icon}
boxSize="48px"
alt="Controller Icon"
borderRadius="md"
/>
)}
</Avatar>
<VStack w="full" align="stretch" gap={1} minW={0}>
<Text
w="full"
Expand Down Expand Up @@ -160,22 +163,24 @@ export function Banner({ Icon, icon, title, description }: BannerProps) {
/>

<HStack w="full" p={4} gap={4} minW={0}>
{!!Icon ? (
<Square size="44px" bg="solid.primary" borderRadius="md">
<Icon boxSize={8} />
</Square>
) : !!icon ? (
<Square size="44px" bg="solid.primary" borderRadius="md">
{icon}
</Square>
) : (
<Image
src={theme.icon}
boxSize="44px"
alt="Controller Icon"
borderRadius="md"
/>
)}
<Avatar>
{!!Icon ? (
<Square size="48px" bg="solid.primary" borderRadius="md">
<Icon boxSize={8} />
</Square>
) : !!icon ? (
<Square size="48px" bg="solid.primary" borderRadius="md">
{icon}
</Square>
) : (
<Image
src={theme.icon}
boxSize="48px"
alt="Controller Icon"
borderRadius="md"
/>
)}
</Avatar>

<VStack w="full" align="stretch" gap={1} minW={0}>
<Text
Expand Down
1 change: 1 addition & 0 deletions packages/keychain/src/utils/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const selectors = {
[VERSION]: {
active: () => `@cartridge/active`,
account: (address: string) => `@cartridge/account/${address}`,
avatar: (address: string) => `@cartridge/avatar/${address}`,
deployment: (address: string, chainId: string) =>
`@cartridge/deployment/${address}/${chainId}`,
admin: (address: string, origin: string) =>
Expand Down

0 comments on commit d668649

Please sign in to comment.