Bug 1549809 - Live filter logins in the login list. r=MattN
authorJared Wein <jwein@mozilla.com>
Tue, 14 May 2019 20:06:08 +0000
changeset 473852 60941bb2b5242eebb8ec1a855dd5fd06f017bb5b
parent 473851 06466fbe6b4eab8f0d8cd8d86bcd4777300adfbb
child 473853 bba51fabf09d9868343e6f12cb55d62ae168d961
push id36017
push userrgurzau@mozilla.com
push dateWed, 15 May 2019 09:25:56 +0000
treeherdermozilla-central@76bbedc1ec1a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMattN
bugs1549809
milestone68.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 1549809 - Live filter logins in the login list. r=MattN Differential Revision: https://phabricator.services.mozilla.com/D30757
browser/components/aboutlogins/content/components/login-filter.js
browser/components/aboutlogins/content/components/login-list-item.css
browser/components/aboutlogins/content/components/login-list.js
--- a/browser/components/aboutlogins/content/components/login-filter.js
+++ b/browser/components/aboutlogins/content/components/login-filter.js
@@ -6,16 +6,31 @@ class LoginFilter extends HTMLElement {
   connectedCallback() {
     if (this.children.length) {
       return;
     }
 
     let loginFilterTemplate = document.querySelector("#login-filter-template");
     this.attachShadow({mode: "open"})
         .appendChild(loginFilterTemplate.content.cloneNode(true));
+
+    this.addEventListener("input", this);
+  }
+
+  handleEvent(event) {
+    switch (event.type) {
+      case "input": {
+        this.dispatchEvent(new CustomEvent("AboutLoginsFilterLogins", {
+          bubbles: true,
+          composed: true,
+          detail: event.originalTarget.value,
+        }));
+        break;
+      }
+    }
   }
 
   static get observedAttributes() {
     return ["placeholder"];
   }
 
   /* Fluent doesn't handle localizing into Shadow DOM yet so strings
      need to get reflected in to their targeted element. */
--- a/browser/components/aboutlogins/content/components/login-list-item.css
+++ b/browser/components/aboutlogins/content/components/login-list-item.css
@@ -4,16 +4,21 @@
 
 :host {
   border-inline-start: 4px solid transparent;
   border-bottom: 1px solid var(--grey-30);
   display: block;
   padding: 10px;
 }
 
+/* [hidden] isn't applying to elements in Shadow DOM. */
+:host([hidden]) {
+  display: none;
+}
+
 :host(:hover) {
   background-color: var(--grey-90-a10);
 }
 
 :host(:hover:active) {
   background-color: var(--grey-90-a20);
 }
 
--- a/browser/components/aboutlogins/content/components/login-list.js
+++ b/browser/components/aboutlogins/content/components/login-list.js
@@ -16,27 +16,50 @@ class LoginList extends HTMLElement {
       return;
     }
     let loginListTemplate = document.querySelector("#login-list-template");
     this.attachShadow({mode: "open"})
         .appendChild(loginListTemplate.content.cloneNode(true));
     this.render();
 
     window.addEventListener("AboutLoginsLoginSelected", this);
+    window.addEventListener("AboutLoginsFilterLogins", this);
   }
 
   render() {
     let list = this.shadowRoot.querySelector("ol");
     for (let login of this._logins) {
       list.append(new LoginListItem(login));
     }
   }
 
   handleEvent(event) {
     switch (event.type) {
+      case "AboutLoginsFilterLogins": {
+        let query = event.detail.toLocaleLowerCase();
+        let matchingLoginGuids;
+        if (query) {
+          matchingLoginGuids = this._logins.filter(login => {
+            return login.hostname.toLocaleLowerCase().includes(query) ||
+                   login.username.toLocaleLowerCase().includes(query);
+          }).map(login => login.guid);
+        } else {
+          matchingLoginGuids = this._logins.map(login => login.guid);
+        }
+        for (let listItem of this.shadowRoot.querySelectorAll("login-list-item")) {
+          if (matchingLoginGuids.includes(listItem.getAttribute("guid"))) {
+            if (listItem.hidden) {
+              listItem.hidden = false;
+            }
+          } else if (!listItem.hidden) {
+            listItem.hidden = true;
+          }
+        }
+        break;
+      }
       case "AboutLoginsLoginSelected": {
         if (this._selectedItem) {
           if (this._selectedItem.getAttribute("guid") == event.detail.guid) {
             return;
           }
           this._selectedItem.classList.toggle("selected", false);
         }
         this._selectedItem = this.shadowRoot.querySelector(`login-list-item[guid="${event.detail.guid}"]`);