Only show chevron in trees where appropriate

This commit is contained in:
2026-09-30 15:52:06 +02:00
parent 3170d1c6d9
commit b5a8d3d003
2 changed files with 38 additions and 2 deletions
+36 -1
View File
@@ -12,6 +12,10 @@ import (
type treeEntry struct {
Name string `json:"name"`
Kind string `json:"kind"`
// HasChildren reports whether a folder has any visible entries (under the
// same foldersOnly filter), so the client can hide the expand chevron on
// empty folders without a round-trip. Always false for files.
HasChildren bool `json:"hasChildren"`
// Children is populated only along the expandTo chain (see handleTree);
// omitted otherwise so the flat picker listing keeps its original shape.
Children []treeEntry `json:"children,omitempty"`
@@ -81,7 +85,11 @@ func listTreeEntries(fsPath string, foldersOnly bool) ([]treeEntry, error) {
continue
}
if e.IsDir() {
folders = append(folders, treeEntry{Name: name, Kind: "folder"})
folders = append(folders, treeEntry{
Name: name,
Kind: "folder",
HasChildren: folderHasChildren(filepath.Join(fsPath, name), foldersOnly),
})
} else {
if foldersOnly || name == "index.md" {
continue
@@ -94,6 +102,33 @@ func listTreeEntries(fsPath string, foldersOnly bool) ([]treeEntry, error) {
return append(folders, files...), nil
}
// folderHasChildren reports whether fsPath contains at least one entry that
// listTreeEntries would list. It reads the directory in small batches and
// stops at the first match, so large folders stay cheap. Unreadable folders
// report false.
func folderHasChildren(fsPath string, foldersOnly bool) bool {
f, err := os.Open(fsPath)
if err != nil {
return false
}
defer f.Close()
for {
batch, err := f.ReadDir(32)
for _, e := range batch {
name := e.Name()
if strings.HasPrefix(name, ".") {
continue
}
if e.IsDir() || (!foldersOnly && name != "index.md") {
return true
}
}
if err != nil {
return false
}
}
}
// treePathSegments splits a wiki path into its non-empty segments.
func treePathSegments(p string) []string {
var segs []string