Skip to content

Commit

Permalink
wallet-ext: nfts view
Browse files Browse the repository at this point in the history
  • Loading branch information
pchrysochoidis committed May 31, 2022
1 parent 8a572af commit 91decc3
Show file tree
Hide file tree
Showing 21 changed files with 489 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,3 @@
font-weight: 700;
color: #404040;
}

.copy-icon {
margin-left: 6px;
cursor: pointer;
}
52 changes: 8 additions & 44 deletions wallet/src/ui/app/components/account-address/index.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,22 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { useCallback, useEffect, useMemo, useState } from 'react';

import BsIcon from '_components/bs-icon';
import { useAppSelector } from '_hooks';
import CopyToClipboard from '_components/copy-to-clipboard';
import { useAppSelector, useMiddleEllipsis } from '_hooks';

import st from './AccountAddress.module.scss';

const COPY_CHECKMARK_MILLIS = 600;

// TODO: make copy to clipboard reusable
function AccountAddress() {
const address = useAppSelector(
({ account: { address } }) => address && `0x${address}`
);
const shortenAddress = useMemo(() => {
if (!address) {
return '';
}
return `${address.substring(0, 7)}...${address.substring(
address.length - 7
)}`;
}, [address]);
const [copied, setCopied] = useState(false);
const copyToClipboard = useCallback(async () => {
if (!address) {
return;
}
await navigator.clipboard.writeText(address);
setCopied(true);
}, [address]);
useEffect(() => {
let timeout: number;
if (copied) {
timeout = window.setTimeout(
() => setCopied(false),
COPY_CHECKMARK_MILLIS
);
}
return () => {
if (timeout) {
clearTimeout(timeout);
}
};
}, [copied]);
const shortenAddress = useMiddleEllipsis(address || '');
return address ? (
<span className={st.address} title={address} onClick={copyToClipboard}>
{shortenAddress}
<BsIcon
className={st['copy-icon']}
icon={`clipboard${copied ? '-check' : ''}`}
/>
</span>
<CopyToClipboard txt={address}>
<span className={st.address} title={address}>
{shortenAddress}
</span>
</CopyToClipboard>
) : null;
}

Expand Down
14 changes: 12 additions & 2 deletions wallet/src/ui/app/components/bs-icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,23 @@
import cl from 'classnames';
import { memo } from 'react';

import type { MouseEventHandler } from 'react';

export type BsIconProps = {
className?: string;
icon: string;
onClick?: MouseEventHandler<HTMLElement>;
title?: string;
};

function BsIcon({ className, icon }: BsIconProps) {
return <i className={cl(className, `bi-${icon}`, 'bi')}></i>;
function BsIcon({ className, icon, onClick, title }: BsIconProps) {
return (
<i
className={cl(className, `bi-${icon}`, 'bi')}
onClick={onClick}
title={title}
></i>
);
}

export default memo(BsIcon);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
padding: 24px 16px;
align-self: stretch;
flex: 1;
border-radius: 4px;
border-radius: 2px;
background-color: #f0f0f0;
box-shadow: 0 0 3px 0 #00000050;
position: relative;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.container {
display: inline-flex;
flex-flow: row nowrap;
align-items: center;
}

.copy-icon {
margin-left: 6px;
cursor: pointer;
}
71 changes: 71 additions & 0 deletions wallet/src/ui/app/components/copy-to-clipboard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import cl from 'classnames';
import { memo, useCallback, useEffect, useState } from 'react';

import BsIcon from '_components/bs-icon';

import type { ReactNode, MouseEventHandler } from 'react';

import st from './CopyToClipboard.module.scss';

const COPY_CHECKMARK_MILLIS = 600;

export type CopyToClipboardProps = {
txt: string;
children: ReactNode;
copyOnlyOnIconClick?: boolean;
className?: string;
};

function CopyToClipboard({
txt,
children,
copyOnlyOnIconClick = false,
className,
}: CopyToClipboardProps) {
const [copied, setCopied] = useState(false);
const copyToClipboard = useCallback<MouseEventHandler<HTMLElement>>(
async (e) => {
e.stopPropagation();
e.preventDefault();
if (!txt) {
return;
}
await navigator.clipboard.writeText(txt);
setCopied(true);
},
[txt]
);
useEffect(() => {
let timeout: number;
if (copied) {
timeout = window.setTimeout(
() => setCopied(false),
COPY_CHECKMARK_MILLIS
);
}
return () => {
if (timeout) {
clearTimeout(timeout);
}
};
}, [copied]);
return (
<span
className={cl(st.container, className)}
onClick={!copyOnlyOnIconClick ? copyToClipboard : undefined}
>
{children}
<BsIcon
className={st['copy-icon']}
icon={`clipboard${copied ? '-check' : ''}`}
onClick={copyToClipboard}
title="Copy to clipboard"
/>
</span>
);
}

export default memo(CopyToClipboard);
66 changes: 66 additions & 0 deletions wallet/src/ui/app/components/objects-layout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { memo } from 'react';

import AccountAddress from '_components/account-address';
import Alert from '_components/alert';
import BsIcon from '_components/bs-icon';
import LoadingIndicator from '_components/loading/LoadingIndicator';
import { useAppSelector } from '_hooks';

import type { ReactNode } from 'react';

import st from './ObjectsLayout.module.scss';

export type ObjectsLayoutProps = {
children: ReactNode;
emptyMsg: string;
totalItems: number;
};

function ObjectsLayout({ children, emptyMsg, totalItems }: ObjectsLayoutProps) {
const objectsLoading = useAppSelector(
({ suiObjects }) => suiObjects.loading
);
const objectsLastSync = useAppSelector(
({ suiObjects }) => suiObjects.lastSync
);
const objectsError = useAppSelector(({ suiObjects }) => suiObjects.error);
const showError =
!!objectsError &&
(!objectsLastSync || Date.now() - objectsLastSync > 30 * 1000);
const showEmptyNotice = !!(objectsLastSync && !totalItems);
const showItems = !!(objectsLastSync && totalItems);
const showLoading = objectsLoading && !objectsLastSync;
return (
<div className={st.container}>
<div>
<span className={st.title}>Active Account:</span>
<AccountAddress />
</div>
<div className={st.items}>
{showError ? (
<Alert className={st.alert}>
<strong>Sync error (data might be outdated).</strong>{' '}
<small>{objectsError.message}</small>
</Alert>
) : null}
{showItems ? children : null}
{showEmptyNotice ? (
<div className={st.empty}>
<BsIcon icon="droplet" className={st['empty-icon']} />
<div className={st['empty-text']}>{emptyMsg}</div>
</div>
) : null}
{showLoading ? (
<div className={st.loader}>
<LoadingIndicator />
</div>
) : null}
</div>
</div>
);
}

export default memo(ObjectsLayout);
72 changes: 72 additions & 0 deletions wallet/src/ui/app/components/sui-object/SuiObject.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.container {
display: flex;
padding: 24px 16px;
align-self: stretch;
flex: 1;
border-radius: 2px;
background-color: #f0f0f0;
box-shadow: 0 0 3px 0 #00000050;
position: relative;

& + .container {
margin-top: 12px;
}
}

.type {
position: absolute;
top: 2px;
right: 3px;
font-size: 8px;
font-weight: 700;
letter-spacing: -0.6px;
color: #8bc3df;
}

.id {
font-size: 9px;
font-weight: 700;
letter-spacing: -0.5px;
position: absolute;
top: 2px;
left: 2px;
}

.content {
display: flex;
flex-flow: row nowrap;
align-items: center;
max-width: 100%;
max-height: 20vh;
overflow: hidden;
}

.splitter {
align-self: stretch;
background-color: #d5d5d5;
width: 1px;
margin: 5px 16px;
}

.img-container {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
width: 30%;
max-height: 100%;
}

.img {
max-width: 100%;
max-height: 100%;
min-height: 0;
}

.fields {
max-width: 70%;
display: flex;
flex-flow: column nowrap;
overflow-y: auto;
max-height: 100%;
}
16 changes: 16 additions & 0 deletions wallet/src/ui/app/components/sui-object/field/Field.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.field {
margin: 0 6px 6px 0;
}

.name {
font-size: 10px;
font-weight: 500;
color: #666;
margin-bottom: 2px;
margin-right: 3px;
}

.value {
overflow-wrap: anywhere;
font-weight: 600;
}
24 changes: 24 additions & 0 deletions wallet/src/ui/app/components/sui-object/field/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { memo } from 'react';

import type { ReactNode } from 'react';

import st from './Field.module.scss';

export type FieldProps = {
name: string;
children: ReactNode;
};

function Field({ name, children }: FieldProps) {
return (
<div className={st.field}>
<span className={st.name}>{name}</span>
<span className={st.value}>{children}</span>
</div>
);
}

export default memo(Field);
Loading

0 comments on commit 91decc3

Please sign in to comment.