From d2596203710c9c8906e44585bb7e9328bd1b2b08 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Mon, 13 Oct 2025 17:49:19 +0200 Subject: [PATCH] Refactors edge scroll start detection Improves edge scroll detection by listening for actual scroll events instead of relying on mouse position. This change ensures that the 'edgescroll:started' event is only emitted when scrolling has actually begun, preventing false positives and improving the accuracy of scroll compensation. It also removes the unnecessary scroll listener from the DragDropManager, consolidating scroll handling in the EdgeScrollManager. --- src/managers/DragDropManager.ts | 17 +--------- src/managers/EdgeScrollManager.ts | 52 ++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/managers/DragDropManager.ts b/src/managers/DragDropManager.ts index 42b9708..cece3df 100644 --- a/src/managers/DragDropManager.ts +++ b/src/managers/DragDropManager.ts @@ -182,7 +182,7 @@ export class DragDropManager { * Optimized mouse move handler with consolidated position calculations */ private handleMouseMove(event: MouseEvent): void { - + console.log('handleMouseMove', event) if (this.isScrollCompensating) return; //this.currentMouseY = event.clientY; // this.lastMousePosition = { x: event.clientX, y: event.clientY }; @@ -305,7 +305,6 @@ export class DragDropManager { */ private handleMouseUp(event: MouseEvent): void { this.stopDragAnimation(); - this.removeScrollListener(); if (this.originalElement) { @@ -376,7 +375,6 @@ export class DragDropManager { console.log('🚫 DragDropManager: Cancelling drag - mouse left grid container'); this.cleanupAllClones(); - this.removeScrollListener(); this.originalElement.style.opacity = ''; this.originalElement.style.cursor = ''; @@ -486,19 +484,6 @@ export class DragDropManager { }); } - /** - * Remove scroll listener - */ - private removeScrollListener(): void { - if (this.scrollListener && this.scrollableContent) { - this.scrollableContent.removeEventListener('scroll', this.scrollListener); - this.scrollListener = null; - } - this.isScrollCompensating = false; - this.initialScrollTop = 0; - this.initialCloneTop = 0; - } - /** * Stop drag animation */ diff --git a/src/managers/EdgeScrollManager.ts b/src/managers/EdgeScrollManager.ts index eea8b0f..77a2ec6 100644 --- a/src/managers/EdgeScrollManager.ts +++ b/src/managers/EdgeScrollManager.ts @@ -14,6 +14,8 @@ export class EdgeScrollManager { private isScrolling = false; // Track if edge-scroll is active private lastTs = 0; private rect: DOMRect | null = null; + private initialScrollTop = 0; + private scrollListener: ((e: Event) => void) | null = null; // Constants - fixed values as per requirements private readonly OUTER_ZONE = 100; // px from edge (slow zone) @@ -32,6 +34,10 @@ export class EdgeScrollManager { if (this.scrollableContent) { // Disable smooth scroll for instant auto-scroll this.scrollableContent.style.scrollBehavior = 'auto'; + + // Add scroll listener to detect actual scrolling + this.scrollListener = this.handleScroll.bind(this); + this.scrollableContent.addEventListener('scroll', this.scrollListener, { passive: true }); } }, 100); @@ -62,7 +68,10 @@ export class EdgeScrollManager { this.isScrolling = false; // Reset scroll state this.lastTs = performance.now(); - // Don't save initial positions here - wait until scrolling actually starts! + // Save initial scroll position + if (this.scrollableContent) { + this.initialScrollTop = this.scrollableContent.scrollTop; + } if (this.scrollRAF === null) { this.scrollRAF = requestAnimationFrame((ts) => this.scrollTick(ts)); @@ -71,13 +80,39 @@ export class EdgeScrollManager { private stopDrag(): void { this.isDragging = false; - this.isScrolling = false; + + // Emit stopped event if we were scrolling + if (this.isScrolling) { + this.isScrolling = false; + console.log('🛑 EdgeScrollManager: Edge-scroll stopped (drag ended)'); + this.eventBus.emit('edgescroll:stopped', {}); + } + if (this.scrollRAF !== null) { cancelAnimationFrame(this.scrollRAF); this.scrollRAF = null; } this.rect = null; this.lastTs = 0; + this.initialScrollTop = 0; + } + + private handleScroll(): void { + if (!this.isDragging || !this.scrollableContent) return; + + const currentScrollTop = this.scrollableContent.scrollTop; + const scrollDelta = Math.abs(currentScrollTop - this.initialScrollTop); + + // Only emit started event if we've actually scrolled more than 1px + if (scrollDelta > 1 && !this.isScrolling) { + this.isScrolling = true; + console.log('💾 EdgeScrollManager: Edge-scroll started (actual scroll detected)', { + initialScrollTop: this.initialScrollTop, + currentScrollTop, + scrollDelta + }); + this.eventBus.emit('edgescroll:started', {}); + } } private scrollTick(ts: number): void { @@ -114,15 +149,8 @@ export class EdgeScrollManager { } if (vy !== 0 && this.isDragging) { - // Mark that scrolling is active - if (!this.isScrolling) { - this.isScrolling = true; - console.log('💾 EdgeScrollManager: Edge-scroll started'); - // Notify DragDropManager that scroll compensation should start - this.eventBus.emit('edgescroll:started', {}); - } - // Time-based scrolling for frame-rate independence + // The scroll listener will detect actual scrolling and emit edgescroll:started this.scrollableContent.scrollTop += vy * dt; this.rect = null; // Invalidate cache for next frame this.scrollRAF = requestAnimationFrame((ts) => this.scrollTick(ts)); @@ -130,8 +158,8 @@ export class EdgeScrollManager { // Mouse moved away from edge - stop scrolling if (this.isScrolling) { this.isScrolling = false; - console.log('🛑 EdgeScrollManager: Edge-scroll stopped'); - // Notify DragDropManager that scroll compensation should stop + this.initialScrollTop = this.scrollableContent.scrollTop; // Reset for next scroll + console.log('🛑 EdgeScrollManager: Edge-scroll stopped (mouse left edge)'); this.eventBus.emit('edgescroll:stopped', {}); }