diff options
Diffstat (limited to 'comm/mail/extensions/mailviews')
-rw-r--r-- | comm/mail/extensions/mailviews/content/mailViewList.js | 116 | ||||
-rw-r--r-- | comm/mail/extensions/mailviews/content/mailViewList.xhtml | 63 | ||||
-rw-r--r-- | comm/mail/extensions/mailviews/content/mailViewSetup.js | 108 | ||||
-rw-r--r-- | comm/mail/extensions/mailviews/content/mailViewSetup.xhtml | 61 | ||||
-rw-r--r-- | comm/mail/extensions/mailviews/content/msgViewPickerOverlay.js | 282 | ||||
-rw-r--r-- | comm/mail/extensions/mailviews/jar.mn | 10 | ||||
-rw-r--r-- | comm/mail/extensions/mailviews/moz.build | 6 |
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"] |