inline non-complex parts in the ViewCodec

This commit is contained in:
Victor Oliva
2024-10-27 17:20:01 +01:00
parent ce64794acd
commit fd312876bf
5 changed files with 95 additions and 46 deletions
+50 -26
View File
@@ -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<HTMLElement | null>(null)
const isComplexShape = isComplexNested(field, value)
const title = isComplexShape ? (
<span
onClick={() => toggleCollapsed(pathStr)}
className="cursor-pointer flex select-none items-center py-1 gap-1"
>
{hasParentTitle && <ItemMarker />}
<ExpandBtn expanded={isExpanded} />
<span className="flex items-center gap-1" ref={setTitleElement}>
<span className="opacity-75">{name}</span>
</span>
<div className="flex-1 text-right">
<CopyChildBinary visible={isActive} />
</div>
</span>
) : (
<span className="flex items-center py-1 gap-1">
{hasParentTitle && <ItemMarker />}
<span className="select-none flex items-center gap-1">
<span className="opacity-75">{name}</span>
<span ref={setTitleElement} />
</span>
<div>{children}</div>
<div className="flex-1 text-right">
<CopyChildBinary visible={isActive} />
</div>
</span>
)
return (
<li
className={twMerge(
@@ -39,27 +71,17 @@ const StructItem: React.FC<{
>
<ChildProvider titleElement={titleElement}>
<Marker id={path} />
<span
onClick={() => toggleCollapsed(pathStr)}
className="cursor-pointer flex select-none items-center py-1 gap-1"
>
{hasParentTitle && <ItemMarker />}
<ExpandBtn expanded={isExpanded} />
<span className="flex items-center gap-1" ref={setTitleElement}>
<span className="opacity-75">{name}</span>
</span>
<div className="flex-1 text-right">
<CopyChildBinary visible={isActive} />
{title}
{isComplexShape && (
<div
className={clsx(
"flex flex-row pl-2 pb-2",
isExpanded ? "" : "hidden",
)}
>
{children}
</div>
</span>
<div
className={clsx(
"flex flex-row pl-4 pb-2",
isExpanded ? "" : "hidden",
)}
>
{children}
</div>
)}
</ChildProvider>
</li>
)
@@ -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}
</StructItem>
+14
View File
@@ -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
}
+2 -2
View File
@@ -30,8 +30,8 @@ const metadataStorage$ = state(
export const Storage = withSubscribe(() => {
const { lookup, entries } = useStateObservable(metadataStorage$)
const [pallet, setPallet] = useState<string | null>("Staking")
const [entry, setEntry] = useState<string | null>("ErasStakersPaged")
const [pallet, setPallet] = useState<string | null>("System")
const [entry, setEntry] = useState<string | null>("Account")
const selectedPallet =
(pallet && lookup.metadata.pallets.find((p) => p.name === pallet)) || null
+11 -9
View File
@@ -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<{
<h3 className="overflow-hidden text-ellipsis">{title}</h3>
</div>
{mode === "decoded" ? (
<ViewCodec
codecType={storageSubscription.type}
value={{
type: CodecComponentType.Initial,
value: codec.enc(value),
}}
metadata={metadata}
/>
<div className="leading-tight">
<ViewCodec
codecType={storageSubscription.type}
value={{
type: CodecComponentType.Initial,
value: codec.enc(value),
}}
metadata={metadata}
/>
</div>
) : (
<JsonDisplay src={value} />
)}
+18 -9
View File
@@ -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<Var["type"]>([
"array",
"sequence",
"struct",
"enum",
"result",
"option",
])
export const isComplex = (type: Var["type"]) => complexTypes.has(type)
export const isEnumComplex = <T extends EnumVar>(
shape: T,
@@ -13,15 +20,17 @@ export const isEnumComplex = <T extends EnumVar>(
)
}
export const getEnumInnerVar = <T extends EnumVar>(
shape: T,
type: keyof T["value"],
): Var => {
const innerShape = shape.value[type]
return innerShape.type === "lookupEntry" ? innerShape.value : innerShape
}
export const getEnumInnerType = <T extends EnumVar>(
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 = <T extends StructVar>(
shape: T,