fix: sidebar touch scroll via scrollTop — bypasses broken CSS path
position:fixed + overflow:hidden on .session-sidebar in mobile overlay mode prevents Android Chrome from routing native touch-scroll to the child .sidebar-list (overflow-y:auto). Direct scrollTop manipulation always works. Mirrors the terminal WheelEvent approach: take JS control rather than relying on native CSS touch-scroll routing.
This commit is contained in:
@@ -1050,6 +1050,34 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.addEventListener('keydown', trackInteraction);
|
document.addEventListener('keydown', trackInteraction);
|
||||||
document.addEventListener('click', trackInteraction);
|
document.addEventListener('click', trackInteraction);
|
||||||
document.addEventListener('touchstart', trackInteraction);
|
document.addEventListener('touchstart', trackInteraction);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Sidebar touch scroll — manual scrollTop manipulation bypasses the CSS
|
||||||
|
// touch-scroll path that fails when position:fixed + overflow:hidden is on
|
||||||
|
// the parent (.session-sidebar) in mobile overlay mode.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
;(function initSidebarTouchScroll() {
|
||||||
|
var list = document.querySelector('.sidebar-list');
|
||||||
|
if (!list || typeof list.addEventListener !== 'function') return;
|
||||||
|
|
||||||
|
var _lastY = 0;
|
||||||
|
|
||||||
|
list.addEventListener('touchstart', function (e) {
|
||||||
|
_lastY = e.touches[0].clientY;
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
list.addEventListener('touchmove', function (e) {
|
||||||
|
e.preventDefault(); // block page scroll
|
||||||
|
var y = e.touches[0].clientY;
|
||||||
|
list.scrollTop += _lastY - y; // direct scrollTop — always works
|
||||||
|
_lastY = y;
|
||||||
|
}, { passive: false }); // passive:false required for preventDefault
|
||||||
|
|
||||||
|
list.addEventListener('touchend', function () {
|
||||||
|
_lastY = 0;
|
||||||
|
}, { passive: true });
|
||||||
|
})();
|
||||||
|
|
||||||
restoreState()
|
restoreState()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
startPolling();
|
startPolling();
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ Object.defineProperty(globalThis, 'navigator', {
|
|||||||
configurable: true,
|
configurable: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import fs from 'node:fs';
|
||||||
import { createRequire } from 'node:module';
|
import { createRequire } from 'node:module';
|
||||||
import { test } from 'node:test';
|
import { test } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
@@ -2024,3 +2025,14 @@ test('bindSidebarClickAway registers click listener on terminal-container', () =
|
|||||||
assert.strictEqual(addEventListenerCalledWith, 'click', 'bindSidebarClickAway should register a click listener on terminal-container');
|
assert.strictEqual(addEventListenerCalledWith, 'click', 'bindSidebarClickAway should register a click listener on terminal-container');
|
||||||
globalThis.document.getElementById = origGetById;
|
globalThis.document.getElementById = origGetById;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Sidebar touch scroll ---
|
||||||
|
|
||||||
|
test('app.js has sidebar touch scroll handler that uses scrollTop', () => {
|
||||||
|
const source = fs.readFileSync(
|
||||||
|
new URL('../app.js', import.meta.url), 'utf8'
|
||||||
|
);
|
||||||
|
assert.ok(source.includes('sidebar-list'), 'must target .sidebar-list');
|
||||||
|
assert.ok(source.includes('scrollTop'), 'must use scrollTop (not scrollLines or WheelEvent)');
|
||||||
|
assert.ok(source.includes('passive: false'), 'touchmove must be non-passive to allow preventDefault');
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user