From 036c61dc4e600ad89940bc9be222f07e598a484a Mon Sep 17 00:00:00 2001 From: jelveh Date: Sat, 18 Jul 2026 19:58:22 -0700 Subject: [PATCH] fix: match raw item paths in move_items cleanup and shortcut re-point Item rows store data-path/data-shortcut_to_path unencoded, so the html_encode()d attribute selectors missed names containing & < > " ' and the destination-row exclusion guard could remove a legitimate row just created by a concurrent item.moved handler. Compare raw values case-insensitively instead. --- src/gui/src/helpers.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/gui/src/helpers.js b/src/gui/src/helpers.js index ce6c1fc3e..4522cd0ba 100644 --- a/src/gui/src/helpers.js +++ b/src/gui/src/helpers.js @@ -1814,15 +1814,24 @@ window.move_items = async function (el_items, dest_path, is_undo = false) { // skip next loop iteration because this iteration was successful item_with_same_name_already_exists = false; - // update all shortcut_to_path - $(`.item[data-shortcut_to_path="${html_encode($(el_item).attr('data-path'))}" i]`).attr('data-shortcut_to_path', fsentry.path); + // update all shortcut_to_path — compare raw attribute values + // (item rows store paths unencoded, so an html_encode()d + // selector misses names containing & < > " ') + const moved_from_path_lc = String($(el_item).attr('data-path') || '').toLowerCase(); + $('.item[data-shortcut_to_path]').filter(function () { + return String($(this).attr('data-shortcut_to_path')).toLowerCase() === moved_from_path_lc; + }).attr('data-shortcut_to_path', fsentry.path); // Remove all items with matching uids from their OLD location(s). // Exclude any row already at the item's new path: a concurrent // item.moved socket handler may have just created a row at the // destination (e.g. the dashboard file view showing the target // directory), and removing by uid alone would delete it too. - $(`.item[data-uid='${$(el_item).attr('data-uid')}']`).not(`[data-path="${html_encode(fsentry.path)}" i]`).fadeOut(150, function () { + // Raw case-insensitive compare, for the same reason as above. + const dest_item_path_lc = fsentry.path.toLowerCase(); + $(`.item[data-uid='${$(el_item).attr('data-uid')}']`).not(function () { + return String($(this).attr('data-path') || '').toLowerCase() === dest_item_path_lc; + }).fadeOut(150, function () { // find all parent windows that contain this item let parent_windows = $(`.item[data-uid='${$(el_item).attr('data-uid')}']`).closest('.window'); // remove this item