// src/layout/file-tree/useFileTree.ts import { useState, useCallback, useEffect } from 'react' import type { AutomergeUrl } from '../../storage/document-runtime-contract' import type { Vault } from '../../plugin/vault' import { TFolder, type TAbstractFile } from '../../plugin/files' import { loadExpandedFolders, saveExpandedFolders } from './file-tree-persistence' export function useFileTree(vault: Vault, storageKey?: string) { const [expanded, setExpanded] = useState>(() => loadExpandedFolders(storageKey)) const [, setVersion] = useState(0) const toggleExpanded = useCallback((url: AutomergeUrl) => { setExpanded(prev => { const next = new Set(prev) if (next.has(url)) { next.delete(url) } else { next.add(url) } saveExpandedFolders(next, storageKey) return next }) }, [storageKey]) const isExpanded = useCallback((url: AutomergeUrl) => expanded.has(url), [expanded]) const getFolderChildren = useCallback((folderUrl: AutomergeUrl): TAbstractFile[] => { const file = vault.getAbstractFileByUrl(folderUrl) if (!file || !(file instanceof TFolder)) return [] return file.children }, [vault]) useEffect(() => { const bump = () => setVersion(v => v + 1) const createRef = vault.on('create', bump) const deleteRef = vault.on('delete', bump) const renameRef = vault.on('rename', bump) // 'modify' fires when a file's stat changes (e.g. mtime updated by // an Automerge change). Without this subscription, the date-sort // modes wouldn't re-sort when an existing file is edited. const modifyRef = vault.on('modify', bump) const statsRef = vault.on('reams-internal-stats-hydrated', bump) return () => { vault.offref(createRef) vault.offref(deleteRef) vault.offref(renameRef) vault.offref(modifyRef) vault.offref(statsRef) } }, [vault]) return { rootChildren: vault.getRoot().children, toggleExpanded, isExpanded, getFolderChildren, } }