Toolbar.js (7766B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { 8 createElement, 9 createFactory, 10 Fragment, 11 PureComponent, 12 } = require("resource://devtools/client/shared/vendor/react.mjs"); 13 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); 14 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs"); 15 const { 16 connect, 17 } = require("resource://devtools/client/shared/vendor/react-redux.js"); 18 19 const DevicePixelRatioMenu = createFactory( 20 require("resource://devtools/client/responsive/components/DevicePixelRatioMenu.js") 21 ); 22 const DeviceSelector = createFactory( 23 require("resource://devtools/client/responsive/components/DeviceSelector.js") 24 ); 25 const NetworkThrottlingMenu = createFactory( 26 require("resource://devtools/client/shared/components/throttling/NetworkThrottlingMenu.js") 27 ); 28 const SettingsMenu = createFactory( 29 require("resource://devtools/client/responsive/components/SettingsMenu.js") 30 ); 31 const ViewportDimension = createFactory( 32 require("resource://devtools/client/responsive/components/ViewportDimension.js") 33 ); 34 35 loader.lazyGetter(this, "UserAgentInput", function () { 36 return createFactory( 37 require("resource://devtools/client/responsive/components/UserAgentInput.js") 38 ); 39 }); 40 41 const { 42 getStr, 43 } = require("resource://devtools/client/responsive/utils/l10n.js"); 44 const Types = require("resource://devtools/client/responsive/types.js"); 45 46 class Toolbar extends PureComponent { 47 static get propTypes() { 48 return { 49 devices: PropTypes.shape(Types.devices).isRequired, 50 displayPixelRatio: PropTypes.number.isRequired, 51 leftAlignmentEnabled: PropTypes.bool.isRequired, 52 networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired, 53 onChangeDevice: PropTypes.func.isRequired, 54 onChangeNetworkThrottling: PropTypes.func.isRequired, 55 onChangePixelRatio: PropTypes.func.isRequired, 56 onChangeTouchSimulation: PropTypes.func.isRequired, 57 onChangeUserAgent: PropTypes.func.isRequired, 58 onExit: PropTypes.func.isRequired, 59 onRemoveDeviceAssociation: PropTypes.func.isRequired, 60 doResizeViewport: PropTypes.func.isRequired, 61 onRotateViewport: PropTypes.func.isRequired, 62 onScreenshot: PropTypes.func.isRequired, 63 onToggleLeftAlignment: PropTypes.func.isRequired, 64 onToggleReloadOnTouchSimulation: PropTypes.func.isRequired, 65 onToggleReloadOnUserAgent: PropTypes.func.isRequired, 66 onToggleUserAgentInput: PropTypes.func.isRequired, 67 onUpdateDeviceModal: PropTypes.func.isRequired, 68 screenshot: PropTypes.shape(Types.screenshot).isRequired, 69 selectedDevice: PropTypes.string.isRequired, 70 selectedPixelRatio: PropTypes.number.isRequired, 71 showUserAgentInput: PropTypes.bool.isRequired, 72 touchSimulationEnabled: PropTypes.bool.isRequired, 73 viewport: PropTypes.shape(Types.viewport).isRequired, 74 }; 75 } 76 77 renderUserAgent() { 78 const { onChangeUserAgent, showUserAgentInput, viewport, devices } = 79 this.props; 80 81 if (!showUserAgentInput) { 82 return null; 83 } 84 85 const selectedDeviceName = viewport.device; 86 let selectedDeviceUserAgent = null; 87 if (selectedDeviceName) { 88 // Find the matching device by name 89 for (const type of devices.types) { 90 for (const device of devices[type]) { 91 if (device.name == selectedDeviceName) { 92 selectedDeviceUserAgent = device.userAgent; 93 break; 94 } 95 } 96 if (selectedDeviceUserAgent) { 97 break; 98 } 99 } 100 } 101 102 return createElement( 103 Fragment, 104 null, 105 UserAgentInput({ 106 onChangeUserAgent, 107 selectedDeviceName, 108 selectedDeviceUserAgent, 109 }), 110 dom.div({ className: "devtools-separator" }) 111 ); 112 } 113 114 render() { 115 const { 116 devices, 117 displayPixelRatio, 118 leftAlignmentEnabled, 119 networkThrottling, 120 onChangeDevice, 121 onChangeNetworkThrottling, 122 onChangePixelRatio, 123 onChangeTouchSimulation, 124 onExit, 125 onRemoveDeviceAssociation, 126 doResizeViewport, 127 onRotateViewport, 128 onScreenshot, 129 onToggleLeftAlignment, 130 onToggleReloadOnTouchSimulation, 131 onToggleReloadOnUserAgent, 132 onToggleUserAgentInput, 133 onUpdateDeviceModal, 134 screenshot, 135 selectedDevice, 136 selectedPixelRatio, 137 showUserAgentInput, 138 touchSimulationEnabled, 139 viewport, 140 } = this.props; 141 142 return dom.header( 143 { 144 id: "toolbar", 145 className: [ 146 leftAlignmentEnabled ? "left-aligned" : "", 147 showUserAgentInput ? "user-agent" : "", 148 ] 149 .join(" ") 150 .trim(), 151 }, 152 dom.div( 153 { id: "toolbar-center-controls" }, 154 DeviceSelector({ 155 devices, 156 onChangeDevice, 157 onUpdateDeviceModal, 158 selectedDevice, 159 viewportId: viewport.id, 160 }), 161 dom.div({ className: "devtools-separator" }), 162 ViewportDimension({ 163 onRemoveDeviceAssociation, 164 doResizeViewport, 165 viewport, 166 }), 167 dom.button({ 168 id: "rotate-button", 169 className: `devtools-button viewport-orientation-${ 170 viewport.width > viewport.height ? "landscape" : "portrait" 171 }`, 172 onClick: () => onRotateViewport(viewport.id), 173 title: getStr("responsive.rotate"), 174 }), 175 dom.div({ className: "devtools-separator" }), 176 DevicePixelRatioMenu({ 177 devices, 178 displayPixelRatio, 179 onChangePixelRatio, 180 selectedDevice, 181 selectedPixelRatio, 182 }), 183 dom.div({ className: "devtools-separator" }), 184 NetworkThrottlingMenu({ 185 // NetworkThrottlingMenu expects to display the Menu in the toolbox document 186 // but for RDM we can just use window.document, same as for the device 187 // selector MenuButton. 188 toolboxDoc: window.document, 189 networkThrottling, 190 onChangeNetworkThrottling, 191 }), 192 dom.div({ className: "devtools-separator" }), 193 this.renderUserAgent(), 194 dom.button({ 195 id: "touch-simulation-button", 196 className: 197 "devtools-button" + (touchSimulationEnabled ? " checked" : ""), 198 title: touchSimulationEnabled 199 ? getStr("responsive.disableTouch") 200 : getStr("responsive.enableTouch"), 201 onClick: () => onChangeTouchSimulation(!touchSimulationEnabled), 202 }) 203 ), 204 dom.div( 205 { id: "toolbar-end-controls" }, 206 dom.button({ 207 id: "screenshot-button", 208 className: "devtools-button", 209 title: getStr("responsive.screenshot"), 210 onClick: onScreenshot, 211 disabled: screenshot.isCapturing, 212 }), 213 SettingsMenu({ 214 onToggleLeftAlignment, 215 onToggleReloadOnTouchSimulation, 216 onToggleReloadOnUserAgent, 217 onToggleUserAgentInput, 218 }), 219 dom.div({ className: "devtools-separator" }), 220 dom.button({ 221 id: "exit-button", 222 className: "devtools-button", 223 title: getStr("responsive.exit"), 224 onClick: onExit, 225 }) 226 ) 227 ); 228 } 229 } 230 231 const mapStateToProps = state => { 232 return { 233 displayPixelRatio: state.ui.displayPixelRatio, 234 leftAlignmentEnabled: state.ui.leftAlignmentEnabled, 235 showUserAgentInput: state.ui.showUserAgentInput, 236 touchSimulationEnabled: state.ui.touchSimulationEnabled, 237 }; 238 }; 239 240 module.exports = connect(mapStateToProps)(Toolbar);