SidebarRuntimeItem.js (7137B)
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 createFactory, 9 PureComponent, 10 } = require("resource://devtools/client/shared/vendor/react.mjs"); 11 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); 12 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs"); 13 const { 14 withRouter, 15 } = require("resource://devtools/client/shared/vendor/react-router-dom.js"); 16 17 const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js"); 18 const Localized = createFactory(FluentReact.Localized); 19 20 const Message = createFactory( 21 require("resource://devtools/client/aboutdebugging/src/components/shared/Message.js") 22 ); 23 const SidebarItem = createFactory( 24 require("resource://devtools/client/aboutdebugging/src/components/sidebar/SidebarItem.js") 25 ); 26 const Actions = require("resource://devtools/client/aboutdebugging/src/actions/index.js"); 27 const { 28 MESSAGE_LEVEL, 29 } = require("resource://devtools/client/aboutdebugging/src/constants.js"); 30 31 /** 32 * This component displays a runtime item of the Sidebar component. 33 */ 34 class SidebarRuntimeItem extends PureComponent { 35 static get propTypes() { 36 return { 37 deviceName: PropTypes.string, 38 dispatch: PropTypes.func.isRequired, 39 // Provided by wrapping the component with FluentReact.withLocalization. 40 getString: PropTypes.func.isRequired, 41 icon: PropTypes.string.isRequired, 42 isConnected: PropTypes.bool.isRequired, 43 isConnecting: PropTypes.bool.isRequired, 44 isConnectionFailed: PropTypes.bool.isRequired, 45 isConnectionNotResponding: PropTypes.bool.isRequired, 46 isConnectionTimeout: PropTypes.bool.isRequired, 47 isSelected: PropTypes.bool.isRequired, 48 isUnavailable: PropTypes.bool.isRequired, 49 isUnplugged: PropTypes.bool.isRequired, 50 name: PropTypes.string.isRequired, 51 runtimeId: PropTypes.string.isRequired, 52 53 // Provided by react-router 54 match: PropTypes.object.isRequired, 55 location: PropTypes.object.isRequired, 56 history: PropTypes.object.isRequired, 57 }; 58 } 59 60 renderConnectButton() { 61 const { isConnecting, history } = this.props; 62 const localizationId = isConnecting 63 ? "about-debugging-sidebar-item-connect-button-connecting" 64 : "about-debugging-sidebar-item-connect-button"; 65 return Localized( 66 { 67 id: localizationId, 68 }, 69 dom.button( 70 { 71 className: "default-button default-button--micro qa-connect-button", 72 disabled: isConnecting, 73 onClick: async () => { 74 const { dispatch, runtimeId } = this.props; 75 await dispatch(Actions.connectRuntime(runtimeId)); 76 if (this.props.isConnected) { 77 // If the connection was successful, navigate to the new runtime. 78 // Note: By using `this.props`, the latest value is retrieved, as 79 // the result of the `connectRuntime` action. If we had used a 80 // destructuring assignment at the start of the 81 // `renderConnectButton` function instead, we'd have captured the 82 // initial (outdated) value instead. 83 history.push("/runtime/" + encodeURIComponent(runtimeId)); 84 } 85 }, 86 }, 87 localizationId 88 ) 89 ); 90 } 91 92 renderMessage(flag, level, localizationId, className) { 93 if (!flag) { 94 return null; 95 } 96 97 return Message( 98 { 99 level, 100 className: `${className} sidebar-runtime-item__message`, 101 isCloseable: true, 102 }, 103 Localized( 104 { 105 id: localizationId, 106 }, 107 dom.p({ className: "word-wrap-anywhere" }, localizationId) 108 ) 109 ); 110 } 111 112 renderName() { 113 const { deviceName, getString, isUnavailable, isUnplugged, name } = 114 this.props; 115 116 let displayName, qaClassName; 117 if (isUnplugged) { 118 displayName = getString("about-debugging-sidebar-runtime-item-unplugged"); 119 qaClassName = "qa-runtime-item-unplugged"; 120 } else if (isUnavailable) { 121 displayName = getString( 122 "about-debugging-sidebar-runtime-item-waiting-for-browser" 123 ); 124 qaClassName = "qa-runtime-item-waiting-for-browser"; 125 } else { 126 displayName = name; 127 qaClassName = "qa-runtime-item-standard"; 128 } 129 130 const localizationId = deviceName 131 ? "about-debugging-sidebar-runtime-item-name" 132 : "about-debugging-sidebar-runtime-item-name-no-device"; 133 134 const className = "ellipsis-text sidebar-runtime-item__runtime"; 135 136 function renderWithDevice() { 137 return dom.span( 138 { 139 className, 140 title: localizationId, 141 }, 142 deviceName, 143 dom.br({}), 144 dom.span( 145 { 146 className: `sidebar-runtime-item__runtime__details ${qaClassName}`, 147 }, 148 displayName 149 ) 150 ); 151 } 152 153 function renderNoDevice() { 154 return dom.span( 155 { 156 className, 157 title: localizationId, 158 }, 159 displayName 160 ); 161 } 162 163 return Localized( 164 { 165 id: localizationId, 166 attrs: { title: true }, 167 $deviceName: deviceName, 168 $displayName: displayName, 169 }, 170 deviceName ? renderWithDevice() : renderNoDevice() 171 ); 172 } 173 174 render() { 175 const { 176 getString, 177 icon, 178 isConnected, 179 isConnectionFailed, 180 isConnectionTimeout, 181 isConnectionNotResponding, 182 isSelected, 183 isUnavailable, 184 runtimeId, 185 } = this.props; 186 187 const connectionStatus = isConnected 188 ? getString("aboutdebugging-sidebar-runtime-connection-status-connected") 189 : getString( 190 "aboutdebugging-sidebar-runtime-connection-status-disconnected" 191 ); 192 193 return SidebarItem( 194 { 195 isSelected, 196 to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null, 197 }, 198 dom.section( 199 { 200 className: "sidebar-runtime-item__container", 201 }, 202 dom.img({ 203 className: "sidebar-runtime-item__icon ", 204 src: icon, 205 alt: connectionStatus, 206 title: connectionStatus, 207 }), 208 this.renderName(), 209 !isUnavailable && !isConnected ? this.renderConnectButton() : null 210 ), 211 this.renderMessage( 212 isConnectionFailed, 213 MESSAGE_LEVEL.ERROR, 214 "about-debugging-sidebar-item-connect-button-connection-failed", 215 "qa-connection-error" 216 ), 217 this.renderMessage( 218 isConnectionTimeout, 219 MESSAGE_LEVEL.ERROR, 220 "about-debugging-sidebar-item-connect-button-connection-timeout", 221 "qa-connection-timeout" 222 ), 223 this.renderMessage( 224 isConnectionNotResponding, 225 MESSAGE_LEVEL.WARNING, 226 "about-debugging-sidebar-item-connect-button-connection-not-responding", 227 "qa-connection-not-responding" 228 ) 229 ); 230 } 231 } 232 233 module.exports = withRouter(FluentReact.withLocalization(SidebarRuntimeItem));