diff options
Diffstat (limited to 'comm/mail/base/content/widgets/foldersummary.js')
-rw-r--r-- | comm/mail/base/content/widgets/foldersummary.js | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/comm/mail/base/content/widgets/foldersummary.js b/comm/mail/base/content/widgets/foldersummary.js new file mode 100644 index 0000000000..48bcb34d26 --- /dev/null +++ b/comm/mail/base/content/widgets/foldersummary.js @@ -0,0 +1,295 @@ +/** + * 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/. */ + +/* global MozElements */ +/* global MozXULElement */ +/* import-globals-from ../../../../mailnews/base/content/newmailalert.js */ + +// Wrap in a block to prevent leaking to window scope. +{ + const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" + ); + + /** + * MozFolderSummary displays a listing of NEW mails for the folder in question. + * For each mail the subject, sender and a message preview can be included. + * + * @augments {MozXULElement} + */ + class MozFolderSummary extends MozXULElement { + constructor() { + super(); + this.maxMsgHdrsInPopup = 8; + + this.showSubject = Services.prefs.getBoolPref( + "mail.biff.alert.show_subject" + ); + this.showSender = Services.prefs.getBoolPref( + "mail.biff.alert.show_sender" + ); + this.showPreview = Services.prefs.getBoolPref( + "mail.biff.alert.show_preview" + ); + this.messengerBundle = Services.strings.createBundle( + "chrome://messenger/locale/messenger.properties" + ); + + ChromeUtils.defineModuleGetter( + this, + "MailUtils", + "resource:///modules/MailUtils.jsm" + ); + } + + hasMessages() { + return this.lastElementChild; + } + + static createFolderSummaryMessage() { + let vbox = document.createXULElement("vbox"); + vbox.setAttribute("class", "folderSummaryMessage"); + + let hbox = document.createXULElement("hbox"); + hbox.setAttribute("class", "folderSummary-message-row"); + + let subject = document.createXULElement("label"); + subject.setAttribute("class", "folderSummary-subject"); + + let sender = document.createXULElement("label"); + sender.setAttribute("class", "folderSummary-sender"); + sender.setAttribute("crop", "end"); + + hbox.appendChild(subject); + hbox.appendChild(sender); + + let preview = document.createXULElement("description"); + preview.setAttribute( + "class", + "folderSummary-message-row folderSummary-previewText" + ); + preview.setAttribute("crop", "end"); + + vbox.appendChild(hbox); + vbox.appendChild(preview); + return vbox; + } + + /** + * Check the given folder for NEW messages. + * + * @param {nsIMsgFolder} folder - The folder to examine. + * @param {nsIUrlListener} urlListener - Listener to notify if we run urls + * to fetch msgs. + * @param Object outAsync - Object with value property set to true if there + * are async fetches pending (a message preview will be available later). + * @returns true if the folder knows about messages that should be shown. + */ + parseFolder(folder, urlListener, outAsync) { + // Skip servers, Trash, Junk folders and newsgroups. + if ( + !folder || + folder.isServer || + !folder.hasNewMessages || + folder.getFlag(Ci.nsMsgFolderFlags.Junk) || + folder.getFlag(Ci.nsMsgFolderFlags.Trash) || + folder.server instanceof Ci.nsINntpIncomingServer + ) { + return false; + } + + let folderArray = []; + let msgDatabase; + try { + msgDatabase = folder.msgDatabase; + } catch (e) { + // The database for this folder may be missing (e.g. outdated/missing .msf), + // so just skip this folder. + return false; + } + + if (folder.flags & Ci.nsMsgFolderFlags.Virtual) { + let srchFolderUri = + msgDatabase.dBFolderInfo.getCharProperty("searchFolderUri"); + let folderUris = srchFolderUri.split("|"); + for (let uri of folderUris) { + let realFolder = this.MailUtils.getOrCreateFolder(uri); + if (!realFolder.isServer) { + folderArray.push(realFolder); + } + } + } else { + folderArray.push(folder); + } + + let haveMsgsToShow = false; + for (let folder of folderArray) { + // now get the database + try { + msgDatabase = folder.msgDatabase; + } catch (e) { + // The database for this folder may be missing (e.g. outdated/missing .msf), + // then just skip this folder. + continue; + } + + folder.msgDatabase = null; + let msgKeys = msgDatabase.getNewList(); + + let numNewMessages = folder.getNumNewMessages(false); + if (!numNewMessages) { + continue; + } + // NOTE: getNewlist returns all nsMsgMessageFlagType::New messages, + // while getNumNewMessages returns count of new messages since the last + // biff. Only show newly received messages since last biff in + // notification. + msgKeys = msgKeys.slice(-numNewMessages); + if (!msgKeys.length) { + continue; + } + + if (this.showPreview) { + // fetchMsgPreviewText forces the previewText property to get generated + // for each of the message keys. + try { + outAsync.value = folder.fetchMsgPreviewText(msgKeys, urlListener); + folder.msgDatabase = null; + } catch (ex) { + // fetchMsgPreviewText throws an error when we call it on a news + // folder + folder.msgDatabase = null; + continue; + } + } + + // If fetching the preview text is going to be an asynch operation and the + // caller is set up to handle that fact, then don't bother filling in any + // of the fields since we'll have to do this all over again when the fetch + // for the preview text completes. + // We don't expect to get called with a urlListener if we're doing a + // virtual folder. + if (outAsync.value && urlListener) { + return false; + } + + // In the case of async fetching for more than one folder, we may + // already have got enough to show (added by another urllistener). + let curHdrsInPopup = this.children.length; + if (curHdrsInPopup >= this.maxMsgHdrsInPopup) { + return false; + } + + for ( + let i = 0; + i + curHdrsInPopup < this.maxMsgHdrsInPopup && i < msgKeys.length; + i++ + ) { + let msgBox = MozFolderSummary.createFolderSummaryMessage(); + let msgHdr = msgDatabase.getMsgHdrForKey(msgKeys[i]); + msgBox.addEventListener("click", event => { + if (event.button !== 0) { + return; + } + this.MailUtils.displayMessageInFolderTab(msgHdr, true); + }); + + if (this.showSubject) { + let msgSubject = msgHdr.mime2DecodedSubject; + const kMsgFlagHasRe = 0x0010; // MSG_FLAG_HAS_RE + if (msgHdr.flags & kMsgFlagHasRe) { + msgSubject = msgSubject ? "Re: " + msgSubject : "Re: "; + } + msgBox.querySelector(".folderSummary-subject").textContent = + msgSubject; + } + + if (this.showSender) { + let addrs = MailServices.headerParser.parseEncodedHeader( + msgHdr.author, + msgHdr.effectiveCharset, + false + ); + let folderSummarySender = msgBox.querySelector( + ".folderSummary-sender" + ); + // Set the label value instead of textContent to avoid wrapping. + folderSummarySender.value = + addrs.length > 0 ? addrs[0].name || addrs[0].email : ""; + if (addrs.length > 1) { + let andOthersStr = + this.messengerBundle.GetStringFromName("andOthers"); + folderSummarySender.value += " " + andOthersStr; + } + } + + if (this.showPreview) { + msgBox.querySelector(".folderSummary-previewText").textContent = + msgHdr.getStringProperty("preview") || ""; + } + this.appendChild(msgBox); + haveMsgsToShow = true; + } + } + return haveMsgsToShow; + } + + /** + * Render NEW messages in a folder. + * + * @param {nsIMsgFolder} folder - A real folder containing new messages. + * @param {number[]} msgKeys - The keys of new messages. + */ + render(folder, msgKeys) { + let msgDatabase = folder.msgDatabase; + for (let msgKey of msgKeys.slice(0, this.maxMsgHdrsInPopup)) { + let msgBox = MozFolderSummary.createFolderSummaryMessage(); + let msgHdr = msgDatabase.getMsgHdrForKey(msgKey); + msgBox.addEventListener("click", event => { + if (event.button !== 0) { + return; + } + this.MailUtils.displayMessageInFolderTab(msgHdr, true); + }); + + if (this.showSubject) { + let msgSubject = msgHdr.mime2DecodedSubject; + const kMsgFlagHasRe = 0x0010; // MSG_FLAG_HAS_RE + if (msgHdr.flags & kMsgFlagHasRe) { + msgSubject = msgSubject ? "Re: " + msgSubject : "Re: "; + } + msgBox.querySelector(".folderSummary-subject").textContent = + msgSubject; + } + + if (this.showSender) { + let addrs = MailServices.headerParser.parseEncodedHeader( + msgHdr.author, + msgHdr.effectiveCharset, + false + ); + let folderSummarySender = msgBox.querySelector( + ".folderSummary-sender" + ); + // Set the label value instead of textContent to avoid wrapping. + folderSummarySender.value = + addrs.length > 0 ? addrs[0].name || addrs[0].email : ""; + if (addrs.length > 1) { + let andOthersStr = + this.messengerBundle.GetStringFromName("andOthers"); + folderSummarySender.value += " " + andOthersStr; + } + } + + if (this.showPreview) { + msgBox.querySelector(".folderSummary-previewText").textContent = + msgHdr.getStringProperty("preview") || ""; + } + this.appendChild(msgBox); + } + } + } + customElements.define("folder-summary", MozFolderSummary); +} |