mirror of
https://github.com/captbaritone/webamp.git
synced 2026-08-03 07:23:55 +00:00
Refactor context menu components to use hooks
This commit is contained in:
parent
e4713beb00
commit
e8c225e8f5
7 changed files with 57 additions and 42 deletions
|
|
@ -1,19 +1,11 @@
|
|||
import React, { useState, useRef, useEffect, useMemo } from "react";
|
||||
import ContextMenu from "./ContextMenu";
|
||||
|
||||
type DivProps = React.DetailedHTMLProps<
|
||||
React.HTMLAttributes<HTMLDivElement>,
|
||||
HTMLDivElement
|
||||
>;
|
||||
|
||||
interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
handle: React.ReactNode;
|
||||
renderMenu: () => React.ReactNode;
|
||||
top?: boolean;
|
||||
bottom?: boolean;
|
||||
}
|
||||
interface State {
|
||||
selected: boolean;
|
||||
}
|
||||
|
||||
function getNodeOffset(node: HTMLDivElement | null) {
|
||||
if (node == null) {
|
||||
|
|
@ -26,10 +18,18 @@ function getNodeOffset(node: HTMLDivElement | null) {
|
|||
return { top: rect.top + scrollTop, left: rect.left + scrollLeft };
|
||||
}
|
||||
|
||||
// Trigger a context menu relative to the child element when the user
|
||||
// left-clicks on the child.
|
||||
//
|
||||
// For a component that triggers relative to the user's cursor on right-click
|
||||
// see `<ContextMenuWrapper />`.
|
||||
function ContextMenuTarget(props: Props) {
|
||||
const handleNode = useRef<HTMLDivElement>(null);
|
||||
const [selected, setSelected] = useState(false);
|
||||
useEffect(() => {
|
||||
if (!selected) {
|
||||
return;
|
||||
}
|
||||
function handleGlobalClick(e: MouseEvent) {
|
||||
if (
|
||||
selected &&
|
||||
|
|
@ -58,7 +58,7 @@ function ContextMenuTarget(props: Props) {
|
|||
{ top: 0, left: 0 };
|
||||
}, [selected]);
|
||||
|
||||
const { handle, children, top, bottom, ...passThroughProps } = props;
|
||||
const { renderMenu, children, top, bottom, ...passThroughProps } = props;
|
||||
return (
|
||||
<div {...passThroughProps}>
|
||||
<div
|
||||
|
|
@ -67,7 +67,7 @@ function ContextMenuTarget(props: Props) {
|
|||
ref={handleNode}
|
||||
onClick={() => setSelected(!selected)}
|
||||
>
|
||||
{handle}
|
||||
{children}
|
||||
</div>
|
||||
<ContextMenu
|
||||
selected={selected}
|
||||
|
|
@ -76,7 +76,7 @@ function ContextMenuTarget(props: Props) {
|
|||
top={top}
|
||||
bottom={bottom}
|
||||
>
|
||||
{children}
|
||||
{renderMenu()}
|
||||
</ContextMenu>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@ interface Props {
|
|||
children: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
selected: boolean;
|
||||
offsetTop: number | null;
|
||||
offsetLeft: number | null;
|
||||
}
|
||||
// Trigger a context menu at the user's cursor position when the user right
|
||||
// clicks within this component.
|
||||
// For a component that triggers relative to a given component when the user
|
||||
// left-clicks see `<ContextMenuTarget />`.
|
||||
|
||||
// TODO: Consider using nested contexts to ensure we don't ever have multiple
|
||||
// non-nested context menus open at a time.
|
||||
|
|
|
|||
|
|
@ -17,19 +17,27 @@ interface DispatchProps {
|
|||
}
|
||||
|
||||
const PresetsContextMenu = (props: DispatchProps) => (
|
||||
<ContextMenuTarget top id="presets-context" handle={<div id="presets" />}>
|
||||
<Parent label="Load">
|
||||
{builtin.presets.map(preset => (
|
||||
<Node
|
||||
key={preset.name}
|
||||
onClick={() => props.setEqFromObject(preset)}
|
||||
label={preset.name}
|
||||
/>
|
||||
))}
|
||||
<Hr />
|
||||
<Node onClick={props.openEqfFileDialog} label="From Eqf..." />
|
||||
</Parent>
|
||||
<Node onClick={props.downloadPreset} label="Save" />
|
||||
<ContextMenuTarget
|
||||
top
|
||||
id="presets-context"
|
||||
renderMenu={() => (
|
||||
<>
|
||||
<Parent label="Load">
|
||||
{builtin.presets.map(preset => (
|
||||
<Node
|
||||
key={preset.name}
|
||||
onClick={() => props.setEqFromObject(preset)}
|
||||
label={preset.name}
|
||||
/>
|
||||
))}
|
||||
<Hr />
|
||||
<Node onClick={props.openEqfFileDialog} label="From Eqf..." />
|
||||
</Parent>
|
||||
<Node onClick={props.downloadPreset} label="Save" />
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<div id="presets" />
|
||||
</ContextMenuTarget>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ const ClutterBar = React.memo(() => {
|
|||
const doubled = useTypedSelector(Selectors.getDoubled);
|
||||
return (
|
||||
<div id="clutter-bar">
|
||||
<ContextMenuTarget bottom handle={<div id="button-o" />}>
|
||||
<OptionsContextMenu />
|
||||
<ContextMenuTarget bottom renderMenu={() => <OptionsContextMenu />}>
|
||||
<div id="button-o" />
|
||||
</ContextMenuTarget>
|
||||
<div id="button-a" />
|
||||
<div id="button-i" />
|
||||
|
|
|
|||
|
|
@ -88,9 +88,9 @@ const MainWindow = React.memo(({ analyser, filePickers }: Props) => {
|
|||
<ContextMenuTarget
|
||||
id="option-context"
|
||||
bottom
|
||||
handle={<ClickedDiv id="option" title="Winamp Menu" />}
|
||||
renderMenu={() => <MainContextMenu filePickers={filePickers} />}
|
||||
>
|
||||
<MainContextMenu filePickers={filePickers} />
|
||||
<ClickedDiv id="option" title="Winamp Menu" />
|
||||
</ContextMenuTarget>
|
||||
{mainShade && <MiniTime />}
|
||||
<Minimize />
|
||||
|
|
|
|||
|
|
@ -11,11 +11,15 @@ interface DispatchProps {
|
|||
|
||||
const MiscOptionsContextMenu = (props: DispatchProps) => (
|
||||
<ContextMenuTarget
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
top
|
||||
handle={<div />}
|
||||
renderMenu={() => (
|
||||
<Node
|
||||
onClick={props.downloadHtmlPlaylist}
|
||||
label="Generate HTML playlist"
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<Node onClick={props.downloadHtmlPlaylist} label="Generate HTML playlist" />
|
||||
<div />
|
||||
</ContextMenuTarget>
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,16 @@ const SortContextMenu = (props: DispatchProps) => (
|
|||
<ContextMenuTarget
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
top
|
||||
handle={<div />}
|
||||
renderMenu={() => (
|
||||
<>
|
||||
<Node label="Sort list by title" onClick={props.sortListByTitle} />
|
||||
<Hr />
|
||||
<Node label="Reverse list" onClick={props.reverseList} />
|
||||
<Node label="Randomize list" onClick={props.randomizeList} />
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<Node label="Sort list by title" onClick={props.sortListByTitle} />
|
||||
<Hr />
|
||||
<Node label="Reverse list" onClick={props.reverseList} />
|
||||
<Node label="Randomize list" onClick={props.randomizeList} />
|
||||
<div />
|
||||
</ContextMenuTarget>
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue