diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mail/components/unifiedtoolbar/content/items/global-search-bar.mjs | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | comm/mail/components/unifiedtoolbar/content/items/global-search-bar.mjs | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/comm/mail/components/unifiedtoolbar/content/items/global-search-bar.mjs b/comm/mail/components/unifiedtoolbar/content/items/global-search-bar.mjs new file mode 100644 index 0000000000..924955c895 --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/content/items/global-search-bar.mjs @@ -0,0 +1,223 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { SearchBar } from "chrome://messenger/content/unifiedtoolbar/search-bar.mjs"; + +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + GlodaIMSearcher: "resource:///modules/GlodaIMSearcher.sys.mjs", +}); +ChromeUtils.defineModuleGetter( + lazy, + "GlodaMsgSearcher", + "resource:///modules/gloda/GlodaMsgSearcher.jsm" +); +ChromeUtils.defineModuleGetter( + lazy, + "GlodaConstants", + "resource:///modules/gloda/GlodaConstants.jsm" +); +ChromeUtils.defineModuleGetter( + lazy, + "Gloda", + "resource:///modules/gloda/GlodaPublic.jsm" +); +XPCOMUtils.defineLazyGetter( + lazy, + "glodaCompleter", + () => + Cc["@mozilla.org/autocomplete/search;1?name=gloda"].getService( + Ci.nsIAutoCompleteSearch + ).wrappedJSObject +); + +/** + * Unified toolbar global search bar. + */ +class GlobalSearchBar extends SearchBar { + // Fields required for the auto complete popup to work. + + get popup() { + return document.getElementById("PopupGlodaAutocomplete"); + } + + controller = { + matchCount: 0, + searchString: "", + stopSearch() { + lazy.glodaCompleter.stopSearch(); + }, + handleEnter: (isAutocomplete, event) => { + if (!isAutocomplete) { + return; + } + this.#handleSearch({ detail: this.controller.searchString }); + this.reset(); + }, + }; + + _focus() { + this.focus(); + } + + #searchResultListener = { + onSearchResult: (result, search) => { + this.controller.matchCount = search.matchCount; + if (this.controller.matchCount < 1) { + this.popup.closePopup(); + return; + } + if (!this.popup.mPopupOpen) { + this.popup.openAutocompletePopup( + this, + this.shadowRoot.querySelector("input") + ); + return; + } + this.popup.invalidate(); + }, + }; + + // Normal custom element stuff + + connectedCallback() { + if (this.shadowRoot) { + return; + } + if ( + !Services.prefs.getBoolPref( + "mailnews.database.global.indexer.enabled", + true + ) + ) { + return; + } + // Need to call this after the shadow root test, since this will always set + // up a shadow root. + super.connectedCallback(); + this.addEventListener("search", this.#handleSearch); + this.addEventListener("autocomplete", this.#handleAutocomplete); + // Capturing to avoid the default cursor movements inside the input. + this.addEventListener("keydown", this.#handleKeydown, { + capture: true, + }); + this.addEventListener("focus", this.#handleFocus); + this.addEventListener("blur", this); + this.addEventListener("drop", this.#handleDrop, { capture: true }); + } + + handleEvent(event) { + switch (event.type) { + case "blur": + if (this.popup.mPopupOpen) { + this.popup.closePopup(); + } + break; + } + } + + #handleSearch = event => { + let tabmail = document.getElementById("tabmail"); + let args; + // Build the query from the autocomplete result. + const selectedIndex = this.popup.selectedIndex; + if (selectedIndex > -1) { + const curResult = lazy.glodaCompleter.curResult; + if (curResult) { + const row = curResult.getObjectAt(selectedIndex); + if (row && !row.fullText && row.nounDef) { + let query = lazy.Gloda.newQuery(lazy.GlodaConstants.NOUN_MESSAGE); + switch (row.nounDef.name) { + case "tag": + query = query.tags(row.item); + break; + case "identity": + query = query.involves(row.item); + break; + } + query.orderBy("-date"); + args = { query }; + } + } + } + // Or just do a normal full text search. + if (!args) { + let searchString = event.detail; + args = { + searcher: new lazy.GlodaMsgSearcher(null, searchString), + }; + if (Services.prefs.getBoolPref("mail.chat.enabled")) { + args.IMSearcher = new lazy.GlodaIMSearcher(null, searchString); + } + } + tabmail.openTab("glodaFacet", args); + this.popup.closePopup(); + this.controller.matchCount = 0; + this.controller.searchString = ""; + }; + + #handleAutocomplete = event => { + this.controller.searchString = event.detail; + if (!event.detail) { + this.popup.closePopup(); + this.controller.matchCount = 0; + return; + } + lazy.glodaCompleter.startSearch( + this.controller.searchString, + "global", + null, + this.#searchResultListener + ); + }; + + #handleKeydown = event => { + if (event.ctrlKey) { + return; + } + if (event.key == "ArrowDown") { + if (this.popup.selectedIndex < this.controller.matchCount - 1) { + ++this.popup.selectedIndex; + event.preventDefault(); + return; + } + this.popup.selectedIndex = -1; + event.preventDefault(); + return; + } + if (event.key == "ArrowUp") { + if (this.popup.selectedIndex > -1) { + --this.popup.selectedIndex; + event.preventDefault(); + return; + } + this.popup.selectedIndex = this.controller.matchCount - 1; + event.preventDefault(); + } + }; + + #handleFocus = event => { + if (this.controller.searchString && this.controller.matchCount >= 1) { + this.popup.openAutocompletePopup( + this, + this.shadowRoot.querySelector("input") + ); + } + }; + + #handleDrop = event => { + if (event.dataTransfer.types.includes("text/x-moz-address")) { + const searchTerm = event.dataTransfer.getData("text/plain"); + this.#handleSearch({ detail: searchTerm }); + } + event.stopPropagation(); + event.preventDefault(); + }; +} +customElements.define("global-search-bar", GlobalSearchBar); |