Bug 942638 - Clean up the multi-message summary code, part 7: Move FormatDisplayName and friends to a JS module (to help Mail Summaries); r=mconley
This commit is contained in:
Родитель
51792b22f3
Коммит
9b8912dd85
|
@ -9,6 +9,7 @@
|
|||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/displayNameUtils.js");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/gloda/utils.js");
|
||||
let {Status: statusUtils} =
|
||||
|
@ -1249,59 +1250,9 @@ function updateEmailAddressNode(emailAddressNode, address)
|
|||
UpdateEmailNodeDetails(address.emailAddress, emailAddressNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an email address and compose a sensible display name based on the
|
||||
* header display name and/or the display name from the address book. If no
|
||||
* appropriate name can be made (e.g. there is no card for this address),
|
||||
* returns |null|.
|
||||
*
|
||||
* @param aEmailAddress the email address to format
|
||||
* @param aHeaderDisplayName the display name from the header, if any
|
||||
* @param aContext the field being formatted (e.g. "to", "from")
|
||||
* @param aCard the address book card, if any
|
||||
* @return The formatted display name, or null
|
||||
*/
|
||||
function FormatDisplayName(aEmailAddress, aHeaderDisplayName, aContext, aCard)
|
||||
{
|
||||
var displayName = null;
|
||||
var identity = getBestIdentity(accountManager.allIdentities, aEmailAddress);
|
||||
var card = aCard || getCardForEmail(aEmailAddress).card;
|
||||
|
||||
// If this address is one of the user's identities...
|
||||
if (aEmailAddress == identity.email) {
|
||||
var bundle = document.getElementById("bundle_messenger");
|
||||
// ...pick a localized version of the word "Me" appropriate to this
|
||||
// specific header; fall back to the version used by the "to" header
|
||||
// if nothing else is available.
|
||||
try {
|
||||
displayName = bundle.getString("header" + aContext + "FieldMe");
|
||||
} catch (ex) {
|
||||
displayName = bundle.getString("headertoFieldMe");
|
||||
}
|
||||
|
||||
// Make sure we have an unambiguous name if there are multiple identities
|
||||
if (accountManager.allIdentities.length > 1)
|
||||
displayName += " <"+identity.email+">";
|
||||
}
|
||||
|
||||
// If we don't have a card, refuse to generate a display name. Places calling
|
||||
// this are then responsible for falling back to something else (e.g. the
|
||||
// value from the message header).
|
||||
if (card) {
|
||||
if (!displayName && aHeaderDisplayName)
|
||||
displayName = aHeaderDisplayName;
|
||||
|
||||
// getProperty may return a "1" or "0" string, we want a boolean
|
||||
if (!displayName || card.getProperty("PreferDisplayName", true) != false)
|
||||
displayName = card.displayName || null;
|
||||
}
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
function UpdateEmailNodeDetails(aEmailAddress, aDocumentNode, aCardDetails) {
|
||||
// If we haven't been given specific details, search for a card.
|
||||
var cardDetails = aCardDetails || getCardForEmail(aEmailAddress);
|
||||
var cardDetails = aCardDetails || GetCardForEmail(aEmailAddress);
|
||||
aDocumentNode.cardDetails = cardDetails;
|
||||
|
||||
if (!cardDetails.card) {
|
||||
|
|
|
@ -6,13 +6,10 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Components.utils.import("resource:///modules/gloda/gloda.js");
|
||||
Components.utils.import("resource:///modules/gloda/connotent.js");
|
||||
Components.utils.import("resource:///modules/gloda/mimemsg.js");
|
||||
Components.utils.import("resource:///modules/displayNameUtils.js");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/templateUtils.js");
|
||||
|
||||
// This is executed in the context of the message summary page, not main chrome,
|
||||
// but we need to access a few things from the main window.
|
||||
var global = window.top;
|
||||
|
||||
var gMessenger = Components.classes["@mozilla.org/messenger;1"]
|
||||
.createInstance(Components.interfaces.nsIMessenger);
|
||||
|
||||
|
@ -26,34 +23,6 @@ XPCOMUtils.defineLazyGetter(this, "formatString", function() {
|
|||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Format the display name for the multi-message/thread summaries. First, try
|
||||
* using FormatDisplayName, then fall back to the header's display name or the
|
||||
* address.
|
||||
*
|
||||
* @param aHeaderParser An instance of |nsIMsgHeaderParser|.
|
||||
* @param aHeaderValue The raw header value.
|
||||
* @param aContext The context of the header field (e.g. "to", "from").
|
||||
* @return The formatted display name.
|
||||
*/
|
||||
function _mm_FormatDisplayName(aHeaderParser, aHeaderValue, aContext) {
|
||||
let addresses = {};
|
||||
let fullNames = {};
|
||||
let names = {};
|
||||
let numAddresses = aHeaderParser.parseHeadersWithArray(aHeaderValue,
|
||||
addresses, names, fullNames);
|
||||
|
||||
if (numAddresses > 0) {
|
||||
return global.FormatDisplayName(
|
||||
addresses.value[0], names.value[0], aContext
|
||||
) || names.value[0] || addresses.value[0];
|
||||
}
|
||||
else {
|
||||
// Something strange happened, just return the raw header value.
|
||||
return aHeaderValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The MultiMessageSummary class is responsible for populating the message pane
|
||||
* with a reasonable summary of a set of messages.
|
||||
|
@ -124,7 +93,8 @@ MultiMessageSummary.prototype = {
|
|||
|
||||
// Enable/disable the archive button as appropriate.
|
||||
let archiveBtn = document.getElementById("hdrArchiveButton");
|
||||
archiveBtn.collapsed = !global.gFolderDisplay.canArchiveSelectedMessages;
|
||||
archiveBtn.collapsed = !window.top.gFolderDisplay
|
||||
.canArchiveSelectedMessages;
|
||||
|
||||
let summarizer = this._summarizers[aType];
|
||||
if (!summarizer)
|
||||
|
@ -205,8 +175,8 @@ MultiMessageSummary.prototype = {
|
|||
|
||||
let authorNode = document.createElement("span");
|
||||
authorNode.classList.add("author");
|
||||
authorNode.textContent = _mm_FormatDisplayName(
|
||||
MailServices.headerParser, message.mime2DecodedAuthor, "from"
|
||||
authorNode.textContent = FormatDisplayNameList(
|
||||
message.mime2DecodedAuthor, "from"
|
||||
);
|
||||
|
||||
if (aOptions && aOptions.showSubject) {
|
||||
|
@ -218,7 +188,7 @@ MultiMessageSummary.prototype = {
|
|||
subjectNode.textContent = message.mime2DecodedSubject ||
|
||||
formatString("noSubject");
|
||||
subjectNode.addEventListener("click", function() {
|
||||
global.gFolderDisplay.selectMessages(thread);
|
||||
window.top.gFolderDisplay.selectMessages(thread);
|
||||
}, false);
|
||||
itemHeaderNode.appendChild(subjectNode);
|
||||
|
||||
|
@ -246,8 +216,8 @@ MultiMessageSummary.prototype = {
|
|||
|
||||
authorNode.classList.add("primary_header", "link");
|
||||
authorNode.addEventListener("click", function() {
|
||||
global.gFolderDisplay.selectMessage(message);
|
||||
global.document.getElementById("messagepane").focus();
|
||||
window.top.gFolderDisplay.selectMessage(message);
|
||||
window.top.document.getElementById("messagepane").focus();
|
||||
}, false);
|
||||
itemHeaderNode.appendChild(authorNode);
|
||||
}
|
||||
|
@ -569,9 +539,9 @@ MultipleSelectionSummarizer.prototype = {
|
|||
let threads = {};
|
||||
let numThreads = 0;
|
||||
for (let [,msgHdr] in Iterator(aMessages)) {
|
||||
let viewThreadId = global.gFolderDisplay.view.dbView
|
||||
.getThreadContainingMsgHdr(msgHdr)
|
||||
.threadKey;
|
||||
let viewThreadId = window.top.gFolderDisplay.view.dbView
|
||||
.getThreadContainingMsgHdr(msgHdr)
|
||||
.threadKey;
|
||||
if (!(viewThreadId in threads)) {
|
||||
threads[viewThreadId] = [msgHdr];
|
||||
numThreads++;
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource:///modules/iteratorUtils.jsm");
|
||||
Components.utils.import("resource:///modules/mailServices.js");
|
||||
Components.utils.import("resource:///modules/StringBundle.js");
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"GetCardForEmail", "FormatDisplayName", "FormatDisplayNameList",
|
||||
];
|
||||
|
||||
// XXX: Maybe the strings for this file should go in a separate bundle?
|
||||
var gMessengerBundle = new StringBundle(
|
||||
"chrome://messenger/locale/messenger.properties"
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns an object with two properties, .book and .card. If the email address
|
||||
* is found in the address books, then the book will contain an nsIAbDirectory,
|
||||
* and card will contain an nsIAbCard. If the email address is not found, both
|
||||
* items will contain null.
|
||||
*
|
||||
* @param aEmailAddress The address to look for.
|
||||
* @return An object with two properties, .book and .card.
|
||||
*/
|
||||
function GetCardForEmail(aEmailAddress) {
|
||||
// Email address is searched for in any of the address books that support
|
||||
// the cardForEmailAddress function.
|
||||
// Future expansion could be to domain matches
|
||||
let books = MailServices.ab.directories;
|
||||
for (let book in fixIterator(books, Components.interfaces.nsIAbDirectory)) {
|
||||
try {
|
||||
let card = book.cardForEmailAddress(aEmailAddress);
|
||||
if (card)
|
||||
return { book: book, card: card };
|
||||
}
|
||||
catch (ex) {}
|
||||
}
|
||||
|
||||
return { book: null, card: null };
|
||||
}
|
||||
|
||||
function _getIdentityForAddress(aEmailAddress) {
|
||||
let emailAddress = aEmailAddress.toLowerCase();
|
||||
for (let identity in fixIterator(MailServices.accounts.allIdentities,
|
||||
Components.interfaces.nsIMsgIdentity)) {
|
||||
if (!identity.email)
|
||||
continue;
|
||||
if (emailAddress == identity.email.toLowerCase())
|
||||
return identity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an email address and compose a sensible display name based on the
|
||||
* header display name and/or the display name from the address book. If no
|
||||
* appropriate name can be made (e.g. there is no card for this address),
|
||||
* returns |null|.
|
||||
*
|
||||
* @param aEmailAddress The email address to format.
|
||||
* @param aHeaderDisplayName The display name from the header, if any.
|
||||
* @param aContext The field being formatted (e.g. "to", "from").
|
||||
* @param aCard The address book card, if any.
|
||||
* @return The formatted display name, or null.
|
||||
*/
|
||||
function FormatDisplayName(aEmailAddress, aHeaderDisplayName, aContext, aCard)
|
||||
{
|
||||
var displayName = null;
|
||||
var identity = _getIdentityForAddress(aEmailAddress);
|
||||
var card = aCard || GetCardForEmail(aEmailAddress).card;
|
||||
|
||||
// If this address is one of the user's identities...
|
||||
if (identity) {
|
||||
// ...pick a localized version of the word "Me" appropriate to this
|
||||
// specific header; fall back to the version used by the "to" header
|
||||
// if nothing else is available.
|
||||
try {
|
||||
displayName = gMessengerBundle.getString("header" + aContext + "FieldMe");
|
||||
} catch (e) {
|
||||
displayName = gMessenberBundle.getString("headertoFieldMe");
|
||||
}
|
||||
|
||||
// Make sure we have an unambiguous name if there are multiple identities
|
||||
if (MailServices.accounts.allIdentities.length > 1)
|
||||
displayName += " <" + identity.email + ">";
|
||||
}
|
||||
|
||||
// If we don't have a card, refuse to generate a display name. Places calling
|
||||
// this are then responsible for falling back to something else (e.g. the
|
||||
// value from the message header).
|
||||
if (card) {
|
||||
if (!displayName && aHeaderDisplayName)
|
||||
displayName = aHeaderDisplayName;
|
||||
|
||||
// getProperty may return a "1" or "0" string, we want a boolean
|
||||
if (!displayName || card.getProperty("PreferDisplayName", true) != false)
|
||||
displayName = card.displayName || null;
|
||||
}
|
||||
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the display name from a list of addresses. First, try using
|
||||
* FormatDisplayName, then fall back to the header's display name or the
|
||||
* address.
|
||||
*
|
||||
* @param aHeaderValue The raw header value.
|
||||
* @param aContext The context of the header field (e.g. "to", "from").
|
||||
* @return The formatted display name.
|
||||
*/
|
||||
function FormatDisplayNameList(aHeaderValue, aContext) {
|
||||
let addresses = {}, fullNames = {}, names = {};
|
||||
let numAddresses = MailServices.headerParser.parseHeadersWithArray(
|
||||
aHeaderValue, addresses, names, fullNames
|
||||
);
|
||||
|
||||
if (numAddresses > 0) {
|
||||
return FormatDisplayName(addresses.value[0], names.value[0], aContext) ||
|
||||
names.value[0] || addresses.value[0];
|
||||
}
|
||||
else {
|
||||
// Something strange happened, just return the raw header value.
|
||||
return aHeaderValue;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@
|
|||
EXTRA_JS_MODULES += [
|
||||
'attachmentChecker.js',
|
||||
'dbViewWrapper.js',
|
||||
'displayNameUtils.js',
|
||||
'distribution.js',
|
||||
'glodaWebSearch.js',
|
||||
'MailConsts.js',
|
||||
|
|
|
@ -577,6 +577,7 @@ regxpcom.exe
|
|||
modules/attachmentChecker.js
|
||||
modules/ctypes.jsm
|
||||
modules/dbViewWrapper.js
|
||||
modules/displayNameutils.js
|
||||
modules/debug.js
|
||||
modules/errUtils.js
|
||||
modules/folderUtils.jsm
|
||||
|
|
Загрузка…
Ссылка в новой задаче