mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-22 09:37:17 +00:00
Introduce WinampButton
This commit is contained in:
parent
83d18ed9b7
commit
85a80ef084
6 changed files with 527 additions and 1298 deletions
File diff suppressed because one or more lines are too long
|
|
@ -4,6 +4,7 @@ import { useTypedSelector, useActionCreator } from "../../hooks";
|
|||
import * as Selectors from "../../selectors";
|
||||
import * as Actions from "../../actionCreators";
|
||||
import VerticalSlider from "../VerticalSlider";
|
||||
import WinampButton from "../WinampButton";
|
||||
|
||||
interface Props {
|
||||
id: string;
|
||||
|
|
@ -46,7 +47,11 @@ export default function Band({ id, onChange, band }: Props) {
|
|||
// Note: The band background is actually one pixel taller (63) than the slider
|
||||
// it contains (62).
|
||||
return (
|
||||
<div id={id} className="band" style={{ backgroundPosition, height: 63 }}>
|
||||
<WinampButton
|
||||
id={id}
|
||||
className="band"
|
||||
style={{ backgroundPosition, height: 63 }}
|
||||
>
|
||||
<VerticalSlider
|
||||
height={62}
|
||||
width={14}
|
||||
|
|
@ -57,6 +62,6 @@ export default function Band({ id, onChange, band }: Props) {
|
|||
onAfterChange={usetFocus}
|
||||
handle={<Handle />}
|
||||
/>
|
||||
</div>
|
||||
</WinampButton>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { memo } from "react";
|
||||
import * as Actions from "../../actionCreators";
|
||||
import { useActionCreator } from "../../hooks";
|
||||
import WinampButton from "../WinampButton";
|
||||
|
||||
const ActionButtons = memo(() => {
|
||||
const previous = useActionCreator(Actions.previous);
|
||||
|
|
@ -10,11 +11,11 @@ const ActionButtons = memo(() => {
|
|||
const stop = useActionCreator(Actions.stop);
|
||||
return (
|
||||
<div className="actions">
|
||||
<div id="previous" onClick={previous} title="Previous Track" />
|
||||
<div id="play" onClick={play} title="Play" />
|
||||
<div id="pause" onClick={pause} title="Pause" />
|
||||
<div id="stop" onClick={stop} title="Stop" />
|
||||
<div id="next" onClick={next} title="Next Track" />
|
||||
<WinampButton id="previous" onClick={previous} title="Previous Track" />
|
||||
<WinampButton id="play" onClick={play} title="Play" />
|
||||
<WinampButton id="pause" onClick={pause} title="Pause" />
|
||||
<WinampButton id="stop" onClick={stop} title="Stop" />
|
||||
<WinampButton id="next" onClick={next} title="Next Track" />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import PlaylistScrollBar from "./PlaylistScrollBar";
|
|||
import { AppState } from "../../types";
|
||||
import FocusTarget from "../FocusTarget";
|
||||
import { useActionCreator, useTypedSelector } from "../../hooks";
|
||||
import WinampButton from "../WinampButton";
|
||||
|
||||
interface Props {
|
||||
analyser: AnalyserNode;
|
||||
|
|
@ -122,9 +123,9 @@ function PlaylistWindow({ analyser }: Props) {
|
|||
<div className="playlist-middle-center">
|
||||
<TrackList />
|
||||
</div>
|
||||
<div className="playlist-middle-right draggable">
|
||||
<WinampButton className="playlist-middle-right draggable">
|
||||
<PlaylistScrollBar />
|
||||
</div>
|
||||
</WinampButton>
|
||||
</div>
|
||||
<div className="playlist-bottom draggable">
|
||||
<div className="playlist-bottom-left draggable">
|
||||
|
|
|
|||
83
packages/webamp/js/components/WinampButton.tsx
Normal file
83
packages/webamp/js/components/WinampButton.tsx
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import classnames from "classnames";
|
||||
import {
|
||||
useCallback,
|
||||
DetailedHTMLProps,
|
||||
HTMLAttributes,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
const ACTIVE_CLASSNAME = "winamp-active";
|
||||
const LEFT_MOUSE_NUMBER = 0;
|
||||
|
||||
type Props = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
||||
|
||||
/**
|
||||
* Renders a `div` with an `.winamp-active` class if the element is being clicked/tapped.
|
||||
*
|
||||
* For now this mimicks the behavior of `:active`, but in the future we will use
|
||||
* this component to mimic Winamp's behavior, which is quite different than
|
||||
* `:active`.
|
||||
*
|
||||
* https://html.spec.whatwg.org/multipage/semantics-other.html#selector-active
|
||||
*
|
||||
* > An element is said to be being actively pointed at while the user indicates
|
||||
* > the element using a pointing device while that pointing device is in the
|
||||
* > "down" state (e.g. for a mouse, between the time the mouse button is pressed
|
||||
* > and the time it is depressed; for a finger in a multitouch environment, while
|
||||
* > the finger is touching the display surface).
|
||||
*/
|
||||
export default function WinampButton(props: Props): JSX.Element {
|
||||
const [active, setActive] = useState(false);
|
||||
const originalOnMouseDown = props.onMouseDown;
|
||||
|
||||
const onMouseDown = useCallback(
|
||||
(e) => {
|
||||
if (originalOnMouseDown != null) {
|
||||
originalOnMouseDown(e);
|
||||
}
|
||||
// We only care about left mouse.
|
||||
if (e.nativeEvent.button !== LEFT_MOUSE_NUMBER) {
|
||||
return;
|
||||
}
|
||||
setActive(true);
|
||||
|
||||
function onUp(ee: MouseEvent) {
|
||||
if (ee.button !== LEFT_MOUSE_NUMBER) {
|
||||
return;
|
||||
}
|
||||
setActive(false);
|
||||
document.removeEventListener("mouseup", onUp);
|
||||
}
|
||||
document.addEventListener("mouseup", onUp);
|
||||
},
|
||||
[originalOnMouseDown]
|
||||
);
|
||||
|
||||
const originalOnTouchStart = props.onTouchStart;
|
||||
|
||||
const onTouchStart = useCallback(
|
||||
(e) => {
|
||||
if (originalOnTouchStart != null) {
|
||||
originalOnTouchStart(e);
|
||||
}
|
||||
setActive(true);
|
||||
|
||||
function onUp() {
|
||||
setActive(false);
|
||||
document.removeEventListener("touchend", onUp);
|
||||
}
|
||||
document.addEventListener("touchend", onUp);
|
||||
},
|
||||
[originalOnTouchStart]
|
||||
);
|
||||
|
||||
const className = classnames(props.className, { [ACTIVE_CLASSNAME]: active });
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={className}
|
||||
onMouseDown={onMouseDown}
|
||||
onTouchStart={onTouchStart}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -16,17 +16,17 @@ export const imageSelectors: Selectors = {
|
|||
"#balance:active::-moz-range-thumb",
|
||||
],
|
||||
MAIN_PREVIOUS_BUTTON: [".actions #previous"],
|
||||
MAIN_PREVIOUS_BUTTON_ACTIVE: [".actions #previous:active"],
|
||||
MAIN_PREVIOUS_BUTTON_ACTIVE: [".actions #previous.winamp-active"],
|
||||
MAIN_PLAY_BUTTON: [".actions #play"],
|
||||
MAIN_PLAY_BUTTON_ACTIVE: [".actions #play:active"],
|
||||
MAIN_PLAY_BUTTON_ACTIVE: [".actions #play.winamp-active"],
|
||||
MAIN_PAUSE_BUTTON: [".actions #pause"],
|
||||
MAIN_PAUSE_BUTTON_ACTIVE: [".actions #pause:active"],
|
||||
MAIN_PAUSE_BUTTON_ACTIVE: [".actions #pause.winamp-active"],
|
||||
MAIN_STOP_BUTTON: [".actions #stop"],
|
||||
MAIN_STOP_BUTTON_ACTIVE: [".actions #stop:active"],
|
||||
MAIN_STOP_BUTTON_ACTIVE: [".actions #stop.winamp-active"],
|
||||
MAIN_NEXT_BUTTON: [".actions #next"],
|
||||
MAIN_NEXT_BUTTON_ACTIVE: [".actions #next:active"],
|
||||
MAIN_NEXT_BUTTON_ACTIVE: [".actions #next.winamp-active"],
|
||||
MAIN_EJECT_BUTTON: ["#eject"],
|
||||
MAIN_EJECT_BUTTON_ACTIVE: ["#eject:active"],
|
||||
MAIN_EJECT_BUTTON_ACTIVE: ["#eject.winamp-active"],
|
||||
MAIN_WINDOW_BACKGROUND: ["#main-window"],
|
||||
MAIN_STEREO: [".media-info #stereo", ".stop .media-info #stereo.selected"],
|
||||
MAIN_STEREO_SELECTED: [".media-info #stereo.selected"],
|
||||
|
|
@ -83,7 +83,7 @@ export const imageSelectors: Selectors = {
|
|||
PLAYLIST_RIGHT_TILE: [".playlist-middle-right"],
|
||||
PLAYLIST_SCROLL_HANDLE: [".playlist-scrollbar-handle"],
|
||||
PLAYLIST_SCROLL_HANDLE_SELECTED: [
|
||||
".playlist-middle-right:active .playlist-scrollbar-handle",
|
||||
".playlist-middle-right.winamp-active .playlist-scrollbar-handle",
|
||||
],
|
||||
PLAYLIST_BOTTOM_TILE: [".playlist-bottom"],
|
||||
PLAYLIST_BOTTOM_LEFT_CORNER: [".playlist-bottom-left"],
|
||||
|
|
@ -158,7 +158,7 @@ export const imageSelectors: Selectors = {
|
|||
EQ_SLIDER_THUMB: [".band .slider-handle"],
|
||||
// But the "active" pseudo selector on the parent, since clicking
|
||||
// anywhere on the track moves the slider.
|
||||
EQ_SLIDER_THUMB_SELECTED: [".band:active .slider-handle"],
|
||||
EQ_SLIDER_THUMB_SELECTED: [".band.winamp-active .slider-handle"],
|
||||
EQ_ON_BUTTON: ["#on"],
|
||||
EQ_ON_BUTTON_DEPRESSED: ["#on:active"],
|
||||
EQ_ON_BUTTON_SELECTED: ["#on.selected"],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue