summaryrefslogtreecommitdiffstats
path: root/devtools/client/responsive/components/DeviceSelector.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/responsive/components/DeviceSelector.js')
-rw-r--r--devtools/client/responsive/components/DeviceSelector.js173
1 files changed, 173 insertions, 0 deletions
diff --git a/devtools/client/responsive/components/DeviceSelector.js b/devtools/client/responsive/components/DeviceSelector.js
new file mode 100644
index 0000000000..3028f2fa42
--- /dev/null
+++ b/devtools/client/responsive/components/DeviceSelector.js
@@ -0,0 +1,173 @@
+/* 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/. */
+
+"use strict";
+
+const {
+ createFactory,
+ PureComponent,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const { hr } = dom;
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+
+const {
+ getStr,
+} = require("resource://devtools/client/responsive/utils/l10n.js");
+const {
+ parseUserAgent,
+} = require("resource://devtools/client/responsive/utils/ua.js");
+const Types = require("resource://devtools/client/responsive/types.js");
+
+const MenuButton = createFactory(
+ require("resource://devtools/client/shared/components/menu/MenuButton.js")
+);
+
+loader.lazyGetter(this, "MenuItem", () => {
+ const menuItemClass = require("resource://devtools/client/shared/components/menu/MenuItem.js");
+ const menuItem = createFactory(menuItemClass);
+ menuItem.DUMMY_ICON = menuItemClass.DUMMY_ICON;
+ return menuItem;
+});
+
+loader.lazyGetter(this, "MenuList", () => {
+ return createFactory(
+ require("resource://devtools/client/shared/components/menu/MenuList.js")
+ );
+});
+
+class DeviceSelector extends PureComponent {
+ static get propTypes() {
+ return {
+ devices: PropTypes.shape(Types.devices).isRequired,
+ onChangeDevice: PropTypes.func.isRequired,
+ onUpdateDeviceModal: PropTypes.func.isRequired,
+ selectedDevice: PropTypes.string.isRequired,
+ viewportId: PropTypes.number.isRequired,
+ };
+ }
+
+ getMenuProps(device) {
+ if (!device) {
+ return { icon: null, label: null, tooltip: null };
+ }
+
+ const { browser, os } = parseUserAgent(device.userAgent);
+ let label = device.name;
+ if (os) {
+ label += ` ${os.name}`;
+ if (os.version) {
+ label += ` ${os.version}`;
+ }
+ }
+
+ let icon = null;
+ let tooltip = label;
+ if (browser) {
+ icon = `chrome://devtools/skin/images/browsers/${browser.name.toLowerCase()}.svg`;
+ tooltip += ` ${browser.name} ${browser.version}`;
+ }
+
+ return { icon, label, tooltip };
+ }
+
+ getSelectedDevice() {
+ const { devices, selectedDevice } = this.props;
+
+ if (!selectedDevice) {
+ return null;
+ }
+
+ for (const type of devices.types) {
+ for (const device of devices[type]) {
+ if (selectedDevice === device.name) {
+ return device;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ renderMenuList() {
+ const {
+ devices,
+ onChangeDevice,
+ onUpdateDeviceModal,
+ selectedDevice,
+ viewportId,
+ } = this.props;
+
+ const menuItems = [];
+
+ for (const type of devices.types) {
+ for (const device of devices[type]) {
+ if (device.displayed) {
+ const { icon, label, tooltip } = this.getMenuProps(device);
+
+ menuItems.push(
+ MenuItem({
+ key: label,
+ className: "device-selector-item",
+ checked: selectedDevice === device.name,
+ label,
+ icon: icon || MenuItem.DUMMY_ICON,
+ tooltip,
+ onClick: () => onChangeDevice(viewportId, device, type),
+ })
+ );
+ }
+ }
+ }
+
+ menuItems.sort(function (a, b) {
+ return a.props.label.localeCompare(b.props.label);
+ });
+
+ if (menuItems.length) {
+ menuItems.push(hr({ key: "separator" }));
+ }
+
+ menuItems.push(
+ MenuItem({
+ key: "edit-device",
+ label: getStr("responsive.editDeviceList2"),
+ onClick: () => onUpdateDeviceModal(true, viewportId),
+ })
+ );
+
+ return MenuList({}, menuItems);
+ }
+
+ render() {
+ const { devices } = this.props;
+ const selectedDevice = this.getSelectedDevice();
+ let { icon, label, tooltip } = this.getMenuProps(selectedDevice);
+
+ if (!selectedDevice) {
+ label = getStr("responsive.responsiveMode");
+ }
+
+ // MenuButton is expected to be used in the toolbox document usually,
+ // but since RDM's frame also loads theme-switching.js, we can create
+ // MenuButtons (& HTMLTooltips) in the RDM frame document.
+ const toolboxDoc = window.document;
+
+ return MenuButton(
+ {
+ id: "device-selector",
+ menuId: "device-selector-menu",
+ toolboxDoc,
+ className: "devtools-button devtools-dropdown-button",
+ label,
+ icon,
+ title: tooltip,
+ disabled: devices.listState !== Types.loadableState.LOADED,
+ },
+ () => this.renderMenuList()
+ );
+ }
+}
+
+module.exports = DeviceSelector;