173 lines
4.6 KiB
JavaScript
173 lines
4.6 KiB
JavaScript
/* 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.mjs");
|
|
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.mjs");
|
|
|
|
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;
|