From ba6d55f308613d25eda0fbdb774dc2d6b7fc06b0 Mon Sep 17 00:00:00 2001 From: unschooledgamer Date: Thu, 28 May 2026 15:14:40 +0530 Subject: [PATCH 1/4] fix(fileList): rename state --- src/lib/openFolder.js | 96 +++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/src/lib/openFolder.js b/src/lib/openFolder.js index ed177c6f7..671a589bc 100644 --- a/src/lib/openFolder.js +++ b/src/lib/openFolder.js @@ -655,12 +655,7 @@ function execOperation(type, action, url, $target, name) { } newName = Url.basename(newUrl); - $target.querySelector(":scope>.text").textContent = newName; - $target.dataset.url = newUrl; - $target.dataset.name = newName; if (helpers.isFile(type)) { - $target.querySelector(":scope>span").className = - helpers.getIconForFile(newName); let file = editorManager.getFile(url, "uri"); if (file) { file.uri = newUrl; @@ -668,12 +663,11 @@ function execOperation(type, action, url, $target, name) { } } else { helpers.updateUriOfAllActiveFiles(url, newUrl); - //Reloading the folder by collapsing and expanding the folder - $target.click(); //collapse - $target.click(); //expand } - toast(strings.success); + FileList.rename(url, newUrl); + await refreshRenamedEntryInOpenFolders(url, newUrl); + toast(strings.success); } async function createNew() { @@ -1085,6 +1079,67 @@ async function refreshOpenFolder(folderUrl) { ); } +/** + * Move saved expanded-state keys after a rename. + * Supports both exact folder matches and expanded descendants. + * @param {string} oldUrl + * @param {string} newUrl + */ +function migrateOpenFolderStateUrls(oldUrl, newUrl) { + if (!oldUrl || !newUrl || oldUrl === newUrl) return; + + const getEntries = (listState) => { + if (!listState) return []; + if (listState instanceof Map) return Array.from(listState.entries()); + return Object.entries(listState); + }; + const setEntry = (listState, key, value) => { + if (listState instanceof Map) { + listState.set(key, value); + return; + } + listState[key] = value; + }; + const deleteEntry = (listState, key) => { + if (listState instanceof Map) { + listState.delete(key); + return; + } + delete listState[key]; + }; + + addedFolder.forEach(({ listState }) => { + const matchingEntries = getEntries(listState).filter(([folderUrl]) => { + return folderUrl === oldUrl || folderUrl.startsWith(`${oldUrl}/`); + }); + + if (!matchingEntries.length) return; + + matchingEntries.forEach(([folderUrl, isExpanded]) => { + deleteEntry(listState, folderUrl); + setEntry( + listState, + newUrl + folderUrl.slice(oldUrl.length), + isExpanded, + ); + }); + }); +} + +/** + * Refresh the affected parent folders after a rename so FileTree state stays in sync with the filesystem. + * @param {string} oldUrl + * @param {string} newUrl + */ +async function refreshRenamedEntryInOpenFolders(oldUrl, newUrl) { + if (!oldUrl || !newUrl || oldUrl === newUrl) return; + + migrateOpenFolderStateUrls(oldUrl, newUrl); + + const parentUrls = new Set([Url.dirname(oldUrl), Url.dirname(newUrl)]); + await Promise.all(Array.from(parentUrls).map(refreshOpenFolder)); +} + /** * Create a folder tile * @param {string} name @@ -1132,29 +1187,10 @@ openFolder.add = async (url, type) => { appendEntryToOpenFolder(parent, url, type); }; -openFolder.renameItem = (oldFile, newFile, newFilename) => { +openFolder.renameItem = (oldFile, newFile) => { FileList.rename(oldFile, newFile); - helpers.updateUriOfAllActiveFiles(oldFile, newFile); - - const filesApp = sidebarApps.get("files"); - const $els = filesApp.getAll(`[data-url="${oldFile}"]`); - Array.from($els).forEach(($el) => { - if ($el.dataset.type === "dir") { - $el = $el.$title; - setTimeout(() => { - $el.collapse(); - $el.expand(); - }, 0); - } else { - $el.querySelector(":scope>span").className = - helpers.getIconForFile(newFilename); - } - - $el.dataset.url = newFile; - $el.dataset.name = newFilename; - $el.querySelector(":scope>.text").textContent = newFilename; - }); + refreshRenamedEntryInOpenFolders(oldFile, newFile).catch(helpers.error); }; openFolder.removeItem = (url) => { From 57ff2f7c2c1ca3a64cf0d4c314587485cc358e17 Mon Sep 17 00:00:00 2001 From: unschooledgamer Date: Thu, 28 May 2026 15:59:57 +0530 Subject: [PATCH 2/4] fix: the parent selection for refresh; refresh only Ancestor if modified --- src/lib/openFolder.js | 58 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/src/lib/openFolder.js b/src/lib/openFolder.js index 671a589bc..34f66515d 100644 --- a/src/lib/openFolder.js +++ b/src/lib/openFolder.js @@ -429,6 +429,7 @@ async function handleContextmenu(type, url, name, $target) { */ function execOperation(type, action, url, $target, name) { const { clipBoard, $node, remove, url: rootUrl } = openFolder.find(url); + const parentUrl = normalizeFolderUrl(Url.dirname(url)); const startLoading = () => $node.$title.classList.add("loading"); const stopLoading = () => $node.$title.classList.remove("loading"); @@ -441,7 +442,7 @@ function execOperation(type, action, url, $target, name) { return deleteFile(); case "rename": - return renameFile(); + return renameFile(parentUrl); case "paste": return paste(); @@ -626,7 +627,7 @@ function execOperation(type, action, url, $target, name) { FileList.remove(url); } - async function renameFile() { + async function renameFile(parentUrl) { if (isTermuxSafUri(url) && !helpers.isFile(type)) { alert(strings.warning, strings["rename not supported"]); return; @@ -666,7 +667,12 @@ function execOperation(type, action, url, $target, name) { } FileList.rename(url, newUrl); - await refreshRenamedEntryInOpenFolders(url, newUrl); + await refreshRenamedEntryInOpenFolders( + url, + newUrl, + parentUrl, + normalizeFolderUrl(Url.dirname(newUrl)), + ); toast(strings.success); } @@ -1057,11 +1063,27 @@ function appendEntryToOpenFolder(parentUrl, entryUrl, type) { }); } +/** + * Normalize folder URLs for DOM/state lookup. + * Keeps roots intact while removing a trailing slash from non-root folders. + * @param {string} url + * @returns {string} + */ +function normalizeFolderUrl(url) { + if (!url) return url; + const { url: parsedUrl, query } = Url.parse(url); + if (parsedUrl.endsWith("/") && Url.pathname(parsedUrl) !== "/") { + return parsedUrl.slice(0, -1) + query; + } + return parsedUrl + query; +} + /** * Refresh matching expanded folder views. * @param {string} folderUrl */ async function refreshOpenFolder(folderUrl) { + folderUrl = normalizeFolderUrl(folderUrl); const filesApp = sidebarApps.get("files"); const $els = filesApp.getAll(`[data-url="${folderUrl}"]`); @@ -1127,17 +1149,39 @@ function migrateOpenFolderStateUrls(oldUrl, newUrl) { } /** - * Refresh the affected parent folders after a rename so FileTree state stays in sync with the filesystem. + * Refresh the minimal set of affected parent folders after a rename/move so FileTree state stays in sync with the filesystem. + * If an ancestor folder is already being refreshed, descendant folders are skipped because they will be rebuilt with the ancestor. * @param {string} oldUrl * @param {string} newUrl */ -async function refreshRenamedEntryInOpenFolders(oldUrl, newUrl) { +async function refreshRenamedEntryInOpenFolders( + oldUrl, + newUrl, + oldParentUrl = normalizeFolderUrl(Url.dirname(oldUrl)), + newParentUrl = normalizeFolderUrl(Url.dirname(newUrl)), +) { if (!oldUrl || !newUrl || oldUrl === newUrl) return; migrateOpenFolderStateUrls(oldUrl, newUrl); - const parentUrls = new Set([Url.dirname(oldUrl), Url.dirname(newUrl)]); - await Promise.all(Array.from(parentUrls).map(refreshOpenFolder)); + const isAncestorOrSame = (ancestor, descendant) => { + if (ancestor === descendant) return true; + return descendant.startsWith(`${ancestor}/`); + }; + + const parentUrls = Array.from( + new Set([oldParentUrl, newParentUrl].map(normalizeFolderUrl)), + ) + .filter(Boolean) + .filter((parentUrl, index, allParentUrls) => { + return !allParentUrls.some((otherUrl, otherIndex) => { + return ( + otherIndex !== index && isAncestorOrSame(otherUrl, parentUrl) + ); + }); + }); + + await Promise.all(parentUrls.map(refreshOpenFolder)); } /** From 93a6edaf26d8c733c1d516f5cd702a99d0f08f39 Mon Sep 17 00:00:00 2001 From: UnschooledGamer <76094069+UnschooledGamer@users.noreply.github.com> Date: Thu, 28 May 2026 19:50:56 +0530 Subject: [PATCH 3/4] fix(openFolder): normalize URLs when migrating open folder state on rename --- src/lib/openFolder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/openFolder.js b/src/lib/openFolder.js index 34f66515d..9777bf5d3 100644 --- a/src/lib/openFolder.js +++ b/src/lib/openFolder.js @@ -1162,7 +1162,7 @@ async function refreshRenamedEntryInOpenFolders( ) { if (!oldUrl || !newUrl || oldUrl === newUrl) return; - migrateOpenFolderStateUrls(oldUrl, newUrl); + migrateOpenFolderStateUrls(normalizeFolderUrl(oldUrl), normalizeFolderUrl(newUrl)); const isAncestorOrSame = (ancestor, descendant) => { if (ancestor === descendant) return true; From 1e5b55ae10b234ed066c5d459c99536c506e4502 Mon Sep 17 00:00:00 2001 From: UnschooledGamer <76094069+UnschooledGamer@users.noreply.github.com> Date: Thu, 28 May 2026 19:53:23 +0530 Subject: [PATCH 4/4] revert: newFileName removal (just kept it as-is) --- src/lib/openFolder.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/lib/openFolder.js b/src/lib/openFolder.js index 9777bf5d3..1b3f28d37 100644 --- a/src/lib/openFolder.js +++ b/src/lib/openFolder.js @@ -1139,11 +1139,7 @@ function migrateOpenFolderStateUrls(oldUrl, newUrl) { matchingEntries.forEach(([folderUrl, isExpanded]) => { deleteEntry(listState, folderUrl); - setEntry( - listState, - newUrl + folderUrl.slice(oldUrl.length), - isExpanded, - ); + setEntry(listState, newUrl + folderUrl.slice(oldUrl.length), isExpanded); }); }); } @@ -1162,7 +1158,10 @@ async function refreshRenamedEntryInOpenFolders( ) { if (!oldUrl || !newUrl || oldUrl === newUrl) return; - migrateOpenFolderStateUrls(normalizeFolderUrl(oldUrl), normalizeFolderUrl(newUrl)); + migrateOpenFolderStateUrls( + normalizeFolderUrl(oldUrl), + normalizeFolderUrl(newUrl), + ); const isAncestorOrSame = (ancestor, descendant) => { if (ancestor === descendant) return true; @@ -1175,9 +1174,7 @@ async function refreshRenamedEntryInOpenFolders( .filter(Boolean) .filter((parentUrl, index, allParentUrls) => { return !allParentUrls.some((otherUrl, otherIndex) => { - return ( - otherIndex !== index && isAncestorOrSame(otherUrl, parentUrl) - ); + return otherIndex !== index && isAncestorOrSame(otherUrl, parentUrl); }); }); @@ -1231,7 +1228,7 @@ openFolder.add = async (url, type) => { appendEntryToOpenFolder(parent, url, type); }; -openFolder.renameItem = (oldFile, newFile) => { +openFolder.renameItem = (oldFile, newFile, newFilename) => { FileList.rename(oldFile, newFile); helpers.updateUriOfAllActiveFiles(oldFile, newFile); refreshRenamedEntryInOpenFolders(oldFile, newFile).catch(helpers.error);