Retrofit the AddressHighlighter into the new generic SelectionHighlighter

This commit is contained in:
Willian Mitsuda 2021-10-28 02:54:36 -03:00
parent ad94813476
commit 09e89c5f41
5 changed files with 121 additions and 60 deletions

View File

@ -1,5 +1,5 @@
import React, { useMemo } from "react"; import React from "react";
import { useSelectionContext } from "../useSelection"; import SelectionHighlighter, { addressSelector } from "./SelectionHighlighter";
type AddressHighlighterProps = React.PropsWithChildren<{ type AddressHighlighterProps = React.PropsWithChildren<{
address: string; address: string;
@ -8,50 +8,14 @@ type AddressHighlighterProps = React.PropsWithChildren<{
const AddressHighlighter: React.FC<AddressHighlighterProps> = ({ const AddressHighlighter: React.FC<AddressHighlighterProps> = ({
address, address,
children, children,
}) => { }) => (
const [selection, setSelection] = useSelectionContext(); <SelectionHighlighter
const [select, deselect] = useMemo(() => { myType="address"
const _select = () => { myContent={address}
setSelection({ type: "address", content: address }); selector={addressSelector}
}; >
const _deselect = () => { {children}
setSelection(null); </SelectionHighlighter>
}; );
return [_select, _deselect];
}, [setSelection, address]);
return (
<AddressHighlighterImpl
selected={
selection !== null &&
selection.type === "address" &&
selection.content === address
}
select={select}
deselect={deselect}
>
{children}
</AddressHighlighterImpl>
);
};
type _AddressHighlighterImplProps = {
selected: boolean;
select: () => void;
deselect: () => void;
};
const AddressHighlighterImpl: React.FC<_AddressHighlighterImplProps> =
React.memo(({ selected, select, deselect, children }) => (
<div
className={`border border-dashed rounded hover:bg-transparent hover:border-transparent px-1 truncate ${
selected ? "border-orange-400 bg-yellow-100" : "border-transparent"
}`}
onMouseEnter={select}
onMouseLeave={deselect}
>
{children}
</div>
));
export default AddressHighlighter; export default AddressHighlighter;

View File

@ -0,0 +1,76 @@
import React, { useMemo } from "react";
import {
useSelectionContext,
OptionalSelection,
SelectionType,
} from "../useSelection";
export type ContentSelector = (
selection: OptionalSelection,
content: string
) => boolean;
export const genericSelector =
(type: SelectionType) =>
(selection: OptionalSelection, content: string): boolean =>
selection !== null &&
selection.type === type &&
selection.content === content;
export const addressSelector: ContentSelector = genericSelector("address");
type SelectionHighlighterProps = React.PropsWithChildren<{
myType: SelectionType;
myContent: string;
selector: ContentSelector;
}>;
const SelectionHighlighter: React.FC<SelectionHighlighterProps> = ({
myType,
myContent,
selector,
children,
}) => {
const [selection, setSelection] = useSelectionContext();
const [select, deselect] = useMemo(() => {
const _select = () => {
setSelection({ type: myType, content: myContent });
};
const _deselect = () => {
setSelection(null);
};
return [_select, _deselect];
}, [setSelection, myType, myContent]);
return (
<HighlighterBox
selected={selector(selection, myContent)}
select={select}
deselect={deselect}
>
{children}
</HighlighterBox>
);
};
type HighlighterBoxProps = {
selected: boolean;
select: () => void;
deselect: () => void;
};
const HighlighterBox: React.FC<HighlighterBoxProps> = React.memo(
({ selected, select, deselect, children }) => (
<div
className={`border border-dashed rounded hover:bg-transparent hover:border-transparent px-1 truncate ${
selected ? "border-orange-400 bg-yellow-100" : "border-transparent"
}`}
onMouseEnter={select}
onMouseLeave={deselect}
>
{children}
</div>
)
);
export default SelectionHighlighter;

View File

@ -0,0 +1,25 @@
import React from "react";
type FunctionSignatureProps = {
callType: string;
sig: string;
};
const FunctionSignature: React.FC<FunctionSignatureProps> = ({
callType,
sig,
}) => (
<span
className={`font-bold ${
callType === "STATICCALL"
? "text-red-700"
: callType === "DELEGATECALL" || callType === "CALLCODE"
? "text-gray-400"
: "text-blue-900"
}`}
>
{sig}
</span>
);
export default FunctionSignature;

View File

@ -2,6 +2,7 @@ import React from "react";
import AddressHighlighter from "../components/AddressHighlighter"; import AddressHighlighter from "../components/AddressHighlighter";
import DecoratedAddressLink from "../components/DecoratedAddressLink"; import DecoratedAddressLink from "../components/DecoratedAddressLink";
import FormattedBalance from "../components/FormattedBalance"; import FormattedBalance from "../components/FormattedBalance";
import FunctionSignature from "./FunctionSignature";
import { TransactionData } from "../types"; import { TransactionData } from "../types";
import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes"; import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes";
import { TraceGroup } from "../useErigonHooks"; import { TraceGroup } from "../useErigonHooks";
@ -38,17 +39,10 @@ const TraceItem: React.FC<TraceItemProps> = ({ t, txData, last }) => {
</AddressHighlighter> </AddressHighlighter>
</span> </span>
<span>.</span> <span>.</span>
<span <FunctionSignature
className={`font-bold ${ callType={t.type}
t.type === "STATICCALL" sig={fourBytesEntry ? fourBytesEntry.name : raw4Bytes}
? "text-red-700" />
: t.type === "DELEGATECALL" || t.type === "CALLCODE"
? "text-gray-400"
: "text-blue-900"
}`}
>
{fourBytesEntry ? fourBytesEntry.name : raw4Bytes}
</span>
{t.value && !t.value.isZero() && ( {t.value && !t.value.isZero() && (
<span className="text-red-700 whitespace-nowrap"> <span className="text-red-700 whitespace-nowrap">
{"{"}value: <FormattedBalance value={t.value} /> ETH{"}"} {"{"}value: <FormattedBalance value={t.value} /> ETH{"}"}

View File

@ -6,12 +6,14 @@ import {
useContext, useContext,
} from "react"; } from "react";
export type SelectionType = "address" | "value" | "functionSig";
export type Selection = { export type Selection = {
type: "address" | "value"; type: SelectionType;
content: string; content: string;
}; };
type OptionalSelection = Selection | null; export type OptionalSelection = Selection | null;
export const useSelection = (): [ export const useSelection = (): [
OptionalSelection, OptionalSelection,