summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/customizableui/content
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/components/customizableui/content')
-rw-r--r--comm/mail/components/customizableui/content/customizeMode.inc.xhtml128
-rw-r--r--comm/mail/components/customizableui/content/jar.mn6
-rw-r--r--comm/mail/components/customizableui/content/moz.build7
-rw-r--r--comm/mail/components/customizableui/content/panelUI.inc.xhtml606
-rw-r--r--comm/mail/components/customizableui/content/panelUI.js882
5 files changed, 1629 insertions, 0 deletions
diff --git a/comm/mail/components/customizableui/content/customizeMode.inc.xhtml b/comm/mail/components/customizableui/content/customizeMode.inc.xhtml
new file mode 100644
index 0000000000..fc7eb0595b
--- /dev/null
+++ b/comm/mail/components/customizableui/content/customizeMode.inc.xhtml
@@ -0,0 +1,128 @@
+<!-- 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/. -->
+
+<box id="customization-content-container">
+<box flex="1" id="customization-palette-container">
+ <label id="customization-header" data-l10n-id="customize-mode-menu-and-toolbars-header"></label>
+ <vbox id="customization-palette" class="customization-palette" hidden="true"/>
+ <vbox id="customization-pong-arena" hidden="true"/>
+ <spacer id="customization-spacer"/>
+</box>
+<vbox id="customization-panel-container">
+ <vbox id="customization-panelWrapper">
+ <box class="panel-arrowbox">
+ <image class="panel-arrow" side="top"/>
+ </box>
+ <box class="panel-arrowcontent" side="top" flex="1">
+ <vbox id="customization-panelHolder">
+ <description id="customization-panelHeader" data-l10n-id="customize-mode-overflow-list-title"></description>
+ <description id="customization-panelDescription" data-l10n-id="customize-mode-overflow-list-description"></description>
+ </vbox>
+ <box class="panel-inner-arrowcontentfooter" hidden="true"/>
+ </box>
+ </vbox>
+</vbox>
+</box>
+<hbox id="customization-footer">
+<checkbox id="customization-titlebar-visibility-checkbox" class="customizationmode-checkbox"
+# NB: because oncommand fires after click, by the time we've fired, the checkbox binding
+# will already have switched the button's state, so this is correct:
+ oncommand="gCustomizeMode.toggleTitlebar(this.checked)" data-l10n-id="customize-mode-titlebar"/>
+<checkbox id="customization-extra-drag-space-checkbox" class="customizationmode-checkbox"
+ data-l10n-id="customize-mode-extra-drag-space"
+ oncommand="gCustomizeMode.toggleDragSpace(this.checked)"/>
+<button id="customization-toolbar-visibility-button" class="customizationmode-button" type="menu" data-l10n-id="customize-mode-toolbars">
+ <menupopup id="customization-toolbar-menu" onpopupshowing="onViewToolbarsPopupShowing(event)"/>
+</button>
+<button id="customization-lwtheme-button" data-l10n-id="customize-mode-lwthemes" class="customizationmode-button" type="menu">
+ <panel type="arrow" id="customization-lwtheme-menu"
+ orient="vertical"
+ onpopupshowing="gCustomizeMode.onThemesMenuShowing(event);"
+ position="topcenter bottomleft"
+ flip="none"
+ role="menu">
+ <label id="customization-lwtheme-menu-header" data-l10n-id="customize-mode-lwthemes-my-themes"/>
+ <hbox id="customization-lwtheme-menu-footer">
+ <toolbarbutton class="customization-lwtheme-menu-footeritem"
+ data-l10n-id="customize-mode-lwthemes-menu-manage"
+ tabindex="0"
+ oncommand="gCustomizeMode.openAddonsManagerThemes(event);"/>
+ <toolbarbutton class="customization-lwtheme-menu-footeritem"
+ data-l10n-id="customize-mode-lwthemes-menu-get-more"
+ tabindex="0"
+ oncommand="gCustomizeMode.getMoreThemes(event);"/>
+ </hbox>
+ </panel>
+</button>
+<button id="customization-uidensity-button"
+ data-l10n-id="customize-mode-uidensity"
+ class="customizationmode-button"
+ type="menu">
+ <panel type="arrow" id="customization-uidensity-menu"
+ onpopupshowing="gCustomizeMode.onUIDensityMenuShowing();"
+ position="topcenter bottomleft"
+ flip="none"
+ role="menu">
+ <menuitem id="customization-uidensity-menuitem-compact"
+ class="menuitem-iconic customization-uidensity-menuitem"
+ role="menuitemradio"
+ data-l10n-id="customize-mode-uidensity-menu-compact"
+ tabindex="0"
+ onfocus="gCustomizeMode.updateUIDensity(this.mode);"
+ onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
+ onblur="gCustomizeMode.resetUIDensity();"
+ onmouseout="gCustomizeMode.resetUIDensity();"
+ oncommand="gCustomizeMode.setUIDensity(this.mode);"/>
+ <menuitem id="customization-uidensity-menuitem-normal"
+ class="menuitem-iconic customization-uidensity-menuitem"
+ role="menuitemradio"
+ data-l10n-id="customize-mode-uidensity-menu-normal"
+ tabindex="0"
+ onfocus="gCustomizeMode.updateUIDensity(this.mode);"
+ onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
+ onblur="gCustomizeMode.resetUIDensity();"
+ onmouseout="gCustomizeMode.resetUIDensity();"
+ oncommand="gCustomizeMode.setUIDensity(this.mode);"/>
+#ifndef XP_MACOSX
+ <menuitem id="customization-uidensity-menuitem-touch"
+ class="menuitem-iconic customization-uidensity-menuitem"
+ role="menuitemradio"
+ data-l10n-id="customize-mode-uidensity-menu-touch"
+ tabindex="0"
+ onfocus="gCustomizeMode.updateUIDensity(this.mode);"
+ onmouseover="gCustomizeMode.updateUIDensity(this.mode);"
+ onblur="gCustomizeMode.resetUIDensity();"
+ onmouseout="gCustomizeMode.resetUIDensity();"
+ oncommand="gCustomizeMode.setUIDensity(this.mode);">
+ </menuitem>
+ <spacer hidden="true" id="customization-uidensity-touch-spacer"/>
+ <checkbox id="customization-uidensity-autotouchmode-checkbox"
+ hidden="true"
+ data-l10n-id="customize-mode-uidensity-auto-touch-mode-checkbox"
+ oncommand="gCustomizeMode.updateAutoTouchMode(this.checked)"/>
+#endif
+ </panel>
+</button>
+
+<button id="whimsy-button"
+ type="checkbox"
+ class="customizationmode-button"
+ oncommand="gCustomizeMode.togglePong(this.checked);"
+ hidden="true"/>
+
+<spacer id="customization-footer-spacer"/>
+<button id="customization-undo-reset-button"
+ class="customizationmode-button"
+ hidden="true"
+ oncommand="gCustomizeMode.undoReset();"
+ data-l10n-id="customize-mode-undo-cmd"/>
+<button id="customization-reset-button"
+ oncommand="gCustomizeMode.reset();"
+ data-l10n-id="customize-mode-restore-defaults"
+ class="customizationmode-button"/>
+<button id="customization-done-button"
+ oncommand="gCustomizeMode.exit();"
+ data-l10n-id="customize-mode-done"
+ class="customizationmode-button"/>
+</hbox>
diff --git a/comm/mail/components/customizableui/content/jar.mn b/comm/mail/components/customizableui/content/jar.mn
new file mode 100644
index 0000000000..db1978fdb0
--- /dev/null
+++ b/comm/mail/components/customizableui/content/jar.mn
@@ -0,0 +1,6 @@
+# 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/panelUI.js
diff --git a/comm/mail/components/customizableui/content/moz.build b/comm/mail/components/customizableui/content/moz.build
new file mode 100644
index 0000000000..d988c0ff9b
--- /dev/null
+++ b/comm/mail/components/customizableui/content/moz.build
@@ -0,0 +1,7 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# 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"]
diff --git a/comm/mail/components/customizableui/content/panelUI.inc.xhtml b/comm/mail/components/customizableui/content/panelUI.inc.xhtml
new file mode 100644
index 0000000000..3b965da756
--- /dev/null
+++ b/comm/mail/components/customizableui/content/panelUI.inc.xhtml
@@ -0,0 +1,606 @@
+<!-- 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/. -->
+
+<panel id="appMenu-popup"
+ class="cui-widget-panel panel-no-padding"
+ role="group"
+ type="arrow"
+ hidden="true"
+ flip="slide"
+ position="bottomright topright"
+ noautofocus="true">
+ <panelmultiview id="appMenu-multiView"
+ mainViewId="appMenu-mainView"
+ viewCacheId="appMenu-viewCache">
+
+ <!-- Main Appmenu View -->
+ <panelview id="appMenu-mainView" class="PanelUI-subView">
+ <vbox id="appMenu-mainViewItems"
+ class="panel-subview-body">
+ <vbox id="appMenu-addon-banners"/>
+ <toolbarbutton class="panel-banner-item"
+ oncommand="PanelUI._onBannerItemSelected(event)"
+ hidden="true"/>
+#ifdef NIGHTLY_BUILD
+ <toolbarbutton id="appmenu_signin"
+ data-l10n-id="appmenu-signin-panel"
+ class="subviewbutton subviewbutton-iconic"
+ hidden="true"
+ oncommand="gSync.initFxA();"/>
+ <toolbarbutton id="appmenu_sync"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ hidden="true"
+ align="center"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-syncView', this)">
+ <hbox flex="1">
+ <html:img id="appmenu-sync-icon"
+ class="toolbarbutton-icon"
+ alt=""/>
+ <vbox flex="1">
+ <label id="appmenu-sync-sync"
+ crop="end"
+ data-l10n-id="appmenu-sync-sync"/>
+ <label id="appmenu-sync-account"
+ class="appmenu-sync-account-email"
+ crop="end"
+ data-l10n-id="appmenu-sync-account"/>
+ </vbox>
+ </hbox>
+ </toolbarbutton>
+ <toolbarseparator id="syncSeparator" hidden="true"/>
+#endif
+ <toolbarbutton id="appmenu_new"
+ data-l10n-id="appmenu-new-account-panel"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-newView', this)"/>
+ <toolbarbutton id="appmenu_create"
+ data-l10n-id="appmenu-create-panel"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-createView', this)"/>
+ <toolbarseparator id="appmenu_createPopupMenuSeparator"/>
+ <toolbarbutton id="appmenu_open"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ data-l10n-id="appmenu-open-file-panel"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-openView', this)"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_View"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ data-l10n-id="appmenu-view-panel"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-viewView', this)"/>
+ <toolbaritem id="appMenu-uiDensity-controls"
+ class="subviewbutton subviewbutton-iconic toolbaritem-combined-buttons"
+ closemenu="none">
+ <html:img class="toolbarbutton-icon" src="" alt=""/>
+ <label class="toolbarbutton-text" data-l10n-id="appmenu-mail-uidensity-value"/>
+ <toolbarbutton id="appmenu_uiDensityCompact"
+ class="subviewbutton subviewbutton-iconic subviewbutton"
+ data-l10n-id="appmenu-uidensity-compact"
+ type="radio"
+ oncommand="PanelUI.setUIDensity(event);"/>
+ <toolbarbutton id="appmenu_uiDensityNormal"
+ class="subviewbutton subviewbutton-iconic subviewbutton"
+ data-l10n-id="appmenu-uidensity-default"
+ type="radio"
+ oncommand="PanelUI.setUIDensity(event);"/>
+ <toolbarbutton id="appmenu_uiDensityTouch"
+ class="subviewbutton subviewbutton-iconic subviewbutton"
+ data-l10n-id="appmenu-uidensity-relaxed"
+ type="radio"
+ oncommand="PanelUI.setUIDensity(event);"/>
+ </toolbaritem>
+ <toolbaritem id="appMenu-fontSize-controls"
+ class="subviewbutton subviewbutton-iconic toolbaritem-combined-buttons"
+ closemenu="none">
+ <html:img class="toolbarbutton-icon" src="" alt=""/>
+ <label class="toolbarbutton-text" data-l10n-id="appmenu-font-size-value"/>
+ <toolbarbutton id="appMenu-fontSizeReduce-button"
+ class="subviewbutton subviewbutton-iconic"
+ oncommand="UIFontSize.reduceSize();"
+ data-l10n-id="appmenuitem-font-size-reduce"/>
+ <toolbarbutton id="appMenu-fontSizeReset-button"
+ class="subviewbutton"
+ oncommand="UIFontSize.resetSize();"
+ tooltip="fontSizeReset"/>
+ <toolbarbutton id="appMenu-fontSizeEnlarge-button"
+ class="subviewbutton subviewbutton-iconic"
+ oncommand="UIFontSize.increaseSize();"
+ data-l10n-id="appmenuitem-font-size-enlarge"/>
+ </toolbaritem>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_preferences"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-settings"
+ oncommand="openOptionsDialog();"/>
+ <toolbarbutton id="appmenu_accountmgr"
+ class="subviewbutton subviewbutton-iconic"
+ label="&accountManagerCmd2.label;"
+ oncommand="MsgAccountManager(null);"/>
+ <toolbarbutton id="appmenu_addons"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-addons-and-themes"
+ oncommand="openAddonsMgr();"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_toolsMenu"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ data-l10n-id="appmenu-tools-panel"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-toolsView', this)"/>
+ <toolbarbutton id="appmenu_help"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ data-l10n-id="menu-help-help-title"
+ closemenu="none"
+ oncommand="buildHelpMenu(); PanelUI.showSubView('appMenu-helpView', this)"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu-quit"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="menu-quit"
+ key="key_quitApplication"
+ command="cmd_quitApplication"/>
+ </vbox>
+ </panelview>
+#ifdef NIGHTLY_BUILD
+ <!-- Sync -->
+ <panelview id="appMenu-syncView"
+ data-l10n-id="appmenu-sync-panel-title"
+ class="PanelUI-subView">
+ <vbox id="appMenu-syncViewItems"
+ class="panel-subview-body">
+ <toolbarbutton id="appmenu_manageSyncAccountMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ align="center"
+ oncommand="gSync.openFxAManagePage();">
+ <hbox flex="1">
+ <html:img id="appmenu-manage-sync-icon"
+ class="toolbarbutton-icon"
+ alt=""/>
+ <vbox flex="1">
+ <label id="appmenu-sync-menu-manage"
+ crop="end"
+ data-l10n-id="appmenu-sync-manage"/>
+ <label id="appmenu-sync-menu-account"
+ class="appmenu-sync-account-email"
+ crop="end"
+ data-l10n-id="appmenu-sync-account"/>
+ </vbox>
+ </hbox>
+ </toolbarbutton>
+
+ <toolbarbutton id="appmenu-submenu-sync-now"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-sync-now"
+ closemenu="none"
+ oncommand="Weave.Service.sync({});"/>
+ <toolbarbutton id="appmenu-submenu-sync-settings"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-sync-settings"
+ oncommand="openPreferencesTab('sync');"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu-submenu-sync-sign-out"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-sync-sign-out"
+ oncommand="gSync.disconnect({ confirm: true });"/>
+ </vbox>
+ </panelview>
+#endif
+ <!-- New -->
+ <panelview id="appMenu-newView"
+ data-l10n-id="appmenu-new-account-panel-title"
+ class="PanelUI-subView">
+ <vbox id="appMenu-newViewItems"
+ class="panel-subview-body">
+ <toolbarbutton id="appmenu_newCreateEmailAccountMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-create-new-mail-account"
+ oncommand="openAccountProvisionerTab();"/>
+ <toolbarbutton id="appmenu_newMailAccountMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-mail-account"
+ oncommand="openAccountSetupTab();"/>
+#ifdef MAIN_WINDOW
+ <toolbarbutton id="appmenu_calendar-new-calendar-menu-item"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-calendar"
+ command="calendar_new_calendar_command"/>
+#endif
+ <toolbarbutton id="appmenu_newAB"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ data-l10n-id="appmenu-newab-panel"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-newabView', this)"/>
+ <toolbarbutton id="appmenu_newIMAccountMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-chat-account"
+ oncommand="openIMAccountWizard();"/>
+ <toolbarbutton id="appmenu_newFeedAccountMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-feed"
+ oncommand="AddFeedAccount();"/>
+ <toolbarbutton id="appmenu_newNewsgroupAccountMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-newsgroup"
+ oncommand="openNewsgroupAccountWizard();"/>
+ </vbox>
+ </panelview>
+
+ <!-- New AB -->
+ <panelview id="appMenu-newabView"
+ data-l10n-id="appmenu-newab-panel-title"
+ class="PanelUI-subView">
+ <vbox id="appMenu-newABItems"
+ class="panel-subview-body">
+ <toolbarbutton id="appmenu_newABMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-addressbook"
+ oncommand="openNewABDialog();"/>
+ <toolbarbutton id="appmenu_newCardDAVMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-carddav"
+ oncommand="openNewABDialog('CARDDAV');"/>
+ <toolbarbutton id="appmenu_newLdapMenuItem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-new-ldap"
+ oncommand="openNewABDialog('LDAP');"/>
+ </vbox>
+ </panelview>
+
+ <!-- Create -->
+ <panelview id="appMenu-createView"
+ data-l10n-id="appmenu-create-panel-title"
+ class="PanelUI-subView">
+ <vbox id="appMenu-createViewItems"
+ class="panel-subview-body">
+ <toolbarbutton id="appmenu_newNewMsgCmd"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-create-message"
+ key = "key_newMessage2"
+ command="cmd_newMessage"/>
+#ifdef MAIN_WINDOW
+ <toolbarbutton id="appmenu_calendar-new-event-menu-item"
+ class="subviewbutton subviewbutton-iconic hide-when-calendar-deactivated"
+ data-l10n-id="appmenu-create-event"
+ command="calendar_new_event_command"/>
+ <toolbarbutton id="appmenu_calendar-new-task-menu-item"
+ class="subviewbutton subviewbutton-iconic hide-when-calendar-deactivated"
+ data-l10n-id="appmenu-create-task"
+ command="calendar_new_todo_command"/>
+#endif
+ <toolbarbutton id="appmenu_newCard"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-create-contact"
+ command="cmd_newCard"/>
+ </vbox>
+ </panelview>
+
+ <!-- Open -->
+ <panelview id="appMenu-openView"
+ data-l10n-id="appmenu-open-file-panel-title"
+ class="PanelUI-subView">
+ <vbox id="appMenu-openViewItems"
+ class="panel-subview-body">
+ <toolbarbutton id="appmenu_OpenMessageFileMenuitem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-open-message"
+ oncommand="MsgOpenFromFile();"/>
+ <toolbarbutton id="appmenu_OpenCalendarFileMenuitem"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-open-calendar"
+ oncommand="openLocalCalendar();"/>
+ </vbox>
+ </panelview>
+
+ <!-- View / Toolbars -->
+ <panelview id="appMenu-toolbarsView"
+ title="&viewToolbarsMenu.label;"
+ class="PanelUI-subView">
+ <vbox class="panel-subview-body">
+#ifdef MAIN_WINDOW
+ <toolbarbutton id="appmenu_quickFilterBar"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ closemenu="none"
+ data-l10n-id="quick-filter-bar-toggle"
+ command="cmd_toggleQuickFilterBar"/>
+ <toolbarbutton id="appmenu_spacesToolbar"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ data-l10n-id="menu-spaces-toolbar-button"
+ closemenu="none"
+ oncommand="gSpacesToolbar.toggleToolbarFromMenu();"/>
+#endif
+ <toolbarbutton id="appmenu_showStatusbar"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ label="&showTaskbarCmd.label;"
+ oncommand="goToggleToolbar('status-bar', 'menu_showTaskbar')"
+ closemenu="none"
+ checked="true"
+ observes="menu_showTaskbar"/>
+ <toolbarseparator id="appmenu_toggleToolbarsSeparator"/>
+ <toolbarbutton id="appmenu_toolbarLayout"
+ class="subviewbutton subviewbutton-iconic"
+ label="&appmenuToolbarLayout.label;"
+ command="cmd_CustomizeMailToolbar"/>
+ </vbox>
+ </panelview>
+
+ <!-- View / Layout -->
+ <panelview id="appMenu-preferencesLayoutView"
+ title="&messagePaneLayoutStyle.label;"
+ class="PanelUI-subView">
+ <vbox class="panel-subview-body">
+ <toolbarbutton id="appmenu_messagePaneClassic"
+ class="subviewbutton subviewbutton-iconic"
+ type="radio"
+ label="&messagePaneClassic.label;"
+ name="viewlayoutgroup"
+ command="cmd_viewClassicMailLayout"/>
+ <toolbarbutton id="appmenu_messagePaneWide"
+ class="subviewbutton subviewbutton-iconic"
+ type="radio"
+ label="&messagePaneWide.label;"
+ name="viewlayoutgroup"
+ command="cmd_viewWideMailLayout"/>
+ <toolbarbutton id="appmenu_messagePaneVertical"
+ class="subviewbutton subviewbutton-iconic"
+ type="radio"
+ label="&messagePaneVertical.label;"
+ name="viewlayoutgroup"
+ command="cmd_viewVerticalMailLayout"/>
+ <toolbarseparator id="appmenu_viewMenuAfterPaneVerticalSeparator"/>
+ <toolbarbutton id="appmenu_showFolderPane"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ closemenu="none"
+ label="&showFolderPaneCmd.label;"
+ command="cmd_toggleFolderPane"/>
+ <toolbarbutton id="appmenu_toggleThreadPaneHeader"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ name="threadheader"
+ closemenu="none"
+ data-l10n-id="appmenuitem-toggle-thread-pane-header"
+ command="cmd_toggleThreadPaneHeader"/>
+ <toolbarbutton id="appmenu_showMessage"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ closemenu="none"
+ label="&showMessageCmd.label;"
+ key="key_toggleMessagePane"
+ command="cmd_toggleMessagePane"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_calShowTodayPane-2"
+ class="subviewbutton subviewbutton-iconic"
+ label="&todaypane.showTodayPane.label;"
+ type="checkbox"
+ command="calendar_toggle_todaypane_command"/>
+ </vbox>
+ </panelview>
+
+ <!-- View -->
+ <panelview id="appMenu-viewView"
+ class="PanelUI-subView"
+ data-l10n-id="appmenu-view-panel-title">
+ <vbox id="appMenu-viewViewItems"
+ class="panel-subview-body">
+ <toolbarbutton id="appmenu_Toolbars"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ label="&viewToolbarsMenu.label;"
+ accesskey="&viewToolbarsMenu.accesskey;"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-toolbarsView', this)"/>
+ <toolbarbutton id="appmenu_MessagePaneLayout"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ label="&messagePaneLayoutStyle.label;"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-preferencesLayoutView', this)"/>
+ <toolbarbutton id="appmenu_FolderViews"
+ class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+ label="&folderView.label;"
+ closemenu="none"
+ oncommand="PanelUI.showSubView('appMenu-foldersView', this)"/>
+ </vbox>
+ </panelview>
+
+ <!-- View / Folders -->
+ <panelview id="appMenu-foldersView"
+ title="&folderView.label;"
+ class="PanelUI-subView">
+ <vbox class="panel-subview-body">
+ <toolbarbutton id="appmenu_toggleFolderHeader"
+ class="subviewbutton subviewbutton-iconic"
+ name="paneheader"
+ value="toggle-header"
+ data-l10n-id="menu-view-folders-toggle-header"
+ type="checkbox"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarseparator id="appmenu_folderModesSeparator"/>
+ <toolbarbutton id="appmenu_allFolders"
+ class="subviewbutton subviewbutton-iconic"
+ value="all"
+ data-l10n-id="show-all-folders-label"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarbutton id="appmenu_smartFolders"
+ class="subviewbutton subviewbutton-iconic"
+ value="smart"
+ data-l10n-id="show-smart-folders-label"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarbutton id="appmenu_unreadFolders"
+ class="subviewbutton subviewbutton-iconic"
+ value="unread"
+ data-l10n-id="show-unread-folders-label"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarbutton id="appmenu_favoriteFolders"
+ class="subviewbutton subviewbutton-iconic"
+ value="favorite"
+ data-l10n-id="show-favorite-folders-label"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarbutton id="appmenu_recentFolders"
+ class="subviewbutton subviewbutton-iconic"
+ value="recent"
+ data-l10n-id="show-recent-folders-label"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_tagsFolders"
+ class="subviewbutton subviewbutton-iconic"
+ value="tags"
+ data-l10n-id="show-tags-folders-label"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderViewMenuOnCommand(event);"/>
+ <toolbarseparator id="appmenu_compactPropertiesSeparator"/>
+ <toolbarbutton id="appmenu_compactMode"
+ class="subviewbutton subviewbutton-iconic"
+ value="compact"
+ data-l10n-id="folder-toolbar-toggle-folder-compact-view"
+ type="checkbox"
+ name="viewmessages"
+ closemenu="none"
+ oncommand="PanelUI.folderCompactMenuOnCommand(event)"/>
+ <toolbarseparator id="appmenu_favoritePropertiesSeparator"/>
+ <toolbarbutton id="appmenu_favoriteFolder"
+ class="subviewbutton subviewbutton-iconic"
+ type="checkbox"
+ label="&menuFavoriteFolder.label;"
+ checked="false"
+ command="cmd_toggleFavoriteFolder"/>
+ <toolbarbutton id="appmenu_properties"
+ class="subviewbutton subviewbutton-iconic"
+ command="cmd_properties"/>
+ </vbox>
+ </panelview>
+
+ <!-- View / Messages / Tags -->
+ <!-- Dynamically populated when shown. -->
+ <panelview id="appMenu-viewMessagesTagsView"
+ title="&viewTags.label;"
+ class="PanelUI-subView"
+ oncommand="ViewChangeByMenuitem(event.target);">
+ <vbox class="panel-subview-body"/>
+ </panelview>
+
+ <!-- View / Messages / Custom Views -->
+ <!-- Dynamically populated when shown. -->
+ <panelview id="appMenu-viewMessagesCustomViewsView"
+ title="&viewCustomViews.label;"
+ class="PanelUI-subView"
+ oncommand="ViewChangeByMenuitem(event.target);">
+ <vbox class="panel-subview-body"/>
+ </panelview>
+
+ <!-- Tools -->
+ <panelview id="appMenu-toolsView"
+ data-l10n-id="appmenu-tools-panel-title"
+ class="PanelUI-subView">
+ <vbox class="panel-subview-body">
+ <toolbarbutton id="appmenu_import"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-import"
+ oncommand="toImport();"/>
+ <toolbarbutton id="appmenu_export"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-export"
+ oncommand="toExport();"/>
+ <toolbarseparator id="importExportSeparator"/>
+ <toolbarbutton id="appmenu_searchCmd"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-message-search"
+ key="key_searchMail"
+ command="cmd_searchMessages"/>
+ <toolbarbutton id="appmenu_filtersCmd"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-message-filters"
+ oncommand="MsgFilters();"/>
+ <toolbarbutton id="appmenu_manageKeysOpenPGP"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="openpgp-manage-keys-openpgp-cmd"
+ oncommand="openKeyManager()"/>
+ <toolbarbutton id="appmenu_openSavedFilesWnd"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-download-manager"
+ key="key_savedFiles"
+ oncommand="openSavedFilesWnd();"/>
+ <toolbarbutton id="appmenu_activityManager"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-activity-manager"
+ oncommand="openActivityMgr();"/>
+ <toolbarseparator id="devToolsSeparator"/>
+ <toolbarbutton id="appmenu_devtoolsToolbox"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-tools-dev-tools"
+ key="key_devtoolsToolbox"
+ oncommand="BrowserToolboxLauncher.init();"/>
+ </vbox>
+ </panelview>
+
+ <!-- Help -->
+ <panelview id="appMenu-helpView"
+ data-l10n-id="appmenu-help-panel-title"
+ class="PanelUI-subView">
+ <vbox class="panel-subview-body">
+ <toolbarbutton id="appmenu_openHelp"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-get-help"
+ key="key_openHelp"
+ oncommand="openSupportURL();"/>
+ <toolbarbutton id="appmenu_openTour"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-explore-features"
+ oncommand="openLinkText(event, 'tourURL');"/>
+ <toolbarbutton id="appmenu_keyboardShortcuts"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-shortcuts"
+ oncommand="openLinkText(event, 'keyboardShortcutsURL');"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_getInvolved"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-get-involved"
+ oncommand="openLinkText(event, 'getInvolvedURL');"/>
+ <toolbarbutton id="appmenu_makeDonation"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-donation"
+ oncommand="openLinkText(event, 'donateURL');"/>
+ <toolbarbutton id="appmenu_submitFeedback"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-share-feedback"
+ oncommand="openLinkText(event, 'feedbackURL');"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_troubleshootMode"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-enter-troubleshoot-mode2"
+ oncommand="safeModeRestart();"/>
+ <toolbarbutton id="appmenu_troubleshootingInfo"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-troubleshooting-info"
+ oncommand="openAboutSupport();"/>
+ <toolbarseparator/>
+ <toolbarbutton id="appmenu_about"
+ class="subviewbutton subviewbutton-iconic"
+ data-l10n-id="appmenu-help-about-product"
+ oncommand="openAboutDialog();"/>
+ </vbox>
+ </panelview>
+ </panelmultiview>
+</panel>
diff --git a/comm/mail/components/customizableui/content/panelUI.js b/comm/mail/components/customizableui/content/panelUI.js
new file mode 100644
index 0000000000..bad418abb4
--- /dev/null
+++ b/comm/mail/components/customizableui/content/panelUI.js
@@ -0,0 +1,882 @@
+/* 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 ../../../base/content/globalOverlay.js */
+/* import-globals-from ../../../base/content/mailCore.js */
+/* import-globals-from ../../../base/content/mailWindowOverlay.js */
+/* import-globals-from ../../../base/content/messenger.js */
+/* import-globals-from ../../../extensions/mailviews/content/msgViewPickerOverlay.js */
+
+var { ExtensionParent } = ChromeUtils.importESModule(
+ "resource://gre/modules/ExtensionParent.sys.mjs"
+);
+var { ExtensionSupport } = ChromeUtils.import(
+ "resource:///modules/ExtensionSupport.jsm"
+);
+var { ShortcutUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/ShortcutUtils.sys.mjs"
+);
+var { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+var { UIDensity } = ChromeUtils.import("resource:///modules/UIDensity.jsm");
+var { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.sys.mjs",
+ CustomizableUI: "resource:///modules/CustomizableUI.sys.mjs",
+ PanelMultiView: "resource:///modules/PanelMultiView.sys.mjs",
+});
+ChromeUtils.defineModuleGetter(
+ this,
+ "ExtensionsUI",
+ "resource:///modules/ExtensionsUI.jsm"
+);
+
+/**
+ * Maintains the state and dispatches events for the main menu panel.
+ */
+const PanelUI = {
+ /** Panel events that we listen for. */
+ get kEvents() {
+ return [
+ "popupshowing",
+ "popupshown",
+ "popuphiding",
+ "popuphidden",
+ "ViewShowing",
+ ];
+ },
+ /**
+ * Used for lazily getting and memoizing elements from the document. Lazy
+ * getters are set in init, and memoizing happens after the first retrieval.
+ */
+ get kElements() {
+ return {
+ mainView: "appMenu-mainView",
+ multiView: "appMenu-multiView",
+ menuButton: "button-appmenu",
+ panel: "appMenu-popup",
+ addonNotificationContainer: "appMenu-addon-banners",
+ navbar: "mail-bar3",
+ };
+ },
+
+ kAppMenuButtons: new Set(),
+
+ _initialized: false,
+ _notifications: null,
+
+ init() {
+ this._initElements();
+ this.initAppMenuButton("button-appmenu", "mail-toolbox");
+
+ this.menuButton = this.menuButtonMail;
+
+ Services.obs.addObserver(this, "fullscreen-nav-toolbox");
+ Services.obs.addObserver(this, "appMenu-notifications");
+
+ XPCOMUtils.defineLazyPreferenceGetter(
+ this,
+ "autoHideToolbarInFullScreen",
+ "browser.fullscreen.autohide",
+ false,
+ (pref, previousValue, newValue) => {
+ // On OSX, or with autohide preffed off, MozDOMFullscreen is the only
+ // event we care about, since fullscreen should behave just like non
+ // fullscreen. Otherwise, we don't want to listen to these because
+ // we'd just be spamming ourselves with both of them whenever a user
+ // opened a video.
+ if (newValue) {
+ window.removeEventListener("MozDOMFullscreen:Entered", this);
+ window.removeEventListener("MozDOMFullscreen:Exited", this);
+ window.addEventListener("fullscreen", this);
+ } else {
+ window.addEventListener("MozDOMFullscreen:Entered", this);
+ window.addEventListener("MozDOMFullscreen:Exited", this);
+ window.removeEventListener("fullscreen", this);
+ }
+
+ this._updateNotifications(false);
+ },
+ autoHidePref => autoHidePref && Services.appinfo.OS !== "Darwin"
+ );
+
+ if (this.autoHideToolbarInFullScreen) {
+ window.addEventListener("fullscreen", this);
+ } else {
+ window.addEventListener("MozDOMFullscreen:Entered", this);
+ window.addEventListener("MozDOMFullscreen:Exited", this);
+ }
+
+ window.addEventListener("activate", this);
+
+ Services.obs.notifyObservers(
+ null,
+ "appMenu-notifications-request",
+ "refresh"
+ );
+
+ this._initialized = true;
+ },
+
+ _initElements() {
+ for (let [k, v] of Object.entries(this.kElements)) {
+ // Need to do fresh let-bindings per iteration
+ let getKey = k;
+ let id = v;
+ this.__defineGetter__(getKey, function () {
+ delete this[getKey];
+ // eslint-disable-next-line consistent-return
+ return (this[getKey] = document.getElementById(id));
+ });
+ }
+ },
+
+ initAppMenuButton(id, toolboxId) {
+ let button = document.getElementById(id);
+ if (!button) {
+ // If not in the document, the button should be in the toolbox palette,
+ // which isn't part of the document.
+ let toolbox = document.getElementById(toolboxId);
+ if (toolbox) {
+ button = toolbox.palette.querySelector(`#${id}`);
+ }
+ }
+
+ if (button) {
+ button.addEventListener("mousedown", PanelUI);
+ button.addEventListener("keypress", PanelUI);
+
+ this.kAppMenuButtons.add(button);
+ }
+ },
+
+ _eventListenersAdded: false,
+ _ensureEventListenersAdded() {
+ if (this._eventListenersAdded) {
+ return;
+ }
+ this._addEventListeners();
+ },
+
+ _addEventListeners() {
+ for (let event of this.kEvents) {
+ this.panel.addEventListener(event, this);
+ }
+ this._eventListenersAdded = true;
+ },
+
+ _removeEventListeners() {
+ for (let event of this.kEvents) {
+ this.panel.removeEventListener(event, this);
+ }
+ this._eventListenersAdded = false;
+ },
+
+ uninit() {
+ this._removeEventListeners();
+
+ Services.obs.removeObserver(this, "fullscreen-nav-toolbox");
+ Services.obs.removeObserver(this, "appMenu-notifications");
+
+ window.removeEventListener("MozDOMFullscreen:Entered", this);
+ window.removeEventListener("MozDOMFullscreen:Exited", this);
+ window.removeEventListener("fullscreen", this);
+ window.removeEventListener("activate", this);
+
+ [this.menuButtonMail, this.menuButtonChat].forEach(button => {
+ // There's no chat button in the messageWindow.xhtml context.
+ if (button) {
+ button.removeEventListener("mousedown", this);
+ button.removeEventListener("keypress", this);
+ }
+ });
+ },
+
+ /**
+ * Opens the menu panel if it's closed, or closes it if it's open.
+ *
+ * @param event the event that triggers the toggle.
+ */
+ toggle(event) {
+ // Don't show the panel if the window is in customization mode,
+ // since this button doubles as an exit path for the user in this case.
+ if (document.documentElement.hasAttribute("customizing")) {
+ return;
+ }
+
+ // Since we have several menu buttons, make sure the current one is used.
+ // This works for now, but in the long run, if we're showing badges etc.
+ // then the current menuButton needs to be set when the app's view/tab
+ // changes, not just when the menu is toggled.
+ this.menuButton = event.target;
+
+ this._ensureEventListenersAdded();
+ if (this.panel.state == "open") {
+ this.hide();
+ } else if (this.panel.state == "closed") {
+ this.show(event);
+ }
+ },
+
+ /**
+ * Opens the menu panel. If the event target has a child with the
+ * toolbarbutton-icon attribute, the panel will be anchored on that child.
+ * Otherwise, the panel is anchored on the event target itself.
+ *
+ * @param aEvent the event (if any) that triggers showing the menu.
+ */
+ show(aEvent) {
+ this._ensureShortcutsShown();
+ (async () => {
+ await this.ensureReady();
+
+ if (
+ this.panel.state == "open" ||
+ document.documentElement.hasAttribute("customizing")
+ ) {
+ return;
+ }
+
+ let domEvent = null;
+ if (aEvent && aEvent.type != "command") {
+ domEvent = aEvent;
+ }
+
+ // We try to use the event.target to account for clicks triggered
+ // from the #button-chat-appmenu. In case the opening of the menu isn't
+ // triggered by a click event, fallback to the main menu button as anchor.
+ let anchor = this._getPanelAnchor(
+ aEvent ? aEvent.target : this.menuButton
+ );
+ await PanelMultiView.openPopup(this.panel, anchor, {
+ triggerEvent: domEvent,
+ });
+ })().catch(console.error);
+ },
+
+ /**
+ * If the menu panel is being shown, hide it.
+ */
+ hide() {
+ if (document.documentElement.hasAttribute("customizing")) {
+ return;
+ }
+
+ PanelMultiView.hidePopup(this.panel);
+ },
+
+ observe(subject, topic, status) {
+ switch (topic) {
+ case "fullscreen-nav-toolbox":
+ if (this._notifications) {
+ this._updateNotifications(false);
+ }
+ break;
+ case "appMenu-notifications":
+ // Don't initialize twice.
+ if (status == "init" && this._notifications) {
+ break;
+ }
+ this._notifications = AppMenuNotifications.notifications;
+ this._updateNotifications(true);
+ break;
+ }
+ },
+
+ handleEvent(event) {
+ // Ignore context menus and menu button menus showing and hiding:
+ if (event.type.startsWith("popup") && event.target != this.panel) {
+ return;
+ }
+ switch (event.type) {
+ case "popupshowing":
+ initAppMenuPopup();
+ // Fall through
+ case "popupshown":
+ if (event.type == "popupshown") {
+ CustomizableUI.addPanelCloseListeners(this.panel);
+ }
+ // Fall through
+ case "popuphiding":
+ // Fall through
+ case "popuphidden":
+ this._updateNotifications();
+ this._updatePanelButton(event.target);
+ if (event.type == "popuphidden") {
+ CustomizableUI.removePanelCloseListeners(this.panel);
+ }
+ break;
+ case "mousedown":
+ if (event.button == 0) {
+ this.toggle(event);
+ }
+ break;
+ case "keypress":
+ if (event.key == " " || event.key == "Enter") {
+ this.toggle(event);
+ event.stopPropagation();
+ }
+ break;
+ case "MozDOMFullscreen:Entered":
+ case "MozDOMFullscreen:Exited":
+ case "fullscreen":
+ case "activate":
+ this._updateNotifications();
+ break;
+ case "ViewShowing":
+ PanelUI._handleViewShowingEvent(event);
+ break;
+ }
+ },
+
+ /**
+ * When a ViewShowing event happens when a <panelview> element is shown,
+ * do any required set up for that particular view.
+ *
+ * @param {ViewShowingEvent} event - ViewShowing event.
+ */
+ _handleViewShowingEvent(event) {
+ // Typically event.target for "ViewShowing" is a <panelview> element.
+ PanelUI._ensureShortcutsShown(event.target);
+
+ switch (event.target.id) {
+ case "appMenu-foldersView":
+ this._onFoldersViewShow(event);
+ break;
+ case "appMenu-addonsView":
+ initAddonPrefsMenu(
+ event.target.querySelector(".panel-subview-body"),
+ "toolbarbutton",
+ "subviewbutton subviewbutton-iconic",
+ "subviewbutton subviewbutton-iconic"
+ );
+ break;
+ case "appMenu-toolbarsView":
+ onViewToolbarsPopupShowing(
+ event,
+ "mail-toolbox",
+ document.getElementById("appmenu_quickFilterBar"),
+ "toolbarbutton",
+ "subviewbutton subviewbutton-iconic",
+ true
+ );
+ break;
+ case "appMenu-preferencesLayoutView":
+ PanelUI._onPreferencesLayoutViewShow(event);
+ break;
+ // View
+ case "appMenu-viewMessagesTagsView":
+ PanelUI._refreshDynamicView(event, RefreshTagsPopup);
+ break;
+ case "appMenu-viewMessagesCustomViewsView":
+ PanelUI._refreshDynamicView(event, RefreshCustomViewsPopup);
+ break;
+ }
+ },
+
+ /**
+ * Refreshes some views that are dynamically populated. Typically called by
+ * event listeners responding to a ViewShowing event. It calls a given refresh
+ * function (that populates the view), passing appmenu-specific arguments.
+ *
+ * @param {ViewShowingEvent} event - ViewShowing event.
+ * @param {Function} refreshFunction - Function that refreshes a particular view.
+ */
+ _refreshDynamicView(event, refreshFunction) {
+ refreshFunction(
+ event.target.querySelector(".panel-subview-body"),
+ "toolbarbutton",
+ "subviewbutton subviewbutton-iconic",
+ "toolbarseparator"
+ );
+ },
+
+ get isReady() {
+ return !!this._isReady;
+ },
+
+ /**
+ * Registering the menu panel is done lazily for performance reasons. This
+ * method is exposed so that CustomizationMode can force panel-readyness in the
+ * event that customization mode is started before the panel has been opened
+ * by the user.
+ *
+ * @param aCustomizing (optional) set to true if this was called while entering
+ * customization mode. If that's the case, we trust that customization
+ * mode will handle calling beginBatchUpdate and endBatchUpdate.
+ *
+ * @returns a Promise that resolves once the panel is ready to roll.
+ */
+ async ensureReady() {
+ if (this._isReady) {
+ return;
+ }
+
+ await window.delayedStartupPromise;
+ this._ensureEventListenersAdded();
+ this.panel.hidden = false;
+ this._isReady = true;
+ },
+
+ /**
+ * Shows a subview in the panel with a given ID.
+ *
+ * @param aViewId the ID of the subview to show.
+ * @param aAnchor the element that spawned the subview.
+ */
+ async showSubView(aViewId, aAnchor) {
+ this._ensureEventListenersAdded();
+ let viewNode = document.getElementById(aViewId);
+ if (!viewNode) {
+ console.error("Could not show panel subview with id: " + aViewId);
+ return;
+ }
+
+ if (!aAnchor) {
+ console.error(
+ "Expected an anchor when opening subview with id: " + aViewId
+ );
+ return;
+ }
+
+ let container = aAnchor.closest("panelmultiview");
+ if (container) {
+ container.showSubView(aViewId, aAnchor);
+ }
+ },
+
+ /**
+ * NB: The enable- and disableSingleSubviewPanelAnimations methods only
+ * affect the hiding/showing animations of single-subview panels (tempPanel
+ * in the showSubView method).
+ */
+ disableSingleSubviewPanelAnimations() {
+ this._disableAnimations = true;
+ },
+
+ enableSingleSubviewPanelAnimations() {
+ this._disableAnimations = false;
+ },
+
+ /**
+ * Sets the anchor node into the open or closed state, depending
+ * on the state of the panel.
+ */
+ _updatePanelButton() {
+ this.menuButton.open =
+ this.panel.state == "open" || this.panel.state == "showing";
+ },
+
+ /**
+ * Event handler for showing the Preferences/Layout view. Removes "checked"
+ * from all layout menu items and then checks the current layout menu item.
+ *
+ * @param {ViewShowingEvent} event - ViewShowing event.
+ */
+ _onPreferencesLayoutViewShow(event) {
+ event.target
+ .querySelectorAll("[name='viewlayoutgroup']")
+ .forEach(item => item.removeAttribute("checked"));
+
+ InitViewLayoutStyleMenu(event, true);
+ },
+
+ /**
+ * Event listener for showing the Folders view.
+ *
+ * @param {ViewShowingEvent} event - ViewShowing event.
+ */
+ _onFoldersViewShow(event) {
+ let about3Pane = document.getElementById("tabmail").currentAbout3Pane;
+ let folder = about3Pane.gFolder;
+
+ const paneHeaderMenuitem = event.target.querySelector(
+ '[name="paneheader"]'
+ );
+ if (about3Pane.folderPane.isFolderPaneHeaderHidden()) {
+ paneHeaderMenuitem.removeAttribute("checked");
+ } else {
+ paneHeaderMenuitem.setAttribute("checked", "true");
+ }
+
+ let { activeModes, canBeCompact, isCompact } = about3Pane.folderPane;
+ if (isCompact) {
+ activeModes.push("compact");
+ }
+
+ for (let item of event.target.querySelectorAll('[name="viewmessages"]')) {
+ let mode = item.getAttribute("value");
+ if (activeModes.includes(mode)) {
+ item.setAttribute("checked", "true");
+ if (mode == "all") {
+ item.disabled = activeModes.length == 1;
+ }
+ } else {
+ item.removeAttribute("checked");
+ }
+ if (mode == "compact") {
+ item.disabled = !canBeCompact;
+ }
+ }
+
+ goUpdateCommand("cmd_properties");
+ let propertiesMenuItem = document.getElementById("appmenu_properties");
+ if (folder?.server.type == "nntp") {
+ document.l10n.setAttributes(
+ propertiesMenuItem,
+ "menu-edit-newsgroup-properties"
+ );
+ } else {
+ document.l10n.setAttributes(
+ propertiesMenuItem,
+ "menu-edit-folder-properties"
+ );
+ }
+
+ let favoriteFolderMenu = document.getElementById("appmenu_favoriteFolder");
+ if (folder?.getFlag(Ci.nsMsgFolderFlags.Favorite)) {
+ favoriteFolderMenu.setAttribute("checked", "true");
+ } else {
+ favoriteFolderMenu.removeAttribute("checked");
+ }
+ },
+
+ _onToolsMenuShown(event) {
+ let noAccounts = MailServices.accounts.accounts.length == 0;
+ event.target.querySelector("#appmenu_searchCmd").disabled = noAccounts;
+ event.target.querySelector("#appmenu_filtersCmd").disabled = noAccounts;
+ },
+
+ _updateNotifications(notificationsChanged) {
+ let notifications = this._notifications;
+ if (!notifications || !notifications.length) {
+ if (notificationsChanged) {
+ this._clearAllNotifications();
+ }
+ return;
+ }
+
+ let doorhangers = notifications.filter(
+ n => !n.dismissed && !n.options.badgeOnly
+ );
+
+ if (this.panel.state == "showing" || this.panel.state == "open") {
+ // If the menu is already showing, then we need to dismiss all notifications
+ // since we don't want their doorhangers competing for attention
+ doorhangers.forEach(n => {
+ n.dismissed = true;
+ if (n.options.onDismissed) {
+ n.options.onDismissed(window);
+ }
+ });
+ this._clearBadge();
+ if (!notifications[0].options.badgeOnly) {
+ this._showBannerItem(notifications[0]);
+ }
+ } else if (doorhangers.length > 0) {
+ // Only show the doorhanger if the window is focused and not fullscreen
+ if (
+ (window.fullScreen && this.autoHideToolbarInFullScreen) ||
+ Services.focus.activeWindow !== window
+ ) {
+ this._showBadge(doorhangers[0]);
+ this._showBannerItem(doorhangers[0]);
+ } else {
+ this._clearBadge();
+ }
+ } else {
+ this._showBadge(notifications[0]);
+ this._showBannerItem(notifications[0]);
+ }
+ },
+
+ _clearAllNotifications() {
+ this._clearBadge();
+ this._clearBannerItem();
+ },
+
+ _formatDescriptionMessage(n) {
+ let text = {};
+ let array = n.options.message.split("<>");
+ text.start = array[0] || "";
+ text.name = n.options.name || "";
+ text.end = array[1] || "";
+ return text;
+ },
+
+ _showBadge(notification) {
+ let badgeStatus = this._getBadgeStatus(notification);
+ for (let menuButton of this.kAppMenuButtons) {
+ menuButton.setAttribute("badge-status", badgeStatus);
+ }
+ },
+
+ // "Banner item" here refers to an item in the hamburger panel menu. They will
+ // typically show up as a colored row in the panel.
+ _showBannerItem(notification) {
+ const supportedIds = [
+ "update-downloading",
+ "update-available",
+ "update-manual",
+ "update-unsupported",
+ "update-restart",
+ ];
+ if (!supportedIds.includes(notification.id)) {
+ return;
+ }
+
+ if (!this._panelBannerItem) {
+ this._panelBannerItem = this.mainView.querySelector(".panel-banner-item");
+ }
+
+ let l10nId = "appmenuitem-banner-" + notification.id;
+ document.l10n.setAttributes(this._panelBannerItem, l10nId);
+
+ this._panelBannerItem.setAttribute("notificationid", notification.id);
+ this._panelBannerItem.hidden = false;
+ this._panelBannerItem.notification = notification;
+ },
+
+ _clearBadge() {
+ for (let menuButton of this.kAppMenuButtons) {
+ menuButton.removeAttribute("badge-status");
+ }
+ },
+
+ _clearBannerItem() {
+ if (this._panelBannerItem) {
+ this._panelBannerItem.notification = null;
+ this._panelBannerItem.hidden = true;
+ }
+ },
+
+ _onNotificationButtonEvent(event, type) {
+ let notificationEl = getNotificationFromElement(event.target);
+
+ if (!notificationEl) {
+ throw new Error(
+ "PanelUI._onNotificationButtonEvent: couldn't find notification element"
+ );
+ }
+
+ if (!notificationEl.notification) {
+ throw new Error(
+ "PanelUI._onNotificationButtonEvent: couldn't find notification"
+ );
+ }
+
+ let notification = notificationEl.notification;
+
+ if (type == "secondarybuttoncommand") {
+ AppMenuNotifications.callSecondaryAction(window, notification);
+ } else {
+ AppMenuNotifications.callMainAction(window, notification, true);
+ }
+ },
+
+ _onBannerItemSelected(event) {
+ let target = event.target;
+ if (!target.notification) {
+ throw new Error(
+ "menucommand target has no associated action/notification"
+ );
+ }
+
+ event.stopPropagation();
+ AppMenuNotifications.callMainAction(window, target.notification, false);
+ },
+
+ _getPopupId(notification) {
+ return "appMenu-" + notification.id + "-notification";
+ },
+
+ _getBadgeStatus(notification) {
+ return notification.id;
+ },
+
+ _getPanelAnchor(candidate) {
+ let iconAnchor = candidate.badgeStack || candidate.icon;
+ return iconAnchor || candidate;
+ },
+
+ _ensureShortcutsShown(view = this.mainView) {
+ if (view.hasAttribute("added-shortcuts")) {
+ return;
+ }
+ view.setAttribute("added-shortcuts", "true");
+ for (let button of view.querySelectorAll("toolbarbutton[key]")) {
+ let keyId = button.getAttribute("key");
+ let key = document.getElementById(keyId);
+ if (!key) {
+ continue;
+ }
+ button.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(key));
+ }
+ },
+
+ folderViewMenuOnCommand(event) {
+ let about3Pane = document.getElementById("tabmail").currentAbout3Pane;
+ if (!about3Pane) {
+ return;
+ }
+
+ let mode = event.target.getAttribute("value");
+ if (mode == "toggle-header") {
+ about3Pane.folderPane.toggleHeader(event.target.hasAttribute("checked"));
+ return;
+ }
+
+ let activeModes = about3Pane.folderPane.activeModes;
+ let index = activeModes.indexOf(mode);
+ if (event.target.hasAttribute("checked")) {
+ if (index == -1) {
+ activeModes.push(mode);
+ }
+ } else if (index >= 0) {
+ activeModes.splice(index, 1);
+ }
+ about3Pane.folderPane.activeModes = activeModes;
+
+ this._onFoldersViewShow({ target: event.target.parentNode });
+ },
+
+ folderCompactMenuOnCommand(event) {
+ let about3Pane = document.getElementById("tabmail").currentAbout3Pane;
+ if (!about3Pane) {
+ return;
+ }
+
+ about3Pane.folderPane.isCompact = event.target.hasAttribute("checked");
+ },
+
+ setUIDensity(event) {
+ // Loops through all available options and uncheck them. This is necessary
+ // since the toolbarbuttons don't uncheck themselves even if they're radio.
+ for (let item of event.originalTarget
+ .closest(".panel-subview-body")
+ .querySelectorAll("toolbarbutton")) {
+ // Skip this item if it's the one clicked.
+ if (item == event.originalTarget) {
+ continue;
+ }
+
+ item.removeAttribute("checked");
+ }
+ // Update the UI density.
+ UIDensity.setMode(event.originalTarget.mode);
+ },
+};
+
+XPCOMUtils.defineConstant(this, "PanelUI", PanelUI);
+
+/**
+ * Gets the currently selected locale for display.
+ *
+ * @returns the selected locale
+ */
+function getLocale() {
+ return Services.locale.appLocaleAsBCP47;
+}
+
+/**
+ * Given a DOM node inside a <popupnotification>, return the parent <popupnotification>.
+ */
+function getNotificationFromElement(aElement) {
+ return aElement.closest("popupnotification");
+}
+
+/**
+ * This object is Thunderbird's version of the same object in
+ * browser/base/content/browser-addons.js.
+ */
+var gExtensionsNotifications = {
+ initialized: false,
+ init() {
+ this.updateAlerts();
+ this.boundUpdate = this.updateAlerts.bind(this);
+ ExtensionsUI.on("change", this.boundUpdate);
+ this.initialized = true;
+ },
+
+ uninit() {
+ // uninit() can race ahead of init() in some cases, if that happens,
+ // we have no handler to remove.
+ if (!this.initialized) {
+ return;
+ }
+ ExtensionsUI.off("change", this.boundUpdate);
+ },
+
+ get l10n() {
+ if (this._l10n) {
+ return this._l10n;
+ }
+ return (this._l10n = new Localization(
+ ["messenger/addonNotifications.ftl", "branding/brand.ftl"],
+ true
+ ));
+ },
+
+ _createAddonButton(l10nId, addon, callback) {
+ let text = this.l10n.formatValueSync(l10nId, { addonName: addon.name });
+ let button = document.createXULElement("toolbarbutton");
+ button.setAttribute("wrap", "true");
+ button.setAttribute("label", text);
+ button.setAttribute("tooltiptext", text);
+ const DEFAULT_EXTENSION_ICON =
+ "chrome://messenger/skin/icons/new/compact/extension.svg";
+ button.setAttribute("image", addon.iconURL || DEFAULT_EXTENSION_ICON);
+ button.className = "addon-banner-item subviewbutton";
+
+ button.addEventListener("command", callback);
+ PanelUI.addonNotificationContainer.appendChild(button);
+ },
+
+ updateAlerts() {
+ let gBrowser = document.getElementById("tabmail");
+ let sideloaded = ExtensionsUI.sideloaded;
+ let updates = ExtensionsUI.updates;
+
+ let container = PanelUI.addonNotificationContainer;
+
+ while (container.firstChild) {
+ container.firstChild.remove();
+ }
+
+ let items = 0;
+ for (let update of updates) {
+ if (++items > 4) {
+ break;
+ }
+ this._createAddonButton(
+ "webext-perms-update-menu-item",
+ update.addon,
+ evt => {
+ ExtensionsUI.showUpdate(gBrowser, update);
+ }
+ );
+ }
+
+ for (let addon of sideloaded) {
+ if (++items > 4) {
+ break;
+ }
+ this._createAddonButton("webext-perms-sideload-menu-item", addon, evt => {
+ // We need to hide the main menu manually because the toolbarbutton is
+ // removed immediately while processing this event, and PanelUI is
+ // unable to identify which panel should be closed automatically.
+ PanelUI.hide();
+ ExtensionsUI.showSideloaded(gBrowser, addon);
+ });
+ }
+ },
+};
+
+addEventListener("unload", () => gExtensionsNotifications.uninit(), {
+ once: true,
+});