Bug 1748449 - Part 4: Hide invitation display when switching tabs or folders. r=aleca
Also hides the message body when the invitation display is shown. Differential Revision: https://phabricator.services.mozilla.com/D151040 --HG-- extra : histedit_source : 86d839553c7570a30f7cf6411caaeb21b981759b
This commit is contained in:
Родитель
2fdcc9feaf
Коммит
efa2ae47c8
|
@ -12,18 +12,37 @@
|
|||
*/
|
||||
const CalInvitationDisplay = {
|
||||
/**
|
||||
* The node we render the invitation to.
|
||||
* The hbox element that wraps the invitation. We need to make this
|
||||
* scrollable so larger invitations can be seen.
|
||||
*
|
||||
* @type {XULElement}
|
||||
*/
|
||||
container: null,
|
||||
|
||||
/**
|
||||
* The node the invitation details are rendered into.
|
||||
*
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
display: null,
|
||||
|
||||
/**
|
||||
* The <browser> element that displays the message body. This is hidden
|
||||
* when the invitation details are displayed.
|
||||
*/
|
||||
body: null,
|
||||
|
||||
/**
|
||||
* Creates a new instance and sets up listeners.
|
||||
*/
|
||||
init() {
|
||||
this.container = document.getElementById("messagepaneContainer");
|
||||
this.display = document.getElementById("calendarInvitationDisplay");
|
||||
this.body = document.getElementById("messagepane");
|
||||
|
||||
window.addEventListener("onItipItemCreation", this);
|
||||
window.addEventListener("messagepane-unloaded", this);
|
||||
document.getElementById("msgHeaderView").addEventListener("message-header-pane-hidden", this);
|
||||
gMessageListeners.push(this);
|
||||
},
|
||||
|
||||
|
@ -38,28 +57,58 @@
|
|||
case "DOMContentLoaded":
|
||||
this.init();
|
||||
break;
|
||||
|
||||
case "onItipItemCreation":
|
||||
let panel = document.createElement("calendar-invitation-panel");
|
||||
this.display.replaceChildren(panel);
|
||||
panel.itipItem = evt.detail;
|
||||
this.display.hidden = false;
|
||||
this.show(evt.detail);
|
||||
break;
|
||||
case "messagepane-unloaded":
|
||||
case "message-header-pane-hidden":
|
||||
this.hide();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the panel from view each time a new message is loaded.
|
||||
* Hide the invitation display each time a new message to display is
|
||||
* detected. If the message contains an invitation it will be displayed
|
||||
* in the "onItipItemCreation" handler.
|
||||
*/
|
||||
onStartHeaders() {
|
||||
this.display.hidden = true;
|
||||
this.display.replaceChildren();
|
||||
this.hide();
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by messageHeaderSink.
|
||||
*/
|
||||
onEndHeaders() {},
|
||||
|
||||
/**
|
||||
* Displays the invitation display with the data from the provided
|
||||
* calIItipItem.
|
||||
*
|
||||
* @param {calIItipItem} item
|
||||
*/
|
||||
show(item) {
|
||||
this.container.classList.add("scrollable");
|
||||
|
||||
let panel = document.createElement("calendar-invitation-panel");
|
||||
this.display.replaceChildren(panel);
|
||||
panel.itipItem = item;
|
||||
this.display.hidden = false;
|
||||
this.body.hidden = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the invitation display from view, resetting any changes made
|
||||
* to the container and message pane.
|
||||
*/
|
||||
hide() {
|
||||
this.container.classList.remove("scrollable");
|
||||
this.display.hidden = true;
|
||||
this.display.replaceChildren();
|
||||
this.body.hidden = false;
|
||||
},
|
||||
};
|
||||
|
||||
window.addEventListener("DOMContentLoaded", CalInvitationDisplay, { once: true });
|
||||
|
|
|
@ -60,16 +60,11 @@ var calImipBar = {
|
|||
// Add a listener to gMessageListeners defined in msgHdrView.js
|
||||
gMessageListeners.push(calImipBar);
|
||||
|
||||
// We need to extend the HideMessageHeaderPane function to also hide the
|
||||
// message header pane. Otherwise, the imip bar will still be shown when
|
||||
// changing folders.
|
||||
if (!calImipBar.tbHideMessageHeaderPane) {
|
||||
calImipBar.tbHideMessageHeaderPane = HideMessageHeaderPane;
|
||||
HideMessageHeaderPane = function(...args) {
|
||||
calImipBar.resetBar();
|
||||
calImipBar.tbHideMessageHeaderPane(...args);
|
||||
};
|
||||
}
|
||||
// Hook into this event to hide the message header pane otherwise, the imip
|
||||
// bar will still be shown when changing folders.
|
||||
document.getElementById("msgHeaderView").addEventListener("message-header-pane-hidden", () => {
|
||||
calImipBar.resetBar();
|
||||
});
|
||||
|
||||
// Set up our observers
|
||||
Services.obs.addObserver(calImipBar, "onItipItemCreation");
|
||||
|
|
|
@ -97,6 +97,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the value of the title displayed as a string.
|
||||
* @type {string}
|
||||
*/
|
||||
get fullTitle() {
|
||||
return [
|
||||
...this.shadowRoot.querySelectorAll(
|
||||
".calendar-invitation-panel-intro, .calendar-invitation-panel-title"
|
||||
),
|
||||
]
|
||||
.map(node => node.textContent)
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
document.l10n.disconnectRoot(this.shadowRoot);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,21 @@
|
|||
* glanced at quickly to figure out the date of an event.
|
||||
*/
|
||||
class CalendarMinidate extends HTMLElement {
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
_monthSpan;
|
||||
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
_daySpan;
|
||||
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
_yearSpan;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: "open" });
|
||||
|
@ -37,6 +52,9 @@
|
|||
this.shadowRoot.appendChild(
|
||||
document.getElementById("calendarMinidate").content.cloneNode(true)
|
||||
);
|
||||
this._monthSpan = this.shadowRoot.querySelector(".calendar-minidate-month");
|
||||
this._daySpan = this.shadowRoot.querySelector(".calendar-minidate-day");
|
||||
this._yearSpan = this.shadowRoot.querySelector(".calendar-minidate-year");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,12 +63,18 @@
|
|||
*/
|
||||
set date(value) {
|
||||
let { month, day, year } = getParts(cal.dtz.dateTimeToJsDate(value));
|
||||
let monthSpan = this.shadowRoot.querySelector(".calendar-minidate-month");
|
||||
let daySpan = this.shadowRoot.querySelector(".calendar-minidate-day");
|
||||
let yearSpan = this.shadowRoot.querySelector(".calendar-minidate-year");
|
||||
monthSpan.textContent = month;
|
||||
daySpan.textContent = day;
|
||||
yearSpan.textContent = year;
|
||||
this._monthSpan.textContent = month;
|
||||
this._daySpan.textContent = day;
|
||||
this._yearSpan.textContent = year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the displayed date as a string in the format
|
||||
* "month day year".
|
||||
* @type {string}
|
||||
*/
|
||||
get fullDate() {
|
||||
return `${this._monthSpan.textContent} ${this._daySpan.textContent} ${this._yearSpan.textContent}`;
|
||||
}
|
||||
}
|
||||
customElements.define("calendar-minidate", CalendarMinidate);
|
||||
|
|
|
@ -27,4 +27,5 @@ skip-if = os == 'win'
|
|||
[browser_imipBarRepeatCancel.js]
|
||||
[browser_imipBarRepeatUpdates.js]
|
||||
[browser_imipBarUpdates.js]
|
||||
[browser_invitationDisplaySwitching.js]
|
||||
[browser_unsupportedFreq.js]
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Tests the invitation display is hidden when appropriate.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
var {
|
||||
add_message_sets_to_folders,
|
||||
be_in_folder,
|
||||
create_folder,
|
||||
create_thread,
|
||||
open_folder_in_new_tab,
|
||||
close_tab,
|
||||
wait_for_message_display_completion,
|
||||
inboxFolder,
|
||||
select_click_row,
|
||||
} = ChromeUtils.import("resource://testing-common/mozmill/FolderDisplayHelpers.jsm");
|
||||
|
||||
let folderA;
|
||||
let folderB;
|
||||
|
||||
/**
|
||||
* Copied from mail/components/extensions/test/browser/head.js. Allows an .eml
|
||||
* file to be added to a folder.
|
||||
*/
|
||||
async function createMessageFromFile(folder, path) {
|
||||
let message = await IOUtils.readUTF8(path);
|
||||
// A cheap hack to make this acceptable to addMessageBatch. It works for
|
||||
// existing uses but may not work for future uses.
|
||||
let fromChunks = message.match(/From: .* <(.*@.*)>/);
|
||||
if (fromChunks) {
|
||||
let fromAddress = fromChunks[0];
|
||||
message = `From ${fromAddress}\r\n${message}`;
|
||||
}
|
||||
folder.addMessageBatch([message]);
|
||||
folder.callFilterPlugins(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the folders used for testing.
|
||||
*/
|
||||
add_setup(async function() {
|
||||
let identity = MailServices.accounts.createIdentity();
|
||||
identity.email = "receiver@example.com";
|
||||
identity.valid = true;
|
||||
|
||||
let account = MailServices.accounts.createAccount();
|
||||
account.incomingServer = MailServices.accounts.createIncomingServer(
|
||||
"receiver",
|
||||
"example.com",
|
||||
"imap"
|
||||
);
|
||||
account.addIdentity(identity);
|
||||
|
||||
folderA = await create_folder("Folder A");
|
||||
folderB = await create_folder("Folder B");
|
||||
Services.prefs.setBoolPref("calendar.itip.newInvitationDisplay", true);
|
||||
registerCleanupFunction(async () => {
|
||||
be_in_folder(inboxFolder);
|
||||
let trash = folderA.rootFolder.getFolderWithFlags(Ci.nsMsgFolderFlags.Trash);
|
||||
folderA.deleteSelf(null);
|
||||
folderB.deleteSelf(null);
|
||||
trash.emptyTrash(null, null);
|
||||
MailServices.accounts.removeAccount(account);
|
||||
Services.prefs.setBoolPref("calendar.itip.newInvitationDisplay", false);
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests the invitation display is correctly hidden when switching between
|
||||
* folders or to a tab.
|
||||
*/
|
||||
add_task(async function testInvitationDisplaySwitching() {
|
||||
let display = document.getElementById("calendarInvitationDisplay");
|
||||
be_in_folder(folderA);
|
||||
await add_message_sets_to_folders([folderA], [create_thread(1)]);
|
||||
await createMessageFromFile(folderA, getTestFilePath("../invitations/data/single-event.eml"));
|
||||
await createMessageFromFile(folderA, getTestFilePath("../invitations/data/update-minor.eml"));
|
||||
|
||||
info("Ensuring invitation display is initially hidden.");
|
||||
select_click_row(0);
|
||||
Assert.ok(display.hidden, "invitation display is hidden");
|
||||
|
||||
info("Ensuring invitation display is shown when a message with an invitation is selected");
|
||||
select_click_row(1);
|
||||
Assert.ok(!display.hidden, "invitation display is not hidden");
|
||||
|
||||
let panel = document.querySelector("calendar-invitation-panel");
|
||||
let minidate = panel.shadowRoot.querySelector("calendar-minidate");
|
||||
Assert.equal(minidate.fullDate, "Mar 16 2022");
|
||||
let header = panel.shadowRoot.querySelector("calendar-invitation-panel-header");
|
||||
Assert.equal(header.fullTitle, "Sender has invited you to: Single Event");
|
||||
|
||||
info("Ensuring invitation display is hidden when switching folders.");
|
||||
be_in_folder(folderB);
|
||||
Assert.ok(display.hidden, "invitation display is hidden when switching folders");
|
||||
|
||||
info("Ensuring invitation display is hidden when opening a folder in a new tab.");
|
||||
be_in_folder(folderA);
|
||||
select_click_row(1);
|
||||
Assert.ok(!display.hidden);
|
||||
open_folder_in_new_tab(folderB);
|
||||
wait_for_message_display_completion(null);
|
||||
Assert.ok(display.hidden, "invitation display is hidden when viewing a new tab");
|
||||
close_tab(1);
|
||||
});
|
|
@ -23,7 +23,7 @@ var { CalendarTestUtils } = ChromeUtils.import(
|
|||
"resource://testing-common/calendar/CalendarTestUtils.jsm"
|
||||
);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
registerCleanupFunction(async () => {
|
||||
// Some tests that open new windows don't return focus to the main window
|
||||
// in a way that satisfies mochitest, and the test times out.
|
||||
Services.focus.focusedWindow = window;
|
||||
|
@ -32,6 +32,8 @@ registerCleanupFunction(() => {
|
|||
let searchInput = document.getElementById("searchInput");
|
||||
searchInput.focus();
|
||||
searchInput.blur();
|
||||
|
||||
await CalendarTestUtils.closeCalendarTab(window);
|
||||
});
|
||||
|
||||
class EmailTransport extends CalItipDefaultEmailTransport {
|
||||
|
|
|
@ -280,8 +280,10 @@
|
|||
#include ../../../calendar/base/content/widgets/calendar-invitation-panel.xhtml
|
||||
#include ../../../calendar/base/content/widgets/calendar-minidate.xhtml
|
||||
|
||||
<!-- The calendar invitation panel is displayed here. -->
|
||||
<html:div id="calendarInvitationDisplay" hidden="hidden"></html:div>
|
||||
<vbox id="messagepaneContainer" flex="1">
|
||||
<!-- The calendar invitation panel is displayed here. -->
|
||||
<html:div id="calendarInvitationDisplay" hidden="hidden"></html:div>
|
||||
</vbox>
|
||||
|
||||
<!-- message view -->
|
||||
<browser id="messagepane"
|
||||
|
|
|
@ -753,8 +753,11 @@
|
|||
<vbox id="mail-notification-top">
|
||||
<!-- notificationbox will be added here lazily. -->
|
||||
</vbox>
|
||||
<vbox flex="1" class="messagepane-container">
|
||||
<html:div id="calendarInvitationDisplay" hidden="hidden"></html:div>
|
||||
<vbox id="messagepaneContainer" flex="1">
|
||||
<html:div id="calendarInvitationDisplay" hidden="true">
|
||||
<!-- The calendar invitation display widget is loaded
|
||||
here. -->
|
||||
</html:div>
|
||||
<!-- The messagepanewrapper hbox exists to allow
|
||||
extensions to add sidebars to the message. -->
|
||||
<hbox id="messagepanewrapper" flex="1">
|
||||
|
|
|
@ -1298,6 +1298,9 @@ function HideMessageHeaderPane() {
|
|||
gMessageNotificationBar.clearMsgNotifications();
|
||||
// Clear the DBListener since we don't have any visible UI to update.
|
||||
clearFolderDBListener();
|
||||
|
||||
// Now let interested listeners know the pane has been hidden.
|
||||
header.dispatchEvent(new Event("message-header-pane-hidden"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1743,3 +1743,7 @@ printpreview-pagination:focus-within,
|
|||
.dialogOverlay[topmost="true"] {
|
||||
background-color: rgba(28, 27, 34, 0.45);
|
||||
}
|
||||
|
||||
#messagepaneContainer.scrollable {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче