diff --git a/package.json b/package.json index 6205f3a..0db14a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "logseq-plugin-favorite-tree", - "version": "1.0.6", + "version": "1.1.0", "main": "dist/index.html", "logseq": { "id": "_sethyuan-logseq-favorite-tree", diff --git a/src/comps/FavList.tsx b/src/comps/FavList.tsx index f247786..1ef3651 100644 --- a/src/comps/FavList.tsx +++ b/src/comps/FavList.tsx @@ -1,23 +1,38 @@ import { produce } from "immer" import { createPortal } from "preact/compat" -import { useEffect, useState } from "preact/hooks" +import { useEffect, useRef, useState } from "preact/hooks" import { cls } from "reactutils" +import { + readExpansionState, + readRootExpansionState, + writeExpansionState, + writeRootExpansionState, +} from "../libs/storage" import { queryForSubItems } from "../libs/utils" import FavArrow from "./FavArrow" export default function FavList({ items, arrowContainer, + name, }: { items: any[] arrowContainer: HTMLElement + name: string }) { const [expanded, setExpanded] = useState(false) + useEffect(() => { + ;(async () => { + setExpanded(await readRootExpansionState(name)) + })() + }, [name]) + function toggleList(e: Event) { e.preventDefault() e.stopPropagation() setExpanded((v) => !v) + writeRootExpansionState(name, !expanded) } return ( @@ -26,13 +41,22 @@ export default function FavList({ , arrowContainer, )} - + ) } -function SubList({ items, shown }: { items: any[]; shown: boolean }) { +function SubList({ + items, + shown, + storageKey, +}: { + items: any[] + shown: boolean + storageKey: string +}) { const [childrenData, setChildrenData] = useState(null) + const expansionState = useRef>() useEffect(() => { setChildrenData(null) @@ -41,19 +65,23 @@ function SubList({ items, shown }: { items: any[]; shown: boolean }) { useEffect(() => { if (shown && childrenData == null) { ;(async () => { + expansionState.current = await readExpansionState(storageKey) const data: any = {} for (const item of items) { if (item.filters) { if (item.subitems) { data[item.displayName] = { - expanded: false, + expanded: !!expansionState.current[item.displayName], items: Object.values(item.subitems), } } } else { const subitems = await queryForSubItems(item["original-name"]) if (subitems?.length > 0) { - data[item.name] = { expanded: false, items: subitems } + data[item.name] = { + expanded: !!expansionState.current[item.name], + items: subitems, + } } } } @@ -106,6 +134,11 @@ function SubList({ items, shown }: { items: any[]; shown: boolean }) { draft[itemName].expanded = !draft[itemName].expanded }) setChildrenData(newChildrenData) + + if (expansionState.current) { + expansionState.current[itemName] = !childrenData[itemName].expanded + writeExpansionState(storageKey, expansionState.current) + } } function preventSideEffect(e: Event) { @@ -154,7 +187,11 @@ function SubList({ items, shown }: { items: any[]; shown: boolean }) { )} {data?.items?.length > 0 && ( - + )} ) diff --git a/src/libs/storage.ts b/src/libs/storage.ts new file mode 100644 index 0000000..9965020 --- /dev/null +++ b/src/libs/storage.ts @@ -0,0 +1,31 @@ +const storage = logseq.Assets.makeSandboxStorage() + +export async function readExpansionState(key: string) { + key = `expansion-${key}.json` + const str = (await storage.hasItem(key)) + ? (await storage.getItem(key))! + : "{}" + return JSON.parse(str) as Record +} + +export async function readRootExpansionState(key: string) { + key = `expansion-_${key}.json` + if (await storage.hasItem(key)) { + return JSON.parse((await storage.getItem(key))!) as boolean + } else { + return false + } +} + +export async function writeRootExpansionState(key: string, value: boolean) { + key = `expansion-_${key}.json` + await storage.setItem(key, `${value}`) +} + +export async function writeExpansionState( + key: string, + value: Record, +) { + key = `expansion-${key}.json` + await storage.setItem(key, JSON.stringify(value)) +} diff --git a/src/plugin.tsx b/src/plugin.tsx index 4eac4e2..bf858d9 100644 --- a/src/plugin.tsx +++ b/src/plugin.tsx @@ -214,13 +214,21 @@ async function injectList(el: HTMLElement, items: any[]) { } setTimeout(() => { - renderList(key, items, arrowContainer) + renderList(key, items, arrowContainer, el.dataset.ref!) }, 0) } -function renderList(key: string, items: any[], arrowContainer: HTMLElement) { +function renderList( + key: string, + items: any[], + arrowContainer: HTMLElement, + name: string, +) { const el = parent.document.getElementById(key)! - render(, el) + render( + , + el, + ) } async function onTransaction({ blocks, txData, txMeta }: any) {