add a healthy dose of mobile copium

This commit is contained in:
LenAnderson 2023-11-23 20:34:20 +00:00
parent 81f135fa7c
commit cdbcd6cfb2
6 changed files with 104 additions and 24 deletions

View File

@ -102,8 +102,7 @@ function onQuickReplyInput(id) {
function onQuickReplyLabelInput(id) {
extension_settings.quickReply.quickReplySlots[id - 1].label = $(`#quickReply${id}Label`).val();
let quickReplyLabel = extension_settings.quickReply.quickReplySlots[id - 1]?.label || '';
$(`#quickReply${id}`).text(quickReplyLabel + (extension_settings.quickReply.quickReplySlots[id - 1]?.contextMenu?.length?'…':''));
addQuickReplyBar();
saveSettingsDebounced();
}
@ -277,10 +276,11 @@ function addQuickReplyBar() {
for (let i = 0; i < extension_settings.quickReply.numberOfSlots; i++) {
let quickReplyMes = extension_settings.quickReply.quickReplySlots[i]?.mes || '';
let quickReplyLabel = extension_settings.quickReply.quickReplySlots[i]?.label || '';
let expander = '';
if (extension_settings.quickReply.quickReplySlots[i]?.contextMenu?.length) {
quickReplyLabel = `${quickReplyLabel}`;
expander = '<span class="ctx-expander" title="Open context menu">⋮</span>';
}
quickReplyButtonHtml += `<div title="${quickReplyMes}" class="quickReplyButton" data-index="${i}" id="quickReply${i + 1}">${quickReplyLabel}</div>`;
quickReplyButtonHtml += `<div title="${quickReplyMes}" class="quickReplyButton" data-index="${i}" id="quickReply${i + 1}">${quickReplyLabel}${expander}</div>`;
}
const quickReplyBarFullHtml = `
@ -297,6 +297,17 @@ function addQuickReplyBar() {
let index = $(this).data('index');
sendQuickReply(index);
});
$('.quickReplyButton > .ctx-expander').on('click', function (evt) {
evt.stopPropagation();
let index = $(this.closest('.quickReplyButton')).data('index');
const qr = extension_settings.quickReply.quickReplySlots[index];
if (qr.contextMenu?.length) {
evt.preventDefault();
const tree = buildContextMenu(qr);
const menu = new ContextMenu(tree.children);
menu.show(evt);
}
})
$('.quickReplyButton').on('contextmenu', function (evt) {
let index = $(this).data('index');
const qr = extension_settings.quickReply.quickReplySlots[index];

View File

@ -1,16 +1,23 @@
import { MenuItem } from "./MenuItem.js";
export class ContextMenu {
/**@type {MenuItem[]}*/ itemList = [];
/**@type {Boolean}*/ isActive = false;
/**@type {HTMLElement}*/ root;
/**@type {HTMLElement}*/ menu;
/**@type {MenuItem[]}*/ itemList = [];
constructor(/**@type {MenuItem[]}*/items) {
this.itemList = items;
items.forEach(item=>{
item.onExpand = ()=>{
items.filter(it=>it!=item)
.forEach(it=>it.collapse());
};
});
}
render() {
@ -35,12 +42,24 @@ export class ContextMenu {
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() {
this.root.remove();
if (this.root) {
this.root.remove();
}
this.isActive = false;
}
toggle(/**@type {PointerEvent}*/evt) {
if (this.isActive) {
this.hide();
} else {
this.show(evt);
}
}
}

View File

@ -1,15 +1,9 @@
import { MenuItem } from "./MenuItem.js";
import { SubMenu } from "./SubMenu.js";
export class MenuHeader {
/**@type {String}*/ label;
/**@type {HTMLElement}*/ root;
export class MenuHeader extends MenuItem {
constructor(/**@type {String}*/label) {
this.label = label;
super(label, null, null);
}

View File

@ -5,8 +5,12 @@ export class MenuItem {
/**@type {Object}*/ value;
/**@type {Function}*/ callback;
/**@type {MenuItem[]}*/ childList = [];
/**@type {SubMenu}*/ subMenu;
/**@type {Boolean}*/ isForceExpanded = false;
/**@type {HTMLElement}*/ root;
/**@type {Function}*/ onExpand;
@ -29,15 +33,44 @@ export class MenuItem {
if (this.callback) {
item.addEventListener('click', (evt)=>this.callback(evt, this));
}
item.append(this.label);
if (this.childList.length > 0) {
item.classList.add('ctx-has-children');
const sub = new SubMenu(this.childList);
item.addEventListener('pointerover', ()=>sub.show(item));
item.addEventListener('pointerleave', ()=>sub.hide());
this.subMenu = sub;
const trigger = document.createElement('div'); {
trigger.classList.add('ctx-expander');
trigger.textContent = '⋮';
trigger.addEventListener('click', (evt)=>{
evt.stopPropagation();
this.toggle();
});
item.append(trigger);
}
item.addEventListener('mouseover', ()=>sub.show(item));
item.addEventListener('mouseleave', ()=>sub.hide());
}
item.append(this.label);
}
}
return this.root;
}
expand() {
this.subMenu?.show(this.root);
if (this.onExpand) {
this.onExpand();
}
}
collapse() {
this.subMenu?.hide();
}
toggle() {
if (this.subMenu.isActive) {
this.expand();
} else {
this.collapse();
}
}
}

View File

@ -47,9 +47,18 @@ export class SubMenu {
});
}
hide() {
this.root.remove();
this.root.style.top = '';
this.root.style.left = '';
if (this.root) {
this.root.remove();
this.root.style.top = '';
this.root.style.left = '';
}
this.isActive = false;
}
toggle(/**@type {HTMLElement}*/parent) {
if (this.isActive) {
this.hide();
} else {
this.show(parent);
}
}
}

View File

@ -71,11 +71,25 @@
.ctx-item {
position: relative;
}
.ctx-item.ctx-has-children:after {
content: " >";
.ctx-expander {
border-left: 1px solid;
margin-left: 1em;
text-align: center;
width: 2em;
}
.ctx-expander:hover {
font-weight: bold;
}
.ctx-sub-menu {
position: absolute;
top: 0;
left: 100%;
}
@media screen and (max-width: 1000px) {
.ctx-blocker {
position: absolute;
}
.list-group .list-group-item.ctx-item {
padding: 1em;
}
}