diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mail/base/content/msgViewNavigation.js | 207 |
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; +} |