Bug #75866 --> Mark a message as read in JS instead of once for each mail protocol to simplify code.

Hookup the JS function to a timer to allow users to only mark messages as read after they have
been viewed in the preview pane for a configurable number of seconds.

sr=bienvenu
This commit is contained in:
scott%scott-macgregor.org 2004-01-09 07:27:21 +00:00
Родитель 75a5ad67d7
Коммит dbfa473488
12 изменённых файлов: 58 добавлений и 102 удалений

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

@ -298,6 +298,9 @@ function RerootFolder(uri, newFolder, viewType, viewFlags, sortType, sortOrder)
gDBView = null;
}
// cancel the pending mark as read timer
ClearPendingReadTimer();
// if this is the drafts, sent, or send later folder,
// we show "Recipient" instead of "Author"
SetSentFolderColumns(IsSpecialFolder(newFolder, MSG_FOLDER_FLAG_SENTMAIL | MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE));

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

@ -469,10 +469,22 @@ var DefaultController =
break;// This does nothing because the createfilter is invoked from the popupnode oncommand.
case "button_delete":
case "cmd_delete":
// if the user deletes a message before its mark as read timer goes off, we should mark it as read
// this ensures that we clear the biff indicator from the system tray when the user deletes the new message
if (gMarkViewedMessageAsReadTimer)
{
MarkCurrentMessageAsRead();
ClearPendingReadTimer();
}
SetNextMessageAfterDelete();
gDBView.doCommand(nsMsgViewCommandType.deleteMsg);
break;
case "cmd_shiftDelete":
if (gMarkViewedMessageAsReadTimer)
{
MarkCurrentMessageAsRead();
ClearPendingReadTimer();
}
SetNextMessageAfterDelete();
gDBView.doCommand(nsMsgViewCommandType.deleteNoTrash);
break;

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

@ -75,6 +75,7 @@ var gLastKeywords = "";
function OnMailWindowUnload()
{
RemoveMailOfflineObserver();
ClearPendingReadTimer();
var searchSession = GetSearchSession();
if (searchSession)

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

@ -40,6 +40,7 @@ var gWindowManagerInterface;
var gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
var gPrintSettings = null;
var gWindowReuse = 0;
var gMarkViewedMessageAsReadTimer = null; // if the user has configured the app to mark a message as read if it is viewed for more than n seconds
var gTimelineService = null;
var gTimelineEnabled = ("@mozilla.org;timeline-service;1" in Components.classes);
@ -2031,6 +2032,20 @@ function SetUpJunkBar(aMsgHdr)
goUpdateCommand('button_junk');
}
function MarkCurrentMessageAsRead()
{
gDBView.doCommand(nsMsgViewCommandType.markMessagesRead);
}
function ClearPendingReadTimer()
{
if (gMarkViewedMessageAsReadTimer)
{
clearTimeout(gMarkViewedMessageAsReadTimer);
gMarkViewedMessageAsReadTimer = null;
}
}
function OnMsgLoaded(aUrl)
{
if (!aUrl)
@ -2038,6 +2053,8 @@ function OnMsgLoaded(aUrl)
var folder = aUrl.folder;
var msgURI = GetLoadedMessage();
var msgHdr = null;
if (!folder || !msgURI)
return;
@ -2045,10 +2062,22 @@ function OnMsgLoaded(aUrl)
SetUpJunkBar(null);
else
{
var msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
msgHdr = messenger.messageServiceFromURI(msgURI).messageURIToMsgHdr(msgURI);
SetUpJunkBar(msgHdr);
}
// we just finished loading a message. set a timer to actually mark the message as read after n seconds
// where n can be configured by the user.
var markReadOnADelay = gPrefs.getBoolPref("mailnews.mark_message_read.delay");
if (msgHdr && !msgHdr.isRead)
{
var wintype = document.firstChild.getAttribute('windowtype');
if (markReadOnADelay && wintype == "mail:3pane") // only use the timer if viewing using the 3-pane preview pane and the user has set the pref
gMarkViewedMessageAsReadTimer = setTimeout(MarkCurrentMessageAsRead, gPrefs.getIntPref("mailnews.mark_message_read.delay.interval") * 1000);
else
MarkCurrentMessageAsRead();
}
// See if MDN was requested but has not been sent.
HandleMDNResponse(aUrl);

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

@ -173,6 +173,7 @@ nsMsgDBViewCommandUpdater.prototype =
displayMessageChanged : function(aFolder, aSubject, aKeywords)
{
setTitleFromFolder(aFolder, aSubject);
ClearPendingReadTimer(); // we are loading / selecting a new message so kill the mark as read timer for the currently viewed message
gCurrentMessageUri = gDBView.URIForFirstSelectedMessage;
UpdateStandAloneMessageCounts();
SetKeywords(aKeywords);

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

@ -85,6 +85,7 @@ nsMsgDBViewCommandUpdater.prototype =
displayMessageChanged : function(aFolder, aSubject, aKeywords)
{
setTitleFromFolder(aFolder, aSubject);
ClearPendingReadTimer(); // we are loading / selecting a new message so kill the mark as read timer for the currently viewed message
gHaveLoadedMessage = true;
SetKeywords(aKeywords);
goUpdateCommand("button_junk");

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

@ -3786,17 +3786,6 @@ nsImapMailFolder::NormalEndMsgWriteStream(nsMsgKey uidOfMessage,
nsCOMPtr<nsIMsgDBHdr> msgHdr;
m_curMsgUid = uidOfMessage;
res = GetMessageHeader(m_curMsgUid, getter_AddRefs(msgHdr));
if (msgHdr && markRead)
{
PRBool isRead;
msgHdr->GetIsRead(&isRead);
if (!isRead)
{
msgHdr->MarkRead(PR_TRUE);
commit = PR_TRUE;
}
}
if (commit && mDatabase)
mDatabase->Commit(nsMsgDBCommitType::kLargeCommit);

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

@ -555,7 +555,13 @@ NS_IMETHODIMP nsImapService::DisplayMessage(const char* aMessageURI,
if (hasMsgOffline)
msgurl->SetMsgIsInLocalCache(PR_TRUE);
rv = FetchMessage(imapUrl, nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
PRBool forcePeek = PR_FALSE; // should the message fetch force a peak or a traditional fetch?
if (NS_SUCCEEDED(rv) && prefBranch)
prefBranch->GetBoolPref("mailnews.mark_message_read.delay", &forcePeek);
rv = FetchMessage(imapUrl, forcePeek ? nsIImapUrl::nsImapMsgFetchPeek : nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
aMsgWindow, aDisplayConsumer, msgKey, PR_FALSE, (mPrintingOperation) ? "print" : nsnull, aURL);
}
}

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

@ -1347,41 +1347,6 @@ NS_IMETHODIMP nsImapUrl::SetMsgLoadingFromCache(PRBool loadingFromCache)
{
nsresult rv = NS_OK;
m_msgLoadingFromCache = loadingFromCache;
if (loadingFromCache)
{
nsCOMPtr<nsIMsgFolder> folder;
nsMsgKey key;
nsCAutoString folderURI;
rv = nsParseImapMessageURI(mURI.get(), folderURI, &key, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
if (m_imapAction != nsImapMsgFetch) // only do this on msg fetch, i.e., if user is reading msg.
return rv;
rv = GetMsgFolder(getter_AddRefs(folder));
nsCOMPtr <nsIMsgDatabase> database;
if (folder && NS_SUCCEEDED(folder->GetMsgDatabase(nsnull, getter_AddRefs(database))) && database)
{
PRBool msgRead = PR_TRUE;
database->IsRead(key, &msgRead);
if (!msgRead)
{
nsCOMPtr<nsISupportsArray> messages;
rv = NS_NewISupportsArray(getter_AddRefs(messages));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIMsgDBHdr> message;
GetMsgDBHdrFromURI(mURI.get(), getter_AddRefs(message));
nsCOMPtr<nsISupports> msgSupport(do_QueryInterface(message, &rv));
if (msgSupport)
{
messages->AppendElement(msgSupport);
folder->MarkMessagesRead(messages, PR_TRUE);
}
}
}
}
return rv;
}

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

@ -404,32 +404,6 @@ PRInt32 nsMailboxProtocol::DoneReadingMessage()
if (m_mailboxAction == nsIMailboxUrl::ActionSaveMessageToDisk && m_tempMessageFile)
rv = m_tempMessageFile->CloseStream();
nsCOMPtr<nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(m_runningUrl, &rv);
NS_ENSURE_SUCCESS(rv,rv);
nsCAutoString queryStr;
rv = msgUrl->GetQuery(queryStr);
NS_ENSURE_SUCCESS(rv,rv);
// check if this is a filter plugin requesting the message.
// in that case, don't mark it as read,
// since the user didn't actually read it.
// the spec for msgUrl is of the form:
// mailbox:///<path to mbox file on disk>/Inbox?number=3287862&header=filter"
if ((queryStr.Find("header=filter") == kNotFound) && m_mailboxAction == nsIMailboxUrl::ActionFetchMessage)
{
// now mark the message as read
nsCOMPtr<nsIMsgDBHdr> msgHdr;
if (m_runningUrl)
rv = m_runningUrl->GetMessageHeader(getter_AddRefs(msgHdr));
NS_ASSERTION(msgHdr, "no msg hdr!");
if (!msgHdr) return NS_ERROR_UNEXPECTED;
PRBool isRead;
msgHdr->GetIsRead(&isRead);
if (NS_SUCCEEDED(rv) && !isRead)
msgHdr->MarkRead(PR_TRUE);
}
return rv;
}

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

@ -848,7 +848,6 @@ nsresult nsNNTPProtocol::ReadFromMemCache(nsICacheEntryDescriptor *entry)
rv = pump->AsyncRead(cacheListener, m_channelContext);
NS_RELEASE(cacheListener);
MarkCurrentMsgRead();
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
{
// we're not calling nsMsgProtocol::AsyncRead(), which calls nsNNTPProtocol::LoadUrl, so we need to take care of some stuff it does.
@ -913,7 +912,6 @@ PRBool nsNNTPProtocol::ReadFromLocalCache()
rv = pump->AsyncRead(cacheListener, m_channelContext);
NS_RELEASE(cacheListener);
MarkCurrentMsgRead();
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
{
@ -2313,7 +2311,6 @@ PRInt32 nsNNTPProtocol::SendFirstNNTPCommandResponse()
FinishMemCacheEntry(PR_FALSE); // cleanup mem cache entry
if (NS_SUCCEEDED(rv) && group_name && !savingArticleOffline) {
MarkCurrentMsgRead();
nsXPIDLString titleStr;
rv = GetNewsStringByName("htmlNewsErrorTitle", getter_Copies(titleStr));
NS_ENSURE_SUCCESS(rv,rv);
@ -2569,7 +2566,6 @@ PRInt32 nsNNTPProtocol::DisplayArticle(nsIInputStream * inputStream, PRUint32 le
if (line[0] == '.' && line[1] == 0)
{
m_nextState = NEWS_DONE;
MarkCurrentMsgRead();
ClearFlag(NNTP_PAUSE_FOR_READ);
@ -2598,26 +2594,6 @@ PRInt32 nsNNTPProtocol::DisplayArticle(nsIInputStream * inputStream, PRUint32 le
return 0;
}
nsresult nsNNTPProtocol::MarkCurrentMsgRead()
{
nsCOMPtr<nsIMsgDBHdr> msgHdr;
nsresult rv = NS_OK;
// if this is a message id url, (news://host/message-id) then don't go try to mark it read
if (m_runningURL && !m_messageID && (m_key != nsMsgKey_None)) {
rv = m_runningURL->GetMessageHeader(getter_AddRefs(msgHdr));
if (NS_SUCCEEDED(rv) && msgHdr)
{
PRBool isRead;
msgHdr->GetIsRead(&isRead);
if (!isRead)
msgHdr->MarkRead(PR_TRUE);
}
}
return rv;
}
PRInt32 nsNNTPProtocol::ReadArticle(nsIInputStream * inputStream, PRUint32 length)
{
PRUint32 status = 0;

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

@ -183,9 +183,9 @@ public:
NS_IMETHOD Cancel(nsresult status); // handle stop button
NS_IMETHOD GetContentType(nsACString &aContentType);
NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt);
NS_IMETHOD GetOriginalURI(nsIURI* *aURI);
NS_IMETHOD SetOriginalURI(nsIURI* aURI);
NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt);
NS_IMETHOD GetOriginalURI(nsIURI* *aURI);
NS_IMETHOD SetOriginalURI(nsIURI* aURI);
nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer);
@ -410,7 +410,6 @@ private:
void SetProgressBarPercent(PRUint32 aProgress, PRUint32 aProgressMax);
nsresult SetProgressStatus(const PRUnichar *aMessage);
nsresult SetCheckingForNewNewsStatus(PRInt32 current, PRInt32 total);
nsresult MarkCurrentMsgRead(); // marks the message corresponding to the currently running url read.
nsresult InitializeNewsFolderFromUri(const char *uri);
void TimerCallback();
nsCOMPtr <nsIInputStream> mInputStream;