diff --git a/src/codec-components/ViewCodec/CStruct.tsx b/src/codec-components/ViewCodec/CStruct.tsx index e77cf82..b07decd 100644 --- a/src/codec-components/ViewCodec/CStruct.tsx +++ b/src/codec-components/ViewCodec/CStruct.tsx @@ -1,33 +1,65 @@ import { ExpandBtn } from "@/components/Expand" -import { getFinalType } from "@/utils/shape" import { ViewStruct } from "@codec-components" +import { Var } from "@polkadot-api/metadata-builders" import { useStateObservable } from "@react-rxjs/core" import React, { useContext, useState } from "react" import { twMerge as clsx, twMerge } from "tailwind-merge" import { Marker } from "../common/Markers" -import { useSubtreeFocus } from "../common/SubtreeFocus" import { isActive$, isCollapsed$, setHovered, toggleCollapsed, } from "../common/paths.state" +import { useSubtreeFocus } from "../common/SubtreeFocus" import { ItemMarker } from "../EditCodec/Tree/codec-components" -import { ChildProvider, TitleContext } from "./TitleContext" import { CopyChildBinary, useReportBinary } from "./CopyBinary" +import { ChildProvider, TitleContext } from "./TitleContext" +import { isComplexNested } from "./utils" const StructItem: React.FC<{ name: string children: React.ReactNode path: string[] - type?: string -}> = ({ name, children, path }) => { + field: Var + value: unknown +}> = ({ name, children, path, field, value }) => { const pathStr = path.join(".") const isActive = useStateObservable(isActive$(pathStr)) const isExpanded = !useStateObservable(isCollapsed$(pathStr)) const hasParentTitle = !!useContext(TitleContext) const [titleElement, setTitleElement] = useState(null) + const isComplexShape = isComplexNested(field, value) + + const title = isComplexShape ? ( + toggleCollapsed(pathStr)} + className="cursor-pointer flex select-none items-center py-1 gap-1" + > + {hasParentTitle && } + + + {name} + +
+ +
+
+ ) : ( + + {hasParentTitle && } + + {name} + + +
{children}
+
+ +
+
+ ) + return (
  • - toggleCollapsed(pathStr)} - className="cursor-pointer flex select-none items-center py-1 gap-1" - > - {hasParentTitle && } - - - {name} - -
    - + {title} + {isComplexShape && ( +
    + {children}
    - -
    - {children} -
    + )}
  • ) @@ -70,6 +92,7 @@ export const CStruct: ViewStruct = ({ path, shape, encodedValue, + value, }) => { useReportBinary(encodedValue) const focus = useSubtreeFocus() @@ -92,7 +115,8 @@ export const CStruct: ViewStruct = ({ name={name} key={name} path={[...path, name]} - type={getFinalType(shape, name)} + field={shape.value[name]} + value={value[name]} > {jsx} diff --git a/src/codec-components/ViewCodec/utils.ts b/src/codec-components/ViewCodec/utils.ts new file mode 100644 index 0000000..6e90fa1 --- /dev/null +++ b/src/codec-components/ViewCodec/utils.ts @@ -0,0 +1,14 @@ +import { getEnumInnerVar, isComplex } from "@/utils/shape" +import { Var } from "@polkadot-api/metadata-builders" + +export const isComplexNested = (field: Var, value: any): boolean => { + if (!isComplex(field.type)) return false + + if (field.type === "enum") + return isComplexNested(getEnumInnerVar(field, value.type), value.value) + + if (field.type === "option") + return value == null ? false : isComplexNested(field.value, value) + + return true +} diff --git a/src/pages/Storage/Storage.tsx b/src/pages/Storage/Storage.tsx index 7ab3fa8..e6f1d9c 100644 --- a/src/pages/Storage/Storage.tsx +++ b/src/pages/Storage/Storage.tsx @@ -30,8 +30,8 @@ const metadataStorage$ = state( export const Storage = withSubscribe(() => { const { lookup, entries } = useStateObservable(metadataStorage$) - const [pallet, setPallet] = useState("Staking") - const [entry, setEntry] = useState("ErasStakersPaged") + const [pallet, setPallet] = useState("System") + const [entry, setEntry] = useState("Account") const selectedPallet = (pallet && lookup.metadata.pallets.find((p) => p.name === pallet)) || null diff --git a/src/pages/Storage/StorageSubscriptions.tsx b/src/pages/Storage/StorageSubscriptions.tsx index ec5a693..39d74d3 100644 --- a/src/pages/Storage/StorageSubscriptions.tsx +++ b/src/pages/Storage/StorageSubscriptions.tsx @@ -38,7 +38,7 @@ export const StorageSubscriptions: FC = () => { const StorageSubscriptionBox: FC<{ subscription: string }> = ({ subscription, }) => { - const [mode, setMode] = useState<"json" | "decoded">("json") + const [mode, setMode] = useState<"json" | "decoded">("decoded") const storageSubscription = useStateObservable( storageSubscription$(subscription), ) @@ -181,14 +181,16 @@ const ValueDisplay: FC<{

    {title}

    {mode === "decoded" ? ( - +
    + +
    ) : ( )} diff --git a/src/utils/shape.ts b/src/utils/shape.ts index 1be164f..5ca6475 100644 --- a/src/utils/shape.ts +++ b/src/utils/shape.ts @@ -1,7 +1,14 @@ -import { EnumVar, StructVar } from "@polkadot-api/metadata-builders" +import { EnumVar, StructVar, Var } from "@polkadot-api/metadata-builders" -const complexTypes = new Set(["array", "sequence", "struct", "enum", "result"]) -export const isComplex = (type: string) => complexTypes.has(type) +const complexTypes = new Set([ + "array", + "sequence", + "struct", + "enum", + "result", + "option", +]) +export const isComplex = (type: Var["type"]) => complexTypes.has(type) export const isEnumComplex = ( shape: T, @@ -13,15 +20,17 @@ export const isEnumComplex = ( ) } +export const getEnumInnerVar = ( + shape: T, + type: keyof T["value"], +): Var => { + const innerShape = shape.value[type] + return innerShape.type === "lookupEntry" ? innerShape.value : innerShape +} export const getEnumInnerType = ( shape: T, type: keyof T["value"], -) => { - const innerShape = shape.value[type] - return innerShape.type === "lookupEntry" - ? innerShape.value.type - : innerShape.type -} +) => getEnumInnerVar(shape, type).type export const getStructInnerType = ( shape: T,