PageSourceSearch

https://bigmind2.genie9.com/workers/folder-scanner.worker.js

js genie9.com collected 2026-09-24 10:29:11 UTC 4,132 bytes, 158 lines download raw bytes

1/**
2 * Web Worker for Folder Structure Analysis
3 *
4 * Performs folder scanning in background thread to prevent UI blocking
5 * for large folders (hundreds/thousands of files)
6 */
7
8// Listen for messages from main thread
9self.addEventListener('message', async (event) => {
10  const { type, files } = event.data;
11
12  if (type === 'SCAN_FOLDER') {
13    try {
14      console.log('[FolderWorker] Starting scan of', files.length, 'files');
15
16      // Build folder structure
17      const result = await analyzeFolderStructure(files);
18
19      // Send completion message
20      self.postMessage({
21        type: 'SCAN_COMPLETE',
22        result
23      });
24
25    } catch (error) {
26      console.error('[FolderWorker] Scan failed:', error);
27      self.postMessage({
28        type: 'SCAN_ERROR',
29        error: error.message || 'Unknown error'
30      });
31    }
32  }
33});
34
35/**
36 * Analyze folder structure from file list
37 */
38async function analyzeFolderStructure(files) {
39  // Build folder structure from files
40  const root = {
41    name: '',
42    path: '',
43    files: [],
44    children: [],
45    fileCount: 0,
46    totalSize: 0
47  };
48
49  const folderMap = new Map();
50  folderMap.set('', root);
51
52  let processedFiles = 0;
53  const totalFiles = files.length;
54
55  // Process each file and build hierarchy
56  for (let i = 0; i < files.length; i++) {
57    const file = files[i];
58    const relativePath = file.webkitRelativePath || file.name;
59    const parts = relativePath.split('/');
60
61    // Build folder hierarchy
62    let currentPath = '';
63    for (let j = 0; j < parts.length - 1; j++) {
64      const folderPart = parts[j];
65      const parentPath = currentPath;
66      currentPath = currentPath ? `${currentPath}/${folderPart}` : folderPart;
67
68      if (!folderMap.has(currentPath)) {
69        const newFolder = {
70          name: folderPart,
71          path: currentPath,
72          files: [],
73          children: [],
74          fileCount: 0,
75          totalSize: 0
76        };
77
78        folderMap.set(currentPath, newFolder);
79
80        // Add to parent's children
81        const parent = folderMap.get(parentPath);
82        if (parent) {
83          parent.children.push(newFolder);
84        }
85      }
86    }
87
88    // Add file to its parent folder (files are already serialized objects)
89    const parentPath = parts.slice(0, -1).join('/');
90    const parentFolder = folderMap.get(parentPath);
91    if (parentFolder) {
92      parentFolder.files.push(file);
93    }
94
95    // Send progress update every 50 files or if last file
96    processedFiles++;
97    if (processedFiles % 50 === 0 || processedFiles === totalFiles) {
98      const progress = Math.floor((processedFiles / totalFiles) * 90); // Reserve 90% for file processing
99      self.postMessage({
100        type: 'SCAN_PROGRESS',
101        progress,
102        processedFiles,
103        totalFiles
104      });
105    }
106  }
107
108  // Calculate totals recursively
109  const calculateTotals = (node) => {
110    node.fileCount = node.files.length;
111    node.totalSize = node.files.reduce((sum, file) => sum + file.size, 0);
112
113    for (const child of node.children) {
114      calculateTotals(child);
115      node.fileCount += child.fileCount;
116      node.totalSize += child.totalSize;
117    }
118  };
119
120  calculateTotals(root);
121
122  // Calculate max depth
123  const calculateMaxDepth = (node, currentDepth = 0) => {
124    if (node.children.length === 0) {
125      return currentDepth;
126    }
127    return Math.max(...node.children.map(child => calculateMaxDepth(child, currentDepth + 1)));
128  };
129
130  const maxDepth = calculateMaxDepth(root);
131
132  // Get root folder name from first file
133  const firstFile = files[0];
134  const firstPath = firstFile.webkitRelativePath || firstFile.name;
135  const folderName = firstPath.split('/')[0] || 'Unknown Folder';
136
137  // Count total folders
138  const totalFolders = folderMap.size - 1; // Exclude root
139
140  // Final progress update (100%)
141  self.postMessage({
142    type: 'SCAN_PROGRESS',
143    progress: 100,
144    processedFiles: totalFiles,
145    totalFiles
146  });
147
148  return {
149    folderName,
150    totalFiles: files.length,
151    totalFolders,
152    totalSize: root.totalSize,
153    maxDepth,
154    folderTree: root
155  };
156}
157
158console.log('[FolderWorker] Worker initialized and ready');

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.