diff --git a/src/App.tsx b/src/App.tsx index bb06ea0..e601378 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,15 +4,17 @@ import { KeyTree } from './KeyTree'; import { Settings } from './Settings'; import { AllPaths } from './AllPaths'; import { store } from './store'; +import { getDefaultHashState } from './utils'; const queryClient = new QueryClient(); +const defaultState = getDefaultHashState(); function App() { return ( - - + + diff --git a/src/KeyTree.tsx b/src/KeyTree.tsx index bd2277b..6cbe123 100644 --- a/src/KeyTree.tsx +++ b/src/KeyTree.tsx @@ -1,16 +1,20 @@ -import { useAbciQuery, useToggleKeys } from './utils'; +import { useAbciQuery, useToggleKeys, useTrackKeys } from './utils'; import { DataViewer } from './DataViewer'; import * as s from './KeyTree.module.css'; type Props = { path: string; + defaultOpenKeys: { [path: string]: string[] }; + defaultDataKeys: { [path: string]: string[] }; }; -export function KeyTree({ path }: Props) { - const [openKeys, toggleOpenKey] = useToggleKeys(); - const [dataKeys, toggleDataKey] = useToggleKeys(); +export function KeyTree({ path, defaultOpenKeys, defaultDataKeys }: Props) { + const [openKeys, toggleOpenKey] = useToggleKeys(defaultOpenKeys[path]); + const [dataKeys, toggleDataKey] = useToggleKeys(defaultDataKeys[path]); const { isLoading, error, data } = useAbciQuery(`/custom/vstorage/children/${path}`); + useTrackKeys(path, openKeys, dataKeys); + if (isLoading) { return
Loading...
; } @@ -44,7 +48,13 @@ export function KeyTree({ path }: Props) { a - {openKeys.includes(k) && } + {openKeys.includes(k) && ( + + )} {dataKeys.includes(k) && } ); diff --git a/src/Settings.tsx b/src/Settings.tsx index 85d23b9..c36b086 100644 --- a/src/Settings.tsx +++ b/src/Settings.tsx @@ -2,9 +2,13 @@ import { useState, FormEvent } from 'react'; import { useStore } from './store'; import * as s from './Settings.module.css'; -export function Settings() { +type Props = { + newNode: string; +}; + +export function Settings({ newNode }: Props) { const { node, foldAmountObject, dispatch } = useStore('node', 'foldAmountObject'); - const [currentNode, setCurrentNode] = useState(node); + const [currentNode, setCurrentNode] = useState(newNode || node); const saveNode = (e: FormEvent) => { e.preventDefault(); diff --git a/src/utils.ts b/src/utils.ts index 7269d59..c80468d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,4 @@ -import { useState, useCallback } from 'react'; +import { useEffect, useState, useCallback } from 'react'; import { useQuery } from 'react-query'; import { useStore } from './store'; @@ -26,8 +26,8 @@ export const useAbciQuery = (path: string, height?: number) => { return useQuery(`${node}:${path}:${height}`, () => abciQuery(node, path, height)); }; -export const useToggleKeys = (): [string[], (k: string) => void] => { - const [keys, setKeys] = useState([]); +export const useToggleKeys = (defaultValues?: string[]): [string[], (k: string) => void] => { + const [keys, setKeys] = useState(defaultValues || []); const toggle = useCallback((key: string) => { setKeys((ks) => { @@ -40,3 +40,50 @@ export const useToggleKeys = (): [string[], (k: string) => void] => { return [keys, toggle]; }; + +type HashState = { + // node + n: string; + // open keys + o: { [key: string]: string[] }; + // data + d: { [key: string]: string[] }; +}; + +export const getDefaultHashState = () => { + const currentHash = atob(window.location.hash.substr(1)); + + if (currentHash) { + return JSON.parse(currentHash) as HashState; + } + + return { + n: '', + o: {}, + d: {}, + }; +}; + +export const useTrackKeys = (path: string, openKeys: string[], dataKeys: string[]) => { + const data = getDefaultHashState(); + + data.n = useNode(); + + if (openKeys.length > 0) { + data.o = { ...data.o, [path]: openKeys }; + } else { + delete data.o[path]; + } + + if (dataKeys.length > 0) { + data.d = { ...data.d, [path]: dataKeys }; + } else { + delete data.d[path]; + } + + const newLocation = btoa(JSON.stringify(data)); + + if (newLocation !== window.location.hash.substr(1)) { + window.location.hash = newLocation; + } +};