Prevent default on scroll events Fixes #1301

This commit is contained in:
Jordan Eldredge 2025-06-29 17:40:54 -07:00
parent 067623811c
commit 7ededf9bf5
5 changed files with 31 additions and 11 deletions

View file

@ -14,6 +14,7 @@
### Bug Fixes
- Fix bug where scrolling the main window or playlist window would change the volume but also (incorrectly) scroll the page.
- Fix bug where resizing the window such that the current layout cannot fit on the page, while also scrolled down the page, would cause the layout to be recentered out of view.
- Avoid a console log from Redux Dev Tools.

View file

@ -122,10 +122,8 @@ export function adjustVolume(volumeDiff: number): Thunk {
};
}
export function scrollVolume(e: React.WheelEvent<HTMLDivElement>): Thunk {
// https://github.com/facebook/react/issues/22794
// e.preventDefault();
// TODO: https://github.com/captbaritone/webamp/issues/1301
export function scrollVolume(e: WheelEvent): Thunk {
e.preventDefault();
return (dispatch, getState) => {
const currentVolume = getState().media.volume;
// Using pixels as percentage difference here is a bit arbitrary, but... oh well.

View file

@ -1,4 +1,4 @@
import { useCallback } from "react";
import { useCallback, useEffect, useRef } from "react";
import { useActionCreator } from "../hooks";
import * as Actions from "../actionCreators";
import { WindowId } from "../types";
@ -11,6 +11,7 @@ interface Coord {
interface Props extends React.HTMLAttributes<HTMLDivElement> {
handleDrop(e: React.DragEvent<HTMLDivElement>, coord: Coord): void;
windowId: WindowId;
onWheelActive?: (e: WheelEvent) => void;
}
function suppress(e: React.DragEvent<HTMLDivElement>) {
@ -20,16 +21,37 @@ function suppress(e: React.DragEvent<HTMLDivElement>) {
e.dataTransfer.effectAllowed = "link";
}
const DropTarget = (props: Props) => {
export default function DropTarget(props: Props) {
const {
// eslint-disable-next-line no-shadow, no-unused-vars
handleDrop,
windowId,
onWheelActive,
...passThroughProps
} = props;
const divRef = useRef<HTMLDivElement>(null);
const droppedFiles = useActionCreator(Actions.droppedFiles);
// Register onWheelActive as a non-passive event handler
useEffect(() => {
const element = divRef.current;
if (!element || !onWheelActive) {
return;
}
const handleWheel = (e: WheelEvent) => {
// Convert native WheelEvent to React.WheelEvent
onWheelActive(e);
};
element.addEventListener("wheel", handleWheel, { passive: false });
return () => {
element.removeEventListener("wheel", handleWheel);
};
}, [onWheelActive]);
const onDrop = useCallback(
(e: React.DragEvent<HTMLDivElement>) => {
suppress(e);
@ -48,6 +70,7 @@ const DropTarget = (props: Props) => {
);
return (
<div
ref={divRef}
{...passThroughProps}
onDragStart={suppress}
onDragEnter={suppress}
@ -55,6 +78,4 @@ const DropTarget = (props: Props) => {
onDrop={onDrop}
/>
);
};
export default DropTarget;
}

View file

@ -77,7 +77,7 @@ const MainWindow = React.memo(({ analyser, filePickers }: Props) => {
windowId={WINDOWS.MAIN}
className={className}
handleDrop={loadMedia}
onWheel={scrollVolume}
onWheelActive={scrollVolume}
>
<FocusTarget windowId={WINDOWS.MAIN}>
<div

View file

@ -97,7 +97,7 @@ function PlaylistWindow({ analyser }: Props) {
className={classes}
style={style}
handleDrop={handleDrop}
onWheel={scrollVolume}
onWheelActive={scrollVolume}
>
<div className="playlist-top draggable" onDoubleClick={toggleShade}>
<div className="playlist-top-left draggable" />