Bug 1494543 - Part 2: Add model + short runtime name to the sidebar item. r=jdescottes,daisuke
authorBelén Albeza <balbeza@mozilla.com>
Tue, 16 Oct 2018 11:57:45 +0000
changeset 489797 180b08bce5810da4b876e966f291bf1b90b53227
parent 489796 bca2310f556c6848737084fe009f7976f2cf6f3c
child 489798 5d30f69fe9072a2f653f3931304ed3668823c99c
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersjdescottes, daisuke
bugs1494543
milestone64.0a1
Bug 1494543 - Part 2: Add model + short runtime name to the sidebar item. r=jdescottes,daisuke Added new getters to the ADB scanner so our runtime objects have now the information we need. Note that the UX of the devices in this patch doesn't still match what we had in the mockups (icons don't match, and we also need a circle with a tick), but since we have another bug to handle the CSS in the Sidebar, we can always adapt it there. The information needed to display what is shown in the mockups should be passed in this patch –if I miss anything, give me a shout! Differential Revision: https://phabricator.services.mozilla.com/D7705
devtools/client/aboutdebugging-new/src/actions/runtimes.js
devtools/client/aboutdebugging-new/src/components/RuntimeInfo.js
devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.css
devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
devtools/shared/adb/adb-scanner.js
--- a/devtools/client/aboutdebugging-new/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging-new/src/actions/runtimes.js
@@ -50,43 +50,43 @@ async function createNetworkClient(host,
 }
 
 async function createUSBClient(socketPath) {
   const port = await ADB.prepareTCPConnection(socketPath);
   return createNetworkClient("localhost", port);
 }
 
 async function createClientForRuntime(runtime) {
-  const { connectionParameters, type } = runtime;
+  const { extra, type } = runtime;
 
   if (type === RUNTIMES.THIS_FIREFOX) {
     return createLocalClient();
   } else if (type === RUNTIMES.NETWORK) {
-    const { host, port } = connectionParameters;
+    const { host, port } = extra.connectionParameters;
     return createNetworkClient(host, port);
   } else if (type === RUNTIMES.USB) {
-    const { socketPath } = connectionParameters;
+    const { socketPath } = extra.connectionParameters;
     return createUSBClient(socketPath);
   }
 
   return null;
 }
 
 async function getRuntimeInfo(runtime, client) {
-  const { model, type } = runtime;
+  const { extra, type } = runtime;
   const deviceFront = await client.mainRoot.getFront("device");
   const { brandName: name, channel, version } = await deviceFront.getDescription();
   const icon =
     (channel === "release" || channel === "beta" || channel === "aurora")
       ? `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg`
       : "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
 
   return {
     icon,
-    model,
+    deviceName: extra ? extra.deviceName : undefined,
     name,
     type,
     version,
   };
 }
 
 function connectRuntime(id) {
   return async (dispatch, getState) => {
--- a/devtools/client/aboutdebugging-new/src/components/RuntimeInfo.js
+++ b/devtools/client/aboutdebugging-new/src/components/RuntimeInfo.js
@@ -13,42 +13,42 @@ const Localized = createFactory(FluentRe
 
 /**
  * This component displays runtime information.
  */
 class RuntimeInfo extends PureComponent {
   static get propTypes() {
     return {
       icon: PropTypes.string.isRequired,
-      model: PropTypes.string,
+      deviceName: PropTypes.string,
       name: PropTypes.string.isRequired,
       version: PropTypes.string.isRequired,
     };
   }
 
   render() {
-    const { icon, model, name, version } = this.props;
+    const { icon, deviceName, name, version } = this.props;
 
     return dom.h1(
       {
         className: "runtime-info",
       },
       dom.img(
         {
           className: "runtime-info__icon",
           src: icon,
         }
       ),
       Localized(
         {
-          id: model ? "about-debugging-runtime-info-with-model"
-                    : "about-debugging-runtime-info",
+          id: deviceName ? "about-debugging-runtime-info-with-model"
+                          : "about-debugging-runtime-info",
           $name: name,
-          $model: model,
+          $deviceName: deviceName,
           $version: version,
         },
-        dom.label({}, `${ name } on ${ model } (${ version })`)
+        dom.label({}, `${ name } on ${ deviceName } (${ version })`)
       )
     );
   }
 }
 
 module.exports = RuntimeInfo;
--- a/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
@@ -55,16 +55,17 @@ class Sidebar extends PureComponent {
     const { dispatch, selectedPage } = this.props;
 
     return runtimes.map(runtime => {
       const pageId = runtime.type + "-" + runtime.id;
       const runtimeHasConnection = !!runtime.connection;
 
       return SidebarRuntimeItem({
         id: pageId,
+        deviceName: runtime.extra.deviceName,
         dispatch,
         icon,
         isConnected: runtimeHasConnection,
         isSelected: selectedPage === pageId,
         key: pageId,
         name: runtime.name,
         runtimeId: runtime.id,
       });
--- a/devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.css
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.css
@@ -6,12 +6,20 @@
  * Layout of a runtime sidebar item
  *
  *  +--------+----------------+---------------------------+
  *  | Icon   | Runtime name   | Connect button            |
  *  +--------+----------------+---------------------------+
  */
 
 .sidebar-runtime-item {
+  font-size: 0.8em;
   align-items: center;
   display: grid;
-  grid-template-columns: 1fr max-content;
+  grid-column-gap: var(--base-distance);
+  grid-template-columns: 20px 1fr auto;
 }
+
+.sidebar-runtime-item__icon {
+  fill: currentColor;
+  -moz-context-properties: fill;
+  margin-inline-end: var(--base-distance);
+}
--- a/devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
@@ -15,19 +15,22 @@ const SidebarItem = createFactory(requir
 const Actions = require("../../actions/index");
 
 /**
  * This component displays a runtime item of the Sidebar component.
  */
 class SidebarRuntimeItem extends PureComponent {
   static get propTypes() {
     return {
+      id: PropTypes.string.isRequired,
+      deviceName: PropTypes.string,
       dispatch: PropTypes.func.isRequired,
+      // Provided by wrapping the component with FluentReact.withLocalization.
+      getString: PropTypes.func.isRequired,
       icon: PropTypes.string.isRequired,
-      id: PropTypes.string.isRequired,
       isConnected: PropTypes.bool.isRequired,
       isSelected: PropTypes.bool.isRequired,
       name: PropTypes.string.isRequired,
       runtimeId: PropTypes.string.isRequired,
     };
   }
 
   renderConnectButton() {
@@ -43,50 +46,72 @@ class SidebarRuntimeItem extends PureCom
             dispatch(Actions.connectRuntime(runtimeId));
           }
         },
         "Connect"
       )
     );
   }
 
+  renderNameWithDevice(name, device) {
+    return dom.span(
+      {
+        className: "ellipsis-text",
+        title: `${name} (${device})`
+      },
+      `${name}`,
+      dom.br({}),
+      device
+    );
+  }
+
+  renderName(name) {
+    return dom.span(
+      {
+        className: "ellipsis-text",
+        title: name
+      },
+      `${name}`
+    );
+  }
+
   render() {
     const {
+      deviceName,
       dispatch,
+      getString,
       icon,
       id,
       isConnected,
       isSelected,
       name,
       runtimeId,
     } = this.props;
 
+    const connectionStatus = isConnected ?
+      getString("aboutdebugging-sidebar-runtime-connection-status-connected") :
+      getString("aboutdebugging-sidebar-runtime-connection-status-disconnected");
+
     return SidebarItem(
       {
         isSelected,
         selectable: isConnected,
         className: "sidebar-runtime-item",
         onSelect: () => {
           dispatch(Actions.selectPage(id, runtimeId));
         }
       },
-      dom.span(
-        { className: "ellipsis-text" },
-        dom.img(
-          {
-            className: "sidebar-runtime-item__icon " +
-             `${isConnected ? "sidebar-runtime-item__icon--connected" : "" }`,
-            src: icon,
-          }
-        ),
-        dom.span(
-          {
-            title: name,
-          },
-          ` ${name}`
-        ),
+      dom.img(
+        {
+          className: "sidebar-runtime-item__icon " +
+            `${isConnected ? "sidebar-runtime-item__icon--connected" : "" }`,
+          src: icon,
+          alt: connectionStatus,
+          title: connectionStatus
+        }
       ),
+      deviceName ? this.renderNameWithDevice(name, deviceName) : this.renderName(name),
       !isConnected ? this.renderConnectButton() : null
     );
   }
 }
 
-module.exports = SidebarRuntimeItem;
+module.exports = FluentReact.withLocalization(SidebarRuntimeItem);
--- a/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
@@ -77,37 +77,41 @@ function runtimesReducer(state = Runtime
       return _updateRuntimeById(id, { connection: null }, state);
     }
 
     case NETWORK_LOCATIONS_UPDATED: {
       const { locations } = action;
       const networkRuntimes = locations.map(location => {
         const [ host, port ] = location.split(":");
         return {
-          connectionParameters: { host, port },
           id: location,
+          extra: {
+            connectionParameters: { host, port },
+          },
           name: location,
           type: RUNTIMES.NETWORK,
         };
       });
       return Object.assign({}, state, { networkRuntimes });
     }
 
     case UNWATCH_RUNTIME_SUCCESS: {
       return Object.assign({}, state, { selectedRuntimeId: null });
     }
 
     case USB_RUNTIMES_UPDATED: {
       const { runtimes } = action;
       const usbRuntimes = runtimes.map(runtime => {
         return {
-          connectionParameters: { socketPath: runtime._socketPath },
           id: runtime.id,
-          model: runtime._model,
-          name: runtime.name,
+          extra: {
+            connectionParameters: { socketPath: runtime._socketPath },
+            deviceName: runtime.deviceName,
+          },
+          name: runtime.shortName,
           type: RUNTIMES.USB,
         };
       });
       return Object.assign({}, state, { usbRuntimes });
     }
 
     case WATCH_RUNTIME_SUCCESS: {
       const { id } = action.runtime;
--- a/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
+++ b/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
@@ -8,16 +8,21 @@
 # Sidebar heading for selecting the currently running instance of Firefox
 about-debugging-sidebar-this-firefox =
   .name = This Firefox
 
 # Sidebar heading for connecting to some remote source
 about-debugging-sidebar-connect =
   .name = Connect
 
+# Connection status (connected) for runtime items in the sidebar
+aboutdebugging-sidebar-runtime-connection-status-connected = Connected
+# Connection status (disconnected) for runtime items in the sidebar
+aboutdebugging-sidebar-runtime-connection-status-disconnected = Disconnected
+
 # Text displayed in the about:debugging sidebar when no device was found.
 about-debugging-sidebar-no-devices = No devices discovered
 
 # Text displayed in buttons found in sidebar items representing remote runtimes.
 # Clicking on the button will attempt to connect to the runtime.
 about-debugging-sidebar-item-connect-button = Connect
 
 # Temporary text displayed in sidebar items representing remote runtimes after
@@ -168,13 +173,13 @@ about-debugging-worker-status-stopped = 
 # about:debugging, so such service workers are considered as registering.
 about-debugging-worker-status-registering = Registering
 
 # Displayed for runtime info in runtime pages.
 # { $name } is brand name such as "Firefox Nightly"
 # { $version } is version such as "64.0a1"
 about-debugging-runtime-info = { $name } ({ $version })
 
-# Displayed for runtime info in runtime page when we display the model as well.
+# Displayed for runtime info in runtime page when we display the device model as well.
 # { $name } is brand name such as "Firefox Nightly"
 # { $version } is version such as "64.0a1"
-# { $model } is model name of device
-about-debugging-runtime-info-with-model = { $name } on { $model } ({ $version })
+# { $deviceName } is model name of device
+about-debugging-runtime-info-with-model = { $name } on { $deviceName } ({ $version })
--- a/devtools/shared/adb/adb-scanner.js
+++ b/devtools/shared/adb/adb-scanner.js
@@ -139,43 +139,57 @@ FirefoxOnAndroidRuntime.detect = async f
     dumpn("Found " + runtime.name);
     runtimes.push(runtime);
   }
   return runtimes;
 };
 
 FirefoxOnAndroidRuntime.prototype = Object.create(Runtime.prototype);
 
+FirefoxOnAndroidRuntime.prototype._channel = function() {
+  const packageName = this._packageName();
+
+  switch (packageName) {
+    case "org.mozilla.firefox":
+      return "";
+    case "org.mozilla.firefox_beta":
+      return "Beta";
+    case "org.mozilla.fennec":
+    case "org.mozilla.fennec_aurora":
+      // This package name is now the one for Firefox Nightly distributed
+      // through the Google Play Store since "dawn project"
+      // cf. https://bugzilla.mozilla.org/show_bug.cgi?id=1357351#c8
+      return "Nightly";
+    default:
+      return "Custom";
+  }
+};
+
+FirefoxOnAndroidRuntime.prototype._packageName = function() {
+  // If using abstract socket address, it is "@org.mozilla.firefox/..."
+  // If using path base socket, it is "/data/data/<package>...""
+  // Until Fennec 62 only supports path based UNIX domain socket, but
+  // Fennec 63+ supports both path based and abstract socket.
+  return this._socketPath.startsWith("@") ?
+    this._socketPath.substr(1).split("/")[0] :
+    this._socketPath.split("/")[3];
+};
+
+Object.defineProperty(FirefoxOnAndroidRuntime.prototype, "shortName", {
+  get() {
+    return `Firefox ${this._channel()}`;
+  }
+});
+
+Object.defineProperty(FirefoxOnAndroidRuntime.prototype, "deviceName", {
+  get() {
+    return this._model || this.device.id;
+  }
+});
+
 Object.defineProperty(FirefoxOnAndroidRuntime.prototype, "name", {
   get() {
-    // If using abstract socket address, it is "@org.mozilla.firefox/..."
-    // If using path base socket, it is "/data/data/<package>...""
-    // Until Fennec 62 only supports path based UNIX domain socket, but
-    // Fennec 63+ supports both path based and abstract socket.
-    const packageName = this._socketPath.startsWith("@") ?
-                        this._socketPath.substr(1).split("/")[0] :
-                        this._socketPath.split("/")[3];
-    let channel;
-    switch (packageName) {
-      case "org.mozilla.firefox":
-        channel = "";
-        break;
-      case "org.mozilla.firefox_beta":
-        channel = " Beta";
-        break;
-      case "org.mozilla.fennec_aurora":
-        // This package name is now the one for Firefox Nightly distributed
-        // through the Google Play Store since "dawn project"
-        // cf. https://bugzilla.mozilla.org/show_bug.cgi?id=1357351#c8
-        channel = " Nightly";
-        break;
-      case "org.mozilla.fennec":
-        channel = " Nightly";
-        break;
-      default:
-        channel = " Custom";
-    }
-    return "Firefox" + channel + " on Android (" +
-           (this._model || this.device.id) + ")";
+    const channel = this._channel();
+    return "Firefox " + channel + " on Android (" + this.deviceName + ")";
   }
 });
 
 exports.ADBScanner = ADBScanner;