33 * SPDX-License-Identifier: AGPL-3.0-or-later
44 */
55
6- import { getClient , getDefaultPropfind , getRootPath , resultToNode } from '@nextcloud/files/dav'
6+ import { getClient , getDavNameSpaces , getDavProperties , getRootPath , resultToNode } from '@nextcloud/files/dav'
77
88export const OFFICE_MIME_FILTERS = {
99 documents : [
@@ -38,12 +38,48 @@ export const OFFICE_MIME_FILTERS = {
3838
3939const ALL_OFFICE_MIMES = Object . values ( OFFICE_MIME_FILTERS ) . flat ( )
4040
41+ // Pre-computed at module load time — ALL_OFFICE_MIMES is static so this never changes.
42+ const OFFICE_MIME_CONDITIONS = ALL_OFFICE_MIMES
43+ . map ( mime => `\t\t\t\t<d:eq><d:prop><d:getcontenttype/></d:prop><d:literal>${ mime } </d:literal></d:eq>` )
44+ . join ( '\n' )
45+
46+ /**
47+ * Build a DAV SEARCH request body that matches files of any office MIME type
48+ * across all subdirectories (depth: infinity).
49+ *
50+ * @return {string } XML string for the SEARCH request body
51+ */
52+ function getOfficeMimeSearch ( ) {
53+ return `<?xml version="1.0" encoding="UTF-8"?>
54+ <d:searchrequest ${ getDavNameSpaces ( ) } >
55+ <d:basicsearch>
56+ <d:select>
57+ <d:prop>
58+ ${ getDavProperties ( ) }
59+ </d:prop>
60+ </d:select>
61+ <d:from>
62+ <d:scope>
63+ <d:href>${ getRootPath ( ) } /</d:href>
64+ <d:depth>infinity</d:depth>
65+ </d:scope>
66+ </d:from>
67+ <d:where>
68+ <d:or>
69+ ${ OFFICE_MIME_CONDITIONS }
70+ </d:or>
71+ </d:where>
72+ </d:basicsearch>
73+ </d:searchrequest>`
74+ }
75+
4176/** @type {import('@nextcloud/files').Node[]|null } */
4277let cachedNodes = null
4378
4479/**
4580 * Fetch all office files once and cache the result.
4681 * Subsequent calls return the cached array.
82+ * Uses DAV SEARCH to recursively find office files across all subdirectories.
4783 *
4884 * @return {Promise<import('@nextcloud/files').Node[]> }
4985 */
@@ -53,16 +89,15 @@ export async function getAllOfficeFiles() {
5389 }
5490
5591 const client = getClient ( )
56- const propfindPayload = getDefaultPropfind ( )
5792
58- const response = await client . getDirectoryContents ( getRootPath ( ) , {
93+ const response = await client . search ( '/' , {
5994 details : true ,
60- data : propfindPayload ,
95+ data : getOfficeMimeSearch ( ) ,
6196 } )
6297
63- cachedNodes = response . data
98+ cachedNodes = response . data . results
6499 . map ( item => resultToNode ( item ) )
65- . filter ( node => node . type === 'file' && ALL_OFFICE_MIMES . includes ( node . mime ) )
100+ . filter ( node => node . type === 'file' )
66101
67102 return cachedNodes
68103}
0 commit comments