1 # -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 # The contents of this file are subject to the Netscape Public
3 # License Version 1.1 (the "License"); you may not use this file
4 # except in compliance with the License. You may obtain a copy of
5 # the License at http://www.mozilla.org/NPL/
7 # Software distributed under the License is distributed on an "AS
8 # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 # implied. See the License for the specific language governing
10 # rights and limitations under the License.
12 # The Original Code is Mozilla Communicator client code, released
15 # The Initial Developer of the Original Code is Netscape
16 # Communications Corporation. Portions created by Netscape are
17 # Copyright (C) 1998-1999 Netscape Communications Corporation. All
21 # Jan Varga <varga@nixcorp.com>
22 # HÃ¥kan Waara (hwaara@chello.se)
23 # David Bienvenu (bienvenu@netscape.com)
25 * Command-specific code. This stuff should be called by the widgets
28 //NOTE: gMessengerBundle and gBrandBundle must be defined and set
29 // for this Overlay to work properly
31 var gFolderJustSwitched = false;
32 var gBeforeFolderLoadTime;
33 var gRDFNamespace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
35 /* keep in sync with nsMsgFolderFlags.h */
36 var MSG_FOLDER_FLAG_TRASH = 0x0100;
37 var MSG_FOLDER_FLAG_SENTMAIL = 0x0200;
38 var MSG_FOLDER_FLAG_DRAFTS = 0x0400;
39 var MSG_FOLDER_FLAG_QUEUE = 0x0800;
40 var MSG_FOLDER_FLAG_INBOX = 0x1000;
41 var MSG_FOLDER_FLAG_TEMPLATES = 0x400000;
42 var MSG_FOLDER_FLAG_JUNK = 0x40000000;
46 messenger.SetWindow(window, msgWindow);
47 messenger.OpenURL(url);
50 function GetMsgFolderFromResource(folderResource)
55 var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
56 if (msgFolder && (msgFolder.parent || msgFolder.isServer))
62 function GetServer(uri)
64 if (!uri) return null;
66 var folder = GetMsgFolderFromUri(uri, true);
70 dump("GetServer("+uri+") failed, ex="+ex+"\n");
75 function LoadMessageByUri(uri)
77 //dump("XXX LoadMessageByUri " + uri + " vs " + gCurrentDisplayedMessage + "\n");
78 if(uri != gCurrentDisplayedMessage)
80 dump("fix this, get the nsIMsgDBHdr and the nsIMsgFolder from the uri...\n");
82 var resource = RDF.GetResource(uri);
83 var message = resource.QueryInterface(Components.interfaces.nsIMessage);
85 setTitleFromFolder(message.msgFolder, message.mimef2DecodedSubject);
87 var nsIMsgFolder = Components.interfaces.nsIMsgFolder;
88 if (message.msgFolder.server.downloadOnBiff)
89 message.msgFolder.biffState = nsIMsgFolder.nsMsgBiffState_NoMail;
92 gCurrentDisplayedMessage = uri;
93 gHaveLoadedMessage = true;
99 function setTitleFromFolder(msgfolder, subject)
101 var wintype = document.firstChild.getAttribute('windowtype');
104 // If we are showing the mail:3pane. Never include the subject of the selected
105 // message in the title. ("Inbox for greenlantern@mozilla.org - Mozilla Thunderbird")
106 // If we are a stand alone message window, we should show the Subject
107 // and the product but not the account name: "Re: New window Title - Mozilla Thunderbird"
109 if (wintype == "mail:messageWindow")
110 title = subject ? subject : "";
113 title = msgfolder.prettyName;
115 if (!msgfolder.isServer)
117 var server = msgfolder.server;
120 if (server.type == "nntp") {
121 // <folder> on <hostname>
122 middle = gMessengerBundle.getString("titleNewsPreHost");
123 end = server.hostName;
127 var identities = accountManager.GetIdentitiesForServer(server);
129 identity = identities.QueryElementAt(0, Components.interfaces.nsIMsgIdentity);
130 // <folder> for <email>
131 middle = gMessengerBundle.getString("titleMailPreHost");
132 end = identity.email;
135 if (middle) title += " " + middle;
136 if (end) title += " " + end;
141 title += " - " + gBrandBundle.getString("brandShortName");
143 window.title = title;
146 function UpdateMailToolbar(caller)
148 //dump("XXX update mail-toolbar " + caller + "\n");
149 document.commandDispatcher.updateCommands('mail-toolbar');
151 // hook for extra toolbar items
152 var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
153 observerService.notifyObservers(window, "mail:updateToolbarItems", null);
156 function ChangeFolderByURI(uri, viewType, viewFlags, sortType, sortOrder)
158 //dump("In ChangeFolderByURI uri = " + uri + " sortType = " + sortType + "\n");
159 if (uri == gCurrentLoadingFolderURI)
162 // hook for extra toolbar items
163 var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
164 observerService.notifyObservers(window, "mail:setupToolbarItems", uri);
166 var resource = RDF.GetResource(uri);
168 resource.QueryInterface(Components.interfaces.nsIMsgFolder);
171 setTitleFromFolder(msgfolder, null);
173 dump("error setting title: " + ex + "\n");
176 //if it's a server, clear the threadpane and don't bother trying to load.
177 if(msgfolder.isServer) {
178 msgWindow.openFolder = null;
182 // Load AccountCentral page here.
183 ShowAccountCentral();
189 if (msgfolder.server.displayStartupPage)
191 gDisplayStartupPage = true;
192 msgfolder.server.displayStartupPage = false;
196 // If the user clicks on msgfolder, time to display thread pane and message pane.
197 // Hide AccountCentral page
198 if (gAccountCentralLoaded)
200 HideAccountCentral();
203 if (gFakeAccountPageLoaded)
205 HideFakeAccountPage();
208 gCurrentLoadingFolderURI = uri;
209 gNextMessageAfterDelete = null; // forget what message to select, if any
211 gCurrentFolderToReroot = uri;
212 gCurrentLoadingFolderViewFlags = viewFlags;
213 gCurrentLoadingFolderViewType = viewType;
214 gCurrentLoadingFolderSortType = sortType;
215 gCurrentLoadingFolderSortOrder = sortOrder;
217 var showMessagesAfterLoading;
219 var server = msgfolder.server;
220 if (gPrefBranch.getBoolPref("mail.password_protect_local_cache"))
222 showMessagesAfterLoading = server.passwordPromptRequired;
223 // servers w/o passwords (like local mail) will always be non-authenticated.
224 // So we need to use the account manager for that case.
226 else if (server.redirectorType) {
227 var prefString = server.type + "." + server.redirectorType + ".showMessagesAfterLoading";
228 showMessagesAfterLoading = gPrefBranch.getBoolPref(prefString);
231 showMessagesAfterLoading = false;
234 showMessagesAfterLoading = false;
237 if (msgfolder.manyHeadersToDownload || showMessagesAfterLoading)
239 gRerootOnFolderLoad = true;
243 SetBusyCursor(window, true);
244 msgfolder.startFolderLoading();
245 msgfolder.updateFolder(msgWindow);
249 SetBusyCursor(window, false);
250 dump("Error loading with many headers to download: " + ex + "\n");
255 SetBusyCursor(window, true);
256 RerootFolder(uri, msgfolder, viewType, viewFlags, sortType, sortOrder);
257 gRerootOnFolderLoad = false;
258 msgfolder.startFolderLoading();
260 //Need to do this after rerooting folder. Otherwise possibility of receiving folder loaded
261 //notification before folder has actually changed.
262 msgfolder.updateFolder(msgWindow);
266 function isNewsURI(uri)
268 if (!uri || uri[0] != 'n') {
272 return ((uri.substring(0,6) == "news:/") || (uri.substring(0,14) == "news-message:/"));
276 function RerootFolder(uri, newFolder, viewType, viewFlags, sortType, sortOrder)
278 //dump("In reroot folder, sortType = " + sortType + "\n");
280 // workaround for #39655
281 gFolderJustSwitched = true;
283 ClearThreadPaneSelection();
285 //Clear the new messages of the old folder
286 var oldFolder = msgWindow.openFolder;
288 if (oldFolder.hasNewMessages) {
289 oldFolder.clearNewMessages();
293 //Set the window's new open folder.
294 msgWindow.openFolder = newFolder;
296 //the new folder being selected should have its biff state get cleared.
299 newFolder.biffState =
300 Components.interfaces.nsIMsgFolder.nsMsgBiffState_NoMail;
303 //Clear out the thread pane so that we can sort it with the new sort id without taking any time.
304 // folder.setAttribute('ref', "");
306 // null this out, so we don't try sort.
312 // cancel the pending mark as read timer
313 ClearPendingReadTimer();
315 // if this is the drafts, sent, or send later folder,
316 // we show "Recipient" instead of "Author"
317 SetSentFolderColumns(IsSpecialFolder(newFolder, MSG_FOLDER_FLAG_SENTMAIL | MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE));
319 // now create the db view, which will sort it.
320 CreateDBView(newFolder, viewType, viewFlags, sortType, sortOrder);
323 /*disable quick search clear button if we were in the search view on folder switching*/
324 disableQuickSearchClearButton();
326 /*we don't null out the db reference for inbox because inbox is like the "main" folder
327 and performance outweighs footprint */
328 if (!IsSpecialFolder(oldFolder, MSG_FOLDER_FLAG_INBOX))
329 if (oldFolder.URI != newFolder.URI)
330 oldFolder.setMsgDatabase(null);
332 // that should have initialized gDBView, now re-root the thread pane
335 SetUpToolbarButtons(uri);
337 UpdateStatusMessageCounts(newFolder);
339 // hook for extra toolbar items
340 var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
341 observerService.notifyObservers(window, "mail:updateToolbarItems", null);
344 function SwitchView(command)
346 // when switching thread views, we might be coming out of quick search
347 // or a message view.
348 // first set view picker to all
349 ViewMessagesBy("viewPickerAll");
351 // clear the QS text, if we need to
352 ClearQSIfNecessary();
355 var oldSortType = gDBView ? gDBView.sortType : nsMsgViewSortType.byThread;
356 var oldSortOrder = gDBView ? gDBView.sortOrder : nsMsgViewSortOrder.ascending;
357 var viewFlags = gDBView ? gDBView.viewFlags : gCurViewFlags;
359 // close existing view.
367 case "cmd_viewUnreadMsgs":
369 viewFlags = viewFlags | nsMsgViewFlagsType.kUnreadOnly;
370 CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowAllThreads, viewFlags,
371 oldSortType, oldSortOrder );
373 case "cmd_viewAllMsgs":
374 viewFlags = viewFlags & ~nsMsgViewFlagsType.kUnreadOnly;
375 CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowAllThreads, viewFlags,
376 oldSortType, oldSortOrder);
378 case "cmd_viewThreadsWithUnread":
379 CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowThreadsWithUnread, nsMsgViewFlagsType.kThreadedDisplay,
380 nsMsgViewSortType.byThread, oldSortOrder);
383 case "cmd_viewWatchedThreadsWithUnread":
384 CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowWatchedThreadsWithUnread, nsMsgViewFlagsType.kThreadedDisplay,
385 nsMsgViewSortType.byThread, oldSortOrder);
387 case "cmd_viewIgnoredThreads":
388 if (viewFlags & nsMsgViewFlagsType.kShowIgnored)
389 viewFlags = viewFlags & ~nsMsgViewFlagsType.kShowIgnored;
391 viewFlags = viewFlags | nsMsgViewFlagsType.kShowIgnored;
392 CreateDBView(msgWindow.openFolder, nsMsgViewType.eShowAllThreads, viewFlags,
393 oldSortType, oldSortOrder);
400 function SetSentFolderColumns(isSentFolder)
402 var tree = GetThreadTree();
404 var lastFolderSent = tree.getAttribute("lastfoldersent") == "true";
405 if (isSentFolder != lastFolderSent)
407 var senderColumn = document.getElementById("senderCol");
408 var recipientColumn = document.getElementById("recipientCol");
410 var saveHidden = senderColumn.getAttribute("hidden");
411 senderColumn.setAttribute("hidden", senderColumn.getAttribute("swappedhidden"));
412 senderColumn.setAttribute("swappedhidden", saveHidden);
414 saveHidden = recipientColumn.getAttribute("hidden");
415 recipientColumn.setAttribute("hidden", recipientColumn.getAttribute("swappedhidden"));
416 recipientColumn.setAttribute("swappedhidden", saveHidden);
420 tree.setAttribute("lastfoldersent", "true");
422 tree.setAttribute("lastfoldersent", "false");
425 function SetNewsFolderColumns()
427 var sizeColumn = document.getElementById("sizeCol");
429 if (gDBView.usingLines) {
430 sizeColumn.setAttribute("label",gMessengerBundle.getString("linesColumnHeader"));
433 sizeColumn.setAttribute("label", gMessengerBundle.getString("sizeColumnHeader"));
437 function UpdateStatusMessageCounts(folder)
439 var unreadElement = GetUnreadCountElement();
440 var totalElement = GetTotalCountElement();
441 if(folder && unreadElement && totalElement)
444 gMessengerBundle.getFormattedString("unreadMsgStatus",
445 [ folder.getNumUnread(false)]);
447 gMessengerBundle.getFormattedString("totalMsgStatus",
448 [folder.getTotalMessages(false)]);
450 unreadElement.setAttribute("label", numUnread);
451 totalElement.setAttribute("label", numTotal);
457 function ConvertColumnIDToSortType(columnID)
463 sortKey = nsMsgViewSortType.byDate;
466 sortKey = nsMsgViewSortType.byAuthor;
469 sortKey = nsMsgViewSortType.byRecipient;
472 sortKey = nsMsgViewSortType.bySubject;
475 sortKey = nsMsgViewSortType.byLocation;
478 sortKey = nsMsgViewSortType.byAccount;
480 case "unreadButtonColHeader":
481 sortKey = nsMsgViewSortType.byUnread;
484 sortKey = nsMsgViewSortType.byStatus;
487 sortKey = nsMsgViewSortType.bySize;
490 sortKey = nsMsgViewSortType.byPriority;
493 sortKey = nsMsgViewSortType.byFlagged;
496 sortKey = nsMsgViewSortType.byThread;
499 sortKey = nsMsgViewSortType.byLabel;
501 case "junkStatusCol":
502 sortKey = nsMsgViewSortType.byJunkStatus;
505 sortKey = nsMsgViewSortType.byId;
507 case "attachmentCol":
508 sortKey = nsMsgViewSortType.byAttachments;
511 dump("unsupported sort column: " + columnID + "\n");
518 function ConvertSortTypeToColumnID(sortKey)
522 // hack to turn this into an integer, if it was a string
523 // it would be a string if it came from localStore.rdf
524 sortKey = sortKey - 0;
527 case nsMsgViewSortType.byDate:
528 columnID = "dateCol";
530 case nsMsgViewSortType.byAuthor:
531 columnID = "senderCol";
533 case nsMsgViewSortType.byRecipient:
534 columnID = "recipientCol";
536 case nsMsgViewSortType.bySubject:
537 columnID = "subjectCol";
539 case nsMsgViewSortType.byLocation:
540 columnID = "locationCol";
542 case nsMsgViewSortType.byAccount:
543 columnID = "accountCol";
545 case nsMsgViewSortType.byUnread:
546 columnID = "unreadButtonColHeader";
548 case nsMsgViewSortType.byStatus:
549 columnID = "statusCol";
551 case nsMsgViewSortType.byLabel:
552 columnID = "labelCol";
554 case nsMsgViewSortType.bySize:
555 columnID = "sizeCol";
557 case nsMsgViewSortType.byPriority:
558 columnID = "priorityCol";
560 case nsMsgViewSortType.byFlagged:
561 columnID = "flaggedCol";
563 case nsMsgViewSortType.byThread:
564 columnID = "threadCol";
566 case nsMsgViewSortType.byId:
567 // there is no orderReceivedCol, so return null
570 case nsMsgViewSortType.byJunkStatus:
571 columnID = "junkStatusCol";
573 case nsMsgViewSortType.byAttachments:
574 columnID = "attachmentCol";
577 dump("unsupported sort key: " + sortKey + "\n");
584 var nsMsgViewSortType = Components.interfaces.nsMsgViewSortType;
585 var nsMsgViewSortOrder = Components.interfaces.nsMsgViewSortOrder;
586 var nsMsgViewFlagsType = Components.interfaces.nsMsgViewFlagsType;
587 var nsMsgViewCommandType = Components.interfaces.nsMsgViewCommandType;
588 var nsMsgViewType = Components.interfaces.nsMsgViewType;
589 var nsMsgNavigationType = Components.interfaces.nsMsgNavigationType;
595 // CreateDBView is called when we have a thread pane. CreateBareDBView is called when there is no
596 // tree associated with the view. CreateDBView will call into CreateBareDBView...
598 function CreateBareDBView(originalView, msgFolder, viewType, viewFlags, sortType, sortOrder)
600 var dbviewContractId = "@mozilla.org/messenger/msgdbview;1?type=";
601 // hack to turn this into an integer, if it was a string
602 // it would be a string if it came from localStore.rdf
603 viewType = viewType - 0;
606 case nsMsgViewType.eShowQuickSearchResults:
607 dbviewContractId += "quicksearch";
609 case nsMsgViewType.eShowThreadsWithUnread:
610 dbviewContractId += "threadswithunread";
612 case nsMsgViewType.eShowWatchedThreadsWithUnread:
613 dbviewContractId += "watchedthreadswithunread";
615 case nsMsgViewType.eShowAllThreads:
617 dbviewContractId += "threaded";
622 gDBView = Components.classes[dbviewContractId].createInstance(Components.interfaces.nsIMsgDBView);
624 gCurViewFlags = viewFlags;
625 var count = new Object;
626 if (!gThreadPaneCommandUpdater)
627 gThreadPaneCommandUpdater = new nsMsgDBViewCommandUpdater();
629 gCurSortType = sortType;
632 gDBView.init(messenger, msgWindow, gThreadPaneCommandUpdater);
634 gDBView.open(msgFolder, gCurSortType, sortOrder, viewFlags, count);
637 gDBView = originalView.cloneDBView(messenger, msgWindow, gThreadPaneCommandUpdater);
641 function CreateDBView(msgFolder, viewType, viewFlags, sortType, sortOrder)
643 // call the inner create method
644 CreateBareDBView(null, msgFolder, viewType, viewFlags, sortType, sortOrder);
646 // now do tree specific work
648 // based on the collapsed state of the thread pane/message pane splitter,
649 // suppress message display if appropriate.
650 gDBView.suppressMsgDisplay = IsMessagePaneCollapsed();
652 UpdateSortIndicators(gCurSortType, sortOrder);
655 //------------------------------------------------------------
656 // Sets the column header sort icon based on the requested
657 // column and direction.
660 // (1) This function relies on the first part of the
661 // <treecell id> matching the <treecol id>. The treecell
662 // id must have a "Header" suffix.
663 // (2) By changing the "sortDirection" attribute, a different
664 // CSS style will be used, thus changing the icon based on
665 // the "sortDirection" parameter.
666 //------------------------------------------------------------
667 function UpdateSortIndicator(column,sortDirection)
672 function GetSelectedFolderResource()
674 var folderTree = GetFolderTree();
677 folderTree.view.selection.getRangeAt(0, startIndex, endIndex);
678 return GetFolderResource(folderTree, startIndex.value);
681 function ChangeMessagePaneVisibility(now_hidden)
683 // we also have to hide the File/Attachments menuitem
684 node = document.getElementById("fileAttachmentMenu");
686 node.hidden = now_hidden;
689 // the collapsed state is the state after we released the mouse
690 // so we take it as it is
691 gDBView.suppressMsgDisplay = now_hidden;
693 var event = document.createEvent('Events');
695 event.initEvent('messagepane-hide', false, true);
698 event.initEvent('messagepane-unhide', false, true);
700 document.getElementById("messengerWindow").dispatchEvent(event);
703 function OnMouseUpThreadAndMessagePaneSplitter()
705 // the collapsed state is the state after we released the mouse
706 // so we take it as it is
707 ChangeMessagePaneVisibility(IsMessagePaneCollapsed());
710 function FolderPaneSelectionChange()
712 var folderTree = GetFolderTree();
713 var folderSelection = folderTree.view.selection;
715 // This prevents a folder from being loaded in the case that the user
716 // has right-clicked on a folder different from the one that was
717 // originally highlighted. On a right-click, the highlight (selection)
718 // of a row will be different from the value of currentIndex, thus if
719 // the currentIndex is not selected, it means the user right-clicked
720 // and we don't want to load the contents of the folder.
721 if (!folderSelection.isSelected(folderSelection.currentIndex))
724 if(gTimelineEnabled) {
725 gTimelineService.startTimer("FolderLoading");
726 gTimelineService.enter("FolderLoading has Started");
729 if (folderSelection.count == 1)
733 folderSelection.getRangeAt(0, startIndex, endIndex);
734 var folderResource = GetFolderResource(folderTree, startIndex.value);
735 var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
736 if (msgFolder == msgWindow.openFolder)
745 // don't get the db if this folder is a server
746 // we're going to be display account central
747 if (!(msgFolder.isServer))
751 var msgDatabase = msgFolder.getMsgDatabase(msgWindow);
754 var dbFolderInfo = msgDatabase.dBFolderInfo;
755 sortType = dbFolderInfo.sortType;
756 sortOrder = dbFolderInfo.sortOrder;
757 viewFlags = dbFolderInfo.viewFlags;
758 viewType = dbFolderInfo.viewType;
765 dump("failed to get view & sort values. ex = " + ex +"\n");
768 if (gDBView && gDBView.viewType == nsMsgViewType.eShowQuickSearchResults)
770 if (gPreQuickSearchView) //close cached view before quick search
772 gPreQuickSearchView.close();
773 gPreQuickSearchView = null;
775 var searchInput = document.getElementById("searchInput"); //reset the search input on folder switch
777 searchInput.value = "";
781 if (gSearchEmailAddress || gDefaultSearchViewTerms)
782 viewType = nsMsgViewType.eShowQuickSearchResults;
783 else if (viewType == nsMsgViewType.eShowQuickSearchResults)
784 viewType = nsMsgViewType.eShowAllThreads; //override viewType - we don't want to start w/ quick search
785 ChangeFolderByURI(folderResource.Value, viewType, viewFlags, sortType, sortOrder);
790 msgWindow.openFolder = null;
794 if (gAccountCentralLoaded)
795 UpdateMailToolbar("gAccountCentralLoaded");
796 else if (gFakeAccountPageLoaded)
797 UpdateMailToolbar("gFakeAccountPageLoaded");
799 if (gDisplayStartupPage)
802 gDisplayStartupPage = false;
803 UpdateMailToolbar("gDisplayStartupPage");
807 function ClearThreadPane()
815 function IsSpecialFolder(msgFolder, flags)
820 else if ((msgFolder.flags & flags) == 0) {
821 var parentMsgFolder = msgFolder.parentMsgFolder;
823 if(!parentMsgFolder) {
827 return IsSpecialFolder(parentMsgFolder, flags);
830 // the user can set their INBOX to be their SENT folder.
831 // in that case, we want this folder to act like an INBOX,
832 // and not a SENT folder
833 if ((flags & MSG_FOLDER_FLAG_SENTMAIL) && (msgFolder.flags & MSG_FOLDER_FLAG_INBOX)) {
842 function SelectNextMessage(nextMessage)
844 dump("XXX implement SelectNextMessage()\n");
847 function GetSelectTrashUri(folder)
849 if (!folder) return null;
850 var uri = folder.getAttribute('id');
851 var resource = RDF.GetResource(uri);
853 resource.QueryInterface(Components.interfaces.nsIMsgFolder);
856 var rootFolder = msgFolder.rootFolder;
858 var out = new Object();
859 var trashFolder = rootFolder.getFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 1, out);
860 numFolder = out.value;
862 return trashFolder.URI;
870 messenger.Undo(msgWindow);
875 messenger.Redo(msgWindow);
877 var mailOfflineObserver = {
878 observe: function(subject, topic, state) {
880 if (topic != "network:offline-status-changed") return;
881 MailOfflineStateChanged(state == "offline");
885 function AddMailOfflineObserver()
887 var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
888 observerService.addObserver(mailOfflineObserver, "network:offline-status-changed", false);
891 function RemoveMailOfflineObserver()
893 var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
894 observerService.removeObserver(mailOfflineObserver,"network:offline-status-changed");