MonitorPanel.js (8411B)
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 Component, 9 createFactory, 10 } = require("resource://devtools/client/shared/vendor/react.mjs"); 11 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); 12 const { div } = dom; 13 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs"); 14 const { 15 connect, 16 } = require("resource://devtools/client/shared/vendor/react-redux.js"); 17 const { 18 findDOMNode, 19 } = require("resource://devtools/client/shared/vendor/react-dom.mjs"); 20 const Actions = require("resource://devtools/client/netmonitor/src/actions/index.js"); 21 const { 22 updateFormDataSections, 23 } = require("resource://devtools/client/netmonitor/src/utils/request-utils.js"); 24 const { 25 getSelectedRequest, 26 isSelectedRequestVisible, 27 } = require("resource://devtools/client/netmonitor/src/selectors/index.js"); 28 29 // Components 30 const SplitBox = createFactory( 31 require("resource://devtools/client/shared/components/splitter/SplitBox.js") 32 ); 33 const RequestList = createFactory( 34 require("resource://devtools/client/netmonitor/src/components/request-list/RequestList.js") 35 ); 36 const Toolbar = createFactory( 37 require("resource://devtools/client/netmonitor/src/components/Toolbar.js") 38 ); 39 40 loader.lazyGetter(this, "NetworkDetailsBar", function () { 41 return createFactory( 42 require("resource://devtools/client/netmonitor/src/components/request-details/NetworkDetailsBar.js") 43 ); 44 }); 45 46 loader.lazyGetter(this, "NetworkActionBar", function () { 47 return createFactory( 48 require("resource://devtools/client/netmonitor/src/components/NetworkActionBar.js") 49 ); 50 }); 51 52 // MediaQueryList object responsible for switching sidebar splitter 53 // between landscape and portrait mode (depending on browser window size). 54 const MediaQueryVert = window.matchMedia("(min-width: 700px)"); 55 56 // MediaQueryList object responsible for switching the toolbar 57 // between single and 2-rows layout (depending on browser window size). 58 const MediaQuerySingleRow = window.matchMedia("(min-width: 1020px)"); 59 60 /** 61 * Monitor panel component 62 * The main panel for displaying various network request information 63 */ 64 class MonitorPanel extends Component { 65 static get propTypes() { 66 return { 67 actions: PropTypes.object.isRequired, 68 connector: PropTypes.object.isRequired, 69 isEmpty: PropTypes.bool.isRequired, 70 networkDetailsOpen: PropTypes.bool.isRequired, 71 openNetworkDetails: PropTypes.func.isRequired, 72 toolboxDoc: PropTypes.object.isRequired, 73 // Callback for opening split console. 74 openSplitConsole: PropTypes.func, 75 onNetworkDetailsResized: PropTypes.func.isRequired, 76 request: PropTypes.object, 77 selectedRequestVisible: PropTypes.bool.isRequired, 78 sourceMapURLService: PropTypes.object, 79 openLink: PropTypes.func, 80 updateRequest: PropTypes.func.isRequired, 81 networkActionOpen: PropTypes.bool.isRequired, 82 }; 83 } 84 85 constructor(props) { 86 super(props); 87 88 this.state = { 89 isSingleRow: MediaQuerySingleRow.matches, 90 isVerticalSpliter: MediaQueryVert.matches, 91 }; 92 93 this.onLayoutChange = this.onLayoutChange.bind(this); 94 this.onNetworkDetailsResized = this.onNetworkDetailsResized.bind(this); 95 } 96 97 componentDidMount() { 98 MediaQuerySingleRow.addListener(this.onLayoutChange); 99 MediaQueryVert.addListener(this.onLayoutChange); 100 this.persistDetailsPanelSize(); 101 this.persistActionBarSize(); 102 } 103 104 // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1774507 105 UNSAFE_componentWillReceiveProps(nextProps) { 106 updateFormDataSections(nextProps); 107 } 108 109 componentDidUpdate() { 110 const { selectedRequestVisible, openNetworkDetails, networkDetailsOpen } = 111 this.props; 112 // Close the side panel if it was open and there is no more selected request 113 if (!selectedRequestVisible && networkDetailsOpen) { 114 openNetworkDetails(false); 115 } 116 } 117 118 componentWillUnmount() { 119 MediaQuerySingleRow.removeListener(this.onLayoutChange); 120 MediaQueryVert.removeListener(this.onLayoutChange); 121 this.persistDetailsPanelSize(); 122 this.persistActionBarSize(); 123 } 124 125 persistDetailsPanelSize() { 126 const { clientWidth, clientHeight } = findDOMNode(this.refs.endPanel) || {}; 127 128 if (this.state.isVerticalSpliter && clientWidth) { 129 Services.prefs.setIntPref( 130 "devtools.netmonitor.panes-network-details-width", 131 clientWidth 132 ); 133 } 134 if (!this.state.isVerticalSpliter && clientHeight) { 135 Services.prefs.setIntPref( 136 "devtools.netmonitor.panes-network-details-height", 137 clientHeight 138 ); 139 } 140 } 141 142 persistActionBarSize() { 143 const { clientWidth, clientHeight } = 144 findDOMNode(this.refs.actionBar) || {}; 145 if (clientWidth) { 146 Services.prefs.setIntPref( 147 "devtools.netmonitor.panes-search-width", 148 clientWidth 149 ); 150 } 151 if (clientHeight) { 152 Services.prefs.setIntPref( 153 "devtools.netmonitor.panes-search-height", 154 clientHeight 155 ); 156 } 157 } 158 159 onLayoutChange() { 160 this.setState({ 161 isSingleRow: MediaQuerySingleRow.matches, 162 isVerticalSpliter: MediaQueryVert.matches, 163 }); 164 } 165 166 onNetworkDetailsResized(width, height) { 167 // Cleaning width and height parameters, because SplitBox passes ALWAYS two values, 168 // while depending on orientation ONLY ONE dimension is managed by it at a time. 169 const { isVerticalSpliter } = this.state; 170 return this.props.onNetworkDetailsResized( 171 isVerticalSpliter ? width : null, 172 isVerticalSpliter ? null : height 173 ); 174 } 175 176 renderActionBar() { 177 const { connector, isEmpty, networkActionOpen } = this.props; 178 179 const initialWidth = Services.prefs.getIntPref( 180 "devtools.netmonitor.panes-search-width" 181 ); 182 const initialHeight = Services.prefs.getIntPref( 183 "devtools.netmonitor.panes-search-height" 184 ); 185 186 return SplitBox({ 187 className: "devtools-responsive-container", 188 initialWidth, 189 initialHeight, 190 minSize: "250px", 191 maxSize: "80%", 192 splitterSize: networkActionOpen ? 1 : 0, 193 startPanel: 194 networkActionOpen && 195 NetworkActionBar({ 196 ref: "actionBar", 197 connector, 198 }), 199 endPanel: RequestList({ isEmpty, connector }), 200 endPanelControl: false, 201 vert: true, 202 }); 203 } 204 205 render() { 206 const { 207 actions, 208 connector, 209 networkDetailsOpen, 210 openLink, 211 openSplitConsole, 212 sourceMapURLService, 213 toolboxDoc, 214 } = this.props; 215 216 const initialWidth = Services.prefs.getIntPref( 217 "devtools.netmonitor.panes-network-details-width" 218 ); 219 220 const initialHeight = Services.prefs.getIntPref( 221 "devtools.netmonitor.panes-network-details-height" 222 ); 223 224 return div( 225 { className: "monitor-panel" }, 226 Toolbar({ 227 actions, 228 connector, 229 openSplitConsole, 230 singleRow: this.state.isSingleRow, 231 toolboxDoc, 232 }), 233 SplitBox({ 234 className: "devtools-responsive-container", 235 initialWidth, 236 initialHeight, 237 minSize: "50px", 238 maxSize: "80%", 239 splitterSize: networkDetailsOpen ? 1 : 0, 240 startPanel: this.renderActionBar(), 241 endPanel: 242 networkDetailsOpen && 243 NetworkDetailsBar({ 244 ref: "endPanel", 245 connector, 246 openLink, 247 sourceMapURLService, 248 }), 249 endPanelCollapsed: !networkDetailsOpen, 250 endPanelControl: true, 251 vert: this.state.isVerticalSpliter, 252 onControlledPanelResized: this.onNetworkDetailsResized, 253 }) 254 ); 255 } 256 } 257 258 module.exports = connect( 259 state => ({ 260 isEmpty: !state.requests.requests.length, 261 networkDetailsOpen: state.ui.networkDetailsOpen, 262 networkActionOpen: state.ui.networkActionOpen, 263 request: getSelectedRequest(state), 264 selectedRequestVisible: isSelectedRequestVisible(state), 265 }), 266 dispatch => ({ 267 openNetworkDetails: open => dispatch(Actions.openNetworkDetails(open)), 268 onNetworkDetailsResized: (width, height) => 269 dispatch(Actions.resizeNetworkDetails(width, height)), 270 updateRequest: (id, data, batch) => 271 dispatch(Actions.updateRequest(id, data, batch)), 272 }) 273 )(MonitorPanel);