summaryrefslogtreecommitdiffstats
path: root/comm/suite/mailnews/content/searchBar.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/suite/mailnews/content/searchBar.js
parentInitial commit. (diff)
downloadthunderbird-upstream.tar.xz
thunderbird-upstream.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 'comm/suite/mailnews/content/searchBar.js')
-rw-r--r--comm/suite/mailnews/content/searchBar.js432
1 files changed, 432 insertions, 0 deletions
diff --git a/comm/suite/mailnews/content/searchBar.js b/comm/suite/mailnews/content/searchBar.js
new file mode 100644
index 0000000000..2c23b395a3
--- /dev/null
+++ b/comm/suite/mailnews/content/searchBar.js
@@ -0,0 +1,432 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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/. */
+
+const {PluralForm} = ChromeUtils.import("resource://gre/modules/PluralForm.jsm");
+
+var gSearchSession = null;
+var gPreQuickSearchView = null;
+var gSearchTimer = null;
+var gViewSearchListener;
+var gSearchBundle;
+var gProgressMeter = null;
+var gSearchInProgress = false;
+var gClearButton = null;
+var gDefaultSearchViewTerms = null;
+var gQSViewIsDirty = false;
+var gNumTotalMessages;
+var gNumUnreadMessages;
+
+function SetQSStatusText(aNumHits)
+{
+ var statusMsg;
+ // if there are no hits, it means no matches were found in the search.
+ if (aNumHits == 0)
+ {
+ statusMsg = gSearchBundle.getString("noMatchesFound");
+ }
+ else
+ {
+ statusMsg = PluralForm.get(aNumHits,
+ gSearchBundle.getString("matchesFound"));
+ statusMsg = statusMsg.replace("#1", aNumHits);
+ }
+ statusFeedback.showStatusString(statusMsg);
+}
+
+// nsIMsgSearchNotify object
+var gSearchNotificationListener =
+{
+ onSearchHit: function(header, folder)
+ {
+ gNumTotalMessages++;
+ if (!header.isRead)
+ gNumUnreadMessages++;
+ // XXX todo
+ // update status text?
+ },
+
+ onSearchDone: function(status)
+ {
+ SetQSStatusText(gDBView.QueryInterface(Ci.nsITreeView).rowCount)
+ statusFeedback.showProgress(0);
+ gProgressMeter.setAttribute("mode", "normal");
+ gSearchInProgress = false;
+
+ // ### TODO need to find out if there's quick search within a virtual folder.
+ if (gCurrentVirtualFolderUri &&
+ (!gSearchInput || gSearchInput.value == ""))
+ {
+ var vFolder = MailUtils.getFolderForURI(gCurrentVirtualFolderUri, false);
+ var dbFolderInfo = vFolder.msgDatabase.dBFolderInfo;
+ dbFolderInfo.numUnreadMessages = gNumUnreadMessages;
+ dbFolderInfo.numMessages = gNumTotalMessages;
+ vFolder.updateSummaryTotals(true); // force update from db.
+ var msgdb = vFolder.msgDatabase;
+ msgdb.Commit(Ci.nsMsgDBCommitType.kLargeCommit);
+ // now that we have finished loading a virtual folder,
+ // scroll to the correct message if there is at least one.
+ if (vFolder.getTotalMessages(false) > 0)
+ ScrollToMessageAfterFolderLoad(vFolder);
+ }
+ },
+
+ onNewSearch: function()
+ {
+ statusFeedback.showProgress(0);
+ statusFeedback.showStatusString(gSearchBundle.getString("searchingMessage"));
+ gProgressMeter.setAttribute("mode", "undetermined");
+ gSearchInProgress = true;
+ gNumTotalMessages = 0;
+ gNumUnreadMessages = 0;
+ }
+}
+
+function getDocumentElements()
+{
+ gSearchBundle = document.getElementById("bundle_search");
+ gProgressMeter = document.getElementById('statusbar-icon');
+ gClearButton = document.getElementById('clearButton');
+ GetSearchInput();
+}
+
+function addListeners()
+{
+ gViewSearchListener = gDBView.QueryInterface(Ci.nsIMsgSearchNotify);
+ gSearchSession.registerListener(gViewSearchListener);
+}
+
+function removeListeners()
+{
+ gSearchSession.unregisterListener(gViewSearchListener);
+}
+
+function removeGlobalListeners()
+{
+ removeListeners();
+ gSearchSession.unregisterListener(gSearchNotificationListener);
+}
+
+function initializeGlobalListeners()
+{
+ // Setup the javascript object as a listener on the search results
+ gSearchSession.registerListener(gSearchNotificationListener);
+}
+
+function createQuickSearchView()
+{
+ //if not already in quick search view
+ if (gDBView.viewType != nsMsgViewType.eShowQuickSearchResults)
+ {
+ var treeView = gDBView.QueryInterface(Ci.nsITreeView); //clear selection
+ if (treeView && treeView.selection)
+ treeView.selection.clearSelection();
+ gPreQuickSearchView = gDBView;
+ if (gDBView.viewType == nsMsgViewType.eShowVirtualFolderResults)
+ {
+ // remove the view as a listener on the search results
+ var saveViewSearchListener = gDBView.QueryInterface(Ci.nsIMsgSearchNotify);
+ gSearchSession.unregisterListener(saveViewSearchListener);
+ }
+ CreateDBView(gDBView.msgFolder, (gXFVirtualFolderTerms) ? nsMsgViewType.eShowVirtualFolderResults : nsMsgViewType.eShowQuickSearchResults, gDBView.viewFlags, gDBView.sortType, gDBView.sortOrder);
+ }
+}
+
+function initializeSearchBar()
+{
+ createQuickSearchView();
+ if (!gSearchSession)
+ {
+ var searchSessionContractID = "@mozilla.org/messenger/searchSession;1";
+ gSearchSession = Cc[searchSessionContractID].createInstance(Ci.nsIMsgSearchSession);
+ initializeGlobalListeners();
+ }
+ else
+ {
+ if (gSearchInProgress)
+ {
+ onSearchStop();
+ gSearchInProgress = false;
+ }
+ removeListeners();
+ }
+ addListeners();
+}
+
+function onEnterInSearchBar()
+{
+ if (!gSearchBundle)
+ getDocumentElements();
+ if (gSearchInput.value == "")
+ {
+ let viewType = gDBView && gDBView.viewType;
+ if (viewType == nsMsgViewType.eShowQuickSearchResults ||
+ viewType == nsMsgViewType.eShowVirtualFolderResults)
+ {
+ statusFeedback.showStatusString("");
+ disableQuickSearchClearButton();
+
+ viewDebug ("onEnterInSearchBar gDefaultSearchViewTerms = " + gDefaultSearchViewTerms + "gVirtualFolderTerms = "
+ + gVirtualFolderTerms + "gXFVirtualFolderTerms = " + gXFVirtualFolderTerms + "\n");
+ var addTerms = gDefaultSearchViewTerms || gVirtualFolderTerms || gXFVirtualFolderTerms;
+ if (addTerms)
+ {
+ viewDebug ("addTerms = " + addTerms + " count = " + addTerms.length + "\n");
+ initializeSearchBar();
+ onSearch(addTerms);
+ }
+ else
+ restorePreSearchView();
+ }
+ else if (gPreQuickSearchView && !gDefaultSearchViewTerms)// may be a quick search from a cross-folder virtual folder
+ restorePreSearchView();
+
+ gQSViewIsDirty = false;
+ return;
+ }
+
+ initializeSearchBar();
+
+ if (gClearButton)
+ gClearButton.setAttribute("disabled", false); //coming into search enable clear button
+
+ ClearThreadPaneSelection();
+ ClearMessagePane();
+
+ onSearch(null);
+ gQSViewIsDirty = false;
+}
+
+function restorePreSearchView()
+{
+ var selectedHdr = null;
+ //save selection
+ try
+ {
+ selectedHdr = gDBView.hdrForFirstSelectedMessage;
+ }
+ catch (ex)
+ {}
+
+ //we might have to sort the view coming out of quick search
+ var sortType = gDBView.sortType;
+ var sortOrder = gDBView.sortOrder;
+ var viewFlags = gDBView.viewFlags;
+ var folder = gDBView.msgFolder;
+
+ gDBView.close();
+ gDBView = null;
+
+ if (gPreQuickSearchView)
+ {
+ gDBView = gPreQuickSearchView;
+ if (gDBView.viewType == nsMsgViewType.eShowVirtualFolderResults)
+ {
+ // readd the view as a listener on the search results
+ var saveViewSearchListener = gDBView.QueryInterface(Ci.nsIMsgSearchNotify);
+ if (gSearchSession)
+ gSearchSession.registerListener(saveViewSearchListener);
+ }
+// dump ("view type = " + gDBView.viewType + "\n");
+
+ if (sortType != gDBView.sortType || sortOrder != gDBView.sortOrder)
+ {
+ gDBView.sort(sortType, sortOrder);
+ }
+ UpdateSortIndicators(sortType, sortOrder);
+
+ gPreQuickSearchView = null;
+ }
+ else //create default view type
+ CreateDBView(folder, nsMsgViewType.eShowAllThreads, viewFlags, sortType, sortOrder);
+
+ RerootThreadPane();
+
+ var scrolled = false;
+
+ // now restore selection
+ if (selectedHdr)
+ {
+ gDBView.selectMsgByKey(selectedHdr.messageKey);
+ var treeView = gDBView.QueryInterface(Ci.nsITreeView);
+ var selectedIndex = treeView.selection.currentIndex;
+ if (selectedIndex >= 0)
+ {
+ // scroll
+ EnsureRowInThreadTreeIsVisible(selectedIndex);
+ scrolled = true;
+ }
+ else
+ ClearMessagePane();
+ }
+ if (!scrolled)
+ ScrollToMessageAfterFolderLoad(null);
+}
+
+function onSearch(aSearchTerms)
+{
+ viewDebug("in OnSearch, searchTerms = " + aSearchTerms + "\n");
+ RerootThreadPane();
+
+ if (aSearchTerms)
+ createSearchTermsWithList(aSearchTerms);
+ else
+ createSearchTerms();
+
+ gDBView.searchSession = gSearchSession;
+ try
+ {
+ gSearchSession.search(msgWindow);
+ }
+ catch(ex)
+ {
+ dump("Search Exception\n");
+ }
+}
+
+function createSearchTermsWithList(aTermsArray)
+{
+ var nsMsgSearchScope = Ci.nsMsgSearchScope;
+ var nsMsgSearchAttrib = Ci.nsMsgSearchAttrib;
+ var nsMsgSearchOp = Ci.nsMsgSearchOp;
+
+ gSearchSession.searchTerms.clear();
+ gSearchSession.clearScopes();
+
+ var i;
+ var selectedFolder = GetThreadPaneFolder();
+ if (gXFVirtualFolderTerms)
+ {
+ var msgDatabase = selectedFolder.msgDatabase;
+ if (msgDatabase)
+ {
+ var dbFolderInfo = msgDatabase.dBFolderInfo;
+ var srchFolderUri = dbFolderInfo.getCharProperty("searchFolderUri");
+ viewDebug("createSearchTermsWithList xf vf scope = " + srchFolderUri + "\n");
+ var srchFolderUriArray = srchFolderUri.split('|');
+ for (i in srchFolderUriArray)
+ {
+ let realFolder = MailUtils.getFolderForURI(srchFolderUriArray[i]);
+ if (!realFolder.isServer)
+ gSearchSession.addScopeTerm(nsMsgSearchScope.offlineMail, realFolder);
+ }
+ }
+ }
+ else
+ {
+ viewDebug ("in createSearchTermsWithList, adding scope term for selected folder\n");
+ gSearchSession.addScopeTerm(nsMsgSearchScope.offlineMail, selectedFolder);
+ }
+
+ // Add each item in aTermsArray to the search session.
+ for (let term of aTermsArray) {
+ gSearchSession.appendTerm(term);
+ }
+}
+
+function createSearchTerms()
+{
+ var nsMsgSearchScope = Ci.nsMsgSearchScope;
+ var nsMsgSearchAttrib = Ci.nsMsgSearchAttrib;
+ var nsMsgSearchOp = Ci.nsMsgSearchOp;
+
+ // create an nsIMutableArray to store our search terms
+ var searchTermsArray = Cc["@mozilla.org/array;1"]
+ .createInstance(Ci.nsIMutableArray);
+ var selectedFolder = GetThreadPaneFolder();
+
+ // implement | for QS
+ // does this break if the user types "foo|bar" expecting to see subjects with that string?
+ // I claim no, since "foo|bar" will be a hit for "foo" || "bar"
+ // they just might get more false positives
+ var termList = gSearchInput.value.split("|");
+ for (var i = 0; i < termList.length; i ++)
+ {
+ // if the term is empty, skip it
+ if (termList[i] == "")
+ continue;
+
+ // create, fill, and append the subject term
+ var term = gSearchSession.createTerm();
+ var value = term.value;
+ value.str = termList[i];
+ term.value = value;
+ term.attrib = nsMsgSearchAttrib.Subject;
+ term.op = nsMsgSearchOp.Contains;
+ term.booleanAnd = false;
+ searchTermsArray.appendElement(term);
+
+ // create, fill, and append the AllAddresses term
+ term = gSearchSession.createTerm();
+ value = term.value;
+ value.str = termList[i];
+ term.value = value;
+ term.attrib = nsMsgSearchAttrib.AllAddresses;
+ term.op = nsMsgSearchOp.Contains;
+ term.booleanAnd = false;
+ searchTermsArray.appendElement(term);
+ }
+
+ // now append the default view or virtual folder criteria to the quick search
+ // so we don't lose any default view information
+ viewDebug("gDefaultSearchViewTerms = " + gDefaultSearchViewTerms + "gVirtualFolderTerms = " + gVirtualFolderTerms +
+ "gXFVirtualFolderTerms = " + gXFVirtualFolderTerms + "\n");
+ var defaultSearchTerms = (gDefaultSearchViewTerms || gVirtualFolderTerms || gXFVirtualFolderTerms);
+ if (defaultSearchTerms)
+ {
+ for (let searchTerm of defaultSearchTerms)
+ {
+ searchTermsArray.appendElement(searchTerm);
+ }
+ }
+
+ createSearchTermsWithList(searchTermsArray);
+
+ // now that we've added the terms, clear out our input array
+ searchTermsArray.clear();
+}
+
+function onSearchStop()
+{
+ gSearchSession.interruptSearch();
+}
+
+function onClearSearch()
+{
+ // Use the last focused element so that focus can be restored
+ // if it does not exist, try and get the thread tree instead
+ var focusedElement = gLastFocusedElement || GetThreadTree();
+ Search("");
+ focusedElement.focus();
+}
+
+function disableQuickSearchClearButton()
+{
+ if (gClearButton)
+ gClearButton.setAttribute("disabled", true); //going out of search disable clear button
+}
+
+function ClearQSIfNecessary()
+{
+ GetSearchInput();
+
+ if (gSearchInput.value == "")
+ return;
+
+ Search("");
+}
+
+function Search(str)
+{
+ GetSearchInput();
+
+ if (str != gSearchInput.value)
+ {
+ gQSViewIsDirty = true;
+ viewDebug("in Search(), setting gQSViewIsDirty true\n");
+ }
+
+ gSearchInput.value = str; //on input does not get fired for some reason
+ onEnterInSearchBar();
+}