diff --git a/mailnews/base/public/nsIMsgDBView.idl b/mailnews/base/public/nsIMsgDBView.idl index e004a62a84e8..349828fb5104 100644 --- a/mailnews/base/public/nsIMsgDBView.idl +++ b/mailnews/base/public/nsIMsgDBView.idl @@ -308,6 +308,7 @@ interface nsIMsgDBView : nsISupports readonly attribute boolean supportsThreading; attribute nsIMsgSearchSession searchSession; + readonly attribute boolean removeRowOnMoveOrDelete; nsMsgViewIndex findIndexFromKey(in nsMsgKey aMsgKey, in boolean aExpand); }; diff --git a/mailnews/base/resources/content/mailContextMenus.js b/mailnews/base/resources/content/mailContextMenus.js index be4955b2ada5..6075ec96ec11 100644 --- a/mailnews/base/resources/content/mailContextMenus.js +++ b/mailnews/base/resources/content/mailContextMenus.js @@ -31,6 +31,16 @@ // (onpopuphiding). function RestoreSelectionWithoutContentLoad(tree) { + // If a delete or move command had been issued, then we should + // reset gRightMouseButtonDown and gThreadPaneDeleteOrMoveOccurred + // and return (see bug 142065). + if(gThreadPaneDeleteOrMoveOccurred) + { + gRightMouseButtonDown = false; + gThreadPaneDeleteOrMoveOccurred = false; + return; + } + var treeBoxObj = tree.treeBoxObject; var treeSelection = treeBoxObj.selection; @@ -49,7 +59,7 @@ function RestoreSelectionWithoutContentLoad(tree) if(tree.id == "threadTree") gThreadPaneCurrentSelectedIndex = treeSelection.currentIndex; } - else if(!gThreadPaneDeleteOrMoveOccurred && (treeSelection.currentIndex < 0)) + else if(treeSelection.currentIndex < 0) // Clear the selection in the case of when a folder has just been // loaded where the message pane does not have a message loaded yet. // When right-clicking a message in this case and dismissing the diff --git a/mailnews/base/resources/content/msgMail3PaneWindow.js b/mailnews/base/resources/content/msgMail3PaneWindow.js index de9ff40c1f4b..2d31a99040dc 100644 --- a/mailnews/base/resources/content/msgMail3PaneWindow.js +++ b/mailnews/base/resources/content/msgMail3PaneWindow.js @@ -1328,22 +1328,42 @@ function GetCompositeDataSource(command) return null; } +// Figures out how many messages are selected (hilighted - does not necessarily +// have the dotted outline) above a given index row value in the thread pane. +function NumberOfSelectedMessagesAboveCurrentIndex(index) +{ + var numberOfMessages = 0; + var indicies = GetSelectedIndices(gDBView); + + if (indicies && indicies.length) + { + for (var i = 0; i < indicies.length; i++) + { + if (indicies[i] < index) + ++numberOfMessages; + else + break; + } + } + return numberOfMessages; +} + function SetNextMessageAfterDelete() { var treeSelection = GetThreadTree().treeBoxObject.selection; - gThreadPaneDeleteOrMoveOccurred = true; - if (treeSelection.isSelected(treeSelection.currentIndex)) - gNextMessageViewIndexAfterDelete = gDBView.msgToSelectAfterDelete; - else if (treeSelection.currentIndex > gThreadPaneCurrentSelectedIndex) - // Since the currentIndex (the row with the outline/dotted line) is greater - // than the currently selected row (the row that is highlighted), we need to - // make sure that upon a Delete or Move of the selected row, the highlight - // returns to the currentIndex'ed row. It is necessary to subtract 1 - // because the row being deleted is above the row with the currentIndex. - // If the subtraction is not done, then the highlight will end up on the - // row listed after the currentIndex'ed row. - gNextMessageViewIndexAfterDelete = treeSelection.currentIndex - 1; + // Only set gThreadPaneDeleteOrMoveOccurred to true if the message was + // truly moved to the trash or deleted, as opposed to an IMAP delete + // (where it is only "marked as deleted". This will prevent bug 142065. + // + // If it's an IMAP delete, then just set gNextMessageViewIndexAfterDelete + // to treeSelection.currentIndex (where the outline is at) because nothing + // was moved or deleted from the folder. + if(gDBView.removeRowOnMoveOrDelete) + { + gThreadPaneDeleteOrMoveOccurred = true; + gNextMessageViewIndexAfterDelete = treeSelection.currentIndex - NumberOfSelectedMessagesAboveCurrentIndex(treeSelection.currentIndex); + } else gNextMessageViewIndexAfterDelete = treeSelection.currentIndex; } diff --git a/mailnews/base/src/nsMsgDBView.cpp b/mailnews/base/src/nsMsgDBView.cpp index 9988ba938cff..5a6b3ebf42a0 100644 --- a/mailnews/base/src/nsMsgDBView.cpp +++ b/mailnews/base/src/nsMsgDBView.cpp @@ -5242,6 +5242,24 @@ nsMsgDBView::GetMsgToSelectAfterDelete(nsMsgViewIndex *msgToSelectAfterDelete) return NS_OK; } +NS_IMETHODIMP +nsMsgDBView::GetRemoveRowOnMoveOrDelete(PRBool *aRemoveRowOnMoveOrDelete) +{ + NS_ENSURE_ARG_POINTER(aRemoveRowOnMoveOrDelete); + nsCOMPtr imapFolder = do_QueryInterface(m_folder); + if (!imapFolder) { + *aRemoveRowOnMoveOrDelete = PR_TRUE; + return NS_OK; + } + + // need to update the imap-delete model, can change more than once in a session. + GetImapDeleteModel(nsnull); + + // unlike the other imap delete models, "mark as deleted" does not remove rows on delete (or move) + *aRemoveRowOnMoveOrDelete = (mDeleteModel != nsMsgImapDeleteModels::IMAPDelete); + return NS_OK; +} + NS_IMETHODIMP nsMsgDBView::GetCurrentlyDisplayedMessage(nsMsgViewIndex *currentlyDisplayedMessage)