Bug 131571 - [RFE] when clicking on a mail adress that is already in the adressbook the option should be "edit address book entry", not "add to address book" r=mnyromyr
This commit is contained in:
Родитель
e431698ec8
Коммит
3fcd7dcd81
|
@ -5,6 +5,10 @@
|
|||
<!-- Message Header View Popup -->
|
||||
<!ENTITY AddToAddressBook.label "Add To Address Book…">
|
||||
<!ENTITY AddToAddressBook.accesskey "B">
|
||||
<!ENTITY EditContact.label "Edit Contact…">
|
||||
<!ENTITY EditContact.accesskey "E">
|
||||
<!ENTITY ViewContact.label "View Contact">
|
||||
<!ENTITY ViewContact.accesskey "V">
|
||||
<!ENTITY SendMailTo.label "Compose Mail To…">
|
||||
<!ENTITY SendMailTo.accesskey "s">
|
||||
<!ENTITY CopyEmailAddress.label "Copy Email Address">
|
||||
|
|
|
@ -415,11 +415,11 @@ function ShowSeparator(aSeparatorID)
|
|||
}
|
||||
|
||||
// message pane context menu helper methods
|
||||
function AddNodeToAddressBook(emailAddressNode)
|
||||
function AddContact(aEmailAddressNode)
|
||||
{
|
||||
if (emailAddressNode)
|
||||
AddEmailToAddressBook(emailAddressNode.getAttribute("emailAddress"),
|
||||
emailAddressNode.getAttribute("displayName"));
|
||||
if (aEmailAddressNode)
|
||||
AddEmailToAddressBook(aEmailAddressNode.getAttribute("emailAddress"),
|
||||
aEmailAddressNode.getAttribute("displayName"));
|
||||
}
|
||||
|
||||
function AddEmailToAddressBook(primaryEmail, displayName)
|
||||
|
@ -429,6 +429,17 @@ function AddEmailToAddressBook(primaryEmail, displayName)
|
|||
{primaryEmail:primaryEmail, displayName:displayName});
|
||||
}
|
||||
|
||||
function EditContact(aEmailAddressNode)
|
||||
{
|
||||
if (aEmailAddressNode.cardDetails.card)
|
||||
{
|
||||
window.openDialog("chrome://messenger/content/addressbook/abEditCardDialog.xul",
|
||||
"", "chrome,resizable=no,modal,titlebar,centerscreen",
|
||||
{ abURI: aEmailAddressNode.cardDetails.book.URI,
|
||||
card: aEmailAddressNode.cardDetails.card });
|
||||
}
|
||||
}
|
||||
|
||||
// SendMailToNode takes the email address title button, extracts
|
||||
// the email address we stored in there and opens a compose window
|
||||
// with that address
|
||||
|
|
|
@ -312,12 +312,12 @@
|
|||
|
||||
try
|
||||
{
|
||||
if ("AddExtraAddressProcessing" in top)
|
||||
AddExtraAddressProcessing(aAddress.emailAddress, aEmailNode);
|
||||
if ("UpdateEmailNodeDetails" in top)
|
||||
UpdateEmailNodeDetails(aAddress.emailAddress, aEmailNode);
|
||||
}
|
||||
catch(ex)
|
||||
{
|
||||
dump("AddExtraAddressProcessing failed: " + ex + "\n");
|
||||
dump("UpdateEmailNodeDetails failed: " + ex + "\n");
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
|
@ -389,6 +389,11 @@
|
|||
while (index < numAddresses && index < aNumAddressesToShow)
|
||||
{
|
||||
var newAddressNode = document.createElement("mail-emailaddress");
|
||||
|
||||
// Stash the headerName somewhere that UpdateEmailNodeDetails
|
||||
// will be able to find it.
|
||||
newAddressNode.setAttribute("headerName", this.headerName);
|
||||
|
||||
if (index)
|
||||
{
|
||||
var textNode = document.createElement("text");
|
||||
|
|
|
@ -91,6 +91,10 @@ var gExpandedHeaderList = [ {name:"subject"},
|
|||
{name:"content-base"},
|
||||
{name:"tags"} ];
|
||||
|
||||
// These are all the items that use a mail-multi-emailHeaderField widget and
|
||||
// therefore may require updating if the address book changes.
|
||||
const gEmailAddressHeaderNames = ["from", "reply-to", "to", "cc", "bcc"];
|
||||
|
||||
// Now, for each view the message pane can generate, we need a global table of headerEntries. These
|
||||
// header entry objects are generated dynamically based on the static data in the header lists (see above)
|
||||
// and elements we find in the DOM based on properties in the header lists.
|
||||
|
@ -113,6 +117,10 @@ var currentHeaderData = {};
|
|||
// isExternalAttachment --> boolean flag stating whether the attachment is external or not.
|
||||
var currentAttachments = new Array();
|
||||
|
||||
const nsIAbDirectory = Components.interfaces.nsIAbDirectory;
|
||||
const nsIAbListener = Components.interfaces.nsIAbListener;
|
||||
const nsIAbCard = Components.interfaces.nsIAbCard;
|
||||
|
||||
// createHeaderEntry --> our constructor method which creates a header Entry
|
||||
// based on an entry in one of the header lists. A header entry is different from a header list.
|
||||
// a header list just describes how you want a particular header to be presented. The header entry
|
||||
|
@ -157,6 +165,12 @@ function createHeaderEntry(prefix, headerListInfo)
|
|||
this.outputFunction = headerListInfo.outputFunction;
|
||||
else
|
||||
this.outputFunction = updateHeaderValue;
|
||||
|
||||
// Stash this so that the <mail-multi-emailheaderfield/> binding can
|
||||
// later attach it to any <mail-emailaddress> tags it creates for later
|
||||
// extraction and use by UpdateEmailNodeDetails.
|
||||
this.enclosingBox.headerName = headerListInfo.name;
|
||||
|
||||
}
|
||||
|
||||
function initializeHeaderViewTables()
|
||||
|
@ -225,6 +239,12 @@ function OnLoadMsgHeaderPane()
|
|||
|
||||
initializeHeaderViewTables();
|
||||
|
||||
// Add an address book listener so we can update the header view when things
|
||||
// change.
|
||||
Components.classes["@mozilla.org/abmanager;1"]
|
||||
.getService(Components.interfaces.nsIAbManager)
|
||||
.addAddressBookListener(AddressBookListener, nsIAbListener.all);
|
||||
|
||||
var toggleHeaderView = GetHeaderPane();
|
||||
var initialCollapsedSetting = toggleHeaderView.getAttribute("state");
|
||||
if (initialCollapsedSetting == "true")
|
||||
|
@ -240,6 +260,10 @@ function OnUnloadMsgHeaderPane()
|
|||
{
|
||||
pref.removeObserver("mail.showCondensedAddresses", MsgHdrViewObserver);
|
||||
|
||||
Components.classes["@mozilla.org/abmanager;1"]
|
||||
.getService(Components.interfaces.nsIAbManager)
|
||||
.removeAddressBookListener(AddressBookListener);
|
||||
|
||||
// dispatch an event letting any listeners know that we have unloaded the message pane
|
||||
var event = document.createEvent('Events');
|
||||
event.initEvent('messagepane-unloaded', false, true);
|
||||
|
@ -262,6 +286,53 @@ const MsgHdrViewObserver =
|
|||
}
|
||||
};
|
||||
|
||||
var AddressBookListener =
|
||||
{
|
||||
onItemAdded: function(aParentDir, aItem) {
|
||||
OnAddressBookDataChanged(nsIAbListener.itemAdded,
|
||||
aParentDir, aItem);
|
||||
},
|
||||
onItemRemoved: function(aParentDir, aItem) {
|
||||
OnAddressBookDataChanged(aItem instanceof nsIAbCard ?
|
||||
nsIAbListener.directoryItemRemoved :
|
||||
nsIAbListener.directoryRemoved,
|
||||
aParentDir, aItem);
|
||||
},
|
||||
onItemPropertyChanged: function(aItem, aProperty, aOldValue, aNewValue) {
|
||||
// We only need updates for card changes, address book and mailing list
|
||||
// ones don't affect us here.
|
||||
if (aItem instanceof nsIAbCard)
|
||||
OnAddressBookDataChanged(nsIAbListener.itemChanged, null, aItem);
|
||||
}
|
||||
};
|
||||
|
||||
function OnAddressBookDataChanged(aAction, aParentDir, aItem)
|
||||
{
|
||||
gEmailAddressHeaderNames.forEach(function (aHeaderName)
|
||||
{
|
||||
var headerEntry = null;
|
||||
|
||||
// Ensure both collapsed and expanded are updated in case we toggle
|
||||
// between the two.
|
||||
if (aHeaderName in gCollapsedHeaderView)
|
||||
{
|
||||
headerEntry = gCollapsedHeaderView[aHeaderName];
|
||||
if (headerEntry)
|
||||
headerEntry.enclosingBox.updateExtraAddressProcessing(aAction,
|
||||
aParentDir,
|
||||
aItem);
|
||||
}
|
||||
if (aHeaderName in gExpandedHeaderView)
|
||||
{
|
||||
headerEntry = gExpandedHeaderView[aHeaderName];
|
||||
if (headerEntry)
|
||||
headerEntry.enclosingBox.updateExtraAddressProcessing(aAction,
|
||||
aParentDir,
|
||||
aItem);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// The messageHeaderSink is the class that gets notified of a message's headers as we display the message
|
||||
// through our mime converter.
|
||||
|
||||
|
@ -1076,69 +1147,167 @@ function setFromBuddyIcon(email)
|
|||
|
||||
function updateEmailAddressNode(emailAddressNode, address)
|
||||
{
|
||||
emailAddressNode.setAttribute("label", address.fullAddress || address.displayName);
|
||||
emailAddressNode.setAttribute("emailAddress", address.emailAddress);
|
||||
emailAddressNode.setAttribute("fullAddress", address.fullAddress);
|
||||
emailAddressNode.setAttribute("displayName", address.displayName);
|
||||
emailAddressNode.removeAttribute("tooltiptext");
|
||||
|
||||
AddExtraAddressProcessing(address.emailAddress, emailAddressNode);
|
||||
UpdateEmailNodeDetails(address.emailAddress, emailAddressNode);
|
||||
}
|
||||
|
||||
// If the email address is found in any of the address books,
|
||||
// then consider this user a 'known' user and use the display name.
|
||||
function AddExtraAddressProcessing(emailAddress, addressNode)
|
||||
function UpdateEmailNodeDetails(aEmailAddress, aDocumentNode, aCardDetails)
|
||||
{
|
||||
if (!gShowCondensedEmailAddresses)
|
||||
return;
|
||||
// If we haven't been given specific details, search for a card.
|
||||
var cardDetails = aCardDetails || GetCardForEmail(aEmailAddress);
|
||||
aDocumentNode.cardDetails = cardDetails;
|
||||
|
||||
var condense = gShowCondensedEmailAddresses;
|
||||
// Get the id of the mail-multi-emailHeaderField binding parent.
|
||||
var parentElementId = addressNode.parentNode.parentNode.parentNode.id;
|
||||
var parentElementId = aDocumentNode.parentNode.parentNode.parentNode.id;
|
||||
// Don't condense the address for the from and reply-to fields.
|
||||
// Ids: "collapsedfromValue", "expandedfromBox", "expandedreply-toBox".
|
||||
if (/^(collapsedfromValue|expanded(from|reply-to)Box)$/.test(parentElementId))
|
||||
return;
|
||||
condense = false;
|
||||
|
||||
// TODO: Maybe do domain matches too (i.e. any email from someone in my
|
||||
// company should use the friendly display name).
|
||||
var displayName = "";
|
||||
if (condense && cardDetails.card)
|
||||
displayName = cardDetails.card.displayName;
|
||||
|
||||
var card = getCardForAddress(emailAddress);
|
||||
if (!(card && card.displayName))
|
||||
return;
|
||||
if (displayName)
|
||||
{
|
||||
aDocumentNode.setAttribute("tooltiptext", aEmailAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
aDocumentNode.removeAttribute("tooltiptext");
|
||||
displayName = aDocumentNode.getAttribute("fullAddress") ||
|
||||
aDocumentNode.getAttribute("displayName");
|
||||
}
|
||||
|
||||
addressNode.setAttribute("label", card.displayName);
|
||||
addressNode.setAttribute("tooltiptext", emailAddress);
|
||||
aDocumentNode.setAttribute("label", displayName);
|
||||
}
|
||||
|
||||
function fillEmailAddressPopup(emailAddressNode)
|
||||
function UpdateExtraAddressProcessing(aAddressData, aDocumentNode, aAction,
|
||||
aParentDir, aItem)
|
||||
{
|
||||
switch (aAction)
|
||||
{
|
||||
case nsIAbListener.itemChanged:
|
||||
if (aAddressData &&
|
||||
aDocumentNode.cardDetails.card &&
|
||||
aItem.hasEmailAddress(aAddressData.emailAddress)) {
|
||||
aDocumentNode.cardDetails.card = aItem;
|
||||
UpdateEmailNodeDetails(aAddressData.emailAddress, aDocumentNode,
|
||||
aDocumentNode.cardDetails);
|
||||
}
|
||||
break;
|
||||
case nsIAbListener.itemAdded:
|
||||
// Is it a new address book?
|
||||
if (aItem instanceof nsIAbDirectory)
|
||||
{
|
||||
// If we don't have a match, search again for updates (e.g. a interface
|
||||
// to an existing book may just have been added).
|
||||
if (!aDocumentNode.cardDetails.card)
|
||||
UpdateEmailNodeDetails(aAddressData.emailAddress, aDocumentNode);
|
||||
}
|
||||
else if (aItem instanceof nsIAbCard)
|
||||
{
|
||||
// If we don't have a card, does this new one match?
|
||||
if (!aDocumentNode.cardDetails.card &&
|
||||
aItem.hasEmailAddress(aAddressData.emailAddress))
|
||||
{
|
||||
// Just in case we have a bogus parent directory.
|
||||
if (aParentDir instanceof nsIAbDirectory)
|
||||
{
|
||||
let cardDetails = { book: aParentDir, card: aItem };
|
||||
UpdateEmailNodeDetails(aAddressData.emailAddress, aDocumentNode,
|
||||
cardDetails);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateEmailNodeDetails(aAddressData.emailAddress, aDocumentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nsIAbListener.directoryItemRemoved:
|
||||
// Unfortunately we don't necessarily get the same card object back.
|
||||
if (aAddressData &&
|
||||
aDocumentNode.cardDetails.card &&
|
||||
aDocumentNode.cardDetails.book == aParentDir &&
|
||||
aItem.hasEmailAddress(aAddressData.emailAddress))
|
||||
{
|
||||
UpdateEmailNodeDetails(aAddressData.emailAddress, aDocumentNode);
|
||||
}
|
||||
break;
|
||||
case nsIAbListener.directoryRemoved:
|
||||
if (aDocumentNode.cardDetails.book == aItem)
|
||||
UpdateEmailNodeDetails(aAddressData.emailAddress, aDocumentNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function SetupEmailAddressPopup(aAddressNode)
|
||||
{
|
||||
document.getElementById("emailAddressPlaceHolder")
|
||||
.setAttribute("label", emailAddressNode.getAttribute("emailAddress"));
|
||||
.setAttribute("label", aAddressNode.getAttribute("emailAddress"));
|
||||
|
||||
var addItem = document.getElementById("addToAddressBookItem");
|
||||
var editItem = document.getElementById("editContactItem");
|
||||
var viewItem = document.getElementById("viewContactItem");
|
||||
|
||||
if (aAddressNode.cardDetails.card)
|
||||
{
|
||||
addItem.setAttribute("hidden", true);
|
||||
if (!aAddressNode.cardDetails.book.readOnly)
|
||||
{
|
||||
editItem.removeAttribute("hidden");
|
||||
viewItem.setAttribute("hidden", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
editItem.setAttribute("hidden", true);
|
||||
viewItem.removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addItem.removeAttribute("hidden");
|
||||
editItem.setAttribute("hidden", true);
|
||||
viewItem.setAttribute("hidden", true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a card matching the given address, or |null|.
|
||||
* Searches all (searchable) address books, until a (first) card is found.
|
||||
* Returns an object with two properties, book and card. If the email address
|
||||
* is found in the address books, then book will contain an nsIAbDirectory,
|
||||
* and card will contain an nsIAbCard. If the email address is not found, both
|
||||
* properties will be null.
|
||||
*
|
||||
* @param emailAddress The email address to find.
|
||||
* @return A card, or |null|.
|
||||
* @return An object with two properties, book and card.
|
||||
* @see nsIAbDirectory.cardForEmailAddress()
|
||||
*/
|
||||
function getCardForAddress(emailAddress)
|
||||
function GetCardForEmail(aEmailAddress)
|
||||
{
|
||||
var books = Components.classes["@mozilla.org/abmanager;1"]
|
||||
.getService(Components.interfaces.nsIAbManager)
|
||||
.directories;
|
||||
while (books.hasMoreElements())
|
||||
|
||||
var result = { book: null, card: null};
|
||||
|
||||
while (!result.card && books.hasMoreElements())
|
||||
{
|
||||
var ab = books.getNext();
|
||||
if (ab instanceof Components.interfaces.nsIAbDirectory)
|
||||
if (ab instanceof nsIAbDirectory)
|
||||
{
|
||||
try
|
||||
{
|
||||
var card = ab.cardForEmailAddress(emailAddress);
|
||||
var card = ab.cardForEmailAddress(aEmailAddress);
|
||||
if (card)
|
||||
return card;
|
||||
{
|
||||
result.book = ab;
|
||||
result.card = card;
|
||||
}
|
||||
}
|
||||
catch (ex)
|
||||
{
|
||||
|
@ -1147,7 +1316,7 @@ function getCardForAddress(emailAddress)
|
|||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,20 +50,34 @@
|
|||
</menupopup>
|
||||
|
||||
<menupopup id="emailAddressPopup" popupanchor="bottomleft"
|
||||
onpopupshowing="fillEmailAddressPopup(document.popupNode);
|
||||
goUpdateCommand('cmd_createFilterFromPopup');">
|
||||
onpopupshowing="SetupEmailAddressPopup(document.popupNode);
|
||||
goUpdateCommand('cmd_createFilterFromPopup');">
|
||||
<menuitem id="emailAddressPlaceHolder" label="" disabled="true"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&SendMailTo.label;"
|
||||
<menuitem id="sendMailToItem"
|
||||
label="&SendMailTo.label;"
|
||||
accesskey="&SendMailTo.accesskey;"
|
||||
oncommand="SendMailToNode(document.popupNode)"/>
|
||||
<menuitem label="&CreateFilterFrom.label;"
|
||||
<menuitem id="createFilterFromItem"
|
||||
label="&CreateFilterFrom.label;"
|
||||
accesskey="&CreateFilterFrom.accesskey;"
|
||||
command="cmd_createFilterFromPopup"/>
|
||||
<menuitem label="&AddToAddressBook.label;"
|
||||
<menuitem id="addToAddressBookItem"
|
||||
label="&AddToAddressBook.label;"
|
||||
accesskey="&AddToAddressBook.accesskey;"
|
||||
oncommand="AddNodeToAddressBook(document.popupNode)"/>
|
||||
<menuitem label="&CopyEmailAddress.label;"
|
||||
oncommand="AddContact(document.popupNode);"/>
|
||||
<menuitem id="editContactItem"
|
||||
label="&EditContact.label;"
|
||||
accesskey="&EditContact.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="EditContact(document.popupNode);"/>
|
||||
<menuitem id="viewContactItem"
|
||||
label="&ViewContact.label;"
|
||||
accesskey="&ViewContact.accesskey;"
|
||||
hidden="true"
|
||||
oncommand="EditContact(document.popupNode);"/>
|
||||
<menuitem id="copyEmailAddressItem"
|
||||
label="&CopyEmailAddress.label;"
|
||||
accesskey="&CopyEmailAddress.accesskey;"
|
||||
oncommand="CopyEmailAddress(document.popupNode)"/>
|
||||
</menupopup>
|
||||
|
|
Загрузка…
Ссылка в новой задаче