summaryrefslogtreecommitdiffstats
path: root/toolkit/components/satchel/megalist/content/MegalistView.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/satchel/megalist/content/MegalistView.mjs')
-rw-r--r--toolkit/components/satchel/megalist/content/MegalistView.mjs98
1 files changed, 76 insertions, 22 deletions
diff --git a/toolkit/components/satchel/megalist/content/MegalistView.mjs b/toolkit/components/satchel/megalist/content/MegalistView.mjs
index 44a0198692..feec2409f8 100644
--- a/toolkit/components/satchel/megalist/content/MegalistView.mjs
+++ b/toolkit/components/satchel/megalist/content/MegalistView.mjs
@@ -4,13 +4,14 @@
import { html } from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
+import {
+ createDialog,
+ cancelDialog,
+} from "chrome://global/content/megalist/Dialog.mjs";
// eslint-disable-next-line import/no-unassigned-import
import "chrome://global/content/megalist/VirtualizedList.mjs";
-// eslint-disable-next-line import/no-unassigned-import
-import "chrome://global/content/megalist/search-input.mjs";
-
/**
* Map with limit on how many entries it can have.
* When over limit entries are added, oldest one are removed.
@@ -77,6 +78,7 @@ export class MegalistView extends MozLitElement {
super();
this.selectedIndex = 0;
this.searchText = "";
+ this.layout = null;
window.addEventListener("MessageFromViewModel", ev =>
this.#onMessageFromViewModel(ev)
@@ -88,6 +90,7 @@ export class MegalistView extends MozLitElement {
listLength: { type: Number },
selectedIndex: { type: Number },
searchText: { type: String },
+ layout: { type: Object },
};
}
@@ -112,6 +115,10 @@ export class MegalistView extends MozLitElement {
#templates = {};
+ static queries = {
+ searchInput: ".search",
+ };
+
connectedCallback() {
super.connectedCallback();
this.ownerDocument.addEventListener("keydown", e => this.#handleKeydown(e));
@@ -296,6 +303,16 @@ export class MegalistView extends MozLitElement {
this.requestUpdate();
}
+ receiveSetLayout({ layout }) {
+ if (layout) {
+ createDialog(layout, commandId =>
+ this.#messageToViewModel("Command", { commandId })
+ );
+ } else {
+ cancelDialog();
+ }
+ }
+
#handleInputChange(e) {
const searchText = e.target.value;
this.#messageToViewModel("UpdateFilter", { searchText });
@@ -333,6 +350,15 @@ export class MegalistView extends MozLitElement {
}
#handleClick(e) {
+ const elementWithCommand = e.composedTarget.closest("[data-command]");
+ if (elementWithCommand) {
+ const commandId = elementWithCommand.dataset.command;
+ if (commandId) {
+ this.#messageToViewModel("Command", { commandId });
+ return;
+ }
+ }
+
const lineElement = e.composedTarget.closest(".line");
if (!lineElement) {
return;
@@ -360,6 +386,12 @@ export class MegalistView extends MozLitElement {
const popup = this.ownerDocument.createElement("div");
popup.className = "menuPopup";
+
+ let closeMenu = () => {
+ popup.remove();
+ this.searchInput.focus();
+ };
+
popup.addEventListener(
"keydown",
e => {
@@ -385,7 +417,7 @@ export class MegalistView extends MozLitElement {
switch (e.code) {
case "Escape":
- popup.remove();
+ closeMenu();
break;
case "Tab":
if (e.shiftKey) {
@@ -416,9 +448,7 @@ export class MegalistView extends MozLitElement {
e.composedTarget?.closest(".menuPopup") !=
e.relatedTarget?.closest(".menuPopup")
) {
- // TODO: this triggers on macOS before "click" event. Due to this,
- // we are not receiving the command.
- popup.remove();
+ closeMenu();
}
},
{ capture: true }
@@ -433,7 +463,7 @@ export class MegalistView extends MozLitElement {
}
const menuItem = this.ownerDocument.createElement("button");
- menuItem.textContent = command.label;
+ menuItem.setAttribute("data-l10n-id", command.label);
menuItem.addEventListener("click", e => {
this.#messageToViewModel("Command", {
snapshotId,
@@ -449,26 +479,50 @@ export class MegalistView extends MozLitElement {
popup.querySelector("button")?.focus();
}
+ /**
+ * Renders data-source specific UI that should be displayed before the
+ * virtualized list. This is determined by the "SetLayout" message provided
+ * by the View Model. Defaults to displaying the search input.
+ */
+ renderBeforeList() {
+ return html`
+ <input
+ class="search"
+ type="search"
+ data-l10n-id="filter-placeholder"
+ .value=${this.searchText}
+ @input=${e => this.#handleInputChange(e)}
+ />
+ `;
+ }
+
+ renderList() {
+ if (this.layout) {
+ return null;
+ }
+
+ return html` <virtualized-list
+ .lineCount=${this.listLength}
+ .lineHeight=${MegalistView.LINE_HEIGHT}
+ .selectedIndex=${this.selectedIndex}
+ .createLineElement=${index => this.createLineElement(index)}
+ @click=${e => this.#handleClick(e)}
+ >
+ </virtualized-list>`;
+ }
+
+ renderAfterList() {}
+
render() {
return html`
<link
rel="stylesheet"
href="chrome://global/content/megalist/megalist.css"
/>
- <div class="container">
- <search-input
- .value=${this.searchText}
- .change=${e => this.#handleInputChange(e)}
- >
- </search-input>
- <virtualized-list
- .lineCount=${this.listLength}
- .lineHeight=${MegalistView.LINE_HEIGHT}
- .selectedIndex=${this.selectedIndex}
- .createLineElement=${index => this.createLineElement(index)}
- @click=${e => this.#handleClick(e)}
- >
- </virtualized-list>
+ <div @click=${this.#handleClick} class="container">
+ <div class="beforeList">${this.renderBeforeList()}</div>
+ ${this.renderList()}
+ <div class="afterList">${this.renderAfterList()}</div>
</div>
`;
}