put large message editor into additional options dlg

This commit is contained in:
LenAnderson
2023-12-24 00:20:30 +00:00
parent 3d5dc18d0c
commit 5cd911db6b
5 changed files with 249 additions and 92 deletions

View File

@ -38,6 +38,8 @@ export class QuickReply {
/**@type {HTMLElement}*/ dom;
/**@type {HTMLElement}*/ domLabel;
/**@type {HTMLElement}*/ settingsDom;
/**@type {HTMLInputElement}*/ settingsDomLabel;
/**@type {HTMLTextAreaElement}*/ settingsDomMessage;
get hasContext() {
@ -124,6 +126,7 @@ export class QuickReply {
const lblContainer = document.createElement('div'); {
lblContainer.classList.add('qr--set-itemLabelContainer');
const lbl = document.createElement('input'); {
this.settingsDomLabel = lbl;
lbl.classList.add('qr--set-itemLabel');
lbl.classList.add('text_pole');
lbl.value = this.label;
@ -139,29 +142,14 @@ export class QuickReply {
opt.classList.add('menu_button');
opt.classList.add('fa-solid');
opt.textContent = '⁝';
opt.title = 'Additional options:\n - context menu\n - auto-execution\n - tooltip';
opt.addEventListener('click', ()=>this.showOptions());
opt.title = 'Additional options:\n - large editor\n - context menu\n - auto-execution\n - tooltip';
opt.addEventListener('click', ()=>this.showEditor());
optContainer.append(opt);
}
item.append(optContainer);
}
const expandContainer = document.createElement('div'); {
expandContainer.classList.add('qr--set-optionsContainer');
const expand = document.createElement('div'); {
expand.classList.add('qr--expand');
expand.classList.add('menu_button');
expand.classList.add('menu_button_icon');
expand.classList.add('editor_maximize');
expand.classList.add('fa-solid');
expand.classList.add('fa-maximize');
expand.title = 'Expand the editor';
expand.setAttribute('data-for', `qr--set--item${this.id}`);
expand.setAttribute('data-tab', 'true');
expandContainer.append(expand);
}
item.append(expandContainer);
}
const mes = document.createElement('textarea'); {
this.settingsDomMessage = mes;
mes.id = `qr--set--item${this.id}`;
mes.classList.add('qr--set-itemMessage');
mes.value = this.message;
@ -191,14 +179,67 @@ export class QuickReply {
this.settingsDom?.remove();
}
async showOptions() {
const response = await fetch('/scripts/extensions/quick-reply/html/qrOptions.html', { cache: 'no-store' });
async showEditor() {
const response = await fetch('/scripts/extensions/quick-reply/html/qrEditor.html', { cache: 'no-store' });
if (response.ok) {
this.template = document.createRange().createContextualFragment(await response.text()).querySelector('#qr--qrOptions');
this.template = document.createRange().createContextualFragment(await response.text()).querySelector('#qr--modalEditor');
/**@type {HTMLElement} */
// @ts-ignore
const dom = this.template.cloneNode(true);
const popupResult = callPopup(dom, 'text', undefined, { okButton: 'OK', wide: false, large: false, rows: 1 });
const popupResult = callPopup(dom, 'text', undefined, { okButton: 'OK', wide: true, large: true, rows: 1 });
// basics
/**@type {HTMLInputElement}*/
const label = dom.querySelector('#qr--modal-label');
label.value = this.label;
label.addEventListener('input', ()=>{
this.updateLabel(label.value);
});
/**@type {HTMLInputElement}*/
const title = dom.querySelector('#qr--modal-title');
title.value = this.title;
title.addEventListener('input', () => {
this.updateTitle(title.value);
});
/**@type {HTMLTextAreaElement}*/
const message = dom.querySelector('#qr--modal-message');
message.value = this.message;
message.addEventListener('input', () => {
this.updateMessage(message.value);
});
//TODO move tab support for textarea into its own helper(?) and use for both this and .editor_maximize
message.addEventListener('keydown', (evt) => {
if (evt.key == 'Tab' && !evt.shiftKey && !evt.ctrlKey && !evt.altKey) {
evt.preventDefault();
const start = message.selectionStart;
const end = message.selectionEnd;
if (end - start > 0 && message.value.substring(start, end).includes('\n')) {
const lineStart = message.value.lastIndexOf('\n', start);
const count = message.value.substring(lineStart, end).split('\n').length - 1;
message.value = `${message.value.substring(0, lineStart)}${message.value.substring(lineStart, end).replace(/\n/g, '\n\t')}${message.value.substring(end)}`;
message.selectionStart = start + 1;
message.selectionEnd = end + count;
this.updateMessage(message.value);
} else {
message.value = `${message.value.substring(0, start)}\t${message.value.substring(end)}`;
message.selectionStart = start + 1;
message.selectionEnd = end + 1;
this.updateMessage(message.value);
}
} else if (evt.key == 'Tab' && evt.shiftKey && !evt.ctrlKey && !evt.altKey) {
evt.preventDefault();
const start = message.selectionStart;
const end = message.selectionEnd;
const lineStart = message.value.lastIndexOf('\n', start);
const count = message.value.substring(lineStart, end).split('\n\t').length - 1;
message.value = `${message.value.substring(0, lineStart)}${message.value.substring(lineStart, end).replace(/\n\t/g, '\n')}${message.value.substring(end)}`;
message.selectionStart = start - 1;
message.selectionEnd = end - count;
this.updateMessage(message.value);
}
});
// context menu
/**@type {HTMLTemplateElement}*/
const tpl = dom.querySelector('#qr--ctxItem');
const linkList = dom.querySelector('#qr--ctxEditor');
@ -300,18 +341,9 @@ export class QuickReply {
this.updateContext();
});
// UI options
/**@type {HTMLInputElement}*/
const title = dom.querySelector('#qr--title');
title.value = this.title;
title.addEventListener('input', () => {
this.title = title.value.trim();
this.updateContext();
});
await popupResult;
} else {
warn('failed to fetch qrOptions template');
warn('failed to fetch qrEditor template');
}
}
@ -331,6 +363,9 @@ export class QuickReply {
*/
updateMessage(value) {
if (this.onUpdate) {
if (this.settingsDomMessage.value != value) {
this.settingsDomMessage.value = value;
}
this.message = value;
this.updateRender();
this.onUpdate(this);
@ -342,12 +377,26 @@ export class QuickReply {
*/
updateLabel(value) {
if (this.onUpdate) {
if (this.settingsDomLabel.value != value) {
this.settingsDomLabel.value = value;
}
this.label = value;
this.updateRender();
this.onUpdate(this);
}
}
/**
* @param {string} value
*/
updateTitle(value) {
if (this.onUpdate) {
this.title = value;
this.updateRender();
this.onUpdate(this);
}
}
updateContext() {
if (this.onUpdate) {
this.updateRender();