/* 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/. */ Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource:///modules/iteratorUtils.jsm"); // Copied from nsILookAndFeel.h, see comments on eMetric_AlertNotificationOrigin var NS_ALERT_HORIZONTAL = 1; var NS_ALERT_LEFT = 2; var NS_ALERT_TOP = 4; var gNumNewMsgsToShowInAlert = 4; // the more messages we show in the alert, the larger it will be var gOpenTime = 4000; // total time the alert should stay up once we are done animating. var gAlertListener = null; var gPendingPreviewFetchRequests = 0; var gUserInitiated = false; var gOrigin = 0; // Default value: alert from bottom right. function prefillAlertInfo() { const Ci = Components.interfaces; // unwrap all the args.... // arguments[0] --> nsIArray of folders with new mail // arguments[1] --> the observer to call back with notifications about the alert // arguments[2] --> user initiated boolean. true if the user initiated opening the alert // (which means skip the fade effect and don't auto close the alert) // arguments[3] --> the alert origin returned by the look and feel var foldersWithNewMail = window.arguments[0]; gAlertListener = window.arguments[1]; gUserInitiated = window.arguments[2]; gOrigin = window.arguments[3]; // For now just grab the first folder which should be a root folder // for the account that has new mail. If we can't find a folder, just // return to avoid the exception and empty dialog in upper left-hand corner. if (!foldersWithNewMail || foldersWithNewMail.length < 1) return; let rootFolder = foldersWithNewMail.queryElementAt(0, Ci.nsIWeakReference) .QueryReferent(Ci.nsIMsgFolder); // Generate an account label string based on the root folder. var label = document.getElementById('alertTitle'); var totalNumNewMessages = rootFolder.getNumNewMessages(true); var message = totalNumNewMessages == 1 ? "newMailNotification_message" : "newMailNotification_messages"; label.value = document.getElementById('bundle_messenger') .getFormattedString(message, [rootFolder.prettiestName, totalNumNewMessages]); // This is really the root folder and we have to walk through the list to // find the real folder that has new mail in it...:( let allFolders = rootFolder.descendants; var folderSummaryInfoEl = document.getElementById('folderSummaryInfo'); folderSummaryInfoEl.mMaxMsgHdrsInPopup = gNumNewMsgsToShowInAlert; for (let folder in fixIterator(allFolders, Components.interfaces.nsIMsgFolder)) { if (folder.hasNewMessages) { let notify = // Any folder which is an inbox or ... folder.getFlag(Ci.nsMsgFolderFlags.Inbox) || // any non-special or non-virtual folder. In other words, we don't // notify for Drafts|Trash|SentMail|Templates|Junk|Archive|Queue or virtual. !(folder.flags & (Ci.nsMsgFolderFlags.SpecialUse | Ci.nsMsgFolderFlags.Virtual)); if (notify) { var asyncFetch = {}; folderSummaryInfoEl.parseFolder(folder, new urlListener(folder), asyncFetch); if (asyncFetch.value) gPendingPreviewFetchRequests++; } } } } function urlListener(aFolder) { this.mFolder = aFolder; } urlListener.prototype = { OnStartRunningUrl: function(aUrl) { }, OnStopRunningUrl: function(aUrl, aExitCode) { var folderSummaryInfoEl = document.getElementById('folderSummaryInfo'); folderSummaryInfoEl.parseFolder(this.mFolder, null, {}); gPendingPreviewFetchRequests--; // when we are done running all of our urls for fetching the preview text, // start the alert. if (!gPendingPreviewFetchRequests) showAlert(); } } function onAlertLoad() { prefillAlertInfo(); // read out our initial settings from prefs. try { gOpenTime = Services.prefs.getIntPref("alerts.totalOpenTime"); } catch (ex) {} // bogus call to make sure the window is moved offscreen until we are ready for it. resizeAlert(true); // if we aren't waiting to fetch preview text, then go ahead and // start showing the alert. if (!gPendingPreviewFetchRequests) setTimeout(showAlert, 0); // let the JS thread unwind, to give layout // a chance to recompute the styles and widths for our alert text. } // If the user initiated the alert, show it right away, otherwise start opening the alert with // the fade effect. function showAlert() { if (!document.getElementById("folderSummaryInfo").hasMessages) { closeAlert(); // no mail, so don't bother showing the alert... return; } // resize the alert based on our current content resizeAlert(false); var alertContainer = document.getElementById("alertContainer"); // Don't fade in if the user opened the alert or the pref is true. if (gUserInitiated || Services.prefs.getBoolPref("alerts.disableSlidingEffect")) { alertContainer.setAttribute("noanimation", true); setTimeout(closeAlert, gOpenTime); return; } alertContainer.addEventListener("animationend", function hideAlert(event) { if (event.animationName == "fade-in") { alertContainer.removeEventListener("animationend", hideAlert, false); let remaining = Math.max(Math.round(gOpenTime - event.elapsedTime * 1000), 0); setTimeout(fadeOutAlert, remaining); } }, false); alertContainer.setAttribute("fade-in", true); } function resizeAlert(aMoveOffScreen) { var alertTextBox = document.getElementById("alertTextBox"); var alertImageBox = document.getElementById("alertImageBox"); alertImageBox.style.minHeight = alertTextBox.scrollHeight + "px"; sizeToContent(); // leftover hack to get the window properly hidden when we first open it if (aMoveOffScreen) window.outerHeight = 1; // Determine position var x = gOrigin & NS_ALERT_LEFT ? screen.availLeft : screen.availLeft + screen.availWidth - window.outerWidth; var y = gOrigin & NS_ALERT_TOP ? screen.availTop : screen.availTop + screen.availHeight - window.outerHeight; // Offset the alert by 10 pixels from the edge of the screen y += gOrigin & NS_ALERT_TOP ? 10 : -10; x += gOrigin & NS_ALERT_LEFT ? 10 : -10; window.moveTo(x, y); } function fadeOutAlert() { var alertContainer = document.getElementById("alertContainer"); alertContainer.addEventListener("animationend", function fadeOut(event) { if (event.animationName == "fade-out") { alertContainer.removeEventListener("animationend", fadeOut, false); closeAlert(); } }, false); alertContainer.setAttribute("fade-out", true); } function closeAlert() { if (gAlertListener) gAlertListener.observe(null, "alertfinished", ""); window.close(); }