From 74a819c92f6416b1a9106dbc42ceeb70dac4cbe8 Mon Sep 17 00:00:00 2001 From: jelveh Date: Sat, 8 Aug 2026 00:02:27 -0700 Subject: [PATCH] fix(gui): hold page edge-flips while a folder merge is being offered MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A tile in the pager's last column sits inside the 60px edge-flip zone, so resting a dragged icon on it — the folder-making gesture — armed the edge dwell alongside the merge dwell, and the page flipped out from under the very folder the user was watching form (the merge target scrolls away mid-offer, and the drop then resolves against its stale resting rect). Worst on phones, where 72px tiles overlap the zone across the whole last column. A live merge offer now holds the edge flip: entering the zone arms no dwell while an offer stands, and an offer that arrives during a running dwell is re-checked at the flip (a resting pointer fires no event that could clear the timer). Carrying the icon off the tile withdraws the offer and the hold with it, so deliberate flips — resting in the bare edge gutter — behave as before. --- src/gui/src/UI/Dashboard/TabApps.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/gui/src/UI/Dashboard/TabApps.js b/src/gui/src/UI/Dashboard/TabApps.js index a13f81677..41d8ab746 100644 --- a/src/gui/src/UI/Dashboard/TabApps.js +++ b/src/gui/src/UI/Dashboard/TabApps.js @@ -1791,8 +1791,16 @@ const TabApps = { const r = scroller.getBoundingClientRect(); let dir = 0; - if ( px >= r.right - DRAG_EDGE_ZONE ) dir = 1; - else if ( px <= r.left + DRAG_EDGE_ZONE ) dir = -1; + // A merge offer in progress means the icon is parked on a tile, not + // asking for a page — and a last-column tile sits inside the edge + // zone, so without this hold the page would flip out from under the + // very folder the user is watching form. Carrying the icon off the + // tile withdraws the offer (see _updatePlaceholder), and with it + // this hold. + if ( ! d.mergeEl ) { + if ( px >= r.right - DRAG_EDGE_ZONE ) dir = 1; + else if ( px <= r.left + DRAG_EDGE_ZONE ) dir = -1; + } const atEnd = (dir === 1 && this._page >= this._pageCount - 1); const atStart = (dir === -1 && this._page <= 0); @@ -1810,6 +1818,10 @@ const TabApps = { d.edgeTimer = null; d.edgeDir = 0; if ( this._drag !== d ) return; + // The offer can arrive while this dwell runs (resting on an + // edge-zone tile starts both countdowns): no pointer event fires + // during a rest to clear the timer, so re-check at the flip. + if ( d.mergeEl ) return; d.flipping = true; this.goToPage(d.$el_window, this._page + dir, true); clearTimeout(d.flipClearTimer);