|
Packit |
f0b94e |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* eslint-env browser */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
"use strict";
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
const { PureComponent, createFactory } = require("devtools/client/shared/vendor/react");
|
|
Packit |
f0b94e |
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
|
Packit |
f0b94e |
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
const { getStr, getFormatStr } = require("../utils/l10n");
|
|
Packit |
f0b94e |
const Types = require("../types");
|
|
Packit |
f0b94e |
const DeviceAdder = createFactory(require("./DeviceAdder"));
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
class DeviceModal extends PureComponent {
|
|
Packit |
f0b94e |
static get propTypes() {
|
|
Packit |
f0b94e |
return {
|
|
Packit |
f0b94e |
deviceAdderViewportTemplate: PropTypes.shape(Types.viewport).isRequired,
|
|
Packit |
f0b94e |
devices: PropTypes.shape(Types.devices).isRequired,
|
|
Packit |
f0b94e |
onAddCustomDevice: PropTypes.func.isRequired,
|
|
Packit |
f0b94e |
onDeviceListUpdate: PropTypes.func.isRequired,
|
|
Packit |
f0b94e |
onRemoveCustomDevice: PropTypes.func.isRequired,
|
|
Packit |
f0b94e |
onUpdateDeviceDisplayed: PropTypes.func.isRequired,
|
|
Packit |
f0b94e |
onUpdateDeviceModal: PropTypes.func.isRequired,
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
constructor(props) {
|
|
Packit |
f0b94e |
super(props);
|
|
Packit |
f0b94e |
this.state = {};
|
|
Packit |
f0b94e |
this.onAddCustomDevice = this.onAddCustomDevice.bind(this);
|
|
Packit |
f0b94e |
this.onDeviceCheckboxChange = this.onDeviceCheckboxChange.bind(this);
|
|
Packit |
f0b94e |
this.onDeviceModalSubmit = this.onDeviceModalSubmit.bind(this);
|
|
Packit |
f0b94e |
this.onKeyDown = this.onKeyDown.bind(this);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
componentDidMount() {
|
|
Packit |
f0b94e |
window.addEventListener("keydown", this.onKeyDown, true);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
componentWillReceiveProps(nextProps) {
|
|
Packit |
f0b94e |
let {
|
|
Packit |
f0b94e |
devices: oldDevices,
|
|
Packit |
f0b94e |
} = this.props;
|
|
Packit |
f0b94e |
let {
|
|
Packit |
f0b94e |
devices,
|
|
Packit |
f0b94e |
} = nextProps;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Refresh component state only when model transitions from closed to open
|
|
Packit |
f0b94e |
if (!oldDevices.isModalOpen && devices.isModalOpen) {
|
|
Packit |
f0b94e |
for (let type of devices.types) {
|
|
Packit |
f0b94e |
for (let device of devices[type]) {
|
|
Packit |
f0b94e |
this.setState({
|
|
Packit |
f0b94e |
[device.name]: device.displayed,
|
|
Packit |
f0b94e |
});
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
componentWillUnmount() {
|
|
Packit |
f0b94e |
window.removeEventListener("keydown", this.onKeyDown, true);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
onAddCustomDevice(device) {
|
|
Packit |
f0b94e |
this.props.onAddCustomDevice(device);
|
|
Packit |
f0b94e |
// Default custom devices to enabled
|
|
Packit |
f0b94e |
this.setState({
|
|
Packit |
f0b94e |
[device.name]: true,
|
|
Packit |
f0b94e |
});
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
onDeviceCheckboxChange({ nativeEvent: { button }, target }) {
|
|
Packit |
f0b94e |
if (button !== 0) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
this.setState({
|
|
Packit |
f0b94e |
[target.value]: !this.state[target.value]
|
|
Packit |
f0b94e |
});
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
onDeviceModalSubmit() {
|
|
Packit |
f0b94e |
let {
|
|
Packit |
f0b94e |
devices,
|
|
Packit |
f0b94e |
onDeviceListUpdate,
|
|
Packit |
f0b94e |
onUpdateDeviceDisplayed,
|
|
Packit |
f0b94e |
onUpdateDeviceModal,
|
|
Packit |
f0b94e |
} = this.props;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
let preferredDevices = {
|
|
Packit |
f0b94e |
"added": new Set(),
|
|
Packit |
f0b94e |
"removed": new Set(),
|
|
Packit |
f0b94e |
};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
for (let type of devices.types) {
|
|
Packit |
f0b94e |
for (let device of devices[type]) {
|
|
Packit |
f0b94e |
let newState = this.state[device.name];
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (device.featured && !newState) {
|
|
Packit |
f0b94e |
preferredDevices.removed.add(device.name);
|
|
Packit |
f0b94e |
} else if (!device.featured && newState) {
|
|
Packit |
f0b94e |
preferredDevices.added.add(device.name);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (this.state[device.name] != device.displayed) {
|
|
Packit |
f0b94e |
onUpdateDeviceDisplayed(device, type, this.state[device.name]);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
onDeviceListUpdate(preferredDevices);
|
|
Packit |
f0b94e |
onUpdateDeviceModal(false);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
onKeyDown(event) {
|
|
Packit |
f0b94e |
if (!this.props.devices.isModalOpen) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
// Escape keycode
|
|
Packit |
f0b94e |
if (event.keyCode === 27) {
|
|
Packit |
f0b94e |
let {
|
|
Packit |
f0b94e |
onUpdateDeviceModal
|
|
Packit |
f0b94e |
} = this.props;
|
|
Packit |
f0b94e |
onUpdateDeviceModal(false);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
render() {
|
|
Packit |
f0b94e |
let {
|
|
Packit |
f0b94e |
deviceAdderViewportTemplate,
|
|
Packit |
f0b94e |
devices,
|
|
Packit |
f0b94e |
onRemoveCustomDevice,
|
|
Packit |
f0b94e |
onUpdateDeviceModal,
|
|
Packit |
f0b94e |
} = this.props;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
let {
|
|
Packit |
f0b94e |
onAddCustomDevice,
|
|
Packit |
f0b94e |
} = this;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
const sortedDevices = {};
|
|
Packit |
f0b94e |
for (let type of devices.types) {
|
|
Packit |
f0b94e |
sortedDevices[type] = Object.assign([], devices[type])
|
|
Packit |
f0b94e |
.sort((a, b) => a.name.localeCompare(b.name));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return dom.div(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
id: "device-modal-wrapper",
|
|
Packit |
f0b94e |
className: this.props.devices.isModalOpen ? "opened" : "closed",
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
dom.div(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: "device-modal container",
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
dom.button({
|
|
Packit |
f0b94e |
id: "device-close-button",
|
|
Packit |
f0b94e |
className: "toolbar-button devtools-button",
|
|
Packit |
f0b94e |
onClick: () => onUpdateDeviceModal(false),
|
|
Packit |
f0b94e |
}),
|
|
Packit |
f0b94e |
dom.div(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: "device-modal-content",
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
devices.types.map(type => {
|
|
Packit |
f0b94e |
return dom.div(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: `device-type device-type-${type}`,
|
|
Packit |
f0b94e |
key: type,
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
dom.header(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: "device-header",
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
type
|
|
Packit |
f0b94e |
),
|
|
Packit |
f0b94e |
sortedDevices[type].map(device => {
|
|
Packit |
f0b94e |
let details = getFormatStr(
|
|
Packit |
f0b94e |
"responsive.deviceDetails", device.width, device.height,
|
|
Packit |
f0b94e |
device.pixelRatio, device.userAgent, device.touch
|
|
Packit |
f0b94e |
);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
let removeDeviceButton;
|
|
Packit |
f0b94e |
if (type == "custom") {
|
|
Packit |
f0b94e |
removeDeviceButton = dom.button({
|
|
Packit |
f0b94e |
className: "device-remove-button toolbar-button devtools-button",
|
|
Packit |
f0b94e |
onClick: () => onRemoveCustomDevice(device),
|
|
Packit |
f0b94e |
});
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return dom.label(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: "device-label",
|
|
Packit |
f0b94e |
key: device.name,
|
|
Packit |
f0b94e |
title: details,
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
dom.input({
|
|
Packit |
f0b94e |
className: "device-input-checkbox",
|
|
Packit |
f0b94e |
type: "checkbox",
|
|
Packit |
f0b94e |
value: device.name,
|
|
Packit |
f0b94e |
checked: this.state[device.name],
|
|
Packit |
f0b94e |
onChange: this.onDeviceCheckboxChange,
|
|
Packit |
f0b94e |
}),
|
|
Packit |
f0b94e |
dom.span(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: "device-name",
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
device.name
|
|
Packit |
f0b94e |
),
|
|
Packit |
f0b94e |
removeDeviceButton
|
|
Packit |
f0b94e |
);
|
|
Packit |
f0b94e |
})
|
|
Packit |
f0b94e |
);
|
|
Packit |
f0b94e |
})
|
|
Packit |
f0b94e |
),
|
|
Packit |
f0b94e |
DeviceAdder({
|
|
Packit |
f0b94e |
devices,
|
|
Packit |
f0b94e |
viewportTemplate: deviceAdderViewportTemplate,
|
|
Packit |
f0b94e |
onAddCustomDevice,
|
|
Packit |
f0b94e |
}),
|
|
Packit |
f0b94e |
dom.button(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
id: "device-submit-button",
|
|
Packit |
f0b94e |
onClick: this.onDeviceModalSubmit,
|
|
Packit |
f0b94e |
},
|
|
Packit |
f0b94e |
getStr("responsive.done")
|
|
Packit |
f0b94e |
)
|
|
Packit |
f0b94e |
),
|
|
Packit |
f0b94e |
dom.div(
|
|
Packit |
f0b94e |
{
|
|
Packit |
f0b94e |
className: "modal-overlay",
|
|
Packit |
f0b94e |
onClick: () => onUpdateDeviceModal(false),
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
)
|
|
Packit |
f0b94e |
);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
module.exports = DeviceModal;
|