From 7639d18aeabad8ff07d0491008412edc5d95f024 Mon Sep 17 00:00:00 2001 From: Quaffel <9200663+Quaffel@users.noreply.github.com> Date: Wed, 24 Mar 2021 22:23:24 +0100 Subject: [PATCH 1/2] Handle touch inputs appropriately --- frontend/src/tipsyselector/circleselector.tsx | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/frontend/src/tipsyselector/circleselector.tsx b/frontend/src/tipsyselector/circleselector.tsx index 8ee01ef..cc4f7ae 100644 --- a/frontend/src/tipsyselector/circleselector.tsx +++ b/frontend/src/tipsyselector/circleselector.tsx @@ -89,7 +89,13 @@ export function CircleSelector({ pressed.current.lastRegisteredInput = 0; } - function onMove(event: React.MouseEvent) { + function onMove(this: HTMLDivElement, event: MouseEvent | TouchEvent) { + function isTouchEvent(event: Event): event is TouchEvent { + return (event as any).touches; + } + + event.preventDefault(); + /* Debounce and check for mouse press */ const currentTime = new Date().getTime(); // Mouse movement only, so the input must not change the value @@ -116,10 +122,10 @@ export function CircleSelector({ } // Rectangle containing all elements. Offsets are relative to the viewport. - const targetDimensionsInViewport: DOMRect = event.currentTarget.getBoundingClientRect(); + const targetDimensionsInViewport: DOMRect = this.getBoundingClientRect(); const cursorPosition: Vector = new CartesianPoint( - event.clientX - targetDimensionsInViewport.left, - event.clientY - targetDimensionsInViewport.top + (isTouchEvent(event) ? event.touches[0].clientX : event.clientX) - targetDimensionsInViewport.left, + (isTouchEvent(event) ? event.touches[0].clientY : event.clientY) - targetDimensionsInViewport.top ); const pointOnCircleCartesian = calculateClosestPointOnCircle(cursorPosition); @@ -147,7 +153,24 @@ export function CircleSelector({ setValue(percentage); } - return
(null); + React.useEffect(() => { + const element = containerRef.current; + if (!element) { + return; + } + + // Necessary as event listeners must not be passive (Event#preventDefault fails otherwise) + element.addEventListener("mousemove", onMove, { passive: false }); + element.addEventListener("touchmove", onMove, { passive: false }); + + return () => { + element.removeEventListener("mousemove", onMove); + element.removeEventListener("touchmove", onMove); + } + }); + + return
Date: Thu, 25 Mar 2021 00:03:43 +0100 Subject: [PATCH 2/2] Add missing dependency --- frontend/src/tipsyselector/circleselector.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/tipsyselector/circleselector.tsx b/frontend/src/tipsyselector/circleselector.tsx index cc4f7ae..0dbc00b 100644 --- a/frontend/src/tipsyselector/circleselector.tsx +++ b/frontend/src/tipsyselector/circleselector.tsx @@ -168,7 +168,9 @@ export function CircleSelector({ element.removeEventListener("mousemove", onMove); element.removeEventListener("touchmove", onMove); } - }); + // eslint demands 'onMove' to be in the dependencies array as well + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [containerRef]); return