Bug 1609647 - Add 'Move to To/Cc/Bcc' to recipient pill context menu. r=mkmelin

This commit is contained in:
Alessandro Castellani 2020-02-18 12:03:52 -08:00
Родитель 0f670b6839
Коммит 0679539d04
5 изменённых файлов: 186 добавлений и 22 удалений

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

@ -2199,6 +2199,7 @@
* @param {HTMLElement} element - The original autocomplete input that
* generated the pill.
* @param {Array} address - The array containing the recipient's info.
* @return {Element} The newly created pill.
*/
createRecipientPill(element, address) {
let pill = document.createXULElement("mail-address-pill");
@ -2243,6 +2244,14 @@
this.handleKeyPress(pill, event);
});
pill.addEventListener("contextmenu", event => {
// Update the context menu options only if opened via the context menu
// keyboard button.
if (event.buttons == 0) {
emailAddressPillOnPopupShown();
}
});
element.closest(".address-container").insertBefore(pill, element);
// The emailInput attribute is accessible only after the pill has been
@ -2267,6 +2276,8 @@
"autocompletesearchparam",
JSON.stringify(params)
);
return pill;
}
/**
@ -2386,10 +2397,12 @@
* @param {Event} event - The DOM Event.
*/
checkSelected(pill, event) {
if (
pill.isEditing ||
(pill.hasAttribute("selected") && event.which == 3)
) {
if (pill.isEditing) {
return;
}
if (pill.hasAttribute("selected") && event.button == 2) {
emailAddressPillOnPopupShown();
return;
}
@ -2403,6 +2416,12 @@
} else {
pill.focus();
}
// Update the options in the context menu only after the pills were
// selected and if the event was a right click.
if (event.button == 2) {
emailAddressPillOnPopupShown();
}
}
/**
@ -2450,6 +2469,33 @@
pill.startEditing();
}
/**
* Move the selected pills email address to another addressing row.
*
* @param {Element} element - The element from which the context menu was
* opened.
* @param {string} targetFieldType - The target recipient type,
* e.g. "addr_to".
*/
moveSelectedPills(element, targetFieldType) {
// Store all the selected addresses inside an array.
let selectedAddresses = [...this.getAllSelectedPills()].map(
pill => pill.fullAddress
);
// Remove all the selected pills.
let pill = element.closest("mail-address-pill");
this.removeSelectedPills(pill);
// Create new addressing pills inside the target recipient row and maintain
// the current selection.
awAddRecipientsArray(targetFieldType, selectedAddresses, true);
// Move focus to the last selected pill.
let selectedPills = this.getAllSelectedPills();
selectedPills[selectedPills.length - 1].focus();
}
/**
* Delete all selected pills and handle focus and selection smartly as needed.
*

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

@ -378,8 +378,9 @@ function awAddRecipients(msgCompFields, recipientType, recipientsList) {
*
* @param aRecipientType Type of recipient, e.g. "addr_to".
* @param aAddressArray An array of recipient addresses (strings) to add.
* @param {boolean} select - If the newly generated pills should be selected.
*/
function awAddRecipientsArray(aRecipientType, aAddressArray) {
function awAddRecipientsArray(aRecipientType, aAddressArray, select = false) {
let label = document.getElementById(aRecipientType);
let addresses = MailServices.headerParser.makeFromDisplayAddress(
aAddressArray
@ -392,7 +393,10 @@ function awAddRecipientsArray(aRecipientType, aAddressArray) {
let recipientArea = document.getElementById("recipientsContainer");
for (let address of addresses) {
recipientArea.createRecipientPill(element, address);
let pill = recipientArea.createRecipientPill(element, address);
if (select) {
pill.setAttribute("selected", "selected");
}
}
if (element.id != "replyAddrInput") {
@ -701,17 +705,14 @@ function editAddressPill(element, event) {
* opened.
*/
function copyEmailNewsAddress(element) {
let allAddresses = [];
for (let pill of document
.getElementById("recipientsContainer")
.getAllSelectedPills()) {
allAddresses.push(pill.fullAddress);
}
let selectedAddresses = [
...document.getElementById("recipientsContainer").getAllSelectedPills(),
].map(pill => pill.fullAddress);
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
Ci.nsIClipboardHelper
);
clipboard.copyString(allAddresses.join(", "));
clipboard.copyString(selectedAddresses.join(", "));
}
/**
@ -722,21 +723,103 @@ function copyEmailNewsAddress(element) {
*/
function cutEmailNewsAddress(element) {
copyEmailNewsAddress(element);
deleteAddressPill(element);
deleteSelectedPills(element);
}
/**
* Delete the selected pill(s).
*
* @param {XULElement} element - The element from which the context menu was
* @param {Element} element - The label element from which the context menu was
* opened.
*/
function deleteAddressPill(element) {
// element is the pill's <label>, get the pill.
function deleteSelectedPills(element) {
// element is the <label> of the focused pill, get the pill itself.
let pill = element.closest("mail-address-pill");
document.getElementById("recipientsContainer").removeSelectedPills(pill);
}
/**
* Handle disabling of "Move to..." context menu items according to the types
* of selected pills.
*/
function emailAddressPillOnPopupShown() {
let menu = document.getElementById("emailAddressPillPopup");
// Reset previously disabled menuitems.
for (let menuitem of menu.querySelectorAll(
".pill-action-move, .pill-action-edit"
)) {
menuitem.disabled = false;
}
// If more than one pill is selected, disable the editing item.
if (
document.getElementById("recipientsContainer").getAllSelectedPills()
.length > 1
) {
menu.querySelector("#editAddressPill").disabled = true;
}
// If Newsgroups or Followups are part of the selection, disable everything.
if (
document.querySelectorAll(
`mail-address-pill[recipienttype="addr_newsgroups"][selected]`
).length ||
document.querySelectorAll(
`mail-address-pill[recipienttype="addr_followup"][selected]`
).length
) {
for (let menuitem of menu.querySelectorAll(".pill-action-move")) {
menuitem.disabled = true;
}
return;
}
let selectedTypes = [];
// Add all the recipient types of the selected pills.
for (let row of document.querySelectorAll(".address-row:not(.hidden)")) {
if (row.querySelectorAll("mail-address-pill[selected]").length) {
selectedTypes.push(
row
.querySelector(`input[is="autocomplete-input"][recipienttype]`)
.getAttribute("recipienttype")
);
}
}
// Interrupt if more than one type is selected.
if (selectedTypes.length > 1) {
return;
}
switch (selectedTypes[0]) {
case "addr_to":
menu.querySelector("#moveAddressPillTo").disabled = true;
break;
case "addr_cc":
menu.querySelector("#moveAddressPillCc").disabled = true;
break;
case "addr_bcc":
menu.querySelector("#moveAddressPillBcc").disabled = true;
break;
}
}
/**
* Move the selected pills email address to another addressing row.
*
* @param {Element} element - The element from which the context menu was
* opened.
* @param {string} targetFieldType - The target recipient type, e.g. "addr_to".
*/
function moveSelectedPills(element, targetFieldType) {
document
.getElementById("recipientsContainer")
.moveSelectedPills(element, targetFieldType);
}
/**
* Handle the keypress event on the recipient labels for keyboard navigation and
* to show the container row of a hidden recipient (Cc, Bcc, etc.).

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

@ -57,6 +57,7 @@
<stringbundle id="charsetBundle" src="chrome://communicator/content/labelsencodings.properties"/>
<linkset>
<html:link rel="localization" href="messenger/messengercompose/messengercompose.ftl"/>
<html:link rel="localization" href="toolkit/main-window/findbar.ftl"/>
<html:link rel="localization" href="toolkit/global/textActions.ftl"/>
<html:link rel="localization" href="messenger/menubar.ftl"/>
@ -770,18 +771,33 @@
<menupopup id="emailAddressPillPopup" class="emailAddressPopup">
<menuitem id="editAddressPill" label="&editMenu.label;"
accesskey="&editMenu.accesskey;"
<menuitem id="editAddressPill"
class="pill-action-edit"
data-l10n-id="pill-action-edit"
oncommand="editAddressPill(document.popupNode, event)"/>
<menuitem id="menu_delete"
data-l10n-id="text-action-delete"
oncommand="deleteSelectedPills(document.popupNode)"/>
<menuseparator/>
<menuitem id="menu_cut"
data-l10n-id="text-action-cut"
oncommand="cutEmailNewsAddress(document.popupNode)"/>
<menuitem id="menu_copy"
data-l10n-id="text-action-copy"
oncommand="copyEmailNewsAddress(document.popupNode)"/>
<menuitem id="menu_delete"
data-l10n-id="text-action-delete"
oncommand="deleteAddressPill(document.popupNode)"/>
<menuseparator/>
<menuitem id="moveAddressPillTo"
class="pill-action-move"
data-l10n-id="pill-action-move-to"
oncommand="moveSelectedPills(document.popupNode, 'addr_to')"/>
<menuitem id="moveAddressPillCc"
class="pill-action-move"
data-l10n-id="pill-action-move-cc"
oncommand="moveSelectedPills(document.popupNode, 'addr_cc')"/>
<menuitem id="moveAddressPillBcc"
class="pill-action-move"
data-l10n-id="pill-action-move-bcc"
oncommand="moveSelectedPills(document.popupNode, 'addr_bcc')"/>
</menupopup>
#ifdef XP_MACOSX

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

@ -14,3 +14,19 @@ address-input-type = { $count ->
[one] { $type } input field with one address
*[other] { $type } input field with { $count } addresses
}
pill-action-edit =
.label = Edit Address
.accesskey = e
pill-action-move-to =
.label = Move to To
.accesskey = t
pill-action-move-cc =
.label = Move to Cc
.accesskey = c
pill-action-move-bcc =
.label = Move to Bcc
.accesskey = b

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

@ -524,6 +524,9 @@
.address-input {
color: inherit;
}
.address-container > .address-input {
padding-block: 4px;
}