mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-20 16:49:52 +00:00
Redo context menus
This commit is contained in:
parent
02d9fa6da0
commit
1680e1b2fb
12 changed files with 95 additions and 229 deletions
|
|
@ -1,5 +1,11 @@
|
|||
#winamp2-js .doubled #context-menu {
|
||||
-moz-transform: scale(0.5);
|
||||
-moz-transform-origin: top left;
|
||||
-webkit-transform: scale(0.5);
|
||||
-webkit-transform-origin: top left;
|
||||
}
|
||||
|
||||
#winamp2-js #context-menu {
|
||||
display: none;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
|
|
@ -11,11 +17,7 @@
|
|||
top: 0px;
|
||||
}
|
||||
|
||||
#winamp2-js div:active > div > #context-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#winamp2-js .selected > #context-menu {
|
||||
#winamp2-js .selected #context-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
|
@ -43,6 +45,7 @@
|
|||
padding: 1px 18px 3px 18px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#winamp2-js #context-menu li.parent:after {
|
||||
float: right;
|
||||
content: "\25b8";
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@
|
|||
left: 40px;
|
||||
}
|
||||
|
||||
#winamp2-js #presets {
|
||||
#winamp2-js #presets-context {
|
||||
position: absolute;
|
||||
width: 44px;
|
||||
height: 12px;
|
||||
|
|
@ -120,6 +120,11 @@
|
|||
left: 217px;
|
||||
}
|
||||
|
||||
#winamp2-js #presets {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#winamp2-js #eqGraph {
|
||||
position: absolute;
|
||||
width: 113px;
|
||||
|
|
|
|||
|
|
@ -12,19 +12,6 @@
|
|||
-ms-interpolation-mode: nearest-neighbor; /* IE (non-standard property) */
|
||||
}
|
||||
|
||||
#winamp2-js #main-window.doubled #context-menu {
|
||||
-moz-transform: scale(0.5);
|
||||
-moz-transform-origin: top left;
|
||||
-webkit-transform: scale(0.5);
|
||||
-webkit-transform-origin: top left;
|
||||
}
|
||||
|
||||
#winamp2-js #main-window.loading {
|
||||
background-image: none;
|
||||
background-color: #ffffff;
|
||||
border: 2px solid #dddddd;
|
||||
}
|
||||
|
||||
#winamp2-js #loading {
|
||||
color: white;
|
||||
text-align: center;
|
||||
|
|
@ -92,7 +79,7 @@
|
|||
cursor: url("../cursors/TITLEBAR.PNG"), auto;
|
||||
}
|
||||
|
||||
#winamp2-js #option,
|
||||
#winamp2-js #option-context,
|
||||
#winamp2-js #minimize,
|
||||
#winamp2-js #shade,
|
||||
#winamp2-js #close {
|
||||
|
|
@ -104,6 +91,11 @@
|
|||
}
|
||||
|
||||
#winamp2-js #title-bar #option {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#winamp2-js #title-bar #option-context {
|
||||
left: 6px;
|
||||
}
|
||||
#winamp2-js #title-bar #minimize {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
export const LOAD_AUDIO_URL = "LOAD_AUDIO_URL";
|
||||
export const LOAD_AUDIO_FILE = "LOAD_AUDIO_FILE";
|
||||
export const CLOSE_CONTEXT_MENU = "CLOSE_CONTEXT_MENU";
|
||||
export const CLOSE_PRESETS_CONTEXT_MENU = "CLOSE_PRESETS_CONTEXT_MENU";
|
||||
export const CLOSE_WINAMP = "CLOSE_WINAMP";
|
||||
export const CLOSE_EQUALIZER_WINDOW = "CLOSE_EQUALIZER_WINDOW";
|
||||
export const IS_PLAYING = "IS_PLAYING";
|
||||
|
|
@ -24,8 +22,6 @@ export const START_WORKING = "START_WORKING";
|
|||
export const STEP_MARQUEE = "STEP_MARQUEE";
|
||||
export const STOP = "STOP";
|
||||
export const STOP_WORKING = "STOP_WORKING";
|
||||
export const TOGGLE_CONTEXT_MENU = "TOGGLE_CONTEXT_MENU";
|
||||
export const TOGGLE_PRESETS_CONTEXT_MENU = "TOGGLE_PRESET_CONTEXT_MENU";
|
||||
export const TOGGLE_DOUBLESIZE_MODE = "TOGGLE_DOUBLESIZE_MODE";
|
||||
export const TOGGLE_EQUALIZER_WINDOW = "TOGGLE_EQUALIZER_WINDOW";
|
||||
export const TOGGLE_PLAYLIST_WINDOW = "TOGGLE_PLAYLIST_WINDOW";
|
||||
|
|
|
|||
|
|
@ -37,28 +37,56 @@ Node.propTypes = {
|
|||
};
|
||||
|
||||
export class ContextMenu extends React.Component {
|
||||
componentWillMount() {
|
||||
// Clicking anywhere outside the context menu will close the window
|
||||
document.addEventListener("click", this.props.closeMenu);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { selected: false };
|
||||
this._handleHandleClick = this._handleHandleClick.bind(this);
|
||||
this._handleGlobalClick = this._handleGlobalClick.bind(this);
|
||||
}
|
||||
|
||||
componantWillUnmount() {
|
||||
document.removeEventListener("click", this.props.closeMenu);
|
||||
componentDidMount() {
|
||||
document.addEventListener("click", this._handleGlobalClick);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener("click", this._handleGlobalClick);
|
||||
}
|
||||
|
||||
_handleHandleClick() {
|
||||
this.setState({ selected: !this.state.selected });
|
||||
}
|
||||
|
||||
_handleGlobalClick(e) {
|
||||
if (this.state.selected && !this.handleNode.contains(e.target)) {
|
||||
this.setState({ selected: false });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { selected, top, bottom, children } = this.props;
|
||||
const { handle, children, top, bottom, ...passThroughProps } = this.props;
|
||||
return (
|
||||
<div className={classnames({ selected, top, bottom })}>
|
||||
<ul id="context-menu">{children}</ul>
|
||||
<div {...passThroughProps}>
|
||||
<div
|
||||
className="handle"
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
ref={node => (this.handleNode = node)}
|
||||
onClick={this._handleHandleClick}
|
||||
>
|
||||
{handle}
|
||||
</div>
|
||||
{this.state.selected && (
|
||||
<div className={classnames({ top, bottom })}>
|
||||
<ul id="context-menu">{children}</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ContextMenu.propTypes = {
|
||||
closeMenu: PropTypes.func.isRequired,
|
||||
children: PropTypes.any.isRequired,
|
||||
handle: PropTypes.any.isRequired,
|
||||
top: PropTypes.bool,
|
||||
bottom: PropTypes.bool
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { CLOSE_PRESETS_CONTEXT_MENU } from "../../actionTypes";
|
||||
import { openFileDialog, downloadPreset } from "../../actionCreators";
|
||||
import { ContextMenu, Node } from "../ContextMenu";
|
||||
|
||||
const MainContextMenu = props => (
|
||||
<ContextMenu closeMenu={props.closeMenu} selected={props.selected} top>
|
||||
<ContextMenu top id="presets-context" handle={<div id="presets" />}>
|
||||
<Node onClick={props.openFileDialog} label="Load" />
|
||||
<Node onClick={props.downloadPreset} label="Save" />
|
||||
</ContextMenu>
|
||||
);
|
||||
|
||||
const mapDispatchToProps = (dispatch, ownProps) => ({
|
||||
closeMenu: () => dispatch({ type: CLOSE_PRESETS_CONTEXT_MENU }),
|
||||
openFileDialog: () => dispatch(openFileDialog(ownProps.fileInput)),
|
||||
downloadPreset: () => dispatch(downloadPreset())
|
||||
});
|
||||
|
|
|
|||
|
|
@ -35,28 +35,21 @@ exports[`EqualizerWindow renders to snapshot 1`] = `
|
|||
width="152"
|
||||
/>
|
||||
<div
|
||||
id="presets"
|
||||
onClick={[Function]}
|
||||
id="presets-context"
|
||||
>
|
||||
<div
|
||||
className="top"
|
||||
className="handle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ul
|
||||
id="context-menu"
|
||||
>
|
||||
<li
|
||||
label="Load"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Load
|
||||
</li>
|
||||
<li
|
||||
label="Save"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Save
|
||||
</li>
|
||||
</ul>
|
||||
<div
|
||||
id="presets"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ import {
|
|||
toggleEqualizerShadeMode
|
||||
} from "../../actionCreators";
|
||||
|
||||
import {
|
||||
SET_FOCUSED_WINDOW,
|
||||
TOGGLE_PRESETS_CONTEXT_MENU
|
||||
} from "../../actionTypes";
|
||||
import { SET_FOCUSED_WINDOW } from "../../actionTypes";
|
||||
|
||||
import Band from "./Band";
|
||||
import EqOn from "./EqOn";
|
||||
|
|
@ -71,12 +68,7 @@ const EqualizerWindow = props => {
|
|||
<EqOn />
|
||||
<EqAuto />
|
||||
<EqGraph />
|
||||
<div id="presets" onClick={props.togglePresetsContextMenu}>
|
||||
<PresetsContextMenu
|
||||
selected={props.contextMenuSelected}
|
||||
fileInput={props.fileInput}
|
||||
/>
|
||||
</div>
|
||||
<PresetsContextMenu fileInput={props.fileInput} />
|
||||
<Band id="preamp" band="preamp" onChange={props.setPreampValue} />
|
||||
<div id="plus12db" onClick={props.setEqToMax} />
|
||||
<div id="zerodb" onClick={props.setEqToMid} />
|
||||
|
|
@ -109,12 +101,6 @@ const mapDispatchToProps = dispatch => ({
|
|||
setEqToMid: () => dispatch(setEqToMid()),
|
||||
setEqToMax: () => dispatch(setEqToMax()),
|
||||
setHertzValue: hertz => value => dispatch(setEqBand(hertz, value)),
|
||||
togglePresetsContextMenu: e => {
|
||||
dispatch({ type: TOGGLE_PRESETS_CONTEXT_MENU });
|
||||
// TODO: Consider binding to a ref instead.
|
||||
// https://stackoverflow.com/a/24421834
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
},
|
||||
closeEqualizerWindow: () => dispatch(closeEqualizerWindow()),
|
||||
toggleEqualizerShadeMode: () => dispatch(toggleEqualizerShadeMode())
|
||||
});
|
||||
|
|
@ -122,7 +108,6 @@ const mapDispatchToProps = dispatch => ({
|
|||
const mapStateToProps = state => ({
|
||||
doubled: state.display.doubled,
|
||||
selected: state.windows.focused === WINDOWS.EQUALIZER,
|
||||
contextMenuSelected: state.presetsContextMenu.selected,
|
||||
shade: state.display.equalizerShade,
|
||||
volume: state.media.volume,
|
||||
balance: state.media.balance
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { CLOSE_CONTEXT_MENU, TOGGLE_CONTEXT_MENU } from "../../actionTypes";
|
||||
import {
|
||||
close,
|
||||
setSkinFromFilename,
|
||||
|
|
@ -19,10 +18,9 @@ const SKINS = [
|
|||
|
||||
const MainContextMenu = props => (
|
||||
<ContextMenu
|
||||
closeMenu={props.closeMenu}
|
||||
openMenu={props.openMenu}
|
||||
selected={props.selected}
|
||||
id="option-context"
|
||||
bottom
|
||||
handle={<div id="option" title="Winamp Menu" />}
|
||||
>
|
||||
<LinkNode
|
||||
href="https://github.com/captbaritone/winamp2-js"
|
||||
|
|
@ -49,17 +47,8 @@ const MainContextMenu = props => (
|
|||
|
||||
const mapDispatchToProps = (dispatch, ownProps) => ({
|
||||
close: () => dispatch(close()),
|
||||
closeMenu: () => {
|
||||
dispatch({ type: CLOSE_CONTEXT_MENU });
|
||||
},
|
||||
openMenu: () => {
|
||||
dispatch({ type: TOGGLE_CONTEXT_MENU });
|
||||
},
|
||||
openFileDialog: () => dispatch(openFileDialog(ownProps.fileInput)),
|
||||
setSkin: filename => dispatch(setSkinFromFilename(filename))
|
||||
});
|
||||
|
||||
export default connect(
|
||||
state => ({ selected: state.contextMenu.selected }),
|
||||
mapDispatchToProps
|
||||
)(MainContextMenu);
|
||||
export default connect(null, mapDispatchToProps)(MainContextMenu);
|
||||
|
|
|
|||
|
|
@ -14,102 +14,22 @@ exports[`MainWindow renders to snapshot 1`] = `
|
|||
id="title-bar"
|
||||
>
|
||||
<div
|
||||
id="option"
|
||||
onClick={[Function]}
|
||||
title="Winamp Menu"
|
||||
id="option-context"
|
||||
>
|
||||
<div
|
||||
className="bottom"
|
||||
className="handle"
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"height": "100%",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<ul
|
||||
id="context-menu"
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/captbaritone/winamp2-js"
|
||||
label="Winamp2-js"
|
||||
target="_blank"
|
||||
>
|
||||
Winamp2-js
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
className="hr"
|
||||
>
|
||||
<hr />
|
||||
</li>
|
||||
<li
|
||||
label="Play File..."
|
||||
onClick={[Function]}
|
||||
>
|
||||
Play File...
|
||||
</li>
|
||||
<li
|
||||
className="parent"
|
||||
>
|
||||
<ul>
|
||||
<li
|
||||
label="Load Skin..."
|
||||
onClick={[Function]}
|
||||
>
|
||||
Load Skin...
|
||||
</li>
|
||||
<li
|
||||
className="hr"
|
||||
>
|
||||
<hr />
|
||||
</li>
|
||||
<li
|
||||
label="<Base Skin>"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<Base Skin>
|
||||
</li>
|
||||
<li
|
||||
label="Mac OSX v1.5 (Aqua)"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Mac OSX v1.5 (Aqua)
|
||||
</li>
|
||||
<li
|
||||
label="TopazAmp"
|
||||
onClick={[Function]}
|
||||
>
|
||||
TopazAmp
|
||||
</li>
|
||||
<li
|
||||
label="Vizor"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Vizor
|
||||
</li>
|
||||
<li
|
||||
label="XMMS Turquoise "
|
||||
onClick={[Function]}
|
||||
>
|
||||
XMMS Turquoise
|
||||
</li>
|
||||
<li
|
||||
label="Zaxon Remake"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Zaxon Remake
|
||||
</li>
|
||||
</ul>
|
||||
Skins
|
||||
</li>
|
||||
<li
|
||||
className="hr"
|
||||
>
|
||||
<hr />
|
||||
</li>
|
||||
<li
|
||||
label="Exit"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Exit
|
||||
</li>
|
||||
</ul>
|
||||
<div
|
||||
id="option"
|
||||
title="Winamp Menu"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import Time from "./Time";
|
|||
import Visualizer from "./Visualizer";
|
||||
import MainVolume from "./MainVolume";
|
||||
|
||||
import { SET_FOCUSED_WINDOW, TOGGLE_CONTEXT_MENU } from "../../actionTypes";
|
||||
import { SET_FOCUSED_WINDOW } from "../../actionTypes";
|
||||
|
||||
import { loadFileFromReference } from "../../actionCreators";
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ export class MainWindow extends React.Component {
|
|||
}
|
||||
|
||||
handleClick() {
|
||||
this.props.dispatch({ type: SET_FOCUSED_WINDOW, window: WINDOWS.MAIN });
|
||||
this.props.setFocus();
|
||||
}
|
||||
|
||||
supress(e) {
|
||||
|
|
@ -90,9 +90,7 @@ export class MainWindow extends React.Component {
|
|||
onDrop={this.handleDrop}
|
||||
>
|
||||
<div id="title-bar" className="selected title-bard draggable">
|
||||
<div id="option" onClick={this.props.toggleMenu} title="Winamp Menu">
|
||||
<MainContextMenu fileInput={this.props.fileInput} />
|
||||
</div>
|
||||
<MainContextMenu fileInput={this.props.fileInput} />
|
||||
{shade && <MiniTime />}
|
||||
<div id="minimize" />
|
||||
<Shade />
|
||||
|
|
@ -148,12 +146,8 @@ const mapStateToProps = state => {
|
|||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
toggleMenu: e => {
|
||||
dispatch({ type: TOGGLE_CONTEXT_MENU });
|
||||
// TODO: Consider binding to a ref instead.
|
||||
// https://stackoverflow.com/a/24421834
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
},
|
||||
dispatch
|
||||
setFocus: () => {
|
||||
dispatch({ type: SET_FOCUSED_WINDOW, window: WINDOWS.MAIN });
|
||||
}
|
||||
});
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MainWindow);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { combineReducers } from "redux";
|
||||
import { BANDS, WINDOWS } from "./constants";
|
||||
import {
|
||||
CLOSE_CONTEXT_MENU,
|
||||
CLOSE_PRESETS_CONTEXT_MENU,
|
||||
CLOSE_WINAMP,
|
||||
SET_BALANCE,
|
||||
SET_BAND_VALUE,
|
||||
|
|
@ -17,8 +15,6 @@ import {
|
|||
START_WORKING,
|
||||
STEP_MARQUEE,
|
||||
STOP_WORKING,
|
||||
TOGGLE_CONTEXT_MENU,
|
||||
TOGGLE_PRESETS_CONTEXT_MENU,
|
||||
TOGGLE_DOUBLESIZE_MODE,
|
||||
TOGGLE_EQUALIZER_WINDOW,
|
||||
CLOSE_EQUALIZER_WINDOW,
|
||||
|
|
@ -137,37 +133,6 @@ const display = (state = defaultDisplayState, action) => {
|
|||
}
|
||||
};
|
||||
|
||||
const defaultContextMenuState = {
|
||||
selected: false
|
||||
};
|
||||
|
||||
const contextMenu = (state = defaultContextMenuState, action) => {
|
||||
switch (action.type) {
|
||||
case TOGGLE_CONTEXT_MENU:
|
||||
return { ...state, selected: !state.selected };
|
||||
case CLOSE_CONTEXT_MENU:
|
||||
return { ...state, selected: false };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const presetsContextMenu = (state, action) => {
|
||||
if (!state) {
|
||||
return {
|
||||
selected: false
|
||||
};
|
||||
}
|
||||
switch (action.type) {
|
||||
case TOGGLE_PRESETS_CONTEXT_MENU:
|
||||
return { ...state, selected: !state.selected };
|
||||
case CLOSE_PRESETS_CONTEXT_MENU:
|
||||
return { ...state, selected: false };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const equalizer = (state, action) => {
|
||||
if (!state) {
|
||||
state = {
|
||||
|
|
@ -255,8 +220,6 @@ const reducer = combineReducers({
|
|||
userInput,
|
||||
windows,
|
||||
display,
|
||||
contextMenu,
|
||||
presetsContextMenu,
|
||||
equalizer,
|
||||
media
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue