mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
add QR popout
This commit is contained in:
@ -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
|
||||||
|
@ -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');
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user