Bug 1558565 - Refactor the folder-menupopup code; r=mkmelin

Before modifying it to support folder-panelview.
This commit is contained in:
Paul Morris 2019-06-07 21:57:59 -04:00
Родитель 579984d519
Коммит 3e4f109ec7
1 изменённых файлов: 311 добавлений и 290 удалений

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

@ -6,8 +6,7 @@
/* globals MozElements */
// This is loaded into all XUL windows. Wrap in a block to prevent
// leaking to window scope.
// Wrap in a block to prevent leaking to window scope.
{
const { FeedUtils } = ChromeUtils.import("resource:///modules/FeedUtils.jsm");
const { allAccountsSorted, folderNameCompare, getSpecialFolderString, getMostRecentFolders } =
@ -109,7 +108,7 @@
// Folders that can be searched.
search(folder) {
if (!folder.server.canSearchMessages ||
folder.getFlag(Ci.nsMsgFolderFlags.Virtual)) {
folder.getFlag(Ci.nsMsgFolderFlags.Virtual)) {
return false;
}
return true;
@ -118,8 +117,8 @@
// Folders that can subscribe feeds.
feeds(folder) {
if (folder.server.type != "rss" ||
folder.getFlag(Ci.nsMsgFolderFlags.Trash) ||
folder.getFlag(Ci.nsMsgFolderFlags.Virtual)) {
folder.getFlag(Ci.nsMsgFolderFlags.Trash) ||
folder.getFlag(Ci.nsMsgFolderFlags.Virtual)) {
return false;
}
return true;
@ -157,7 +156,15 @@
menu._teardown();
}
},
OnItemAdded(RDFParentItem, item) {
_setCssSelectorsForItem(item) {
const child = this._getChildForItem(item);
if (child) {
this._menu._setCssSelectors(child._folder, child);
}
},
_itemAddedOrRemoved(item) {
if (!(item instanceof Ci.nsIMsgFolder)) {
return;
}
@ -168,15 +175,11 @@
this._clearMenu(this._menu);
},
OnItemRemoved(RDFParentItem, item) {
if (!(item instanceof Ci.nsIMsgFolder)) {
return;
}
if (this._filterFunction && !this._filterFunction(item)) {
return;
}
// xxx we can optimize this later.
this._clearMenu(this._menu);
OnItemAdded(ParentItem, item) {
this._itemAddedOrRemoved(item);
},
OnItemRemoved(ParentItem, item) {
this._itemAddedOrRemoved(item);
},
// xxx I stole this listener list from nsMsgFolderDatasource.cpp, but
@ -187,47 +190,38 @@
if (item instanceof Ci.nsIMsgFolder) {
if (property == "FolderFlag") {
if (this._menu.getAttribute("showFavorites") != "true" ||
!this._menu._initializedSpecials.has("favorites")) {
!this._menu._initializedSpecials.has("favorites")) {
return;
}
if ((old & Ci.nsMsgFolderFlags.Favorite) !=
(aNew & Ci.nsMsgFolderFlags.Favorite)) {
(aNew & Ci.nsMsgFolderFlags.Favorite)) {
setTimeout(this._clearMenu, 0, this._menu);
}
}
}
let child = this._getChildForItem(item);
if (child) {
this._menu._setCssSelectors(child._folder, child);
}
this._setCssSelectorsForItem(item);
},
OnItemBoolPropertyChanged(item, property, old, newItem) {
let child = this._getChildForItem(item);
if (child) {
this._menu._setCssSelectors(child._folder, child);
}
this._setCssSelectorsForItem(item);
},
OnItemUnicharPropertyChanged(item, property, old, newItem) {
let child = this._getChildForItem(item);
if (child) {
this._menu._setCssSelectors(child._folder, child);
}
this._setCssSelectorsForItem(item);
},
OnItemPropertyFlagChanged(item, property, old, newItem) { },
OnItemEvent(folder, event) {
if (event == "MRMTimeChanged") {
OnItemEvent(folder, eventName) {
if (eventName == "MRMTimeChanged") {
if (this._menu.getAttribute("showRecent") != "true" ||
!this._menu._initializedSpecials.has("recent") ||
!this._menu.firstChild || !this._menu.firstChild.firstChild) {
!this._menu._initializedSpecials.has("recent") ||
!this._menu.firstChild || !this._menu.firstChild.firstChild) {
return;
}
// If this folder is already in the recent menu, return.
if (this._getChildForItem(folder,
this._menu.firstChild.firstChild)) {
this._menu.firstChild.firstChild)) {
return;
}
} else if (event == "RenameCompleted") {
} else if (eventName == "RenameCompleted") {
// Special casing folder renames here, since they require more work
// since sort-order may have changed.
if (!this._getChildForItem(folder)) {
@ -244,10 +238,10 @@
* Helper function to check and see whether we have a menuitem for this
* particular nsIMsgFolder.
*
* @param {nsIMsgFolder} item - the folder to check
* @param {Menu} - (optional) menu to look in, defaults to this._menu.
* @returns {Menuitem|null} - if no child for that folder exists, otherwise the
* menuitem for that child.
* @param {nsIMsgFolder} item The folder to check.
* @param {Element} [menu] Optional menu to look in, defaults to this._menu.
* @returns {Element|null} The menuitem for that folder, or null if no
* child for that folder exists.
*/
_getChildForItem(item, menu) {
let _menu = menu || this._menu;
@ -267,7 +261,7 @@
},
};
// True if we have already built our menu-items and are now just
// True if we have already built our menu items and are now just
// listening for changes.
this._initialized = false;
@ -275,6 +269,7 @@
// E.g. "recent", "favorites".
this._initializedSpecials = new Set();
// The format for displaying names of folders.
this._displayformat = null;
}
@ -346,7 +341,7 @@
/**
* Make sure we remove our listener when the window is being destroyed
* or the widget teared down.
* or the widget torn down.
*/
_removeListener() {
if (!this._initialized) {
@ -356,32 +351,31 @@
}
/**
* Call this if you are unsure whether the menu-items have been built,
* but know that they need to be built now if they haven't.
* Call this if you do not know whether the menu items have been built,
* but know that they need to be built now if they haven't been yet.
*/
_ensureInitialized() {
if (this._initialized) {
return;
}
let folders;
// Figure out which folders to build. If we don't have a parent, then
// we assume we should build the top-level accounts. (Actually we
// build the fake root folders for those accounts.)
if (!this._parentFolder) {
let accounts = allAccountsSorted(true);
// The excludeServers attribute is a comma separated list of server keys.
const excludeServers = this.hasAttribute("excludeServers") ?
this.getAttribute("excludeServers").split(",") : [];
// Now generate our folder-list. Note that we'll special case this
// situation below, to avoid destroying the sort order we just made.
folders = accounts.map(acct => acct.incomingServer.rootFolder);
} else {
// If we do have a parent folder, then we just build based on those
// subFolders for that parent.
folders = toArray(fixIterator(this._parentFolder.subFolders,
Ci.nsIMsgFolder));
}
// Extensions and other consumers can add to these modes too, see the
// note on the _filters field. (Note: empty strings ("") are falsy in JS.)
const mode = this.getAttribute("mode");
const filterFunction = mode ? this._filters[mode] : (folder) => true;
const folders = this._getFolders(this._parentFolder, excludeServers,
(mode ? filterFunction : null));
this._listener._filterFunction = filterFunction;
this._build(folders, mode);
this._build(folders);
// Lastly, we add a listener to get notified of changes in the folder
// structure.
MailServices.mailSession.AddFolderListener(this._listener,
@ -391,109 +385,54 @@
}
/**
* Actually constructs the menu-items based on the folders given.
* Get the folders that will appear in the menu.
*
* @param [nsIMsgFolder] inputFolders - An array of nsIMsgFolders to use for building.
* @param {Element} parentFolder The parent menu popup/view element.
* @param {string[]} excludeServers Server keys for the servers to exclude.
* @param {Function} [filterFunction] Function for filtering the folders.
*/
// eslint-disable-next-line complexity
_build(inputFolders) {
_getFolders(parentFolder, excludeServers, filterFunction) {
let folders;
let excludeServers = [];
let disableServers = [];
// excludeServers attribute is a comma separated list of server keys.
if (this.hasAttribute("excludeServers")) {
excludeServers = this.getAttribute("excludeServers").split(",");
}
// disableServers attribute is a comma separated list of server keys.
if (this.hasAttribute("disableServers")) {
disableServers = this.getAttribute("disableServers").split(",");
}
// Extensions and other consumers can add to these modes too, see the
// above note on the _filters field.
let mode = this.getAttribute("mode");
if (mode && mode != "") {
let filterFunction = this._filters[mode];
folders = inputFolders.filter(filterFunction);
this._listener._filterFunction = filterFunction;
// If we have a parent folder, just get the subFolders for that parent.
if (parentFolder) {
folders = toArray(fixIterator(parentFolder.subFolders,
Ci.nsIMsgFolder));
} else {
folders = inputFolders;
this._listener._filterFunction = function(folder) {
return true;
};
// If we don't have a parent, then we assume we should build the
// top-level accounts. (Actually we build the fake root folders for
// those accounts.)
let accounts = allAccountsSorted(true);
// Now generate our folder list. Note that we'll special case this
// situation elsewhere, to avoid destroying the sort order we just made.
folders = accounts.map(acct => acct.incomingServer.rootFolder);
}
if (filterFunction) {
folders = folders.filter(filterFunction);
}
if (excludeServers.length > 0) {
folders = folders.filter(function(aFolder) {
return !excludeServers.includes(aFolder.server.key);
});
}
// This code block will do the following: Add a menu item that refers
// back to the parent folder when there is a showFileHereLabel
// attribute or no mode attribute. However the code won't add such a
// menu item if one of the following conditions is met:
// (-) There is no parent folder.
// (-) Folder is server and showAccountsFileHere is explicitly false.
// (-) Current folder has a mode, the parent folder can be selected,
// no messages can be filed into the parent folder (e.g. when the
// parent folder is a news group or news server) and the folder
// mode is not equal to newFolder.
// The menu item will have the value of the fileHereLabel attribute as
// label or if the attribute does not exist the name of the parent
// folder instead.
let parent = this._parentFolder;
if (parent && (this.getAttribute("showFileHereLabel") == "true" || !mode)) {
let showAccountsFileHere = this.getAttribute("showAccountsFileHere");
if ((!parent.isServer || showAccountsFileHere != "false") &&
(!mode || mode == "newFolder" || parent.noSelect ||
parent.canFileMessages || showAccountsFileHere == "true")) {
let menuitem = document.createXULElement("menuitem");
menuitem._folder = this._parentFolder;
menuitem.setAttribute("generated", "true");
if (this.hasAttribute("fileHereLabel")) {
menuitem.setAttribute("label", this.getAttribute("fileHereLabel"));
menuitem.setAttribute("accesskey", this.getAttribute("fileHereAccessKey"));
} else {
menuitem.setAttribute("label", this._parentFolder.prettyName);
menuitem.setAttribute("class", "folderMenuItem menuitem-iconic");
this._setCssSelectors(this._parentFolder, menuitem);
}
// Eww. have to support some legacy code here.
menuitem.setAttribute("id", this._parentFolder.URI);
this.appendChild(menuitem);
if (this._parentFolder.noSelect) {
menuitem.setAttribute("disabled", "true");
}
let sep = document.createXULElement("menuseparator");
sep.setAttribute("generated", "true");
this.appendChild(sep);
}
folders = folders.filter(folder =>
!excludeServers.includes(folder.server.key));
}
return folders;
}
/**
* Actually constructs the menu items based on the folders given.
*
* @param {nsIMsgFolder[]} folders An array of nsIMsgFolders to use for building.
* @param {string} [mode] The filtering mode. See comment on _filters field.
*/
_build(folders, mode) {
let globalInboxFolder = null;
// See if this is the toplevel menu (usually with accounts).
if (!this._parentFolder) {
let addSeparator = false;
this._addTopLevelMenuItems();
// Some menus want a "Recent" option, but that should only be on our
// top-level menu.
if (this.getAttribute("showRecent") == "true") {
this._buildSpecialMenu("recent");
addSeparator = true;
}
if (this.getAttribute("showFavorites") == "true") {
this._buildSpecialMenu("favorites");
addSeparator = true;
}
if (addSeparator) {
// If we added Recent and/or Favorites, separate them from the rest of the items.
let sep = document.createXULElement("menuseparator");
sep.setAttribute("generated", "true");
this.appendChild(sep);
}
// If we are showing the accounts for deferring, move Local Folders to the top.
if (mode == "deferred") {
globalInboxFolder = MailServices.accounts.localFoldersServer
@ -509,146 +448,57 @@
// folders belong. Since that sorting was already done, we don't need
// to do anything for that case here.
} else {
// Sorts the list of folders. We give first priority to the sortKey
this._maybeAddParentFolderMenuItem(mode);
// Sort the list of folders. We give first priority to the sortKey
// property if it is available, otherwise a case-insensitive
// comparison of names.
folders = folders.sort((a, b) => a.compareSortKeys(b));
}
// In some cases, the user wants to have a list of subfolders for only
// some account types (or maybe all of them). So we use this to
// determine what the user wanted.
let shouldExpand;
let labels = null;
if (this.getAttribute("expandFolders") == "true" ||
!this.hasAttribute("expandFolders")) {
shouldExpand = () => true;
} else if (this.getAttribute("expandFolders") == "false") {
shouldExpand = () => false;
} else {
// We want a subfolder list for only some servers. We also may need
// to create headers to select the servers. If so, then headlabels
// is a comma-delimited list of labels corresponding to the server
// types specified in expandFolders.
let types = this.getAttribute("expandFolders").split(/ *, */);
// Set the labels. labels[type] = label
if (this.hasAttribute("headlabels")) {
let labelNames = this.getAttribute("headlabels").split(/ *, */);
labels = {};
// If the length isn't equal, don't give them any of the labels,
// since any combination will probably be wrong.
if (labelNames.length == types.length) {
for (let index in types) {
labels[types[index]] = labelNames[index];
}
}
}
shouldExpand = (e) => types.includes(e);
this._addFoldersMenuItems(folders, mode, globalInboxFolder);
}
/**
* Add menu items that only appear at top level, like "Recent".
*/
_addTopLevelMenuItems() {
const showRecent = this.getAttribute("showRecent") == "true";
const showFavorites = this.getAttribute("showFavorites") == "true";
if (showRecent) {
this.appendChild(this._buildSpecialMenu("recent"));
}
// We need to call this, or hasSubFolders will always return false.
// Remove this workaround when Bug 502900 is fixed.
MailUtils.discoverFolders();
this._serversOnly = true;
for (let folder of folders) {
let node;
if (!folder.isServer) {
this._serversOnly = false;
}
// If we're going to add subFolders, we need to make menus, not
// menuitems.
if (!folder.hasSubFolders || !shouldExpand(folder.server.type)) {
node = document.createXULElement("menuitem");
// Grumble, grumble, legacy code support
node.setAttribute("id", folder.URI);
node.setAttribute("class", "folderMenuItem menuitem-iconic");
node.setAttribute("generated", "true");
this.appendChild(node);
} else {
this._serversOnly = false;
// xxx this is slightly problematic in that we haven't confirmed
// whether any of the subfolders will pass the filter.
node = document.createXULElement("menu");
node.setAttribute("class", "folderMenuItem menu-iconic");
node.setAttribute("generated", "true");
this.appendChild(node);
// Create the submenu.
let popup = document.createXULElement("menupopup", { "is": "folder-menupopup" });
popup._parentFolder = folder;
popup.setAttribute("class", this.getAttribute("class"));
popup.setAttribute("type", this.getAttribute("type"));
if (this.hasAttribute("fileHereLabel")) {
popup.setAttribute("fileHereLabel",
this.getAttribute("fileHereLabel"));
}
popup.setAttribute("showFileHereLabel",
this.getAttribute("showFileHereLabel"));
popup.setAttribute("oncommand",
this.getAttribute("oncommand"));
popup.setAttribute("mode",
this.getAttribute("mode"));
if (this.hasAttribute("disableServers")) {
popup.setAttribute("disableServers",
this.getAttribute("disableServers"));
}
if (this.hasAttribute("position")) {
popup.setAttribute("position",
this.getAttribute("position"));
}
// If there are labels, add the labels now.
if (labels) {
let serverNode = document.createXULElement("menuitem");
serverNode.setAttribute("label", labels[folder.server.type]);
serverNode._folder = folder;
serverNode.setAttribute("generated", "true");
popup.appendChild(serverNode);
let sep = document.createXULElement("menuseparator");
sep.setAttribute("generated", "true");
popup.appendChild(sep);
}
popup.setAttribute("generated", "true");
node.appendChild(popup);
}
if (disableServers.includes(folder.server.key)) {
node.setAttribute("disabled", "true");
}
node._folder = folder;
let label = "";
if (mode == "deferred" && folder.isServer &&
folder.server.rootFolder == globalInboxFolder) {
label = this._stringBundle.get("globalInbox", [folder.prettyName]);
} else {
label = folder.prettyName;
}
node.setAttribute("label", label);
this._setCssSelectors(folder, node);
if (showFavorites) {
this.appendChild(this._buildSpecialMenu("favorites"));
}
if (showRecent || showFavorites) {
// If we added Recent and/or Favorites, separate them from the rest of the items.
const sep = document.createXULElement("menuseparator");
sep.setAttribute("generated", "true");
this.appendChild(sep);
}
}
/**
* This only builds the menu item in the top-level menulist.
* The real submenu will be created once the popup is really shown,
* This only creates the menu item (or toolbarbutton) in the top-level
* menulist. The submenu is created once the popup is really shown,
* via the _buildSpecialSubmenu method.
*
* @param {string} type - the type of the special menu to build.
* @param {string} type Type of special menu (e.g. "recent", "favorites").
* @return {Element} The `menu` or `toolbarbutton` element.
*/
_buildSpecialMenu(type) {
// Now create the Recent folder and its children.
// Now create the Recent folder menu and its children.
let menu = document.createXULElement("menu");
if (type == "recent") {
menu.setAttribute("label", this.getAttribute("recentLabel"));
menu.setAttribute("accesskey", this.getAttribute("recentAccessKey"));
} else {
menu.setAttribute("label", this.getAttribute("favoritesLabel"));
menu.setAttribute("accesskey", this.getAttribute("favoritesAccessKey"));
}
menu.setAttribute("special", type);
menu.setAttribute("label", this.getAttribute((type == "recent") ?
"recentLabel" : "favoritesLabel"));
menu.setAttribute("accesskey", this.getAttribute((type == "recent") ?
"recentAccessKey" : "favoritesAccessKey"));
menu.setAttribute("generated", "true");
let popup = document.createXULElement("menupopup");
@ -658,14 +508,14 @@
}, { once: true });
menu.appendChild(popup);
this.appendChild(menu);
return menu;
}
/**
* Builds a submenu with all of the recently used folders in it, to
* allow for easy access.
*
* @param {Menu} menu - the menu for which one wants to build the special sub menu.
* @param {Element} menu The menu element for which one wants to build the special sub menu.
*/
_buildSpecialSubmenu(menu) {
let specialType = menu.getAttribute("special");
@ -694,10 +544,10 @@
// Cache the pretty names so that they do not need to be fetched
// _MAXRECENT^2 times later.
let specialFoldersMap = specialFolders.map(function(f) {
let specialFoldersMap = specialFolders.map(folder => {
return {
folder: f,
name: f.prettyName,
folder,
name: folder.prettyName,
};
});
@ -751,12 +601,184 @@
this._initializedSpecials.add(specialType);
}
/**
* Add a menu item that refers back to the parent folder when there is a
* showFileHereLabel attribute or no mode attribute. However don't
* add such a menu item if one of the following conditions is met:
* (-) There is no parent folder.
* (-) Folder is server and showAccountsFileHere is explicitly false.
* (-) Current folder has a mode, the parent folder can be selected,
* no messages can be filed into the parent folder (e.g. when the
* parent folder is a news group or news server) and the folder
* mode is not equal to newFolder.
* The menu item will have the value of the fileHereLabel attribute as
* label or if the attribute does not exist the name of the parent
* folder instead.
*
* @param {string} mode The mode attribute.
*/
_maybeAddParentFolderMenuItem(mode) {
let parent = this._parentFolder;
if (parent && (this.getAttribute("showFileHereLabel") == "true" || !mode)) {
let showAccountsFileHere = this.getAttribute("showAccountsFileHere");
if ((!parent.isServer || showAccountsFileHere != "false") &&
(!mode || mode == "newFolder" || parent.noSelect ||
parent.canFileMessages || showAccountsFileHere == "true")) {
let menuitem = document.createXULElement("menuitem");
menuitem._folder = parent;
menuitem.setAttribute("generated", "true");
if (this.hasAttribute("fileHereLabel")) {
menuitem.setAttribute("label", this.getAttribute("fileHereLabel"));
menuitem.setAttribute("accesskey", this.getAttribute("fileHereAccessKey"));
} else {
menuitem.setAttribute("label", parent.prettyName);
menuitem.setAttribute("class", "folderMenuItem menuitem-iconic");
this._setCssSelectors(parent, menuitem);
}
this.appendChild(menuitem);
if (parent.noSelect) {
menuitem.setAttribute("disabled", "true");
}
let sep = document.createXULElement("menuseparator");
sep.setAttribute("generated", "true");
this.appendChild(sep);
}
}
}
/**
* Add menu items, one for each folder.
*
* @param {nsIMsgFolder[]} folders Array of folder objects.
* @param {string} mode The mode attribute.
* @param {nsIMsgFolder} globalInboxFolder The root/global inbox folder.
*/
_addFoldersMenuItems(folders, mode, globalInboxFolder) {
// disableServers attribute is a comma separated list of server keys.
const disableServers = this.hasAttribute("disableServers") ?
this.getAttribute("disableServers").split(",") : [];
// We need to call this, or hasSubFolders will always return false.
// Remove this workaround when Bug 502900 is fixed.
MailUtils.discoverFolders();
this._serversOnly = true;
let [shouldExpand, labels] = this._getShouldExpandAndLabels();
for (let folder of folders) {
let node;
if (!folder.isServer) {
this._serversOnly = false;
}
// If we're going to add subFolders, we need to make menus, not
// menuitems.
if (!folder.hasSubFolders || !shouldExpand(folder.server.type)) {
node = document.createXULElement("menuitem");
node.setAttribute("class", "folderMenuItem menuitem-iconic");
node.setAttribute("generated", "true");
this.appendChild(node);
} else {
this._serversOnly = false;
// xxx this is slightly problematic in that we haven't confirmed
// whether any of the subfolders will pass the filter.
node = document.createXULElement("menu");
node.setAttribute("class", "folderMenuItem menu-iconic");
node.setAttribute("generated", "true");
this.appendChild(node);
// Create the submenu.
let popup = document.createXULElement("menupopup", { "is": "folder-menupopup" });
popup._parentFolder = folder;
["class", "type", "fileHereLabel", "showFileHereLabel", "oncommand",
"mode", "disableServers", "position"].forEach(attribute => {
if (this.hasAttribute(attribute)) {
popup.setAttribute(attribute, this.getAttribute(attribute));
}
});
// If there are labels, add the labels now.
if (labels) {
let serverNode = document.createXULElement("menuitem");
serverNode.setAttribute("label", labels[folder.server.type]);
serverNode._folder = folder;
serverNode.setAttribute("generated", "true");
popup.appendChild(serverNode);
let sep = document.createXULElement("menuseparator");
sep.setAttribute("generated", "true");
popup.appendChild(sep);
}
popup.setAttribute("generated", "true");
node.appendChild(popup);
}
if (disableServers.includes(folder.server.key)) {
node.setAttribute("disabled", "true");
}
node._folder = folder;
let label = "";
if (mode == "deferred" && folder.isServer &&
folder.server.rootFolder == globalInboxFolder) {
label = this._stringBundle.get("globalInbox", [folder.prettyName]);
} else {
label = folder.prettyName;
}
node.setAttribute("label", label);
this._setCssSelectors(folder, node);
}
}
/**
* Let the user have a list of subfolders for all account types, none of
* them, or only some of them. Returns an array containing a function that
* determines whether to show subfolders for a given account type, and an
* object mapping account types to label names (may be null).
*
* @return {[Function, Object|null]} Array containing the shouldExpand
* function and the labels object.
*/
_getShouldExpandAndLabels() {
let shouldExpand;
let labels = null;
if (this.getAttribute("expandFolders") == "true" ||
!this.hasAttribute("expandFolders")) {
shouldExpand = () => true;
} else if (this.getAttribute("expandFolders") == "false") {
shouldExpand = () => false;
} else {
// We want a subfolder list for only some servers. We also may need
// to create headers to select the servers. If so, then headlabels
// is a comma-delimited list of labels corresponding to the server
// types specified in expandFolders.
let types = this.getAttribute("expandFolders").split(/ *, */);
// Set the labels. labels[type] = label
if (this.hasAttribute("headlabels")) {
let labelNames = this.getAttribute("headlabels").split(/ *, */);
labels = {};
// If the length isn't equal, don't give them any of the labels,
// since any combination will probably be wrong.
if (labelNames.length == types.length) {
for (let index in types) {
labels[types[index]] = labelNames[index];
}
}
}
shouldExpand = (e) => types.includes(e);
}
return [shouldExpand, labels];
}
/**
* This function adds attributes on menu/menuitems to make it easier for
* css to style them.
*
* @param {nsIMsgFolder} folder - the folder that corresponds to the menu/menuitem
* @param {Menu} menuNode - the actual DOM node to set attributes on
* @param {nsIMsgFolder} folder The folder that corresponds to the menu/menuitem.
* @param {Element} menuNode The actual DOM node to set attributes on.
*/
_setCssSelectors(folder, menuNode) {
// First set the SpecialFolder attribute.
@ -765,8 +787,7 @@
// Now set the biffState.
let biffStates = ["NewMail", "NoMail", "UnknownMail"];
for (let state of biffStates) {
if (folder.biffState ==
Ci.nsIMsgFolder["nsMsgBiffState_" + state]) {
if (folder.biffState == Ci.nsIMsgFolder["nsMsgBiffState_" + state]) {
menuNode.setAttribute("BiffState", state);
break;
}
@ -786,8 +807,8 @@
* 'verbose' - Folder on Account
* 'path' - Account/Folder/Subfolder
*
* @param {nsIMsgFolder} folder - the folder that corresponds to the menu/menuitem
* @return {string} - display name
* @param {nsIMsgFolder} folder The folder that corresponds to the menu/menuitem.
* @return {string} The display name.
*/
getDisplayName(folder) {
if (folder.isServer) {
@ -809,8 +830,8 @@
/**
* Makes a given folder selected.
*
* @param {nsIMsgFolder} inputFolder - the folder to select (if none, then Choose Folder)
* @return {boolean} - true if any usable folder was found, otherwise false.
* @param {nsIMsgFolder} inputFolder The folder to select (if none, then Choose Folder).
* @return {boolean} Is true if any usable folder was found, otherwise false.
* @note If inputFolder is not in this popup, but is instead a descendant of
* a member of the popup, that ancestor will be selected.
*/
@ -845,9 +866,9 @@
if (inputFolder) {
for (let child of this.childNodes) {
if (child && child._folder && !child.disabled &&
(child._folder.URI == inputFolder.URI ||
(child.tagName == "menu" &&
child._folder.isAncestorOf(inputFolder)))) {
(child._folder.URI == inputFolder.URI ||
(child.tagName == "menu" &&
child._folder.isAncestorOf(inputFolder)))) {
if (child._folder.URI == inputFolder.URI) {
this.parentNode.selectedItem = child;
}
@ -878,7 +899,7 @@
}
/**
* Removes all menu-items for this popup, resets all fields, and
* Removes all menu items for this popup, resets all fields, and
* removes the listener. This function is invoked when a change
* that affects this menu is detected by our listener.
*/