Bug 1583529 - Do not show today pane in tabs like preferences tab. r=darktrojan
authorPaul Morris <paul@thunderbird.net>
Mon, 30 Sep 2019 17:09:36 -0400
changeset 37073 8e2b67d5ceb3750a49184dbfda9f54f19ab259c5
parent 37072 f10404956c726a4e69a50fadec2110788ce6de08
child 37074 1daf024a9ced503a886cdc78c01da4836a933238
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewersdarktrojan
bugs1583529
Bug 1583529 - Do not show today pane in tabs like preferences tab. r=darktrojan
calendar/lightning/content/messenger-overlay-sidebar.js
calendar/lightning/content/messenger-overlay-sidebar.xul
calendar/test/browser/browser_todayPane_visibility.js
calendar/test/browser/head.js
--- a/calendar/lightning/content/messenger-overlay-sidebar.js
+++ b/calendar/lightning/content/messenger-overlay-sidebar.js
@@ -45,53 +45,54 @@ var calendarTabMonitor = {
     } else if (window.calItemSaveControls) {
       // we need to reset the labels of the menu controls for saving if we
       // are not switching to an item tab and displayed an item tab before
       let saveMenu = document.getElementById("ltnSave");
       let saveandcloseMenu = document.getElementById("ltnSaveAndClose");
       saveMenu.label = window.calItemSaveControls.saveMenu.label;
       saveandcloseMenu.label = window.calItemSaveControls.saveandcloseMenu.label;
     }
+
+    // Change the mode (gCurrentMode) to match the new tab.
+    switch (aNewTab.mode.name) {
+      case "calendar":
+        calSwitchToCalendarMode();
+        break;
+      case "tasks":
+        calSwitchToTaskMode();
+        break;
+      case "preferencesTab":
+      case "contentTab":
+        calSwitchToMode("special");
+        break;
+      default:
+        calSwitchToMode("mail");
+        break;
+    }
   },
 };
 
 var calendarTabType = {
   name: "calendar",
   panelId: "calendarTabPanel",
   modes: {
     calendar: {
       type: "calendar",
       maxTabs: 1,
       openTab: function(aTab, aArgs) {
         gLastShownCalendarView = getLastCalendarView();
-
         aTab.title = aArgs.title;
-        if (!("background" in aArgs) || !aArgs.background) {
-          // Only do calendar mode switching if the tab is opened in
-          // foreground.
-          ltnSwitch2Calendar();
-        }
       },
-
-      showTab: function(aTab) {
-        ltnSwitch2Calendar();
-      },
-      closeTab: function(aTab) {
-        if (gCurrentMode == "calendar") {
-          // Only revert menu hacks if closing the active tab, otherwise we
-          // would switch to mail mode even if in task mode and closing the
-          // calendar tab.
-          ltnSwitch2Mail();
-        }
-      },
+      showTab: function(tab) {},
+      closeTab: function(tab) {},
 
       persistTab: function(aTab) {
         let tabmail = document.getElementById("tabmail");
         return {
-          // Since we do strange tab switching logic in ltnSwitch2Calendar,
+          // Since we do strange tab switching logic in calSwitchToCalendarMode,
           // we should store the current tab state ourselves.
           background: aTab != tabmail.currentTabInfo,
         };
       },
 
       restoreTab: function(aTabmail, aState) {
         aState.title = cal.l10n.getLtnString("tabTitleCalendar");
         aTabmail.openTab("calendar", aState);
@@ -107,36 +108,24 @@ var calendarTabType = {
       onEvent: (aEvent, aTab) => calendarController2.onEvent(aEvent),
     },
 
     tasks: {
       type: "tasks",
       maxTabs: 1,
       openTab: function(aTab, aArgs) {
         aTab.title = aArgs.title;
-        if (!("background" in aArgs) || !aArgs.background) {
-          ltnSwitch2Task();
-        }
       },
-      showTab: function(aTab) {
-        ltnSwitch2Task();
-      },
-      closeTab: function(aTab) {
-        if (gCurrentMode == "task") {
-          // Only revert menu hacks if closing the active tab, otherwise we
-          // would switch to mail mode even if in calendar mode and closing the
-          // tasks tab.
-          ltnSwitch2Mail();
-        }
-      },
+      showTab: function(tab) {},
+      closeTab: function(tab) {},
 
       persistTab: function(aTab) {
         let tabmail = document.getElementById("tabmail");
         return {
-          // Since we do strange tab switching logic in ltnSwitch2Task,
+          // Since we do strange tab switching logic in calSwitchToTaskMode,
           // we should store the current tab state ourselves.
           background: aTab != tabmail.currentTabInfo,
         };
       },
 
       restoreTab: function(aTabmail, aState) {
         aState.title = cal.l10n.getLtnString("tabTitleTasks");
         aTabmail.openTab("tasks", aState);
@@ -148,25 +137,17 @@ var calendarTabType = {
 
       supportsCommand: (aCommand, aTab) => calendarController2.supportsCommand(aCommand),
       isCommandEnabled: (aCommand, aTab) => calendarController2.isCommandEnabled(aCommand),
       doCommand: (aCommand, aTab) => calendarController2.doCommand(aCommand),
       onEvent: (aEvent, aTab) => calendarController2.onEvent(aEvent),
     },
   },
 
-  /**
-   * Because calendar does some direct menu manipulation, we need to
-   * change to the mail mode to clean up after those hacks.
-   *
-   * @param {Object} aTab  A tab info object
-   */
-  saveTabState: function(aTab) {
-    ltnSwitch2Mail();
-  },
+  saveTabState: function(tab) {},
 };
 
 /**
  * For details about tab info objects and the tabmail interface see:
  * comm/mail/base/content/mailTabs.js
  * comm/mail/base/content/tabmail.js
  */
 var calendarItemTabType = {
@@ -506,55 +487,57 @@ function updateTodayPaneButtonDate() {
  * @param aShow     If true, the mode will be switched to calendar if not
  *                    already there.
  */
 function switchCalendarView(aType, aShow) {
   gLastShownCalendarView = aType;
 
   if (aShow && gCurrentMode != "calendar") {
     // This function in turn calls switchToView(), so return afterwards.
-    ltnSwitch2Calendar();
+    calSwitchToCalendarMode();
     return;
   }
 
   switchToView(aType);
 }
 
 /**
  * This function has the sole responsibility to switch back to
- * mail mode (by calling ltnSwitch2Mail()) if we are getting
+ * mail mode (by calling calSwitchToMode("mail")) if we are getting
  * notifications from other panels (besides the calendar views)
  * but find out that we're not in mail mode. This situation can
  * for example happen if we're in calendar mode but the 'new mail'
  * slider gets clicked and wants to display the appropriate mail.
  * All necessary logic for switching between the different modes
- * should live inside of the corresponding functions:
- * - ltnSwitch2Mail()
- * - ltnSwitch2Calendar()
- * - ltnSwitch2Task()
+ * should live inside of the corresponding functions like:
+ * - calSwitchToCalendarMode()
+ * - calSwitchToTaskMode()
+ * - calSwitchToMode()
  */
 function LtnObserveDisplayDeckChange(event) {
   let deck = event.target;
 
   // Bug 309505: The 'select' event also fires when we change the selected
   // panel of calendar-view-box.  Workaround with this check.
   if (deck.id != "calendarDisplayDeck") {
     return;
   }
 
   let id = deck.selectedPanel && deck.selectedPanel.id;
 
   // Switch back to mail mode in case we find that this
   // notification has been fired but we're still in calendar or task mode.
   // Specifically, switch back if we're *not* in mail mode but the notification
   // did *not* come from either the "calendar-view-box" or the "calendar-task-box".
-  if (gCurrentMode != "mail") {
-    if (id != "calendar-view-box" && id != "calendar-task-box") {
-      ltnSwitch2Mail();
-    }
+  if (
+    (gCurrentMode == "calendar" || gCurrentMode == "task") &&
+    id != "calendar-view-box" &&
+    id != "calendar-task-box"
+  ) {
+    calSwitchToMode("mail");
   }
 }
 
 function ltnFinish() {
   cal.getCalendarManager().removeObserver(gInvitationsCalendarManagerObserver);
 
   // Remove listener for mailContext.
   let mailContextPopup = document.getElementById("mailContext");
@@ -629,23 +612,24 @@ function openInvitationsDialog() {
   );
 }
 
 /**
  * The current mode defining the current mode we're in. Allowed values are:
  *  - 'mail'
  *  - 'calendar'
  *  - 'task'
+ *  - 'special' - For special tabs like preferences, add-ons manager, about:xyz, etc.
  * @global
  */
 var gCurrentMode = "mail";
 
 /**
  * Changes the mode (gCurrentMode) and adapts the UI to the new mode.
- * @param {string} [mode="mail"] - the new mode: one of 'mail', 'calendar' or 'task'
+ * @param {string} [mode="mail"] - the new mode: 'mail', 'calendar', 'task', etc.
  */
 function changeMode(mode = "mail") {
   gCurrentMode = mode; // eslint-disable-line no-global-assign
 
   document
     .querySelectorAll(
       `menuitem[command="switch2calendar"],menuitem[command="switch2task"],
        toolbarbutton[command="switch2calendar"],toolbarbutton[command="switch2task"]`
@@ -660,31 +644,41 @@ function changeMode(mode = "mail") {
 
   TodayPane.onModeModified();
   if (gCurrentMode != "calendar") {
     timeIndicator.cancel();
   }
 }
 
 /**
- * Switches to the mail mode.
+ * For switching to modes like "mail" or "special". (For switching to "calendar"
+ * and "task" modes use calSwitchToCalendarMode and calSwitchToTaskMode.)
+ *
+ * @param {string} mode  The mode to switch to.
  */
-function ltnSwitch2Mail() {
-  if (gCurrentMode != "mail") {
-    changeMode("mail");
+function calSwitchToMode(mode) {
+  if (mode != "mail" && mode != "special") {
+    cal.WARN("Attempted to switch to unknown mode: " + mode);
+    return;
+  }
+  if (gCurrentMode != mode) {
+    const previousMode = gCurrentMode;
+    changeMode(mode);
 
-    document.commandDispatcher.updateCommands("calendar_commands");
+    if (previousMode == "calendar" || previousMode == "task") {
+      document.commandDispatcher.updateCommands("calendar_commands");
+    }
     window.setCursor("auto");
   }
 }
 
 /**
  * Switches to the calendar mode.
  */
-function ltnSwitch2Calendar() {
+function calSwitchToCalendarMode() {
   if (gCurrentMode != "calendar") {
     changeMode("calendar");
 
     // display the calendar panel on the display deck
     let deck = document.getElementById("calendarDisplayDeck");
     deck.selectedPanel = document.getElementById("calendar-view-box");
 
     // show the last displayed type of calendar view
@@ -700,17 +694,17 @@ function ltnSwitch2Calendar() {
     // Load the unifinder if it isn't already loaded.
     ensureUnifinderLoaded();
   }
 }
 
 /**
  * Switches to the task mode.
  */
-function ltnSwitch2Task() {
+function calSwitchToTaskMode() {
   if (gCurrentMode != "task") {
     changeMode("task");
 
     // display the task panel on the display deck
     let deck = document.getElementById("calendarDisplayDeck");
     deck.selectedPanel = document.getElementById("calendar-task-box");
 
     document.getElementById("calMinimonth").setAttribute("freebusy", "true");
--- a/calendar/lightning/content/messenger-overlay-sidebar.xul
+++ b/calendar/lightning/content/messenger-overlay-sidebar.xul
@@ -349,26 +349,28 @@
       <label id="status-freebusy-free-label"
              value="&event.freebusy.legend.free;"
              hidden="true"/>
       <label id="status-freebusy-busy-label"
              value="&event.freebusy.legend.busy;"
              hidden="true"/>
     </hbox>
     <!-- end event/task in tab statusbarpanels -->
-    <hbox id="calendar-show-todaypane-panel"
-          class="statusbarpanel"
-          pack="center">
+    <calendar-modebox id="calendar-show-todaypane-panel"
+                      class="statusbarpanel"
+                      mode="mail,calendar,task"
+                      collapsedinmodes="special"
+                      pack="center">
       <toolbarbutton id="calendar-status-todaypane-button"
                      type="checkbox"
                      label="&todaypane.statusButton.label;"
                      tooltiptext="&calendar.todaypane.button.tooltip;"
                      observes="calendar_toggle_todaypane_command"
                      command="calendar_toggle_todaypane_command"/>
-    </hbox>
+    </calendar-modebox>
     <hbox id="calendar-invitations-panel"
           class="statusbarpanel"
           insertbefore="unreadMessageCount,totalMessageCount"
           oncommand="openInvitationsDialog()">
       <label id="calendar-invitations-label"
              class="text-link"
              onclick="openInvitationsDialog()"
              onkeypress="if (event.key == 'Enter') { openInvitationsDialog(); }"/>
--- a/calendar/test/browser/browser_todayPane_visibility.js
+++ b/calendar/test/browser/browser_todayPane_visibility.js
@@ -1,25 +1,28 @@
 /* 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 openCalendarTab, openTasksTab, selectFolderTab */
+/* globals openAddonsTab, openCalendarTab, openTasksTab, selectFolderTab,
+  openPreferencesTab */
 
 async function clickTodayPaneButton() {
   const button = document.getElementById("calendar-status-todaypane-button");
   // The today pane button will be hidden for certain tabs (e.g. preferences), and then
   // the user won't be able to click it, so we shouldn't be able to here either.
   if (BrowserTestUtils.is_visible(button)) {
     EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 });
   }
   await new Promise(resolve => setTimeout(resolve));
 }
 
 // Test that today pane is visible/collapsed correctly for various tab types.
+// In all cases today pane should not be visible in preferences or addons tab.
+// Test that the today pane button is visible/hidden for various tab types.
 add_task(async () => {
   const todayPane = document.getElementById("today-pane-panel");
 
   // Show today pane in folder (mail) tab, but not in other tabs.
   await selectFolderTab();
   if (!BrowserTestUtils.is_visible(todayPane)) {
     await clickTodayPaneButton();
   }
@@ -33,39 +36,64 @@ add_task(async () => {
   }
 
   await selectFolderTab();
   ok(BrowserTestUtils.is_visible(todayPane), "today pane is visible in folder tab");
   await openCalendarTab();
   is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in calendar tab");
   await openTasksTab();
   is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in tasks tab");
+  await openPreferencesTab();
+  is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in preferences tab");
+  await openAddonsTab();
+  is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in addons tab");
 
   // Show today pane in calendar tab, but not in other tabs.
   // Hide it in folder tab.
   await selectFolderTab();
   await clickTodayPaneButton();
   // Show it in calendar tab.
   await openCalendarTab();
   await clickTodayPaneButton();
 
   await selectFolderTab();
   is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in folder tab");
   await openCalendarTab();
   ok(BrowserTestUtils.is_visible(todayPane), "today pane is visible in calendar tab");
   await openTasksTab();
   is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in tasks tab");
+  await openPreferencesTab();
+  is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in preferences tab");
+  await openAddonsTab();
+  is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in addons tab");
 
   // Show today pane in tasks tab, but not in other tabs.
   // Hide it in calendar tab.
   await openCalendarTab();
   await clickTodayPaneButton();
   // Show it in tasks tab.
   await openTasksTab();
   await clickTodayPaneButton();
 
   await selectFolderTab();
   is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in folder tab");
   await openCalendarTab();
   is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in calendar tab");
   await openTasksTab();
   ok(BrowserTestUtils.is_visible(todayPane), "today pane is visible in tasks tab");
+  await openPreferencesTab();
+  is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in preferences tab");
+  await openAddonsTab();
+  is(BrowserTestUtils.is_visible(todayPane), false, "today pane is collapsed in addons tab");
+
+  // Check the visibility of the today pane button.
+  const button = document.getElementById("calendar-status-todaypane-button");
+  await selectFolderTab();
+  ok(BrowserTestUtils.is_visible(button), "today pane button is visible in folder tab");
+  await openCalendarTab();
+  ok(BrowserTestUtils.is_visible(button), "today pane button is visible in calendar tab");
+  await openTasksTab();
+  ok(BrowserTestUtils.is_visible(button), "today pane button is visible in tasks tab");
+  await openPreferencesTab();
+  is(BrowserTestUtils.is_visible(button), false, "today pane button is hidden in preferences tab");
+  await openAddonsTab();
+  is(BrowserTestUtils.is_visible(button), false, "today pane button is hidden in addons tab");
 });
--- a/calendar/test/browser/head.js
+++ b/calendar/test/browser/head.js
@@ -1,18 +1,21 @@
 /* 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/. */
 
 /* exported openCalendarTab, setCalendarView, closeCalendarTab, openTasksTab,
- * closeTasksTab, selectFolderTab
+ * closeTasksTab, selectFolderTab, openPreferencesTab, closePreferencesTab,
+ * openAddonsTab, closeAddonsTab
  */
 
 /* import-globals-from ../../base/content/calendar-views-utils.js */
 
+/* globals openOptionsDialog, openAddonsMgr */
+
 async function openCalendarTab() {
   let tabmail = document.getElementById("tabmail");
   let calendarMode = tabmail.tabModes.calendar;
 
   if (calendarMode.tabs.length == 1) {
     tabmail.selectedTab = calendarMode.tabs[0];
   } else {
     let calendarTabButton = document.getElementById("calendar-tab-button");
@@ -89,12 +92,72 @@ async function selectFolderTab() {
   tabmail.selectedTab = folderMode.tabs[0];
 
   is(folderMode.tabs.length > 0, true, "at least one folder tab is open");
   is(tabmail.selectedTab, folderMode.tabs[0], "a folder tab is selected");
 
   await new Promise(resolve => setTimeout(resolve));
 }
 
+async function openPreferencesTab() {
+  const tabmail = document.getElementById("tabmail");
+  const prefsMode = tabmail.tabModes.preferencesTab;
+
+  if (prefsMode.tabs.length == 1) {
+    tabmail.selectedTab = prefsMode.tabs[0];
+  } else {
+    openOptionsDialog();
+  }
+
+  is(prefsMode.tabs.length, 1, "preferences tab is open");
+  is(tabmail.selectedTab, prefsMode.tabs[0], "preferences tab is selected");
+
+  await new Promise(resolve => setTimeout(resolve));
+}
+
+async function closePreferencesTab() {
+  let tabmail = document.getElementById("tabmail");
+  let prefsMode = tabmail.tabModes.preferencesTab;
+
+  if (prefsMode.tabs.length == 1) {
+    tabmail.closeTab(prefsMode.tabs[0]);
+  }
+
+  is(prefsMode.tabs.length, 0, "preferences tab is not open");
+
+  await new Promise(resolve => setTimeout(resolve));
+}
+
+async function openAddonsTab() {
+  const tabmail = document.getElementById("tabmail");
+  const contentMode = tabmail.tabModes.contentTab;
+
+  if (contentMode.tabs.length == 1) {
+    tabmail.selectedTab = contentMode.tabs[0];
+  } else {
+    openAddonsMgr("addons://list/extension");
+  }
+
+  is(contentMode.tabs.length, 1, "addons tab is open");
+  is(tabmail.selectedTab, contentMode.tabs[0], "addons tab is selected");
+
+  await new Promise(resolve => setTimeout(resolve));
+}
+
+async function closeAddonsTab() {
+  let tabmail = document.getElementById("tabmail");
+  let contentMode = tabmail.tabModes.contentTab;
+
+  if (contentMode.tabs.length == 1) {
+    tabmail.closeTab(contentMode.tabs[0]);
+  }
+
+  is(contentMode.tabs.length, 0, "addons tab is not open");
+
+  await new Promise(resolve => setTimeout(resolve));
+}
+
 registerCleanupFunction(async () => {
   await closeCalendarTab();
   await closeTasksTab();
+  await closePreferencesTab();
+  await closeAddonsTab();
 });