Nocigar's picture
Upload 475 files
b82d373 verified
import { QuickReply } from '../../QuickReply.js';
// eslint-disable-next-line no-unused-vars
import { QuickReplySet } from '../../QuickReplySet.js';
import { MenuHeader } from './MenuHeader.js';
import { MenuItem } from './MenuItem.js';
export class ContextMenu {
/**@type {MenuItem[]}*/ itemList = [];
/**@type {Boolean}*/ isActive = false;
/**@type {HTMLElement}*/ root;
/**@type {HTMLElement}*/ menu;
constructor(/**@type {QuickReply}*/qr) {
// this.itemList = items;
this.itemList = this.build(qr).children;
this.itemList.forEach(item => {
item.onExpand = () => {
this.itemList.filter(it => it != item)
.forEach(it => it.collapse());
};
});
}
/**
* @param {QuickReply} qr
* @param {String} chainedMessage
* @param {QuickReplySet[]} hierarchy
* @param {String[]} labelHierarchy
*/
build(qr, chainedMessage = null, hierarchy = [], labelHierarchy = []) {
const tree = {
icon: qr.icon,
showLabel: qr.showLabel,
label: qr.label,
message: (chainedMessage && qr.message ? `${chainedMessage} | ` : '') + qr.message,
children: [],
};
qr.contextList.forEach((cl) => {
if (!cl.set) return;
if (!hierarchy.includes(cl.set)) {
const nextHierarchy = [...hierarchy, cl.set];
const nextLabelHierarchy = [...labelHierarchy, tree.label];
tree.children.push(new MenuHeader(cl.set.name));
cl.set.qrList.forEach(subQr => {
const subTree = this.build(subQr, cl.isChained ? tree.message : null, nextHierarchy, nextLabelHierarchy);
tree.children.push(new MenuItem(
subTree.icon,
subTree.showLabel,
subTree.label,
subTree.message,
(evt) => {
evt.stopPropagation();
const finalQr = Object.assign(new QuickReply(), subQr);
finalQr.message = subTree.message.replace(/%%parent(-\d+)?%%/g, (_, index) => {
return nextLabelHierarchy.slice(parseInt(index ?? '-1'))[0];
});
cl.set.execute(finalQr);
},
subTree.children,
));
});
}
});
return tree;
}
render() {
if (!this.root) {
const blocker = document.createElement('div'); {
this.root = blocker;
blocker.classList.add('ctx-blocker');
blocker.addEventListener('click', () => this.hide());
const menu = document.createElement('ul'); {
this.menu = menu;
menu.classList.add('list-group');
menu.classList.add('ctx-menu');
this.itemList.forEach(it => menu.append(it.render()));
blocker.append(menu);
}
}
}
return this.root;
}
show({ clientX, clientY }) {
if (this.isActive) return;
this.isActive = true;
this.render();
this.menu.style.bottom = `${window.innerHeight - clientY}px`;
this.menu.style.left = `${clientX}px`;
document.body.append(this.root);
}
hide() {
if (this.root) {
this.root.remove();
}
this.isActive = false;
}
toggle(/**@type {PointerEvent}*/evt) {
if (this.isActive) {
this.hide();
} else {
this.show(evt);
}
}
}