diff --git a/js/components/App.js b/js/components/App.js
index 5ae96674..5a08028c 100644
--- a/js/components/App.js
+++ b/js/components/App.js
@@ -1,6 +1,8 @@
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
+import ContextMenuWrapper from "./ContextMenuWrapper";
+import MainContextMenu from "./MainWindow/MainContextMenu";
import WindowManager from "./WindowManager";
import MainWindow from "./MainWindow";
import PlaylistWindow from "./PlaylistWindow";
@@ -51,7 +53,9 @@ const App = ({
return (
-
+
+
+
);
};
diff --git a/js/components/ContextMenu.js b/js/components/ContextMenu.js
index 5dc67f93..d837fd7b 100644
--- a/js/components/ContextMenu.js
+++ b/js/components/ContextMenu.js
@@ -66,7 +66,7 @@ Node.propTypes = {
label: PropTypes.string.isRequired
};
-class ContextMenu extends React.Component {
+export class ContextMenu extends React.Component {
render() {
const {
children,
@@ -87,71 +87,3 @@ class ContextMenu extends React.Component {
);
}
}
-
-export class ContextMenuTarget extends React.Component {
- constructor(props) {
- super(props);
- this.state = { selected: false };
- this._handleHandleClick = this._handleHandleClick.bind(this);
- this._handleGlobalClick = this._handleGlobalClick.bind(this);
- }
-
- 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 &&
- // Not sure how, but it's possible for this to get called when handleNode is null/undefined.
- // https://sentry.io/share/issue/2066cd79f21e4f279791319f4d2ea35d/
- this.handleNode &&
- !this.handleNode.contains(e.target)
- ) {
- this.setState({ selected: false });
- }
- }
-
- render() {
- const { handle, children, top, bottom, ...passThroughProps } = this.props;
- const rect = this.handleNode
- ? this.handleNode.getBoundingClientRect()
- : { top: 0, left: 0 };
- return (
-
-
(this.handleNode = node)}
- onClick={this._handleHandleClick}
- >
- {handle}
-
-
- {children}
-
-
- );
- }
-}
-
-ContextMenuTarget.propTypes = {
- children: PropTypes.any.isRequired,
- handle: PropTypes.any.isRequired,
- top: PropTypes.bool,
- bottom: PropTypes.bool
-};
diff --git a/js/components/ContextMenuTarget.js b/js/components/ContextMenuTarget.js
new file mode 100644
index 00000000..6851f5fd
--- /dev/null
+++ b/js/components/ContextMenuTarget.js
@@ -0,0 +1,71 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { ContextMenu } from "./ContextMenu";
+
+export default class ContextMenuTarget extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = { selected: false };
+ this._handleHandleClick = this._handleHandleClick.bind(this);
+ this._handleGlobalClick = this._handleGlobalClick.bind(this);
+ }
+
+ 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 &&
+ // Not sure how, but it's possible for this to get called when handleNode is null/undefined.
+ // https://sentry.io/share/issue/2066cd79f21e4f279791319f4d2ea35d/
+ this.handleNode &&
+ !this.handleNode.contains(e.target)
+ ) {
+ this.setState({ selected: false });
+ }
+ }
+
+ render() {
+ const { handle, children, top, bottom, ...passThroughProps } = this.props;
+ const rect = this.handleNode
+ ? this.handleNode.getBoundingClientRect()
+ : { top: 0, left: 0 };
+ return (
+
+
(this.handleNode = node)}
+ onClick={this._handleHandleClick}
+ >
+ {handle}
+
+
+ {children}
+
+
+ );
+ }
+}
+
+ContextMenuTarget.propTypes = {
+ children: PropTypes.any.isRequired,
+ handle: PropTypes.any.isRequired,
+ top: PropTypes.bool,
+ bottom: PropTypes.bool
+};
diff --git a/js/components/ContextMenuWrapper.js b/js/components/ContextMenuWrapper.js
new file mode 100644
index 00000000..8dab1ef9
--- /dev/null
+++ b/js/components/ContextMenuWrapper.js
@@ -0,0 +1,64 @@
+import React from "react";
+import PropTypes from "prop-types";
+import { ContextMenu } from "./ContextMenu";
+
+export default class ContextMenuWraper extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ selected: false,
+ offsetTop: null,
+ offsetLeft: null
+ };
+ this._handleRightClick = this._handleRightClick.bind(this);
+ this._handleGlobalClick = this._handleGlobalClick.bind(this);
+ }
+
+ _handleGlobalClick() {
+ this.setState({
+ selected: false,
+ offsetTop: null,
+ offsetLeft: null
+ });
+ document.removeEventListener("click", this._handleGlobalClick);
+ }
+
+ _handleRightClick(e) {
+ const { pageX, pageY } = e;
+ this.setState({
+ selected: true,
+ offsetTop: pageY,
+ offsetLeft: pageX
+ });
+ // Even if you right click multiple times before closeing,
+ // we should only end up with one global listener.
+ document.addEventListener("click", this._handleGlobalClick);
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ render() {
+ const { children, Contents, ...passThroughProps } = this.props;
+ return (
+
+
+
+
+ {children}
+
+ );
+ }
+}
+
+ContextMenuWraper.propTypes = {
+ children: PropTypes.any.isRequired,
+ Contents: PropTypes.any.isRequired
+};
diff --git a/js/components/EqualizerWindow/PresetsContextMenu.js b/js/components/EqualizerWindow/PresetsContextMenu.js
index b866cc3b..6fe7471c 100644
--- a/js/components/EqualizerWindow/PresetsContextMenu.js
+++ b/js/components/EqualizerWindow/PresetsContextMenu.js
@@ -1,7 +1,8 @@
import React from "react";
import { connect } from "react-redux";
import { openEqfFileDialog, downloadPreset } from "../../actionCreators";
-import { ContextMenuTarget, Node } from "../ContextMenu";
+import { Node } from "../ContextMenu";
+import ContextMenuTarget from "../ContextMenuTarget";
const PresetsContextMenu = props => (
}>
diff --git a/js/components/MainWindow/MainContextMenu.js b/js/components/MainWindow/MainContextMenu.js
index 4b0297cb..5b66cd3d 100644
--- a/js/components/MainWindow/MainContextMenu.js
+++ b/js/components/MainWindow/MainContextMenu.js
@@ -1,6 +1,5 @@
import React from "react";
import { connect } from "react-redux";
-import ClickedDiv from "../ClickedDiv";
import {
close,
setSkinFromUrl,
@@ -16,14 +15,10 @@ import {
} from "../../actionTypes";
import { getGenWindows } from "../../selectors";
import { LOAD_STYLE } from "../../constants";
-import { ContextMenuTarget, Hr, Node, Parent, LinkNode } from "../ContextMenu";
+import { Hr, Node, Parent, LinkNode } from "../ContextMenu";
const MainContextMenu = props => (
- }
- >
+
(
-
+
);
const mapStateToProps = state => ({
diff --git a/js/components/MainWindow/index.js b/js/components/MainWindow/index.js
index 0ecc7962..958467b4 100644
--- a/js/components/MainWindow/index.js
+++ b/js/components/MainWindow/index.js
@@ -14,6 +14,8 @@ import DropTarget from "../DropTarget";
import MiniTime from "../MiniTime";
import { SET_FOCUSED_WINDOW } from "../../actionTypes";
+import ClickedDiv from "../ClickedDiv";
+import ContextMenuTarget from "../ContextMenuTarget";
import ActionButtons from "./ActionButtons";
import MainBalance from "./MainBalance";
import Close from "./Close";
@@ -90,7 +92,13 @@ export class MainWindow extends React.Component {
className="selected title-bard draggable"
onDoubleClick={this.props.toggleMainWindowShadeMode}
>
-
+ }
+ >
+
+
{mainShade && }
diff --git a/js/components/PlaylistWindow/MiscMenu.js b/js/components/PlaylistWindow/MiscMenu.js
index 3242db92..cde4f97a 100644
--- a/js/components/PlaylistWindow/MiscMenu.js
+++ b/js/components/PlaylistWindow/MiscMenu.js
@@ -7,7 +7,8 @@ import {
downloadHtmlPlaylist
} from "../../actionCreators";
-import { ContextMenuTarget, Hr, Node } from "../ContextMenu";
+import { Hr, Node } from "../ContextMenu";
+import ContextMenuTarget from "../ContextMenuTarget";
import PlaylistMenu from "./PlaylistMenu";
/* eslint-disable no-alert */