Make more things copyable
This commit is contained in:
parent
bdbd037257
commit
1172d9cd41
|
@ -7,6 +7,7 @@ import {
|
||||||
Status
|
Status
|
||||||
} from "../providers/accounts";
|
} from "../providers/accounts";
|
||||||
import { TransactionError } from "@solana/web3.js";
|
import { TransactionError } from "@solana/web3.js";
|
||||||
|
import Copyable from "./Copyable";
|
||||||
|
|
||||||
function AccountModal() {
|
function AccountModal() {
|
||||||
const selected = useSelectedAccount();
|
const selected = useSelectedAccount();
|
||||||
|
@ -135,9 +136,11 @@ function ListGroupItem({
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="col min-width-0">
|
<div className="col min-width-0">
|
||||||
<h5 className="mb-0 text-truncate">
|
<Copyable text={signature}>
|
||||||
<code>{signature}</code>
|
<h5 className="mb-0 text-truncate">
|
||||||
</h5>
|
<code>{signature}</code>
|
||||||
|
</h5>
|
||||||
|
</Copyable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -209,7 +209,15 @@ const renderAccountRow = (
|
||||||
</td>
|
</td>
|
||||||
<td>{balance}</td>
|
<td>{balance}</td>
|
||||||
<td>{data}</td>
|
<td>{data}</td>
|
||||||
<td>{owner === "-" ? owner : <code>{owner}</code>}</td>
|
<td>
|
||||||
|
{owner === "-" ? (
|
||||||
|
owner
|
||||||
|
) : (
|
||||||
|
<Copyable text={owner}>
|
||||||
|
<code>{owner}</code>
|
||||||
|
</Copyable>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
<td>{renderDetails()}</td>
|
<td>{renderDetails()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,27 +5,39 @@ type CopyableProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const popover = (
|
type State = "hide" | "copy" | "copied";
|
||||||
<div className="popover fade bs-popover-right show">
|
|
||||||
<div className="arrow" />
|
function Popover({ state }: { state: State }) {
|
||||||
<div className="popover-body">Copied!</div>
|
if (state === "hide") return null;
|
||||||
</div>
|
const text = state === "copy" ? "Copy" : "Copied!";
|
||||||
);
|
return (
|
||||||
|
<div className="popover bs-popover-top show">
|
||||||
|
<div className="arrow" />
|
||||||
|
<div className="popover-body">{text}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function Copyable({ text, children }: CopyableProps) {
|
function Copyable({ text, children }: CopyableProps) {
|
||||||
const [showPopover, setShowPopover] = useState(false);
|
const [state, setState] = useState<State>("hide");
|
||||||
|
|
||||||
const copyToClipboard = () => navigator.clipboard.writeText(text);
|
const copyToClipboard = () => navigator.clipboard.writeText(text);
|
||||||
const handleClick = () =>
|
const handleClick = () =>
|
||||||
copyToClipboard().then(() => {
|
copyToClipboard().then(() => {
|
||||||
setShowPopover(true);
|
setState("copied");
|
||||||
setTimeout(setShowPopover.bind(null, false), 2500);
|
setTimeout(() => setState("hide"), 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="copyable">
|
<div className="copyable">
|
||||||
<div onClick={handleClick}>{children}</div>
|
<div
|
||||||
{showPopover && popover}
|
onClick={handleClick}
|
||||||
|
onMouseOver={() => setState("copy")}
|
||||||
|
onMouseOut={() => state === "copy" && setState("hide")}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
<Popover state={state} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
CreateAccountParams,
|
CreateAccountParams,
|
||||||
TransactionInstruction
|
TransactionInstruction
|
||||||
} from "@solana/web3.js";
|
} from "@solana/web3.js";
|
||||||
|
import Copyable from "./Copyable";
|
||||||
|
|
||||||
function TransactionModal() {
|
function TransactionModal() {
|
||||||
const { selected } = useTransactions();
|
const { selected } = useTransactions();
|
||||||
|
@ -106,15 +107,21 @@ function TransferDetails({
|
||||||
transfer: TransferParams;
|
transfer: TransferParams;
|
||||||
index: number;
|
index: number;
|
||||||
}) {
|
}) {
|
||||||
|
const from = transfer.fromPubkey.toBase58();
|
||||||
|
const to = transfer.toPubkey.toBase58();
|
||||||
return (
|
return (
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h4 className="ix-pill">{`Instruction #${index + 1} (Transfer)`}</h4>
|
<h4 className="ix-pill">{`Instruction #${index + 1} (Transfer)`}</h4>
|
||||||
<div className="list-group list-group-flush my-n3">
|
<div className="list-group list-group-flush my-n3">
|
||||||
<ListGroupItem label="From">
|
<ListGroupItem label="From">
|
||||||
<code>{transfer.fromPubkey.toBase58()}</code>
|
<Copyable text={from}>
|
||||||
|
<code>{from}</code>
|
||||||
|
</Copyable>
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
<ListGroupItem label="To">
|
<ListGroupItem label="To">
|
||||||
<code>{transfer.toPubkey.toBase58()}</code>
|
<Copyable text={to}>
|
||||||
|
<code>{to}</code>
|
||||||
|
</Copyable>
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
<ListGroupItem label="Amount (SOL)">
|
<ListGroupItem label="Amount (SOL)">
|
||||||
{`◎${(1.0 * transfer.lamports) / LAMPORTS_PER_SOL}`}
|
{`◎${(1.0 * transfer.lamports) / LAMPORTS_PER_SOL}`}
|
||||||
|
@ -131,16 +138,22 @@ function CreateDetails({
|
||||||
create: CreateAccountParams;
|
create: CreateAccountParams;
|
||||||
index: number;
|
index: number;
|
||||||
}) {
|
}) {
|
||||||
|
const from = create.fromPubkey.toBase58();
|
||||||
|
const newKey = create.newAccountPubkey.toBase58();
|
||||||
return (
|
return (
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h4 className="ix-pill">{`Instruction #${index +
|
<h4 className="ix-pill">{`Instruction #${index +
|
||||||
1} (Create Account)`}</h4>
|
1} (Create Account)`}</h4>
|
||||||
<div className="list-group list-group-flush my-n3">
|
<div className="list-group list-group-flush my-n3">
|
||||||
<ListGroupItem label="From">
|
<ListGroupItem label="From">
|
||||||
<code>{create.fromPubkey.toBase58()}</code>
|
<Copyable text={from}>
|
||||||
|
<code>{from}</code>
|
||||||
|
</Copyable>
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
<ListGroupItem label="New Account">
|
<ListGroupItem label="New Account">
|
||||||
<code>{create.newAccountPubkey.toBase58()}</code>
|
<Copyable text={newKey}>
|
||||||
|
<code>{newKey}</code>
|
||||||
|
</Copyable>
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
<ListGroupItem label="Amount (SOL)">
|
<ListGroupItem label="Amount (SOL)">
|
||||||
{`◎${(1.0 * create.lamports) / LAMPORTS_PER_SOL}`}
|
{`◎${(1.0 * create.lamports) / LAMPORTS_PER_SOL}`}
|
||||||
|
@ -167,7 +180,9 @@ function InstructionDetails({
|
||||||
<div className="list-group list-group-flush my-n3">
|
<div className="list-group list-group-flush my-n3">
|
||||||
{ix.keys.map(({ pubkey }, keyIndex) => (
|
{ix.keys.map(({ pubkey }, keyIndex) => (
|
||||||
<ListGroupItem key={keyIndex} label={`Address #${keyIndex + 1}`}>
|
<ListGroupItem key={keyIndex} label={`Address #${keyIndex + 1}`}>
|
||||||
<code>{pubkey.toBase58()}</code>
|
<Copyable text={pubkey.toBase58()}>
|
||||||
|
<code>{pubkey.toBase58()}</code>
|
||||||
|
</Copyable>
|
||||||
</ListGroupItem>
|
</ListGroupItem>
|
||||||
))}
|
))}
|
||||||
<ListGroupItem label="Data (Bytes)">{ix.data.length}</ListGroupItem>
|
<ListGroupItem label="Data (Bytes)">{ix.data.length}</ListGroupItem>
|
||||||
|
|
|
@ -17,10 +17,18 @@ code {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover {
|
.popover.bs-popover-top {
|
||||||
top: -1rem;
|
background-color: $dark;
|
||||||
right: -5.12rem;
|
top: -4rem;
|
||||||
left: auto;
|
left: 40%;
|
||||||
|
|
||||||
|
.popover-body {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow::after {
|
||||||
|
border-top-color: $dark;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue