diff options
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/files-app.js | 25 | ||||
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/style.css | 10 |
2 files changed, 29 insertions, 6 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/files-app.js b/packages/meshbay-hub/src/meshbay_hub/static/files-app.js index 16ab9f6..c4b221e 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/files-app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/files-app.js @@ -139,12 +139,21 @@ function FilesPanel({ setSortKey(key); }, [sortKey]); + // With text in the field the user is searching, not browsing: match every + // file in the whole group, wherever it lives, by name or by the folder it + // sits in — and hide the folder rows, there is nothing to walk into. The + // old code only ever filtered files whose folder was exactly `currentPath`, + // so at the top of a group — where the rows are roots, never loose files — + // typing did nothing at all. + const q = filter.trim().toLowerCase(); const dirs = new Set(); const filteredEntries = entries.filter(e => { const ePath = e.path || ''; - if (ePath === currentPath) { - return !filter || e.name.toLowerCase().includes(filter.toLowerCase()); + if (q) { + return (e.name || '').toLowerCase().includes(q) + || ePath.toLowerCase().includes(q); } + if (ePath === currentPath) return true; if (!currentPath && ePath) { dirs.add(ePath.split('/')[0]); } else if (currentPath && ePath.startsWith(currentPath + '/')) { @@ -156,16 +165,17 @@ function FilesPanel({ const sorted = [...filteredEntries].sort((a, b) => { let cmp = 0; - if (sortKey === 'name') cmp = a.name.localeCompare(b.name); + if (sortKey === 'name') cmp = (a.name || '').localeCompare(b.name || ''); else if (sortKey === 'size') cmp = a.size - b.size; - else if (sortKey === 'type') cmp = a.type.localeCompare(b.type); + else if (sortKey === 'type') cmp = (a.type || '').localeCompare(b.type || ''); else if (sortKey === 'date') cmp = a.added_at - b.added_at; return sortAsc ? cmp : -cmp; }); // The node's own listing, so an empty folder is visible, plus anything implied - // by a file path in case the two ever disagree. - for (const d of nodeDirs) { + // by a file path in case the two ever disagree. Skipped while searching — the + // results are a flat list of matches, not a folder view. + if (!q) for (const d of nodeDirs) { if (!currentPath && !d.includes('/')) dirs.add(d); else if (currentPath && d.startsWith(currentPath + '/')) { const rest = d.slice(currentPath.length + 1); @@ -396,6 +406,9 @@ function FilesPanel({ ? html`<a class="file-link" onClick=${() => onPreview(e)}>${e.name}</a>` : e.name } + ${q && e.path && html` + <a class="file-loc" + onClick=${() => { setFilter(''); setCurrentPath(e.path); }}>${e.path}</a>`} </td> <td class="file-size">${formatSize(e.size)}</td> <td class="file-type td-type">${e.type}</td> diff --git a/packages/meshbay-hub/src/meshbay_hub/static/style.css b/packages/meshbay-hub/src/meshbay_hub/static/style.css index 61a5e3b..cd9882e 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/style.css +++ b/packages/meshbay-hub/src/meshbay_hub/static/style.css @@ -817,6 +817,16 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } word-break: break-word; min-width: 0; } +/* Where a search result lives, under its name; click to open that folder + and clear the filter. */ +.file-loc { + display: block; + margin-top: 2px; + font-size: 0.78em; + color: var(--text-dim); + cursor: pointer; +} +.file-loc:hover { color: var(--accent); text-decoration: underline; } .file-size { white-space: nowrap; color: var(--text-secondary); } .file-type { color: var(--text-dim); } .file-date { white-space: nowrap; color: var(--text-dim); } |