more work on 312940 improve alert notification for new mail, sr=mscott

This commit is contained in:
bienvenu%nventure.com 2005-11-22 00:36:16 +00:00
Родитель 3cf29ccdb9
Коммит d9357b7228
7 изменённых файлов: 186 добавлений и 121 удалений

Просмотреть файл

@ -71,7 +71,7 @@ function prefillAlertInfo()
for (var folderIndex = 0; folderIndex < numFolders; folderIndex++)
{
var folder = allFolders.GetElementAt(folderIndex).QueryInterface(Components.interfaces.nsIMsgFolder);
if (folder.getNumNewMessages(false /* no deep search */))
if (folder.hasNewMessages)
folderSummaryInfoEl.parseFolder(folder);
}
}

Просмотреть файл

@ -45,14 +45,18 @@
#include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
#include "nsMsgFolderFlags.h"
#include "nsIMsgHdr.h"
#include "nsIEventQueueService.h"
#include "nsIMsgImapMailFolder.h"
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS1(nsImapMoveCoalescer, nsISupports)
NS_IMPL_ISUPPORTS1(nsImapMoveCoalescer, nsIUrlListener)
nsImapMoveCoalescer::nsImapMoveCoalescer(nsIMsgFolder *sourceFolder, nsIMsgWindow *msgWindow)
{
m_sourceFolder = sourceFolder;
m_msgWindow = msgWindow;
m_hasPendingMoves = PR_FALSE;
}
nsImapMoveCoalescer::~nsImapMoveCoalescer()
@ -71,6 +75,7 @@ nsImapMoveCoalescer::~nsImapMoveCoalescer()
nsresult nsImapMoveCoalescer::AddMove(nsIMsgFolder *folder, nsMsgKey key)
{
m_hasPendingMoves = PR_TRUE;
if (!m_destFolders)
NS_NewISupportsArray(getter_AddRefs(m_destFolders));
if (m_destFolders)
@ -79,7 +84,7 @@ nsresult nsImapMoveCoalescer::AddMove(nsIMsgFolder *folder, nsMsgKey key)
if (supports)
{
PRInt32 folderIndex = m_destFolders->IndexOf(supports);
nsMsgKeyArray *keysToAdd=nsnull;
nsMsgKeyArray *keysToAdd = nsnull;
if (folderIndex >= 0)
{
keysToAdd = (nsMsgKeyArray *) m_sourceKeyArrays.ElementAt(folderIndex);
@ -105,15 +110,16 @@ nsresult nsImapMoveCoalescer::AddMove(nsIMsgFolder *folder, nsMsgKey key)
}
nsresult nsImapMoveCoalescer::PlaybackMoves()
nsresult nsImapMoveCoalescer::PlaybackMoves(PRBool doNewMailNotification /* = PR_FALSE */)
{
PRUint32 numFolders;
nsresult rv = NS_OK;
if (!m_destFolders)
return NS_OK; // nothing to do.
m_hasPendingMoves = PR_FALSE;
m_doNewMailNotification = doNewMailNotification;
m_destFolders->Count(&numFolders);
m_outstandingMoves = 0;
for (PRUint32 i = 0; i < numFolders; i++)
{
// XXX TODO
@ -173,14 +179,48 @@ nsresult nsImapMoveCoalescer::PlaybackMoves()
keysToAdd->RemoveAll();
nsCOMPtr<nsIMsgCopyService> copySvc = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID);
if (copySvc)
{
nsCOMPtr <nsIMsgCopyServiceListener> listener;
if (m_doNewMailNotification)
{
nsMoveCoalescerCopyListener *copyListener = new nsMoveCoalescerCopyListener(this, destFolder);
if (copyListener)
{
listener = do_QueryInterface(copyListener);
NS_ADDREF(copyListener); // it will own its own reference
}
}
rv = copySvc->CopyMessages(m_sourceFolder, messages, destFolder, PR_TRUE,
/*nsIMsgCopyServiceListener* listener*/ nsnull, m_msgWindow, PR_FALSE /*allowUndo*/);
listener, m_msgWindow, PR_FALSE /*allowUndo*/);
if (NS_SUCCEEDED(rv))
m_outstandingMoves++;
}
}
}
}
return rv;
}
NS_IMETHODIMP
nsImapMoveCoalescer::OnStartRunningUrl(nsIURI *aUrl)
{
NS_PRECONDITION(aUrl, "just a sanity check");
return NS_OK;
}
NS_IMETHODIMP
nsImapMoveCoalescer::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
{
m_outstandingMoves--;
if (m_doNewMailNotification && !m_outstandingMoves)
{
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_sourceFolder);
if (imapFolder)
imapFolder->NotifyIfNewMail();
}
return NS_OK;
}
nsMsgKeyArray *nsImapMoveCoalescer::GetKeyBucket(PRInt32 keyArrayIndex)
{
PRInt32 bucketCount = m_keyBuckets.Count();
@ -197,3 +237,68 @@ nsMsgKeyArray *nsImapMoveCoalescer::GetKeyBucket(PRInt32 keyArrayIndex)
}
return (nsMsgKeyArray *) m_keyBuckets.SafeElementAt(keyArrayIndex);
}
NS_IMPL_ISUPPORTS1(nsMoveCoalescerCopyListener, nsIMsgCopyServiceListener)
nsMoveCoalescerCopyListener::nsMoveCoalescerCopyListener(nsImapMoveCoalescer * coalescer,
nsIMsgFolder *destFolder)
{
m_destFolder = destFolder;
m_coalescer = coalescer;
}
nsMoveCoalescerCopyListener::~nsMoveCoalescerCopyListener()
{
}
NS_IMETHODIMP nsMoveCoalescerCopyListener::OnStartCopy()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void OnProgress (in PRUint32 aProgress, in PRUint32 aProgressMax); */
NS_IMETHODIMP nsMoveCoalescerCopyListener::OnProgress(PRUint32 aProgress, PRUint32 aProgressMax)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void SetMessageKey (in PRUint32 aKey); */
NS_IMETHODIMP nsMoveCoalescerCopyListener::SetMessageKey(PRUint32 aKey)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* [noscript] void GetMessageId (in nsCString aMessageId); */
NS_IMETHODIMP nsMoveCoalescerCopyListener::GetMessageId(nsCString * aMessageId)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void OnStopCopy (in nsresult aStatus); */
NS_IMETHODIMP nsMoveCoalescerCopyListener::OnStopCopy(nsresult aStatus)
{
nsresult rv = NS_OK;
if (NS_SUCCEEDED(aStatus))
{
// if the dest folder is imap, update it.
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_destFolder);
if (imapFolder)
{
nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIURI> url;
nsCOMPtr<nsIEventQueueService> pEventQService =
do_GetService(kEventQueueServiceCID, &rv);
nsCOMPtr <nsIEventQueue> eventQueue;
if (NS_SUCCEEDED(rv) && pEventQService)
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(eventQueue));
nsCOMPtr <nsIUrlListener> listener = do_QueryInterface(m_coalescer);
rv = imapService->SelectFolder(eventQueue, m_destFolder, listener, nsnull, getter_AddRefs(url));
}
}
return rv;
}

Просмотреть файл

@ -49,27 +49,51 @@
// This utility class will be used by both the filter code and the offline playback code,
// to avoid multiple moves to the same folder.
class NS_MSG_BASE nsImapMoveCoalescer : public nsISupports
class NS_MSG_BASE nsImapMoveCoalescer : public nsIUrlListener
{
public:
friend class nsMoveCoalescerCopyListener;
NS_DECL_ISUPPORTS
NS_DECL_NSIURLLISTENER
nsImapMoveCoalescer(nsIMsgFolder *sourceFolder, nsIMsgWindow *msgWindow);
virtual ~nsImapMoveCoalescer();
nsresult AddMove(nsIMsgFolder *folder, nsMsgKey key);
nsresult PlaybackMoves();
nsresult PlaybackMoves(PRBool doNewMailNotification = PR_FALSE);
// this lets the caller store keys in an arbitrary number of buckets. If the bucket
// for the passed in index doesn't exist, it will get created.
nsMsgKeyArray *GetKeyBucket(PRInt32 keyArrayIndex);
nsIMsgWindow *GetMsgWindow() {return m_msgWindow;}
PRBool HasPendingMoves() {return m_hasPendingMoves;}
protected:
// m_sourceKeyArrays and m_destFolders are parallel arrays.
nsVoidArray m_sourceKeyArrays;
nsCOMPtr <nsISupportsArray> m_destFolders;
nsCOMPtr <nsIMsgWindow> m_msgWindow;
nsCOMPtr <nsIMsgFolder> m_sourceFolder;
PRBool m_doNewMailNotification;
PRBool m_hasPendingMoves;
nsVoidArray m_keyBuckets;
PRInt32 m_outstandingMoves;
};
class nsMoveCoalescerCopyListener : public nsIMsgCopyServiceListener
{
public:
nsMoveCoalescerCopyListener(nsImapMoveCoalescer * coalescer, nsIMsgFolder *destFolder);
~nsMoveCoalescerCopyListener();
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGCOPYSERVICELISTENER
nsCOMPtr <nsIMsgFolder> m_destFolder;
nsImapMoveCoalescer *m_coalescer;
// when we get OnStopCopy, update the folder. When we've finished all the copies,
// send the biff notification.
};
#endif // _nsImapMoveCoalescer_H

Просмотреть файл

@ -76,7 +76,7 @@ interface nsIMsgImapFolderProps : nsISupports {
};
[scriptable, uuid(ba8ddecd-4814-4757-9a15-028157cdabb3)]
[scriptable, uuid(19eeaeeb-1cb1-445f-bf19-80537189ece4)]
interface nsIMsgImapMailFolder : nsISupports {
void removeSubFolder(in nsIMsgFolder folder);
void createClientSubfolderInfo(in string folderName, in wchar hierarchyDelimiter, in long flags, in boolean suppressNotification);
@ -113,6 +113,8 @@ interface nsIMsgImapMailFolder : nsISupports {
[array, size_is (aNumKeys)] in nsMsgKey aKeysToStore,
in unsigned long aNumKeys);
void notifyIfNewMail();
attribute boolean verifiedAsOnlineFolder;
attribute boolean explicitlyVerify;
attribute wchar hierarchyDelimiter;

Просмотреть файл

@ -730,9 +730,6 @@ nsImapMailFolder::UpdateFolder(nsIMsgWindow *msgWindow)
}
}
nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
selectFolder = PR_TRUE;
PRBool isServer;
@ -796,14 +793,11 @@ nsImapMailFolder::UpdateFolder(nsIMsgWindow *msgWindow)
// don't run select if we're already running a url/select...
if (NS_SUCCEEDED(rv) && !m_urlRunning && selectFolder)
{
nsCOMPtr <nsIEventQueue> eventQ;
nsCOMPtr<nsIEventQueueService> pEventQService =
do_GetService(kEventQueueServiceCID, &rv);
if (NS_SUCCEEDED(rv) && pEventQService)
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(eventQ));
nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr <nsIURI> url;
rv = imapService->SelectFolder(eventQ, this, m_urlListener, msgWindow, getter_AddRefs(url));
rv = imapService->SelectFolder(m_eventQueue, this, m_urlListener, msgWindow, getter_AddRefs(url));
if (NS_SUCCEEDED(rv))
m_urlRunning = PR_TRUE;
if (url)
@ -4312,21 +4306,11 @@ nsImapMailFolder::OnlineCopyCompleted(nsIImapProtocol *aProtocol, ImapOnlineCopy
rv = imapUrl->CreateListOfMessageIdsString(getter_Copies(messageIds));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> queue;
// get the Event Queue for this thread...
nsCOMPtr<nsIEventQueueService> pEventQService =
do_GetService(kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(queue));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIImapService> imapService =
do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = imapService->AddMessageFlags(queue, this, nsnull, nsnull,
rv = imapService->AddMessageFlags(m_eventQueue, this, nsnull, nsnull,
messageIds,
kImapMsgDeletedFlag,
PR_TRUE);
@ -5299,6 +5283,7 @@ nsImapMailFolder::HeaderFetchCompleted(nsIImapProtocol* aProtocol)
if (m_performingBiff)
GetNumNewMessages(PR_FALSE, &numNewBiffMsgs);
PRBool pendingMoves = m_moveCoalescer && m_moveCoalescer->HasPendingMoves();
PlaybackCoalescedOperations();
if (aProtocol)
{
@ -5353,7 +5338,8 @@ nsImapMailFolder::HeaderFetchCompleted(nsIImapProtocol* aProtocol)
PRBool filtersRun;
CallFilterPlugins(msgWindow, &filtersRun);
if (!filtersRun && m_performingBiff && mDatabase && numNewBiffMsgs > 0)
if (!filtersRun && m_performingBiff && mDatabase && numNewBiffMsgs > 0 &&
(!pendingMoves || !ShowPreviewText()))
{
// If we are performing biff for this folder, tell the
// stand-alone biff about the new high water mark
@ -6958,13 +6944,16 @@ nsImapFolderCopyState::StartNextCopy()
nsCOMPtr <nsIImapService> imapService = do_GetService (NS_IMAPSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr <nsIEventQueue> eventQueue;
nsCOMPtr<nsIEventQueueService> pEventQService =
do_GetService(kEventQueueServiceCID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQueue));
nsXPIDLString folderName;
m_srcFolder->GetName(getter_Copies(folderName));
nsCOMPtr<nsIEventQueueService> pEventQService =
do_GetService(kEventQueueServiceCID, &rv);
nsCOMPtr <nsIEventQueue> eventQueue;
if (NS_SUCCEEDED(rv) && pEventQService)
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(eventQueue));
rv = imapService->EnsureFolderExists(eventQueue, m_destParent,
folderName.get(),
this, nsnull);
@ -8135,6 +8124,20 @@ nsImapMailFolder::StoreCustomKeywords(nsIMsgWindow *aMsgWindow, const char *aFla
return imapService->StoreCustomKeywords(m_eventQueue, this, aMsgWindow, aFlagsToAdd, aFlagsToSubtract, msgIds.get(), _retval);
}
NS_IMETHODIMP nsImapMailFolder::NotifyIfNewMail()
{
return PerformBiffNotifications();
}
PRBool nsImapMailFolder::ShowPreviewText()
{
PRBool showPreviewText = PR_FALSE;
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (prefBranch)
prefBranch->GetBoolPref("mail.showPreviewText", &showPreviewText);
return showPreviewText;
}
nsresult
nsImapMailFolder::PlaybackCoalescedOperations()
{
@ -8149,7 +8152,7 @@ nsImapMailFolder::PlaybackCoalescedOperations()
StoreCustomKeywords(m_moveCoalescer->GetMsgWindow(), "NonJunk", "", nonJunkKeysToClassify->GetArray(), nonJunkKeysToClassify->GetSize(), nsnull);
junkKeysToClassify->RemoveAll();
nonJunkKeysToClassify->RemoveAll();
return m_moveCoalescer->PlaybackMoves();
return m_moveCoalescer->PlaybackMoves(ShowPreviewText());
}
return NS_OK; // must not be any coalesced operations
}
@ -8278,9 +8281,10 @@ nsImapMailFolder::OnMessageClassified(const char *aMsgURI, nsMsgJunkStatus aClas
m_junkMessagesToMarkAsRead->SizeTo(0);
}
}
PRBool pendingMoves = m_moveCoalescer && m_moveCoalescer->HasPendingMoves();
PlaybackCoalescedOperations();
// If we are performing biff for this folder, tell the server object
if (m_performingBiff)
if ((!pendingMoves || !ShowPreviewText()) && m_performingBiff)
{
// we don't need to adjust the num new messages in this folder because
// the playback moves code already did that.

Просмотреть файл

@ -423,6 +423,7 @@ protected:
nsresult CopyOfflineMsgBody(nsIMsgFolder *srcFolder, nsIMsgDBHdr *destHdr, nsIMsgDBHdr *origHdr);
void GetTrashFolderName(nsAString &aFolderName);
PRBool ShowPreviewText();
PRBool m_initialized;
PRBool m_haveDiscoveredAllFolders;

Просмотреть файл

@ -270,44 +270,9 @@ nsImapService::LiteSelectFolder(nsIEventQueue * aClientEventQueue,
nsIUrlListener * aUrlListener,
nsIURI ** aURL)
{
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
"/liteselect>", nsIImapUrl::nsImapLiteSelectFolder, aURL);
// create a protocol instance to handle the request.
// NOTE: once we start working with multiple connections, this step will be much more complicated...but for now
// just create a connection and process the request.
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
"Oops ... null pointer");
if (!aImapMailFolder || !aClientEventQueue)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIImapUrl> imapUrl;
nsCAutoString urlSpec;
nsresult rv;
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), aImapMailFolder, aUrlListener, urlSpec, hierarchySeparator);
if (NS_SUCCEEDED(rv))
{
rv = SetImapUrlSink(aImapMailFolder, imapUrl);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
urlSpec.Append("/liteselect>");
urlSpec.Append(char (hierarchySeparator));
nsXPIDLCString folderName;
GetFolderName(aImapMailFolder, getter_Copies(folderName));
urlSpec.Append((const char *) folderName);
rv = uri->SetSpec(urlSpec);
if (NS_SUCCEEDED(rv))
rv = GetImapConnectionAndLoadUrl(aClientEventQueue, imapUrl, nsnull, aURL);
}
} // if we have a url to run....
return rv;
}
NS_IMETHODIMP nsImapService::GetUrlForUri(const char *aMessageURI, nsIURI **aURL, nsIMsgWindow *aMsgWindow)
@ -1526,63 +1491,27 @@ nsImapService::Biff(nsIEventQueue * aClientEventQueue,
}
NS_IMETHODIMP
nsImapService::DeleteFolder(nsIEventQueue* eventQueue,
nsIMsgFolder* folder,
nsIUrlListener* urlListener,
nsIURI** url)
nsImapService::DeleteFolder(nsIEventQueue* aClientEventQueue,
nsIMsgFolder* aImapMailFolder,
nsIUrlListener* aUrlListener,
nsIURI** aURL)
{
nsresult rv = NS_ERROR_NULL_POINTER;
NS_ASSERTION(eventQueue && folder,
"Oops ... [DeleteFolder] null eventQueue or folder");
if (!eventQueue || ! folder)
return rv;
nsCOMPtr<nsIImapUrl> imapUrl;
nsCAutoString urlSpec;
// If it's an aol server then use 'deletefolder' url to
// remove all msgs first and then remove the folder itself.
PRBool removeFolderAndMsgs = PR_FALSE;
nsCOMPtr<nsIMsgIncomingServer> server;
if (NS_SUCCEEDED(folder->GetServer(getter_AddRefs(server))) && server)
if (NS_SUCCEEDED(aImapMailFolder->GetServer(getter_AddRefs(server))) && server)
{
nsCOMPtr <nsIImapIncomingServer> imapServer = do_QueryInterface(server);
if (imapServer)
imapServer->GetIsAOLServer(&removeFolderAndMsgs);
}
PRUnichar hierarchySeparator = GetHierarchyDelimiter(folder);
rv = CreateStartOfImapUrl(nsnull, getter_AddRefs(imapUrl), folder, urlListener, urlSpec, hierarchySeparator);
if (NS_SUCCEEDED(rv))
{
rv = SetImapUrlSink(folder, imapUrl);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIURI> uri = do_QueryInterface(imapUrl);
return FolderCommand(aClientEventQueue, aImapMailFolder, aUrlListener,
removeFolderAndMsgs ? "/deletefolder>": "/delete>",
nsIImapUrl::nsImapDeleteFolder, aURL);
if (removeFolderAndMsgs)
urlSpec.Append("/deletefolder>");
else
urlSpec.Append("/delete>");
urlSpec.Append(char(hierarchySeparator));
nsXPIDLCString folderName;
rv = GetFolderName(folder, getter_Copies(folderName));
if (NS_SUCCEEDED(rv))
{
urlSpec.Append((const char *) folderName);
rv = uri->SetSpec(urlSpec);
if (NS_SUCCEEDED(rv))
{
rv = GetImapConnectionAndLoadUrl(eventQueue, imapUrl,
nsnull,
url);
}
}
}
}
return rv;
}
NS_IMETHODIMP