Skip to content

Commit 8f8f570

Browse files
committed
fix
1 parent d1f877b commit 8f8f570

File tree

1 file changed

+81
-21
lines changed

1 file changed

+81
-21
lines changed

src/components/fileTree/index.js

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export default class FileTree {
105105
const name = entry.name || Path.basename(entry.url);
106106

107107
if (entry.isDirectory) {
108-
return this.createFolderElement(name, entry.url);
108+
return this.createFolderElement(name, entry.url, recycledEl);
109109
} else {
110110
return this.createFileElement(name, entry.url, recycledEl);
111111
}
@@ -115,12 +115,39 @@ export default class FileTree {
115115
* Create folder element (collapsible)
116116
* @param {string} name
117117
* @param {string} url
118+
* @param {HTMLElement} [recycledEl] - Optional recycled element for reuse
118119
* @returns {HTMLElement}
119120
*/
120-
createFolderElement(name, url) {
121+
createFolderElement(name, url, recycledEl) {
122+
// Try to recycle existing folder element
123+
if (recycledEl && recycledEl.classList.contains("collapsible")) {
124+
const $title = recycledEl.$title;
125+
if ($title) {
126+
$title.dataset.url = url;
127+
$title.dataset.name = name;
128+
const textEl = $title.querySelector(".text");
129+
if (textEl) textEl.textContent = name;
130+
131+
// Collapse if expanded and clear children
132+
if (!recycledEl.classList.contains("hidden")) {
133+
recycledEl.classList.add("hidden");
134+
const childTree = this.childTrees.get(recycledEl._folderUrl);
135+
if (childTree) {
136+
childTree.destroy();
137+
this.childTrees.delete(recycledEl._folderUrl);
138+
}
139+
recycledEl.$ul.innerHTML = "";
140+
}
141+
142+
recycledEl._folderUrl = url;
143+
return recycledEl;
144+
}
145+
}
146+
121147
const $wrapper = tag("div", {
122148
className: "list collapsible hidden",
123149
});
150+
$wrapper._folderUrl = url;
124151

125152
const $indicator = tag("span", { className: "icon folder" });
126153

@@ -189,10 +216,11 @@ export default class FileTree {
189216
queueMicrotask(() => toggle());
190217
}
191218

192-
// Add properties for external access
219+
// Add properties for external access (keep unclasped for collapsableList compatibility)
193220
Object.defineProperties($wrapper, {
194221
collapsed: { get: () => $wrapper.classList.contains("hidden") },
195-
unclasped: { get: () => !$wrapper.classList.contains("hidden") },
222+
expanded: { get: () => !$wrapper.classList.contains("hidden") },
223+
unclasped: { get: () => !$wrapper.classList.contains("hidden") }, // Legacy compatibility
196224
$title: { get: () => $title },
197225
$ul: { get: () => $content },
198226
expand: {
@@ -302,38 +330,70 @@ export default class FileTree {
302330
*/
303331
appendEntry(name, url, isDirectory) {
304332
const entry = { name, url, isDirectory, isFile: !isDirectory };
305-
const $el = this.createEntryElement(entry);
306333

334+
// Insert in sorted position
307335
if (isDirectory) {
308-
// Insert at beginning (before files)
309-
const firstFile = this.container.querySelector('[data-type="file"]');
310-
if (firstFile) {
311-
this.container.insertBefore($el, firstFile);
336+
// Find first file or end of dirs
337+
const insertIndex = this.entries.findIndex((e) => !e.isDirectory);
338+
if (insertIndex === -1) {
339+
this.entries.push(entry);
312340
} else {
313-
this.container.appendChild($el);
341+
this.entries.splice(insertIndex, 0, entry);
314342
}
315343
} else {
316-
// Append at end
317-
this.container.appendChild($el);
344+
this.entries.push(entry);
318345
}
319346

320-
this.entries.push(entry);
347+
// Re-sort entries
348+
this.entries = helpers.sortDir(this.entries, {
349+
sortByName: true,
350+
showHiddenFiles: true,
351+
});
352+
353+
// Update rendering based on mode
354+
if (this.virtualList) {
355+
// Virtual list mode: update items
356+
this.virtualList.setItems(this.entries);
357+
} else {
358+
// Fragment mode: re-render
359+
this.container.innerHTML = "";
360+
this.renderWithFragment();
361+
}
321362
}
322363

323364
/**
324365
* Remove an entry from the tree
325366
* @param {string} url
326367
*/
327368
removeEntry(url) {
328-
const $el = this.findElement(url);
329-
if ($el) {
330-
// For folders, remove the wrapper div
331-
if ($el.dataset.type === "dir") {
332-
$el.closest(".list.collapsible")?.remove();
333-
} else {
334-
$el.remove();
369+
// Update data first
370+
const index = this.entries.findIndex((e) => e.url === url);
371+
if (index === -1) return;
372+
373+
// Clean up child tree if folder
374+
const entry = this.entries[index];
375+
if (entry.isDirectory && this.childTrees.has(url)) {
376+
this.childTrees.get(url).destroy();
377+
this.childTrees.delete(url);
378+
}
379+
380+
// Remove from entries
381+
this.entries.splice(index, 1);
382+
383+
// Update rendering based on mode
384+
if (this.virtualList) {
385+
// Virtual list mode: update items
386+
this.virtualList.setItems(this.entries);
387+
} else {
388+
// Fragment mode: remove element directly
389+
const $el = this.findElement(url);
390+
if ($el) {
391+
if ($el.dataset.type === "dir") {
392+
$el.closest(".list.collapsible")?.remove();
393+
} else {
394+
$el.remove();
395+
}
335396
}
336-
this.entries = this.entries.filter((e) => e.url !== url);
337397
}
338398
}
339399
}

0 commit comments

Comments
 (0)