Abstract context menu style

This commit is contained in:
Jordan Eldredge 2017-06-05 20:03:54 -07:00
parent 513d2aab23
commit 2669b013dd
3 changed files with 102 additions and 65 deletions

View file

@ -1,23 +1,42 @@
import React from "react";
import { connect } from "react-redux";
import classnames from "classnames";
import { close, setSkinFromFilename, openFileDialog } from "../actionCreators";
import { CLOSE_CONTEXT_MENU, TOGGLE_CONTEXT_MENU } from "../actionTypes";
import "../../css/context-menu.css";
const SKINS = [
{ file: "base-2.91.wsz", name: "<Base Skin>" },
{ file: "MacOSXAqua1-5.wsz", name: "Mac OSX v1.5 (Aqua)" },
{ file: "TopazAmp1-2.wsz", name: "TopazAmp" },
{ file: "Vizor1-01.wsz", name: "Vizor" },
{ file: "XMMS-Turquoise.wsz", name: "XMMS Turquoise " },
{ file: "ZaxonRemake1-0.wsz", name: "Zaxon Remake" }
];
export const Hr = () => <li className="hr"><hr /></li>;
class ContextMenu extends React.Component {
// TODO: Add down-arrow
export const Parent = ({ children, label }) =>
<li className="parent">
<ul>
{children}
</ul>
{label}
</li>;
export const LinkNode = props =>
<li>
<a {...props}>
{props.label}
</a>
</li>;
LinkNode.propTypes = {
label: React.PropTypes.string.isRequired,
href: React.PropTypes.string.isRequired
};
export const Node = props =>
<li {...props}>
{props.label}
</li>;
Node.propTypes = {
label: React.PropTypes.string.isRequired
};
export class ContextMenu extends React.Component {
componentWillMount() {
// Clicking anywhere outside the context menu will close the window
document.addEventListener("click", this.props.closeMenu);
@ -35,58 +54,15 @@ class ContextMenu extends React.Component {
onClick={this.props.toggleMenu}
>
<ul id="context-menu">
<li>
<a
href="https://github.com/captbaritone/winamp2-js"
target="_blank"
>
Winamp2-js...
</a>
</li>
<li className="hr"><hr /></li>
<li onClick={this.props.openFileDialog}>
Play File...
</li>
<li className="parent">
<ul>
<li onClick={this.props.openFileDialog}>
Load Skin...
</li>
<li className="hr"><hr /></li>
{SKINS.map(skin =>
<li
key={skin.file}
onClick={this.props.setSkin.bind(null, skin.file)}
>
{skin.name}
</li>
)}
</ul>
Skins
</li>
<li className="hr"><hr /></li>
<li onClick={this.props.close}>Exit</li>
{this.props.children}
</ul>
</div>
);
}
}
const mapStateToProps = state => state.contextMenu;
const mapDispatchToProps = (dispatch, ownProps) => ({
close: () => dispatch(close()),
closeMenu: () => {
console.log("close");
dispatch({ type: CLOSE_CONTEXT_MENU });
},
toggleMenu: e => {
dispatch({ type: TOGGLE_CONTEXT_MENU });
// TODO: Consider binding to a ref instead.
// https://stackoverflow.com/a/24421834
e.nativeEvent.stopImmediatePropagation();
},
openFileDialog: () => dispatch(openFileDialog(ownProps.fileInput)),
setSkin: filename => dispatch(setSkinFromFilename(filename))
});
export default connect(mapStateToProps, mapDispatchToProps)(ContextMenu);
ContextMenu.propTypes = {
closeMenu: React.PropTypes.func.isRequired,
toggleMenu: React.PropTypes.func.isRequired,
children: React.PropTypes.any.isRequired
};

View file

@ -0,0 +1,61 @@
import React from "react";
import { connect } from "react-redux";
import { CLOSE_CONTEXT_MENU, TOGGLE_CONTEXT_MENU } from "../actionTypes";
import { close, setSkinFromFilename, openFileDialog } from "../actionCreators";
import { ContextMenu, Hr, Node, Parent, LinkNode } from "./contextMenu";
const SKINS = [
{ file: "base-2.91.wsz", name: "<Base Skin>" },
{ file: "MacOSXAqua1-5.wsz", name: "Mac OSX v1.5 (Aqua)" },
{ file: "TopazAmp1-2.wsz", name: "TopazAmp" },
{ file: "Vizor1-01.wsz", name: "Vizor" },
{ file: "XMMS-Turquoise.wsz", name: "XMMS Turquoise " },
{ file: "ZaxonRemake1-0.wsz", name: "Zaxon Remake" }
];
const MainContextMenu = props =>
<ContextMenu
closeMenu={props.closeMenu}
toggleMenu={props.toggleMenu}
selected={props.selected}
>
<LinkNode
href="https://github.com/captbaritone/winamp2-js"
target="_blank"
label="Winamp2-js"
/>
<Hr />
<Node onClick={props.openFileDialog} label="Play File..." />
<Parent label="Skins">
<Node onClick={props.openFileDialog} label="Load Skin..." />
<Hr />
{SKINS.map(skin =>
<Node
key={skin.file}
onClick={props.setSkin.bind(null, skin.file)}
label={skin.name}
/>
)}
</Parent>
<Hr />
<Node onClick={props.close} label="Exit" />
</ContextMenu>;
const mapStateToProps = state => state.contextMenu;
const mapDispatchToProps = (dispatch, ownProps) => ({
close: () => dispatch(close()),
closeMenu: () => {
console.log("close");
dispatch({ type: CLOSE_CONTEXT_MENU });
},
toggleMenu: e => {
dispatch({ type: TOGGLE_CONTEXT_MENU });
// TODO: Consider binding to a ref instead.
// https://stackoverflow.com/a/24421834
e.nativeEvent.stopImmediatePropagation();
},
openFileDialog: () => dispatch(openFileDialog(ownProps.fileInput)),
setSkin: filename => dispatch(setSkinFromFilename(filename))
});
export default connect(mapStateToProps, mapDispatchToProps)(MainContextMenu);

View file

@ -8,7 +8,7 @@ import ActionButtons from "./ActionButtons";
import Balance from "./Balance";
import Close from "./Close";
import ClutterBar from "./ClutterBar";
import ContextMenu from "./ContextMenu";
import MainContextMenu from "./MainContextMenu";
import Eject from "./Eject";
import EqToggleButton from "./EqToggleButton";
import Kbps from "./Kbps";
@ -91,7 +91,7 @@ export class MainWindow extends React.Component {
>
<div id="loading">Loading...</div>
<div id="title-bar" className="selected title-bard draggable">
<ContextMenu fileInput={this.props.fileInput} />
<MainContextMenu fileInput={this.props.fileInput} />
<ShadeTime />
<div id="minimize" />
<Shade />