(parent, root, options = {})
| 304 | } |
| 305 | |
| 306 | async function getAllFilesNative(parent, root, options = {}) { |
| 307 | const id = `scan-${Date.now()}-${Math.random().toString(36).slice(2)}`; |
| 308 | |
| 309 | return new Promise((resolve, reject) => { |
| 310 | let settled = false; |
| 311 | |
| 312 | const finish = (fn, value) => { |
| 313 | if (settled) return; |
| 314 | settled = true; |
| 315 | fn(value); |
| 316 | }; |
| 317 | |
| 318 | const cancelIfDisconnected = () => { |
| 319 | if (root.isConnected) return false; |
| 320 | try { |
| 321 | sdcard.workspaceCancel(id); |
| 322 | } catch (_) { |
| 323 | // ignore cancellation failures |
| 324 | } |
| 325 | finish(resolve); |
| 326 | return true; |
| 327 | }; |
| 328 | |
| 329 | sdcard.workspaceScan( |
| 330 | { |
| 331 | id, |
| 332 | rootUrl: parent.url, |
| 333 | title: parent.name, |
| 334 | excludeFolders: settings.value.excludeFolders, |
| 335 | showHiddenFiles: !!settings.value.fileBrowser?.showHiddenFiles, |
| 336 | defaultEncoding: settings.value.defaultFileEncoding, |
| 337 | indexContent: !!options.indexContent, |
| 338 | }, |
| 339 | (event) => { |
| 340 | if (cancelIfDisconnected()) return; |
| 341 | switch (event?.type || event?.action) { |
| 342 | case "batch": |
| 343 | addNativeEntries(root, event.entries || []); |
| 344 | break; |
| 345 | case "done": |
| 346 | finish(resolve); |
| 347 | break; |
| 348 | case "error": |
| 349 | finish(reject, new Error(event.error || "Native scan failed")); |
| 350 | break; |
| 351 | } |
| 352 | }, |
| 353 | (error) => { |
| 354 | finish(reject, error); |
| 355 | }, |
| 356 | ); |
| 357 | }); |
| 358 | } |
| 359 | |
| 360 | function addNativeEntries(root, entries) { |
| 361 | for (const item of entries) { |
no test coverage detected