Blame devtools/client/responsive.html/components/DeviceModal.js

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;