|
import { QuickReply } from '../../QuickReply.js'; |
|
import { QuickReplySet } from '../../QuickReplySet.js'; |
|
import { MenuHeader } from './MenuHeader.js'; |
|
import { MenuItem } from './MenuItem.js'; |
|
|
|
export class ContextMenu { |
|
itemList = []; |
|
isActive = false; |
|
|
|
root; |
|
menu; |
|
|
|
|
|
|
|
|
|
constructor(qr) { |
|
|
|
this.itemList = this.build(qr).children; |
|
this.itemList.forEach(item => { |
|
item.onExpand = () => { |
|
this.itemList.filter(it => it !== item) |
|
.forEach(it => it.collapse()); |
|
}; |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
build(qr, chainedMessage = null, hierarchy = [], labelHierarchy = []) { |
|
const tree = { |
|
icon: qr.icon, |
|
showLabel: qr.showLabel, |
|
label: qr.label, |
|
title: qr.title, |
|
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)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const qrsOwnSetAddedAsContextMenu = cl.set.qrList.includes(qr); |
|
const visible = (subQr) => { |
|
return qrsOwnSetAddedAsContextMenu |
|
? subQr.isHidden && !!subQr.icon |
|
: !subQr.isHidden; |
|
}; |
|
|
|
cl.set.qrList.filter(visible).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.title, |
|
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(evt) { |
|
if (this.isActive) { |
|
this.hide(); |
|
} else { |
|
this.show(evt); |
|
} |
|
} |
|
} |
|
|