diff --git a/static/sessions.js b/static/sessions.js index 36a3e365..0de9a277 100644 --- a/static/sessions.js +++ b/static/sessions.js @@ -7725,6 +7725,7 @@ function renderSessionListFromCache(){ } }; const _finishSessionGesture=(clientX,clientY,target,pointerType)=>{ + if(_gestureState==='idle') return false; // press never began on this row const wasDragging=_gestureState==='dragging'||_swipeTracking; _clearLongPressTimer(); if(_renamingSid){_gestureState='idle';return false;} diff --git a/tests/test_session_touch_actions.py b/tests/test_session_touch_actions.py index a9a8f2af..ce4d8ae8 100644 --- a/tests/test_session_touch_actions.py +++ b/tests/test_session_touch_actions.py @@ -283,3 +283,33 @@ def test_touch_session_rows_preserve_vertical_scroll(): assert "user-select:none" in item_rule assert "-webkit-user-select:none" in item_rule assert "-webkit-touch-callout:none" in item_rule + + +def test_session_gesture_finish_ignores_idle_state(): + """Test that _finishSessionGesture bails early when _gestureState is 'idle'. + + This prevents unintended session switches when a drag starts outside the + session row and ends on top of it. The gesture must have begun with a + pointerdown on the row itself (_gestureState='pressing'), otherwise the + pointerup should be ignored. + + See: https://github.com/nesquena/hermes-webui/issues/5462 + """ + # Find the _finishSessionGesture function + fn_start = SESSIONS_JS.find("const _finishSessionGesture=(clientX,clientY,target,pointerType)=>{") + assert fn_start != -1, "_finishSessionGesture function not found" + + # Extract the first ~200 characters of the function body + fn_body_start = SESSIONS_JS[fn_start:fn_start+200] + + # Verify the idle-state guard is present at the beginning + assert "if(_gestureState==='idle') return false;" in fn_body_start, \ + "Missing idle-state guard at the beginning of _finishSessionGesture" + + # Also verify that the fork row handler has the same guard (consistency check) + # Fork handler pattern: rowEl.onpointerup followed by pointerType/button check, then idle guard + fork_handler_start = SESSIONS_JS.find("rowEl.onpointerup=(e)=>{") + assert fork_handler_start != -1, "Fork row pointerup handler not found" + fork_handler_snippet = SESSIONS_JS[fork_handler_start:fork_handler_start+200] + assert "if(_gestureState==='idle') return;" in fork_handler_snippet, \ + "Fork row pointerup handler should have idle guard"