summaryrefslogtreecommitdiffstats
path: root/comm/mail/base/content/msgViewNavigation.js
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/base/content/msgViewNavigation.js')
-rw-r--r--comm/mail/base/content/msgViewNavigation.js207
1 files changed, 207 insertions, 0 deletions
diff --git a/comm/mail/base/content/msgViewNavigation.js b/comm/mail/base/content/msgViewNavigation.js
new file mode 100644
index 0000000000..6ff860a717
--- /dev/null
+++ b/comm/mail/base/content/msgViewNavigation.js
@@ -0,0 +1,207 @@
+/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
+
+/* This file contains the js functions necessary to implement view navigation within the 3 pane. */
+
+/* globals DBViewWrapper, dbViewWrapperListener, TreeSelection */
+/* globals gDBView: true, gFolder: true, gViewWrapper: true */ // mailCommon.js
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "FolderUtils",
+ "resource:///modules/FolderUtils.jsm"
+);
+
+function GetSubFoldersInFolderPaneOrder(folder) {
+ function compareFolderSortKey(folder1, folder2) {
+ return folder1.compareSortKeys(folder2);
+ }
+ // sort the subfolders
+ return folder.subFolders.sort(compareFolderSortKey);
+}
+
+function FindNextChildFolder(aParent, aAfter) {
+ // Search the child folders of aParent for unread messages
+ // but in the case that we are working up from the current folder
+ // we need to skip up to and including the current folder
+ // we skip the current folder in case a mail view is hiding unread messages
+ if (aParent.getNumUnread(true) > 0) {
+ var subFolders = GetSubFoldersInFolderPaneOrder(aParent);
+ var i = 0;
+ var folder = null;
+
+ // Skip folders until after the specified child
+ while (folder != aAfter) {
+ folder = subFolders[i++];
+ }
+
+ let ignoreFlags =
+ Ci.nsMsgFolderFlags.Trash |
+ Ci.nsMsgFolderFlags.SentMail |
+ Ci.nsMsgFolderFlags.Drafts |
+ Ci.nsMsgFolderFlags.Queue |
+ Ci.nsMsgFolderFlags.Templates |
+ Ci.nsMsgFolderFlags.Junk;
+ while (i < subFolders.length) {
+ folder = subFolders[i++];
+ // If there is unread mail in the trash, sent, drafts, unsent messages
+ // templates or junk special folder,
+ // we ignore it when doing cross folder "next" navigation.
+ if (!folder.isSpecialFolder(ignoreFlags, true)) {
+ if (folder.getNumUnread(false) > 0) {
+ return folder;
+ }
+
+ folder = FindNextChildFolder(folder, null);
+ if (folder) {
+ return folder;
+ }
+ }
+ }
+ }
+
+ return null;
+}
+
+function FindNextFolder() {
+ // look for the next folder, this will only look on the current account
+ // and below us, in the folder pane
+ // note use of gDBView restricts this function to message folders
+ // otherwise you could go next unread from a server
+ var folder = FindNextChildFolder(gDBView.msgFolder, null);
+ if (folder) {
+ return folder;
+ }
+
+ // didn't find folder in children
+ // go up to the parent, and start at the folder after the current one
+ // unless we are at a server, in which case bail out.
+ folder = gDBView.msgFolder;
+ while (!folder.isServer) {
+ var parent = folder.parent;
+ folder = FindNextChildFolder(parent, folder);
+ if (folder) {
+ return folder;
+ }
+
+ // none at this level after the current folder. go up.
+ folder = parent;
+ }
+
+ // nothing in the current account, start with the next account (below)
+ // and try until we hit the bottom of the folder pane
+
+ // start at the account after the current account
+ var rootFolders = GetRootFoldersInFolderPaneOrder();
+ for (var i = 0; i < rootFolders.length; i++) {
+ if (rootFolders[i].URI == gDBView.msgFolder.server.serverURI) {
+ break;
+ }
+ }
+
+ for (var j = i + 1; j < rootFolders.length; j++) {
+ folder = FindNextChildFolder(rootFolders[j], null);
+ if (folder) {
+ return folder;
+ }
+ }
+
+ // if nothing from the current account down to the bottom
+ // (of the folder pane), start again at the top.
+ for (j = 0; j <= i; j++) {
+ folder = FindNextChildFolder(rootFolders[j], null);
+ if (folder) {
+ return folder;
+ }
+ }
+ return null;
+}
+
+function GetRootFoldersInFolderPaneOrder() {
+ let accounts = FolderUtils.allAccountsSorted(false);
+
+ let serversMsgFolders = [];
+ for (let account of accounts) {
+ serversMsgFolders.push(account.incomingServer.rootMsgFolder);
+ }
+
+ return serversMsgFolders;
+}
+
+/**
+ * Handle switching the folder if required for the given kind of navigation.
+ * Only used in about:3pane.
+ *
+ * @param {nsMsgNavigationType} type - The type of navigation.
+ * @returns {boolean} If the folder was changed for the navigation.
+ */
+function CrossFolderNavigation(type) {
+ // do cross folder navigation for next unread message/thread and message history
+ if (
+ type != Ci.nsMsgNavigationType.nextUnreadMessage &&
+ type != Ci.nsMsgNavigationType.nextUnreadThread
+ ) {
+ return false;
+ }
+
+ let nextMode = Services.prefs.getIntPref("mailnews.nav_crosses_folders");
+ // 0: "next" goes to the next folder, without prompting
+ // 1: "next" goes to the next folder, and prompts (the default)
+ // 2: "next" does nothing when there are no unread messages
+
+ // not crossing folders, don't find next
+ if (nextMode == 2) {
+ return false;
+ }
+
+ let folder = FindNextFolder();
+ if (!folder || gDBView.msgFolder.URI == folder.URI) {
+ return false;
+ }
+
+ if (nextMode == 1) {
+ let messengerBundle =
+ window.messengerBundle ||
+ Services.strings.createBundle(
+ "chrome://messenger/locale/messenger.properties"
+ );
+ let promptText = messengerBundle.formatStringFromName("advanceNextPrompt", [
+ folder.name,
+ ]);
+ if (
+ Services.prompt.confirmEx(
+ window,
+ null,
+ promptText,
+ Services.prompt.STD_YES_NO_BUTTONS,
+ null,
+ null,
+ null,
+ null,
+ {}
+ )
+ ) {
+ return false;
+ }
+ }
+
+ if (window.threadPane) {
+ // In about:3pane.
+ window.threadPane.forgetSelection(folder.URI);
+ window.displayFolder(folder.URI);
+ } else {
+ // In standalone about:message. Do just enough to call
+ // `commandController._navigate` again.
+ gViewWrapper = new DBViewWrapper(dbViewWrapperListener);
+ gViewWrapper._viewFlags = Ci.nsMsgViewFlagsType.kThreadedDisplay;
+ gViewWrapper.open(folder);
+ gDBView = gViewWrapper.dbView;
+ let selection = (gDBView.selection = new TreeSelection());
+ selection.view = gDBView;
+ // We're now in a bit of a weird state until `displayMessage` is called,
+ // but being here means we have everything we need for that to happen.
+ }
+ return true;
+}