diff --git a/src/workspaces/officerdev/src/apps/Soulseek/SharesBrowser.tsx b/src/workspaces/officerdev/src/apps/Soulseek/SharesBrowser.tsx index 65e15b42..d09a01b7 100644 --- a/src/workspaces/officerdev/src/apps/Soulseek/SharesBrowser.tsx +++ b/src/workspaces/officerdev/src/apps/Soulseek/SharesBrowser.tsx @@ -246,13 +246,17 @@ type TreeNodeProps = { }; const TreeNode = ({ username, node, filtered, indent, initialOpen }: TreeNodeProps) => { - const [open, setOpen] = useState(initialOpen); const [limit, setLimit] = useState(LEVEL_LIMIT); const [revealed, setRevealed] = useState(false); - // Filtering stops at a revealed row: from here down it's ordinary lazy browsing, so one click gets you - // out of the filtered skeleton and into the real folder — which is usually why you searched. + // Filtering stops at a revealed row: from here down it's ordinary lazy browsing, so opening a matched + // folder shows what's really inside it rather than the filtered skeleton — which is why you searched. const scoped = revealed ? null : filtered; + const scopedChildren = scoped?.childrenOf.get(node.name) ?? []; + + // A filtered row starts open only when the filter matched something below it. One that matched on its own + // name has nothing of its own to show, so it stays shut and behaves like any other collapsed folder. + const [open, setOpen] = useState(() => (filtered ? scopedChildren.length > 0 : initialOpen)); const expandable = node.childCount > 0 || node.fileCount > 0; const level = useSoulseekBrowseLevel({ @@ -262,7 +266,7 @@ const TreeNode = ({ username, node, filtered, indent, initialOpen }: TreeNodePro enabled: !scoped && open && node.childCount > 0, }); - const children = scoped ? (scoped.childrenOf.get(node.name) ?? []) : (level.data?.nodes ?? []); + const children = scoped ? scopedChildren : (level.data?.nodes ?? []); // In the filtered skeleton no level was fetched, so the row's own count is what says how many exist. const total = scoped ? node.childCount : (level.data?.total ?? node.childCount); const capped = !scoped && limit >= LEVEL_LIMIT_MAX; @@ -271,11 +275,18 @@ const TreeNode = ({ username, node, filtered, indent, initialOpen }: TreeNodePro const more = open && total > children.length && (!!scoped || !level.isPending); const isMatch = filtered?.matched.has(node.name) ?? false; + const toggle = () => { + // Opening a matched row with nothing matched below it leaves the filter behind, rather than opening + // into an empty folder. + if (!open && scoped && !scopedChildren.length) setRevealed(true); + setOpen((v) => !v); + }; + return (