Bug 1924170 - Implement the initial shortcuts container component. r=freaktechnik

**How to test**
- Open a console and type `openCustomizableShortcuts()`.
- Calling again `openCustomizableShortcuts()` while the dialog is open it shouldn't trigger anything.
- Ensure that a simple modal dialog is opened and takes over the full UI.
- Clicking on the X button or pressing `Escape` should close the dialog.

Differential Revision: https://phabricator.services.mozilla.com/D225413

--HG--
extra : amend_source : 51ad03feeb7c8bf70331f9eff2f7b6dbde4e22f6
This commit is contained in:
Alessandro Castellani 2024-11-14 18:15:17 +00:00
Родитель 441c794eb3
Коммит 7380170693
13 изменённых файлов: 272 добавлений и 0 удалений

Просмотреть файл

@ -242,6 +242,8 @@
<!-- NEEDED FOR MIGRATION CHECK AT INSTALL -->
<script defer="defer" src="chrome://calendar/content/calendar-migration.js"></script>
<!-- Customizable shortcuts -->
<script defer="defer" src="chrome://messenger/content/shortcutsOverlay.js"></script>
<script defer="defer" src="chrome://messenger/content/accountcreation/accountHub.js"></script>
@ -694,5 +696,6 @@
#include tabDialogs.inc.xhtml
#include ../../components/accountcreation/templates/accountHubTemplate.inc.xhtml
#include ../../components/customizableshortcuts/content/shortcutsContainerTemplate.inc.xhtml
</html:body>
</html>

Просмотреть файл

@ -122,3 +122,20 @@
window.addEventListener("load", setupShortcuts);
}
/**
* Load the shortcuts-container custom element if it's not already defined and
* open the container modal dialog.
*/
async function openCustomizableShortcuts() {
let element = document.querySelector("shortcuts-container");
// If we don't already have the element import it and append it to the DOM.
if (!element) {
await import(
"chrome://messenger/content/customizableshortcuts/shortcuts-container.mjs"
);
element = document.createElement("shortcuts-container");
document.body.appendChild(element);
}
element.open();
}

Просмотреть файл

@ -0,0 +1,101 @@
/* 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/. */
/**
* Base container element that opens a modal overlay to list all currently
* avaialble customizable shortcuts.
*
* Template ID: #shortcutsContainerTemplate
*/
class ShortcutsContainer extends HTMLElement {
/** @type {HTMLDialogElement} */
modal;
/** @type {DOMLocalization} */
l10n;
/**
* Track if the customizable shortcuts dialog is currently being working on
* and some operations are ongoing.
*
* @type {boolean}
*/
#isBusy = false;
connectedCallback() {
if (this.shadowRoot) {
return;
}
const shadowRoot = this.attachShadow({ mode: "open" });
// Load styles in the shadowRoot so we don't leak it.
const style = document.createElement("link");
style.rel = "stylesheet";
style.href = "chrome://messenger/skin/shortcuts-container.css";
shadowRoot.appendChild(style);
// Load the template.
const template = document.getElementById("shortcutsContainerTemplate");
const clonedNode = template.content.cloneNode(true);
shadowRoot.appendChild(clonedNode);
this.modal = shadowRoot.querySelector("dialog");
// Connect fluent strings.
this.l10n = new DOMLocalization([
"messenger/customizableshortcuts/customizableShortcuts.ftl",
]);
this.l10n.connectRoot(shadowRoot);
// Add event listeners.
shadowRoot.querySelector("button").addEventListener("click", this);
this.modal.addEventListener("cancel", this);
}
handleEvent(event) {
switch (event.type) {
case "click":
this.close();
break;
case "cancel":
this.onBeforeClosing(event);
break;
default:
break;
}
}
/**
* Open the modal dialog if it's not already opened.
*/
open() {
if (this.modal.open) {
return;
}
this.modal.showModal();
}
/**
* Close the modal dialog.
*/
close() {
if (this.#isBusy) {
return;
}
this.modal.close();
}
/**
* Helper function to check if we can safely close the dialog without killing
* any ongoing operations if the user presses the Escape key.
*/
onBeforeClosing(event) {
if (this.#isBusy) {
event.preventDefault();
}
}
}
customElements.define("shortcuts-container", ShortcutsContainer);

Просмотреть файл

@ -0,0 +1,13 @@
# 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/.
<html:template id="shortcutsContainerTemplate" xmlns="http://www.w3.org/1999/xhtml">
<dialog>
<main>
<button id="close" type="button" data-l10n-id="shortcuts-close-button-title">
<img class="icon-close" src="" alt="" />
</button>
Body
</main>
</dialog>
</html:template>

Просмотреть файл

@ -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/customizableshortcuts/shortcuts-container.mjs (content/shortcuts-container.mjs)

Просмотреть файл

@ -0,0 +1,17 @@
# 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"]
with Files("**"):
BUG_COMPONENT = ("Thunderbird", "Mail Window Front End")
EXTRA_JS_MODULES += []
BROWSER_CHROME_MANIFESTS += [
"test/browser/browser.toml",
]
XPCSHELL_TESTS_MANIFESTS += []

Просмотреть файл

@ -0,0 +1,14 @@
[DEFAULT]
head = "head.js"
prefs = [
"mail.provider.suppress_dialog_on_startup=true",
"mail.spellcheck.inline=false",
"mail.spotlight.firstRunDone=true",
"mail.winsearch.firstRunDone=true",
"mailnews.database.global.indexer.enabled=false",
"mailnews.start_page.override_url=about:blank",
"mailnews.start_page.url=about:blank",
]
subsuite = "thunderbird"
["browser_shortcutsContainer.js"]

Просмотреть файл

@ -0,0 +1,40 @@
/* 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/. */
"use strict";
// Test that the shortcuts container opens up properly and closes as it should.
add_task(async function test_customizable_shortcuts_opening() {
// TODO: Use an actual button once it's implemented in the UI.
// Open the dialog.
await window.openCustomizableShortcuts();
const container = document.querySelector("shortcuts-container");
await BrowserTestUtils.waitForMutationCondition(
container,
{ childList: true },
() => !!container.modal
);
Assert.ok(container.modal, "The dialog element was created");
const dialog = container.shadowRoot.querySelector("dialog");
Assert.ok(dialog.open, "The dialog element was opened");
EventUtils.synthesizeKey("KEY_Escape", {}, window);
await BrowserTestUtils.waitForEvent(dialog, "close");
Assert.ok(!dialog.open, "The dialog element was closed");
// Open the dialog again.
await window.openCustomizableShortcuts();
Assert.ok(dialog.open, "The dialog element was opened");
EventUtils.synthesizeMouseAtCenter(
container.shadowRoot.querySelector("#close"),
{},
window
);
await BrowserTestUtils.waitForEvent(dialog, "close");
Assert.ok(!dialog.open, "The dialog element was closed");
});

Просмотреть файл

@ -0,0 +1,3 @@
/* 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/. */

Просмотреть файл

@ -12,6 +12,7 @@ DIRS += [
"addrbook",
"cloudfile",
"compose",
"customizableshortcuts",
"customizableui",
"devtools",
"downloads",

Просмотреть файл

@ -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/.
shortcuts-close-button-title =
.title = Close

Просмотреть файл

@ -401,6 +401,7 @@
skin/classic/messenger/shared/primaryToolbar.css (../shared/mail/primaryToolbar.css)
skin/classic/messenger/shared/quickFilterBar.css (../shared/mail/quickFilterBar.css)
skin/classic/messenger/shared/activity/activity.css (../shared/mail/activity/activity.css)
skin/classic/messenger/shortcuts-container.css (../shared/mail/customizableshortcuts/shortcuts-container.css)
skin/classic/messenger/shared/sanitizeDialog.css (../shared/mail/sanitizeDialog.css)
skin/classic/messenger/shared/search-bar.css (../shared/mail/search-bar.css)
skin/classic/messenger/shared/searchBox.css (../shared/mail/searchBox.css)

Просмотреть файл

@ -0,0 +1,50 @@
/* 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 url("chrome://messenger/skin/variables.css");
@import url("chrome://messenger/skin/colors.css");
@import url("chrome://messenger/skin/icons.css");
dialog {
display: grid;
width: 600px;
height: 400px;
overflow: hidden;
padding: 0;
box-shadow: none;
border: none;
border-radius: 6px;
&::backdrop {
background: rgba(0, 0, 0, 0.5);
}
&::after {
content: '';
position: absolute;
top: 17%;
left: 50%;
width: 765px;
height: 500px;
transform: translateX(-50%);
background: linear-gradient(to right, rgba(159, 244, 240, 1), rgba(76, 177, 249, 1), rgba(168, 85, 247, 1));
filter: blur(15px);
z-index: -1;
}
@media (prefers-color-scheme: dark) {
&::after {
background: linear-gradient(to right, rgb(11, 140, 134, 1), rgba(28, 99, 149, 1));
}
}
}
main {
background-color: var(--color-neutral-base);
padding: 9px;
}
.icon-close {
content: var(--icon-close);
}