mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 03:30:17 +01:00
329 lines
11 KiB
JavaScript
329 lines
11 KiB
JavaScript
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
|
* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
* http://www.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is Mozilla Communicator client code, released
|
||
|
* March 31, 1998.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* Netscape Communications Corporation.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 1998-1999
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
|
* of those above. If you wish to allow use of your version of this file only
|
||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
|
* use your version of this file under the terms of the MPL, indicate your
|
||
|
* decision by deleting the provisions above and replace them with the notice
|
||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
|
* the provisions above, a recipient may use your version of this file under
|
||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
/* This file contains the js functions necessary to implement view navigation within the 3 pane. */
|
||
|
|
||
|
//NOTE: gMessengerBundle must be defined and set or this Overlay won't work
|
||
|
|
||
|
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
|
||
|
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
|
||
|
var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);
|
||
|
|
||
|
// we need the account manager datasource for when trying
|
||
|
// to figure out which account is next in the folder pane.
|
||
|
var gAccountManagerDataSource = Components.classes["@mozilla.org/rdf/datasource;1?name=msgaccountmanager"].getService(Components.interfaces.nsIRDFDataSource);
|
||
|
|
||
|
// we can't compare the name to determine the order in the folder pane
|
||
|
// we need to compare the value of the sort resource,
|
||
|
// as that's what we use to sort on in the folder pane
|
||
|
var gNameProperty = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService).GetResource("http://home.netscape.com/NC-rdf#Name?sort=true");
|
||
|
|
||
|
function compareServerSortOrder(server1, server2)
|
||
|
{
|
||
|
var sortValue1, sortValue2;
|
||
|
|
||
|
try {
|
||
|
var res1 = RDF.GetResource(server1.URI);
|
||
|
sortValue1 = gAccountManagerDataSource.GetTarget(res1, gNameProperty, true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||
|
}
|
||
|
catch (ex) {
|
||
|
dump("XXX ex ");
|
||
|
if (server1 && server1.URI)
|
||
|
dump(server1.URI + ",");
|
||
|
dump(ex + "\n");
|
||
|
sortValue1 = "";
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
var res2 = RDF.GetResource(server2.URI);
|
||
|
sortValue2 = gAccountManagerDataSource.GetTarget(res2, gNameProperty, true).QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
|
||
|
}
|
||
|
catch (ex) {
|
||
|
dump("XXX ex ");
|
||
|
if (server2 && server2.URI)
|
||
|
dump(server2.URI + ",");
|
||
|
dump(ex + "\n");
|
||
|
sortValue2 = "";
|
||
|
}
|
||
|
|
||
|
if (sortValue1 < sortValue2)
|
||
|
return -1;
|
||
|
else if (sortValue1 > sortValue2)
|
||
|
return 1;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
function compareFolderSortKey(folder1, folder2)
|
||
|
{
|
||
|
return folder1.compareSortKeys(folder2);
|
||
|
}
|
||
|
|
||
|
function GetSubFoldersInFolderPaneOrder(folder)
|
||
|
{
|
||
|
var subFolderEnumerator = folder.GetSubFolders();
|
||
|
var done = false;
|
||
|
var msgFolders = Array();
|
||
|
|
||
|
// get all the subfolders
|
||
|
while (!done) {
|
||
|
try {
|
||
|
var element = subFolderEnumerator.currentItem();
|
||
|
var msgFolder = element.QueryInterface(Components.interfaces.nsIMsgFolder);
|
||
|
msgFolders[msgFolders.length] = msgFolder;
|
||
|
|
||
|
subFolderEnumerator.next();
|
||
|
}
|
||
|
catch (ex) {
|
||
|
done = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// sort the subfolders
|
||
|
msgFolders.sort(compareFolderSortKey);
|
||
|
return msgFolders;
|
||
|
}
|
||
|
|
||
|
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++];
|
||
|
|
||
|
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 (!IsSpecialFolder(folder, MSG_FOLDER_FLAG_TRASH | MSG_FOLDER_FLAG_SENTMAIL | MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE | MSG_FOLDER_FLAG_TEMPLATES | MSG_FOLDER_FLAG_JUNK, 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.
|
||
|
for (folder = gDBView.msgFolder; !folder.isServer; ) {
|
||
|
|
||
|
var parent = folder.parentMsgFolder;
|
||
|
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 (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()
|
||
|
{
|
||
|
var allServers = accountManager.allServers;
|
||
|
var numServers = allServers.Count();
|
||
|
|
||
|
var serversMsgFolders = Array(numServers);
|
||
|
for (var i = 0; i < numServers; i++)
|
||
|
serversMsgFolders[i] = allServers.GetElementAt(i).QueryInterface(Components.interfaces.nsIMsgIncomingServer).rootMsgFolder;
|
||
|
|
||
|
// sort accounts, so they are in the same order as folder pane
|
||
|
serversMsgFolders.sort(compareServerSortOrder);
|
||
|
|
||
|
return serversMsgFolders;
|
||
|
}
|
||
|
|
||
|
function CrossFolderNavigation(type)
|
||
|
{
|
||
|
// do cross folder navigation for next unread message/thread and message history
|
||
|
if (type != nsMsgNavigationType.nextUnreadMessage &&
|
||
|
type != nsMsgNavigationType.nextUnreadThread &&
|
||
|
type != nsMsgNavigationType.forward &&
|
||
|
type != nsMsgNavigationType.back)
|
||
|
return;
|
||
|
|
||
|
if (type == nsMsgNavigationType.nextUnreadMessage ||
|
||
|
type == nsMsgNavigationType.nextUnreadThread)
|
||
|
{
|
||
|
|
||
|
var nextMode = pref.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;
|
||
|
|
||
|
var folder = FindNextFolder();
|
||
|
if (folder && (gDBView.msgFolder.URI != folder.URI))
|
||
|
{
|
||
|
switch (nextMode)
|
||
|
{
|
||
|
case 0:
|
||
|
// do this unconditionally
|
||
|
gNextMessageAfterLoad = type;
|
||
|
SelectFolder(folder.URI);
|
||
|
break;
|
||
|
case 1:
|
||
|
default:
|
||
|
var promptText = gMessengerBundle.getFormattedString("advanceNextPrompt", [ folder.name ], 1);
|
||
|
if (!promptService.confirmEx(window, promptText, promptText,
|
||
|
promptService.STD_YES_NO_BUTTONS,
|
||
|
null, null, null, null, {}))
|
||
|
{
|
||
|
gNextMessageAfterLoad = type;
|
||
|
SelectFolder(folder.URI);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// if no message is loaded, relPos should be 0, to
|
||
|
// go back to the previously loaded message
|
||
|
var relPos = (type == nsMsgNavigationType.forward)
|
||
|
? 1 : ((GetLoadedMessage()) ? -1 : 0);
|
||
|
var folderUri = messenger.getFolderUriAtNavigatePos(relPos);
|
||
|
var msgHdr = messenger.msgHdrFromURI(messenger.getMsgUriAtNavigatePos(relPos));
|
||
|
gStartMsgKey = msgHdr.messageKey;
|
||
|
var curPos = messenger.navigatePos;
|
||
|
curPos += relPos;
|
||
|
messenger.navigatePos = curPos;
|
||
|
SelectFolder(folderUri);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
function ScrollToMessage(type, wrap, selectMessage)
|
||
|
{
|
||
|
try {
|
||
|
var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
|
||
|
var treeSelection = treeView.selection;
|
||
|
var currentIndex = treeSelection.currentIndex;
|
||
|
|
||
|
var resultId = new Object;
|
||
|
var resultIndex = new Object;
|
||
|
var threadIndex = new Object;
|
||
|
|
||
|
gDBView.viewNavigate(type, resultId, resultIndex, threadIndex, true /* wrap */);
|
||
|
|
||
|
// only scroll and select if we found something
|
||
|
if ((resultId.value != nsMsgViewIndex_None) && (resultIndex.value != nsMsgViewIndex_None)) {
|
||
|
if (selectMessage){
|
||
|
treeSelection.select(resultIndex.value);
|
||
|
}
|
||
|
EnsureRowInThreadTreeIsVisible(resultIndex.value);
|
||
|
return true;
|
||
|
}
|
||
|
else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
catch (ex) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function GoNextMessage(type, startFromBeginning)
|
||
|
{
|
||
|
try {
|
||
|
var succeeded = ScrollToMessage(type, startFromBeginning, true);
|
||
|
if (!succeeded) {
|
||
|
CrossFolderNavigation(type);
|
||
|
}
|
||
|
}
|
||
|
catch (ex) {
|
||
|
dump("GoNextMessage ex = " + ex + "\n");
|
||
|
}
|
||
|
|
||
|
SetFocusThreadPaneIfNotOnMessagePane();
|
||
|
}
|
||
|
|