summaryrefslogtreecommitdiffstats
path: root/comm/mail/extensions/mailviews
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/extensions/mailviews')
-rw-r--r--comm/mail/extensions/mailviews/content/mailViewList.js116
-rw-r--r--comm/mail/extensions/mailviews/content/mailViewList.xhtml63
-rw-r--r--comm/mail/extensions/mailviews/content/mailViewSetup.js108
-rw-r--r--comm/mail/extensions/mailviews/content/mailViewSetup.xhtml61
-rw-r--r--comm/mail/extensions/mailviews/content/msgViewPickerOverlay.js282
-rw-r--r--comm/mail/extensions/mailviews/jar.mn10
-rw-r--r--comm/mail/extensions/mailviews/moz.build6
7 files changed, 646 insertions, 0 deletions
diff --git a/comm/mail/extensions/mailviews/content/mailViewList.js b/comm/mail/extensions/mailviews/content/mailViewList.js
new file mode 100644
index 0000000000..277c74e553
--- /dev/null
+++ b/comm/mail/extensions/mailviews/content/mailViewList.js
@@ -0,0 +1,116 @@
+/* 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/. */
+
+var gMailListView;
+var gListBox;
+var gEditButton;
+var gDeleteButton;
+
+function mailViewListOnLoad() {
+ gMailListView = Cc["@mozilla.org/messenger/mailviewlist;1"].getService(
+ Ci.nsIMsgMailViewList
+ );
+ gListBox = document.getElementById("mailViewList");
+
+ // Construct list view based on current mail view list data
+ refreshListView(null);
+ gEditButton = document.getElementById("editButton");
+ gDeleteButton = document.getElementById("deleteButton");
+
+ updateButtons();
+}
+
+function refreshListView(aSelectedMailView) {
+ // remove any existing items in the view...
+ for (var index = gListBox.getRowCount(); index > 0; index--) {
+ gListBox.getItemAtIndex(index - 1).remove();
+ }
+
+ var numItems = gMailListView.mailViewCount;
+ var mailView;
+ for (index = 0; index < numItems; index++) {
+ mailView = gMailListView.getMailViewAt(index);
+ gListBox.appendItem(mailView.prettyName, index);
+ if (
+ aSelectedMailView &&
+ mailView.prettyName == aSelectedMailView.prettyName
+ ) {
+ gListBox.selectedIndex = index;
+ }
+ }
+}
+
+function onNewMailView() {
+ window.openDialog(
+ "chrome://messenger/content/mailViewSetup.xhtml",
+ "",
+ "centerscreen,resizable,modal,titlebar,chrome",
+ { onOkCallback: refreshListView }
+ );
+}
+
+function onDeleteMailView() {
+ var bundle = Services.strings.createBundle(
+ "chrome://messenger/locale/messenger.properties"
+ );
+
+ if (
+ !Services.prompt.confirm(
+ window,
+ bundle.GetStringFromName("confirmViewDeleteTitle"),
+ bundle.GetStringFromName("confirmViewDeleteMessage")
+ )
+ ) {
+ return;
+ }
+
+ // get the selected index
+ var selectedIndex = gListBox.selectedIndex;
+ if (selectedIndex >= 0) {
+ var mailView = gMailListView.getMailViewAt(selectedIndex);
+ if (mailView) {
+ gMailListView.removeMailView(mailView);
+ // now remove it from the view...
+ gListBox.selectedItem.remove();
+
+ // select the next item in the list..
+ if (selectedIndex < gListBox.getRowCount()) {
+ gListBox.selectedIndex = selectedIndex;
+ } else {
+ gListBox.selectedIndex = gListBox.getRowCount() - 1;
+ }
+
+ gMailListView.save();
+ }
+ }
+}
+
+function onEditMailView() {
+ // get the selected index
+ var selectedIndex = gListBox.selectedIndex;
+ if (selectedIndex >= 0) {
+ var selMailView = gMailListView.getMailViewAt(selectedIndex);
+ // open up the mail view setup dialog passing in the mail view as an argument....
+
+ var args = { mailView: selMailView, onOkCallback: refreshListView };
+
+ window.openDialog(
+ "chrome://messenger/content/mailViewSetup.xhtml",
+ "",
+ "centerscreen,modal,resizable,titlebar,chrome",
+ args
+ );
+ }
+}
+
+function onMailViewSelect(event) {
+ updateButtons();
+}
+
+function updateButtons() {
+ var selectedIndex = gListBox.selectedIndex;
+ // "edit" and "delete" only enabled when one filter selected
+ gEditButton.disabled = selectedIndex < 0;
+ gDeleteButton.disabled = selectedIndex < 0;
+}
diff --git a/comm/mail/extensions/mailviews/content/mailViewList.xhtml b/comm/mail/extensions/mailviews/content/mailViewList.xhtml
new file mode 100644
index 0000000000..2e1115403b
--- /dev/null
+++ b/comm/mail/extensions/mailviews/content/mailViewList.xhtml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://messenger/skin/messenger.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/colors.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/themeableDialog.css" type="text/css"?>
+
+<!DOCTYPE window [ <!ENTITY % mailViewLisDTD SYSTEM "chrome://messenger/locale/mailViewList.dtd">
+%mailViewLisDTD;
+<!ENTITY % FilterListDialogDTD SYSTEM "chrome://messenger/locale/FilterListDialog.dtd">
+%FilterListDialogDTD; ]>
+
+<window
+ id="mailViewListDialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ onload="mailViewListOnLoad();"
+ windowtype="mailnews:mailviewlist"
+ lightweightthemes="true"
+ title="&mailViewListTitle.label;"
+ width="400"
+ height="340"
+ persist="screenX screenY width height"
+>
+ <dialog buttons="accept">
+ <script src="chrome://messenger/content/mailViewList.js" />
+ <script src="chrome://messenger/content/dialogShadowDom.js" />
+
+ <vbox flex="1">
+ <hbox flex="1">
+ <richlistbox
+ id="mailViewList"
+ flex="1"
+ onselect="onMailViewSelect(event);"
+ />
+
+ <vbox>
+ <button
+ id="newButton"
+ label="&newButton.label;"
+ accesskey="&newButton.accesskey;"
+ oncommand="onNewMailView();"
+ />
+ <button
+ id="editButton"
+ label="&editButton.label;"
+ accesskey="&editButton.accesskey;"
+ oncommand="onEditMailView();"
+ />
+ <button
+ id="deleteButton"
+ label="&deleteButton.label;"
+ accesskey="&deleteButton.accesskey;"
+ oncommand="onDeleteMailView();"
+ />
+ </vbox>
+ </hbox>
+ </vbox>
+ </dialog>
+</window>
diff --git a/comm/mail/extensions/mailviews/content/mailViewSetup.js b/comm/mail/extensions/mailviews/content/mailViewSetup.js
new file mode 100644
index 0000000000..b10213c5a7
--- /dev/null
+++ b/comm/mail/extensions/mailviews/content/mailViewSetup.js
@@ -0,0 +1,108 @@
+/* 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/. */
+
+/* import-globals-from ../../../../mailnews/search/content/searchTerm.js */
+
+document.addEventListener("dialogaccept", onOK);
+
+var gMailView = null;
+
+var dialog;
+
+function mailViewOnLoad() {
+ initializeSearchWidgets();
+ initializeMailViewOverrides();
+ dialog = {};
+
+ if ("arguments" in window && window.arguments[0]) {
+ var args = window.arguments[0];
+ if ("mailView" in args) {
+ gMailView = window.arguments[0].mailView;
+ }
+ if ("onOkCallback" in args) {
+ dialog.okCallback = window.arguments[0].onOkCallback;
+ }
+ }
+
+ dialog.OKButton = document.querySelector("dialog").getButton("accept");
+ dialog.nameField = document.getElementById("name");
+ dialog.nameField.focus();
+
+ setSearchScope(Ci.nsMsgSearchScope.offlineMail);
+
+ if (gMailView) {
+ dialog.nameField.value = gMailView.prettyName;
+ initializeSearchRows(
+ Ci.nsMsgSearchScope.offlineMail,
+ gMailView.searchTerms
+ );
+ } else {
+ onMore(null);
+ }
+
+ doEnabling();
+}
+
+function mailViewOnUnLoad() {}
+
+function onOK() {
+ var mailViewList = Cc["@mozilla.org/messenger/mailviewlist;1"].getService(
+ Ci.nsIMsgMailViewList
+ );
+
+ // reflect the search widgets back into the search session
+ var newMailView = null;
+ if (gMailView) {
+ gMailView.searchTerms = saveSearchTerms(gMailView.searchTerms, gMailView);
+ // if the name of the view has been changed...
+ if (gMailView.prettyName != dialog.nameField.value) {
+ gMailView.mailViewName = dialog.nameField.value;
+ }
+ } else {
+ // otherwise, create a new mail view
+ newMailView = mailViewList.createMailView();
+
+ newMailView.searchTerms = saveSearchTerms(
+ newMailView.searchTerms,
+ newMailView
+ );
+ newMailView.mailViewName = dialog.nameField.value;
+ // now add the mail view to our mail view list
+ mailViewList.addMailView(newMailView);
+ }
+
+ mailViewList.save();
+
+ if (dialog.okCallback) {
+ dialog.okCallback(gMailView ? gMailView : newMailView);
+ }
+}
+
+function initializeMailViewOverrides() {
+ // replace some text with something we want. Need to add some ids to searchOverlay.js
+ // var orButton = document.getElementById('or');
+ // orButton.setAttribute('label', 'Any of the following');
+ // var andButton = document.getElementById('and');
+ // andButton.setAttribute('label', 'All of the following');
+ // matchAll doesn't make sense for views, since views are a single folder
+ hideMatchAllItem();
+}
+
+function UpdateAfterCustomHeaderChange() {
+ updateSearchAttributes();
+}
+
+function doEnabling() {
+ if (dialog.nameField.value) {
+ if (dialog.OKButton.disabled) {
+ dialog.OKButton.disabled = false;
+ }
+ } else if (!dialog.OKButton.disabled) {
+ dialog.OKButton.disabled = true;
+ }
+}
+
+function onEnterInSearchTerm() {
+ // no-op for us...
+}
diff --git a/comm/mail/extensions/mailviews/content/mailViewSetup.xhtml b/comm/mail/extensions/mailviews/content/mailViewSetup.xhtml
new file mode 100644
index 0000000000..a9ff2ef5c9
--- /dev/null
+++ b/comm/mail/extensions/mailviews/content/mailViewSetup.xhtml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://messenger/skin/shared/input-fields.css" type="text/css" ?>
+<?xml-stylesheet href="chrome://messenger/skin/searchDialog.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/colors.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/variables.css" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/themeableDialog.css" type="text/css"?>
+
+<!DOCTYPE window [
+ <!ENTITY % mailViewDTD SYSTEM "chrome://messenger/locale/mailViewSetup.dtd">
+ %mailViewDTD;
+ <!ENTITY % searchTermDTD SYSTEM "chrome://messenger/locale/searchTermOverlay.dtd">
+ %searchTermDTD;
+]>
+
+<window id="mailViewSetupDialog"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ lightweightthemes="true"
+ onload="mailViewOnLoad();"
+ onunload="mailViewOnUnLoad();"
+ windowtype="mailnews:mailview"
+ title="&mailViewSetupTitle.label;"
+ style="min-width: 52em; min-height: 22em;"
+ persist="screenX screenY width height">
+<dialog buttons="accept,cancel">
+
+ <script src="chrome://messenger/content/globalOverlay.js"/>
+ <script src="chrome://messenger/content/mailViewSetup.js"/>
+ <script src="chrome://messenger/content/searchTerm.js"/>
+ <script src="chrome://messenger/content/searchWidgets.js"/>
+ <script src="chrome://messenger/content/dateFormat.js"/>
+ <script src="chrome://messenger/content/dialogShadowDom.js"/>
+
+ <vbox flex="1">
+ <separator class="thin"/>
+ <vbox>
+ <hbox align="center">
+ <label value="&mailViewHeading.label;"
+ accesskey="&mailViewHeading.accesskey;"
+ control="name"/>
+ <html:input id="name" type="text"
+ class="input-inline"
+ tabindex="0"
+ oninput="doEnabling();"/>
+ </hbox>
+ </vbox>
+
+ <separator/>
+ <label value="&searchTermCaption.label;"/>
+ <hbox flex="1">
+ <vbox id="searchTermListBox" flex="1">
+#include ../../../../mailnews/search/content/searchTerm.inc.xhtml
+ </hbox>
+ </vbox>
+
+</dialog>
+</window>
diff --git a/comm/mail/extensions/mailviews/content/msgViewPickerOverlay.js b/comm/mail/extensions/mailviews/content/msgViewPickerOverlay.js
new file mode 100644
index 0000000000..4412be2ffe
--- /dev/null
+++ b/comm/mail/extensions/mailviews/content/msgViewPickerOverlay.js
@@ -0,0 +1,282 @@
+/* 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/. */
+
+/* globals OpenOrFocusWindow */ // From mailWindowOverlay.js
+/* globals GetSelectedMsgFolders */ // From messenger.js
+
+var { MailServices } = ChromeUtils.import(
+ "resource:///modules/MailServices.jsm"
+);
+var { MailViewConstants } = ChromeUtils.import(
+ "resource:///modules/MailViewManager.jsm"
+);
+
+// these constants are now authoritatively defined in MailViewManager.jsm (above)
+// tag views have kViewTagMarker + their key as value
+var kViewItemAll = MailViewConstants.kViewItemAll;
+var kViewItemUnread = MailViewConstants.kViewItemUnread;
+var kViewItemTags = MailViewConstants.kViewItemTags; // former labels used values 2-6
+var kViewItemNotDeleted = MailViewConstants.kViewItemNotDeleted;
+// not a real view! a sentinel value to pop up a dialog
+var kViewItemVirtual = MailViewConstants.kViewItemVirtual;
+// not a real view! a sentinel value to pop up a dialog
+var kViewItemCustomize = MailViewConstants.kViewItemCustomize;
+var kViewItemFirstCustom = MailViewConstants.kViewItemFirstCustom;
+
+var kViewCurrent = MailViewConstants.kViewCurrent;
+var kViewCurrentTag = MailViewConstants.kViewCurrentTag;
+var kViewTagMarker = MailViewConstants.kViewTagMarker;
+
+/**
+ * A reference to the nsIMsgMailViewList service that tracks custom mail views.
+ */
+var gMailViewList = null;
+
+// perform the view/action requested by the aValue string
+// and set the view picker label to the aLabel string
+function ViewChange(aValue) {
+ let about3Pane = document.getElementById("tabmail").currentAbout3Pane;
+ let viewWrapper = about3Pane.gViewWrapper;
+ if (!viewWrapper) {
+ return;
+ }
+
+ if (aValue == kViewItemCustomize || aValue == kViewItemVirtual) {
+ // restore to the previous view value, in case they cancel
+ if (aValue == kViewItemCustomize) {
+ LaunchCustomizeDialog();
+ } else {
+ about3Pane.folderPane.newVirtualFolder(
+ ViewPickerBinding.currentViewLabel,
+ viewWrapper.search.viewTerms,
+ about3Pane.gFolder
+ );
+ }
+ return;
+ }
+
+ // tag menuitem values are of the form :<keyword>
+ if (isNaN(aValue)) {
+ // split off the tag key
+ var tagkey = aValue.substr(kViewTagMarker.length);
+ viewWrapper.setMailView(kViewItemTags, tagkey);
+ } else {
+ var numval = Number(aValue);
+ viewWrapper.setMailView(numval, null);
+ }
+}
+
+function ViewChangeByMenuitem(aMenuitem) {
+ // Mac View menu menuitems don't have XBL bindings
+ ViewChange(aMenuitem.getAttribute("value"));
+}
+
+/**
+ * Mediates interaction with the #viewPickerPopup. In theory this should be
+ * an XBL binding, but for the insanity where the view picker may not be
+ * visible at all times (or ever). No view picker widget, no binding.
+ */
+var ViewPickerBinding = {
+ /**
+ * Return true if the view picker is visible. This is used by the
+ * FolderDisplayWidget to know whether or not to actually use mailviews. (The
+ * idea is that if we are not visible, then it would be confusing to the user
+ * if we filtered their mail since they would have no feedback about this and
+ * no way to change it.)
+ */
+ get isVisible() {
+ return !!document.querySelector("#unifiedToolbarContent .view-picker");
+ },
+
+ /**
+ * Return the string value representing the current mail view value as
+ * understood by the view picker widgets. The value is the index for
+ * everything but tags. for tags it's the ":"-prefixed tagname.
+ */
+ get currentViewValue() {
+ let about3Pane = document.getElementById("tabmail").currentAbout3Pane;
+ let viewWrapper = about3Pane.gViewWrapper;
+ if (!viewWrapper) {
+ return "";
+ }
+ if (viewWrapper.mailViewIndex == kViewItemTags) {
+ return kViewTagMarker + viewWrapper.mailViewData;
+ }
+ return viewWrapper.mailViewIndex + "";
+ },
+
+ /**
+ * @returns The label for the current mail view value.
+ */
+ get currentViewLabel() {
+ return document.querySelector(
+ `#toolbarViewPickerPopup [value="${this.currentViewValue}"]`
+ )?.label;
+ },
+};
+
+function LaunchCustomizeDialog() {
+ OpenOrFocusWindow(
+ {},
+ "mailnews:mailviewlist",
+ "chrome://messenger/content/mailViewList.xhtml"
+ );
+}
+
+/**
+ * All of these Refresh*ViewPopup* methods have to deal with several menu
+ * instances. For example, the "View... Messages" menu, the view picker menu
+ * list in the toolbar, in appmenu/View/Messages, etc.
+ *
+ * @param {Element} viewPopup - A menu popup element.
+ */
+function RefreshAllViewPopups(viewPopup) {
+ RefreshViewPopup(viewPopup);
+ let menupopups = viewPopup.getElementsByTagName("menupopup");
+ if (menupopups.length > 1) {
+ // When we have menupopups, we assume both tags and custom views are there.
+ RefreshTagsPopup(menupopups[0]);
+ RefreshCustomViewsPopup(menupopups[1]);
+ }
+}
+
+/**
+ * Refresh the view messages popup menu/panel. For example set checked and
+ * hidden state on menu items. Used for example for appmenu/View/Messages panel.
+ *
+ * @param {Element} viewPopup - A menu popup element.
+ */
+function RefreshViewPopup(viewPopup) {
+ // Mark default views if selected.
+ let currentViewValue = ViewPickerBinding.currentViewValue;
+
+ let viewAll = viewPopup.querySelector('[value="' + kViewItemAll + '"]');
+ viewAll.setAttribute("checked", currentViewValue == kViewItemAll);
+
+ let viewUnread = viewPopup.querySelector('[value="' + kViewItemUnread + '"]');
+ viewUnread.setAttribute("checked", currentViewValue == kViewItemUnread);
+
+ let viewNotDeleted = viewPopup.querySelector(
+ '[value="' + kViewItemNotDeleted + '"]'
+ );
+
+ let folderArray = GetSelectedMsgFolders();
+ if (folderArray.length == 0) {
+ return;
+ }
+
+ // Only show the "Not Deleted" item for IMAP servers that are using the IMAP
+ // delete model.
+ viewNotDeleted.setAttribute("hidden", true);
+ var msgFolder = folderArray[0];
+ var server = msgFolder.server;
+ if (server.type == "imap") {
+ let imapServer = server.QueryInterface(Ci.nsIImapIncomingServer);
+
+ if (imapServer.deleteModel == Ci.nsMsgImapDeleteModels.IMAPDelete) {
+ viewNotDeleted.setAttribute("hidden", false);
+ viewNotDeleted.setAttribute(
+ "checked",
+ currentViewValue == kViewItemNotDeleted
+ );
+ }
+ }
+}
+
+/**
+ * Refresh the contents of the custom views popup menu/panel.
+ * Used for example for appmenu/View/Messages/CustomViews panel.
+ *
+ * @param {Element} parent - Parent element that will receive the menu items.
+ * @param {string} [elementName] - Type of menu items to create (e.g. "menuitem", "toolbarbutton").
+ * @param {string} [classes] - Classes to set on the menu items.
+ */
+function RefreshCustomViewsPopup(parent, elementName = "menuitem", classes) {
+ if (!gMailViewList) {
+ gMailViewList = Cc["@mozilla.org/messenger/mailviewlist;1"].getService(
+ Ci.nsIMsgMailViewList
+ );
+ }
+
+ // Remove all menu items.
+ while (parent.hasChildNodes()) {
+ parent.lastChild.remove();
+ }
+
+ // Rebuild the list.
+ const currentView = ViewPickerBinding.currentViewValue;
+ const numItems = gMailViewList.mailViewCount;
+
+ for (let i = 0; i < numItems; ++i) {
+ const viewInfo = gMailViewList.getMailViewAt(i);
+ const item = document.createXULElement(elementName);
+
+ item.setAttribute("label", viewInfo.prettyName);
+ item.setAttribute("value", kViewItemFirstCustom + i);
+ item.setAttribute("type", "radio");
+
+ if (classes) {
+ item.setAttribute("class", classes);
+ }
+ if (kViewItemFirstCustom + i == currentView) {
+ item.setAttribute("checked", true);
+ }
+
+ item.addEventListener("command", () =>
+ ViewChange(kViewItemFirstCustom + i)
+ );
+
+ parent.appendChild(item);
+ }
+}
+
+/**
+ * Refresh the contents of the tags popup menu/panel. For example, used for
+ * appmenu/View/Messages/Tags.
+ *
+ * @param {Element} parent - Parent element that will receive the menu items.
+ * @param {string} [elementName] - Type of menu items to create (e.g. "menuitem", "toolbarbutton").
+ * @param {string} [classes] - Classes to set on the menu items.
+ */
+function RefreshTagsPopup(parent, elementName = "menuitem", classes) {
+ // Remove all pre-existing menu items.
+ while (parent.hasChildNodes()) {
+ parent.lastChild.remove();
+ }
+
+ // Create tag menu items.
+ let about3Pane = document.getElementById("tabmail").currentAbout3Pane;
+ let viewWrapper = about3Pane.gViewWrapper;
+ if (!viewWrapper) {
+ return;
+ }
+ const currentTagKey =
+ viewWrapper.mailViewIndex == kViewItemTags ? viewWrapper.mailViewData : "";
+
+ const tagArray = MailServices.tags.getAllTags();
+
+ tagArray.forEach(tagInfo => {
+ const item = document.createXULElement(elementName);
+
+ item.setAttribute("label", tagInfo.tag);
+ item.setAttribute("value", kViewTagMarker + tagInfo.key);
+ item.setAttribute("type", "radio");
+
+ if (tagInfo.key == currentTagKey) {
+ item.setAttribute("checked", true);
+ }
+ if (tagInfo.color) {
+ item.setAttribute("style", `color: ${tagInfo.color};`);
+ }
+ if (classes) {
+ item.setAttribute("class", classes);
+ }
+
+ item.addEventListener("command", () =>
+ ViewChange(kViewTagMarker + tagInfo.key)
+ );
+
+ parent.appendChild(item);
+ });
+}
diff --git a/comm/mail/extensions/mailviews/jar.mn b/comm/mail/extensions/mailviews/jar.mn
new file mode 100644
index 0000000000..4050fe704c
--- /dev/null
+++ b/comm/mail/extensions/mailviews/jar.mn
@@ -0,0 +1,10 @@
+# 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/.
+
+messenger.jar:
+ content/messenger/msgViewPickerOverlay.js (content/msgViewPickerOverlay.js)
+ content/messenger/mailViewSetup.js (content/mailViewSetup.js)
+* content/messenger/mailViewSetup.xhtml (content/mailViewSetup.xhtml)
+ content/messenger/mailViewList.xhtml (content/mailViewList.xhtml)
+ content/messenger/mailViewList.js (content/mailViewList.js)
diff --git a/comm/mail/extensions/mailviews/moz.build b/comm/mail/extensions/mailviews/moz.build
new file mode 100644
index 0000000000..de5cd1bf81
--- /dev/null
+++ b/comm/mail/extensions/mailviews/moz.build
@@ -0,0 +1,6 @@
+# vim: set filetype=python:
+# 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/.
+
+JAR_MANIFESTS += ["jar.mn"]