add QR popout

This commit is contained in:
LenAnderson
2023-12-21 16:58:44 +00:00
parent 40706e8430
commit 8959c0d380
6 changed files with 189 additions and 28 deletions

View File

@ -11,7 +11,6 @@ import { SettingsUi } from './src/ui/SettingsUi.js';
//TODO popout QR button bar (allow separate popouts for each QR set?)
//TODO move advanced QR options into own UI class //TODO move advanced QR options into own UI class
//TODO slash commands //TODO slash commands
//TODO easy way to CRUD QRs and sets //TODO easy way to CRUD QRs and sets

View File

@ -63,6 +63,7 @@ export class QuickReply {
const root = document.createElement('div'); { const root = document.createElement('div'); {
this.dom = root; this.dom = root;
root.classList.add('qr--button'); root.classList.add('qr--button');
root.classList.add('menu_button');
if (this.hasContext) { if (this.hasContext) {
root.classList.add('qr--hasCtx'); root.classList.add('qr--hasCtx');
} }

View File

@ -15,6 +15,7 @@ export class QuickReplySettings {
/**@type {Boolean}*/ isEnabled = false; /**@type {Boolean}*/ isEnabled = false;
/**@type {Boolean}*/ isCombined = false; /**@type {Boolean}*/ isCombined = false;
/**@type {Boolean}*/ isPopout = false;
/**@type {QuickReplyConfig}*/ config; /**@type {QuickReplyConfig}*/ config;
/**@type {QuickReplyConfig}*/ _chatConfig; /**@type {QuickReplyConfig}*/ _chatConfig;
get chatConfig() { get chatConfig() {
@ -77,6 +78,7 @@ export class QuickReplySettings {
return { return {
isEnabled: this.isEnabled, isEnabled: this.isEnabled,
isCombined: this.isCombined, isCombined: this.isCombined,
isPopout: this.isPopout,
config: this.config, config: this.config,
}; };
} }

View File

@ -1,9 +1,13 @@
import { animation_duration } from '../../../../../script.js';
import { dragElement } from '../../../../RossAscends-mods.js';
import { loadMovingUIState } from '../../../../power-user.js';
import { QuickReplySettings } from '../QuickReplySettings.js'; import { QuickReplySettings } from '../QuickReplySettings.js';
export class ButtonUi { export class ButtonUi {
/**@type {QuickReplySettings}*/ settings; /**@type {QuickReplySettings}*/ settings;
/**@type {HTMLElement}*/ dom; /**@type {HTMLElement}*/ dom;
/**@type {HTMLElement}*/ popoutDom;
@ -16,6 +20,46 @@ export class ButtonUi {
render() { render() {
if (this.settings.isPopout) {
return this.renderPopout();
}
return this.renderBar();
}
unrender() {
this.dom?.remove();
this.dom = null;
this.popoutDom?.remove();
this.popoutDom = null;
}
show() {
if (!this.settings.isEnabled) return;
if (this.settings.isPopout) {
document.body.append(this.render());
loadMovingUIState();
$(this.render()).fadeIn(animation_duration);
dragElement($(this.render()));
} else {
const sendForm = document.querySelector('#send_form');
if (sendForm.children.length > 0) {
sendForm.children[0].insertAdjacentElement('beforebegin', this.render());
} else {
sendForm.append(this.render());
}
}
}
hide() {
this.unrender();
}
refresh() {
this.hide();
this.show();
}
renderBar() {
if (!this.dom) { if (!this.dom) {
let buttonHolder; let buttonHolder;
const root = document.createElement('div'); { const root = document.createElement('div'); {
@ -24,6 +68,18 @@ export class ButtonUi {
root.id = 'qr--bar'; root.id = 'qr--bar';
root.classList.add('flex-container'); root.classList.add('flex-container');
root.classList.add('flexGap5'); root.classList.add('flexGap5');
const popout = document.createElement('div'); {
popout.id = 'qr--popoutTrigger';
popout.classList.add('menu_button');
popout.classList.add('fa-solid');
popout.classList.add('fa-window-restore');
popout.addEventListener('click', ()=>{
this.settings.isPopout = true;
this.refresh();
this.settings.save();
});
root.append(popout);
}
if (this.settings.isCombined) { if (this.settings.isCombined) {
const buttons = document.createElement('div'); { const buttons = document.createElement('div'); {
buttonHolder = buttons; buttonHolder = buttons;
@ -39,25 +95,66 @@ export class ButtonUi {
} }
return this.dom; return this.dom;
} }
unrender() {
this.dom?.remove();
this.dom = null;
}
show() {
if (!this.settings.isEnabled) return;
const sendForm = document.querySelector('#send_form');
if (sendForm.children.length > 0) { renderPopout() {
sendForm.children[0].insertAdjacentElement('beforebegin', this.render()); if (!this.popoutDom) {
} else { let buttonHolder;
sendForm.append(this.render()); const root = document.createElement('div'); {
this.popoutDom = root;
root.id = 'qr--popout';
root.classList.add('qr--popout');
root.classList.add('draggable');
const head = document.createElement('div'); {
head.classList.add('qr--header');
root.append(head);
const controls = document.createElement('div'); {
controls.classList.add('qr--controls');
controls.classList.add('panelControlBar');
controls.classList.add('flex-container');
const drag = document.createElement('div'); {
drag.id = 'qr--popoutheader';
drag.classList.add('fa-solid');
drag.classList.add('fa-grip');
drag.classList.add('drag-grabber');
drag.classList.add('hoverglow');
controls.append(drag);
}
const close = document.createElement('div'); {
close.classList.add('qr--close');
close.classList.add('fa-solid');
close.classList.add('fa-circle-xmark');
close.classList.add('hoverglow');
close.addEventListener('click', ()=>{
this.settings.isPopout = false;
this.refresh();
this.settings.save();
});
controls.append(close);
}
head.append(controls);
}
}
const body = document.createElement('div'); {
buttonHolder = body;
body.classList.add('qr--body');
if (this.settings.isCombined) {
const buttons = document.createElement('div'); {
buttonHolder = buttons;
buttons.classList.add('qr--buttons');
body.append(buttons);
}
}
[...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? [])]
.filter(link=>link.isVisible)
.forEach(link=>buttonHolder.append(link.set.render()))
;
root.append(body);
}
}
} }
} return this.popoutDom;
hide() {
this.unrender();
}
refresh() {
this.hide();
this.show();
} }
} }

View File

@ -10,9 +10,37 @@
max-width: 100%; max-width: 100%;
overflow-x: auto; overflow-x: auto;
order: 1; order: 1;
padding-right: 2.5em;
position: relative; position: relative;
} }
#qr--bar > .qr--buttons { #qr--bar > #qr--popoutTrigger {
position: absolute;
right: 0.25em;
top: 0.25em;
}
#qr--popout {
display: flex;
flex-direction: column;
padding: 0;
z-index: 31;
}
#qr--popout > .qr--header {
flex: 0 0 auto;
height: 2em;
position: relative;
}
#qr--popout > .qr--header > .qr--controls > .qr--close {
height: 15px;
aspect-ratio: 1 / 1;
font-size: 20px;
opacity: 0.5;
transition: all 250ms;
}
#qr--popout > .qr--body {
overflow-y: auto;
}
#qr--bar > .qr--buttons,
#qr--popout > .qr--body > .qr--buttons {
margin: 0; margin: 0;
padding: 0; padding: 0;
display: flex; display: flex;
@ -21,12 +49,13 @@
gap: 5px; gap: 5px;
width: 100%; width: 100%;
} }
#qr--bar > .qr--buttons > .qr--buttons { #qr--bar > .qr--buttons > .qr--buttons,
#qr--popout > .qr--body > .qr--buttons > .qr--buttons {
display: contents; display: contents;
} }
#qr--bar > .qr--buttons .qr--button { #qr--bar > .qr--buttons .qr--button,
#qr--popout > .qr--body > .qr--buttons .qr--button {
color: var(--SmartThemeBodyColor); color: var(--SmartThemeBodyColor);
background-color: var(--black50a);
border: 1px solid var(--SmartThemeBorderColor); border: 1px solid var(--SmartThemeBorderColor);
border-radius: 10px; border-radius: 10px;
padding: 3px 5px; padding: 3px 5px;
@ -38,14 +67,17 @@
justify-content: center; justify-content: center;
text-align: center; text-align: center;
} }
#qr--bar > .qr--buttons .qr--button:hover { #qr--bar > .qr--buttons .qr--button:hover,
#qr--popout > .qr--body > .qr--buttons .qr--button:hover {
opacity: 1; opacity: 1;
filter: brightness(1.2); filter: brightness(1.2);
} }
#qr--bar > .qr--buttons .qr--button > .qr--button-expander { #qr--bar > .qr--buttons .qr--button > .qr--button-expander,
#qr--popout > .qr--body > .qr--buttons .qr--button > .qr--button-expander {
display: none; display: none;
} }
#qr--bar > .qr--buttons .qr--button.qr--hasCtx > .qr--button-expander { #qr--bar > .qr--buttons .qr--button.qr--hasCtx > .qr--button-expander,
#qr--popout > .qr--body > .qr--buttons .qr--button.qr--hasCtx > .qr--button-expander {
display: block; display: block;
} }
.qr--button-expander { .qr--button-expander {

View File

@ -10,8 +10,38 @@
max-width: 100%; max-width: 100%;
overflow-x: auto; overflow-x: auto;
order: 1; order: 1;
padding-right: 2.5em;
position: relative; position: relative;
> #qr--popoutTrigger {
position: absolute;
right: 0.25em;
top: 0.25em;
}
}
#qr--popout {
display: flex;
flex-direction: column;
padding: 0;
z-index: 31;
> .qr--header {
flex: 0 0 auto;
height: 2em;
position: relative;
> .qr--controls {
> .qr--close {
height: 15px;
aspect-ratio: 1 / 1;
font-size: 20px;
opacity: 0.5;
transition: all 250ms;
}
}
}
> .qr--body {
overflow-y: auto;
}
}
#qr--bar, #qr--popout > .qr--body {
> .qr--buttons { > .qr--buttons {
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -27,7 +57,7 @@
.qr--button { .qr--button {
color: var(--SmartThemeBodyColor); color: var(--SmartThemeBodyColor);
background-color: var(--black50a); // background-color: var(--black50a);
border: 1px solid var(--SmartThemeBorderColor); border: 1px solid var(--SmartThemeBorderColor);
border-radius: 10px; border-radius: 10px;
padding: 3px 5px; padding: 3px 5px;