2016-04-21 00:15:34 +03:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2016-05-17 20:49:29 +03:00
|
|
|
/* eslint-env browser */
|
|
|
|
|
2016-04-21 00:15:34 +03:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const { DOM: dom, createClass, PropTypes, addons } =
|
|
|
|
require("devtools/client/shared/vendor/react");
|
|
|
|
const { getStr } = require("../utils/l10n");
|
|
|
|
const Types = require("../types");
|
|
|
|
|
|
|
|
module.exports = createClass({
|
2016-05-17 21:55:49 +03:00
|
|
|
displayName: "DeviceModal",
|
|
|
|
|
2016-04-21 00:15:34 +03:00
|
|
|
propTypes: {
|
|
|
|
devices: PropTypes.shape(Types.devices).isRequired,
|
|
|
|
onDeviceListUpdate: PropTypes.func.isRequired,
|
|
|
|
onUpdateDeviceDisplayed: PropTypes.func.isRequired,
|
|
|
|
onUpdateDeviceModalOpen: PropTypes.func.isRequired,
|
|
|
|
},
|
|
|
|
|
|
|
|
mixins: [ addons.PureRenderMixin ],
|
|
|
|
|
|
|
|
getInitialState() {
|
|
|
|
return {};
|
|
|
|
},
|
|
|
|
|
2016-05-17 20:49:29 +03:00
|
|
|
componentDidMount() {
|
|
|
|
window.addEventListener("keydown", this.onKeyDown, true);
|
|
|
|
},
|
|
|
|
|
2016-04-21 00:15:34 +03:00
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
let {
|
|
|
|
devices,
|
|
|
|
} = nextProps;
|
|
|
|
|
|
|
|
for (let type of devices.types) {
|
|
|
|
for (let device of devices[type]) {
|
|
|
|
this.setState({
|
|
|
|
[device.name]: device.displayed,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-05-17 20:49:29 +03:00
|
|
|
componentWillUnmount() {
|
|
|
|
window.removeEventListener("keydown", this.onKeyDown, true);
|
|
|
|
},
|
|
|
|
|
2017-01-04 18:34:37 +03:00
|
|
|
onDeviceCheckboxChange({ nativeEvent: { button }, target }) {
|
|
|
|
if (button !== 0) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-21 00:15:34 +03:00
|
|
|
this.setState({
|
|
|
|
[target.value]: !this.state[target.value]
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
onDeviceModalSubmit() {
|
|
|
|
let {
|
|
|
|
devices,
|
|
|
|
onDeviceListUpdate,
|
|
|
|
onUpdateDeviceDisplayed,
|
|
|
|
onUpdateDeviceModalOpen,
|
|
|
|
} = this.props;
|
|
|
|
|
2016-06-22 16:41:00 +03:00
|
|
|
let preferredDevices = {
|
|
|
|
"added": new Set(),
|
|
|
|
"removed": new Set(),
|
|
|
|
};
|
2016-04-21 00:15:34 +03:00
|
|
|
|
|
|
|
for (let type of devices.types) {
|
|
|
|
for (let device of devices[type]) {
|
2016-06-22 16:41:00 +03:00
|
|
|
let newState = this.state[device.name];
|
|
|
|
|
|
|
|
if (device.featured && !newState) {
|
|
|
|
preferredDevices.removed.add(device.name);
|
|
|
|
} else if (!device.featured && newState) {
|
|
|
|
preferredDevices.added.add(device.name);
|
2016-04-21 00:15:34 +03:00
|
|
|
}
|
|
|
|
|
2016-06-22 16:41:00 +03:00
|
|
|
if (this.state[device.name] != device.displayed) {
|
|
|
|
onUpdateDeviceDisplayed(device, type, this.state[device.name]);
|
2016-04-21 00:15:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-22 16:41:00 +03:00
|
|
|
onDeviceListUpdate(preferredDevices);
|
2016-04-21 00:15:34 +03:00
|
|
|
onUpdateDeviceModalOpen(false);
|
|
|
|
},
|
|
|
|
|
2016-05-17 20:49:29 +03:00
|
|
|
onKeyDown(event) {
|
|
|
|
if (!this.props.devices.isModalOpen) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Escape keycode
|
|
|
|
if (event.keyCode === 27) {
|
|
|
|
let {
|
|
|
|
onUpdateDeviceModalOpen
|
|
|
|
} = this.props;
|
|
|
|
onUpdateDeviceModalOpen(false);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2016-04-21 00:15:34 +03:00
|
|
|
render() {
|
|
|
|
let {
|
|
|
|
devices,
|
|
|
|
onUpdateDeviceModalOpen,
|
|
|
|
} = this.props;
|
|
|
|
|
2016-06-02 18:41:00 +03:00
|
|
|
const sortedDevices = {};
|
|
|
|
for (let type of devices.types) {
|
|
|
|
sortedDevices[type] = Object.assign([], devices[type])
|
|
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
|
|
}
|
|
|
|
|
2016-04-21 00:15:34 +03:00
|
|
|
return dom.div(
|
|
|
|
{
|
2016-05-17 20:49:29 +03:00
|
|
|
id: "device-modal-wrapper",
|
|
|
|
className: this.props.devices.isModalOpen ? "opened" : "closed",
|
2016-04-21 00:15:34 +03:00
|
|
|
},
|
|
|
|
dom.div(
|
|
|
|
{
|
2016-05-17 20:49:29 +03:00
|
|
|
className: "device-modal container",
|
2016-04-21 00:15:34 +03:00
|
|
|
},
|
2016-05-17 20:49:29 +03:00
|
|
|
dom.button({
|
|
|
|
id: "device-close-button",
|
|
|
|
className: "toolbar-button devtools-button",
|
|
|
|
onClick: () => onUpdateDeviceModalOpen(false),
|
|
|
|
}),
|
|
|
|
dom.div(
|
|
|
|
{
|
|
|
|
className: "device-modal-content",
|
|
|
|
},
|
|
|
|
devices.types.map(type => {
|
|
|
|
return dom.div(
|
2016-04-21 00:15:34 +03:00
|
|
|
{
|
2016-05-17 20:49:29 +03:00
|
|
|
className: "device-type",
|
|
|
|
key: type,
|
2016-04-21 00:15:34 +03:00
|
|
|
},
|
2016-05-17 20:49:29 +03:00
|
|
|
dom.header(
|
2016-04-21 00:15:34 +03:00
|
|
|
{
|
2016-05-17 20:49:29 +03:00
|
|
|
className: "device-header",
|
2016-04-21 00:15:34 +03:00
|
|
|
},
|
2016-05-17 20:49:29 +03:00
|
|
|
type
|
|
|
|
),
|
|
|
|
sortedDevices[type].map(device => {
|
|
|
|
return dom.label(
|
|
|
|
{
|
|
|
|
className: "device-label",
|
|
|
|
key: device.name,
|
|
|
|
},
|
|
|
|
dom.input({
|
|
|
|
className: "device-input-checkbox",
|
|
|
|
type: "checkbox",
|
|
|
|
value: device.name,
|
|
|
|
checked: this.state[device.name],
|
2017-01-04 18:34:37 +03:00
|
|
|
onChange: this.onDeviceCheckboxChange,
|
2016-05-17 20:49:29 +03:00
|
|
|
}),
|
|
|
|
device.name
|
|
|
|
);
|
|
|
|
})
|
|
|
|
);
|
|
|
|
})
|
|
|
|
),
|
|
|
|
dom.button(
|
|
|
|
{
|
|
|
|
id: "device-submit-button",
|
|
|
|
onClick: this.onDeviceModalSubmit,
|
|
|
|
},
|
|
|
|
getStr("responsive.done")
|
|
|
|
)
|
2016-04-21 00:15:34 +03:00
|
|
|
),
|
2016-05-17 20:49:29 +03:00
|
|
|
dom.div(
|
2016-04-21 00:15:34 +03:00
|
|
|
{
|
2016-05-17 20:49:29 +03:00
|
|
|
className: "modal-overlay",
|
|
|
|
onClick: () => onUpdateDeviceModalOpen(false),
|
|
|
|
}
|
2016-04-21 00:15:34 +03:00
|
|
|
)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
});
|