Bug 1561538 - Render message when there are no addons. r=robwu,flod
authorSamuel Grasse-Haroldsen <sgrasseharoldsen@gmail.com>
Tue, 20 Apr 2021 13:03:01 +0000
changeset 576765 bd6a10e0e8954b3667fc246d174b741f58d37393
parent 576764 ad2c6481c011a2bf9c42d96b64da68c17377de48
child 576766 aea79948fb7a3893ebcae0f9a1f3142f3244cfe8
push id38391
push userncsoregi@mozilla.com
push dateTue, 20 Apr 2021 21:39:49 +0000
treeherdermozilla-central@0c0c1834fbd1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrobwu, flod
bugs1561538
milestone89.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1561538 - Render message when there are no addons. r=robwu,flod Differential Revision: https://phabricator.services.mozilla.com/D106697
toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
toolkit/mozapps/extensions/content/aboutaddons.css
toolkit/mozapps/extensions/content/aboutaddons.js
toolkit/mozapps/extensions/test/browser/browser_html_list_view.js
--- a/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
+++ b/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
@@ -6,16 +6,19 @@ addons-page-title = Add-ons Manager
 
 search-header =
     .placeholder = Search addons.mozilla.org
     .searchbuttonlabel = Search
 
 search-header-shortcut =
     .key = f
 
+list-empty-get-extensions-message =
+    Get extensions and themes on <a data-l10n-name="get-extensions">{ $domain }</a>
+
 list-empty-installed =
     .value = You don’t have any add-ons of this type installed
 
 list-empty-available-updates =
     .value = No updates found
 
 list-empty-recent-updates =
     .value = You haven’t recently updated any add-ons
--- a/toolkit/mozapps/extensions/content/aboutaddons.css
+++ b/toolkit/mozapps/extensions/content/aboutaddons.css
@@ -732,16 +732,20 @@ button.tab-button:-moz-focusring {
   outline: none;
   box-shadow: none;
 }
 
 panel-list {
   font: menu;
 }
 
+section:not(:empty) ~ #empty-addons-message {
+  display: none;
+}
+
 @media (max-width: 830px) {
   .category[badge-count]::after {
     content: "";
     display: block;
     width: 5px;
     height: 5px;
     border-radius: 50%;
     min-width: auto;
--- a/toolkit/mozapps/extensions/content/aboutaddons.js
+++ b/toolkit/mozapps/extensions/content/aboutaddons.js
@@ -3953,16 +3953,34 @@ class AddonList extends HTMLElement {
   createSectionHeading(headingIndex) {
     let { headingId } = this.sections[headingIndex];
     let heading = document.createElement("h2");
     heading.classList.add("list-section-heading");
     document.l10n.setAttributes(heading, headingId);
     return heading;
   }
 
+  createEmptyListMessage() {
+    let messageContainer = document.createElement("p");
+    messageContainer.id = "empty-addons-message";
+    let a = document.createElement("a");
+    a.href = Services.urlFormatter.formatURLPref(
+      "extensions.getAddons.link.url"
+    );
+    a.setAttribute("target", "_blank");
+    a.setAttribute("data-l10n-name", "get-extensions");
+    document.l10n.setAttributes(
+      messageContainer,
+      "list-empty-get-extensions-message",
+      { domain: a.hostname }
+    );
+    messageContainer.appendChild(a);
+    return messageContainer;
+  }
+
   updateSectionIfEmpty(section) {
     // The header is added before any add-on cards, so if there's only one
     // child then it's the header. In that case we should empty out the section.
     if (section.children.length == 1) {
       section.textContent = "";
     }
   }
 
@@ -4194,16 +4212,23 @@ class AddonList extends HTMLElement {
     frag.appendChild(this.pendingUninstallStack);
 
     // Render the sections.
     for (let i = 0; i < sectionedAddons.length; i++) {
       this.sections[i].node = this.renderSection(sectionedAddons[i], i);
       frag.appendChild(this.sections[i].node);
     }
 
+    // Render the placeholder that is shown when all sections are empty.
+    // This call is after rendering the sections, because its visibility
+    // is controlled through the general sibling combinator relative to
+    // the sections (section ~).
+    let message = this.createEmptyListMessage();
+    frag.appendChild(message);
+
     // Make sure fluent has set all the strings before we render. This will
     // avoid the height changing as strings go from 0 height to having text.
     await document.l10n.translateFragment(frag);
     this.appendChild(frag);
   }
 
   registerListener() {
     AddonManagerListenerHandler.addListener(this);
--- a/toolkit/mozapps/extensions/test/browser/browser_html_list_view.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_html_list_view.js
@@ -983,8 +983,34 @@ add_task(async function testDisabledDimm
   transitionEnded = waitForTransition(card);
   EventUtils.synthesizeMouseAtCenter(pageHeader, {}, win);
   await transitionEnded;
   checkOpacity(card, "0.6", "The card is dimmed again");
 
   await closeView(win);
   await extension.unload();
 });
+
+add_task(async function testEmptyMessage() {
+  let win = await loadInitialView("extension");
+  let doc = win.document;
+  let enabledSection = getSection(doc, "enabled");
+  let disabledSection = getSection(doc, "disabled");
+  const message = doc.querySelector("#empty-addons-message");
+
+  // With 3 enabled addons and 1 disabled, the message is hidden
+  is_element_hidden(message, "Empty addons message hidden");
+
+  // The test runner (Mochitest) relies on add-ons that should not be removed.
+  // Simulate the scenario of zero add-ons by clearing all rendered sections.
+  while (enabledSection.firstChild) {
+    enabledSection.firstChild.remove();
+  }
+
+  while (disabledSection.firstChild) {
+    disabledSection.firstChild.remove();
+  }
+
+  // Message should now be displayed
+  is_element_visible(message, "Empty addons message visible");
+
+  await closeView(win);
+});