fix: leave the Files trash out of search results

This commit is contained in:
Linus Rath
2026-11-03 00:17:44 +01:00
parent c34c0d4173
commit 70ffd7f000
2 changed files with 21 additions and 1 deletions
@@ -445,4 +445,21 @@ describe('files provider', () => {
expect(hits.map((h) => h.id)).toEqual(['d']);
expect(hits[0]).toMatchObject({ isFolder: true });
});
// The Files trash is a folder the app keeps (.Trash, one folder per
// delete): neither it nor what was deleted is a hit.
it('leaves the Files trash and everything in it out of the hits', async () => {
const listing = [
{ id: 'zebra-live', parentId: null, name: 'zebra.txt', type: 'text/plain', blobId: 'b1', size: 1, created: '', modified: '' },
{ id: 'trash', parentId: null, name: '.Trash', type: 'd', blobId: null, size: 0, created: '', modified: '' },
{ id: 'batch', parentId: 'trash', name: '1730112000000~zebra', type: 'd', blobId: null, size: 0, created: '', modified: '' },
{ id: 'zebra-gone', parentId: 'batch', name: 'zebra old.txt', type: 'text/plain', blobId: 'b2', size: 1, created: '', modified: '' },
];
invalidateFileSearchCache();
const acc = account('login-t', { listAllFileNodesAcrossAccounts: vi.fn(async () => listing) });
const { hits } = await filesProvider.remote(parseSearchQuery('zebra'), acc, { limit: 10, signal });
expect(hits.map((h) => h.id)).toEqual(['zebra-live']);
const trash = await filesProvider.remote(parseSearchQuery('trash'), acc, { limit: 10, signal });
expect(trash.hits).toEqual([]);
});
});
+4 -1
View File
@@ -2,6 +2,7 @@ import { matchesTerms, type ParsedQuery } from '@/lib/global-search/query-parser
import type { FileHit, SearchAccount, SearchProvider } from '@/lib/global-search/types';
import type { FileNode } from '@/lib/jmap/types';
import { fileNodeKind } from '@/lib/jmap/filenode-kind';
import { findTrashFolder, trashSubtreeIds } from '@/lib/files-trash';
import { useFileStore } from '@/stores/file-store';
/**
@@ -93,9 +94,11 @@ export function rawFileNodeId(node: FileNode): string {
function filterNodes(parsed: ParsedQuery, nodes: FileNode[], account: SearchAccount, limit: number, source: 'local' | 'remote'): FileHit[] {
const hits: FileHit[] = [];
// The Files trash (.Trash, one folder per delete, what was deleted) is no hit.
const trashed = trashSubtreeIds(nodes, findTrashFolder(nodes)?.id);
for (const node of nodes) {
// The owner's folders above a shared node only feed the path below.
if (node.discoverableOnly) continue;
if (node.discoverableOnly || trashed.has(node.id)) continue;
const kind = fileNodeKind(node);
// A symlink has nothing a hit could open.
if (kind === 'symlink') continue;