mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	add quick QR switcher to editor
This commit is contained in:
		@@ -6,7 +6,7 @@
 | 
			
		||||
				<span class="qr--labelText" data-i18n="Label">Icon</span>
 | 
			
		||||
				<div class="menu_button" id="qr--modal-icon" title="Click to change icon"></div>
 | 
			
		||||
			</label>
 | 
			
		||||
			<label>
 | 
			
		||||
			<div class="label">
 | 
			
		||||
				<span class="qr--labelText" data-i18n="Label">Label</span>
 | 
			
		||||
				<div class="qr--inputGroup">
 | 
			
		||||
					<label class="checkbox_label" title="Show label even if an icon is assigned">
 | 
			
		||||
@@ -14,8 +14,9 @@
 | 
			
		||||
						Show
 | 
			
		||||
					</label>
 | 
			
		||||
					<input type="text" class="text_pole" id="qr--modal-label">
 | 
			
		||||
					<div class="menu_button fa-solid fa-chevron-down" id="qr--modal-switcher" title="Switch to another QR"></div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</label>
 | 
			
		||||
			</div>
 | 
			
		||||
			<label>
 | 
			
		||||
				<span class="qr--labelText" data-i18n="Title">Title</span>
 | 
			
		||||
				<small class="qr--labelHint" data-i18n="(tooltip, leave empty to show message or /command)">(tooltip, leave empty to show message or /command)</small>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ import { SlashCommandParser } from '../../../slash-commands/SlashCommandParser.j
 | 
			
		||||
import { SlashCommandParserError } from '../../../slash-commands/SlashCommandParserError.js';
 | 
			
		||||
import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js';
 | 
			
		||||
import { debounce, delay, getSortableDelay, showFontAwesomePicker } from '../../../utils.js';
 | 
			
		||||
import { log, warn } from '../index.js';
 | 
			
		||||
import { log, quickReplyApi, warn } from '../index.js';
 | 
			
		||||
import { QuickReplyContextLink } from './QuickReplyContextLink.js';
 | 
			
		||||
import { QuickReplySet } from './QuickReplySet.js';
 | 
			
		||||
import { ContextMenu } from './ui/ctx/ContextMenu.js';
 | 
			
		||||
@@ -417,6 +417,75 @@ export class QuickReply {
 | 
			
		||||
            label.addEventListener('input', ()=>{
 | 
			
		||||
                this.updateLabel(label.value);
 | 
			
		||||
            });
 | 
			
		||||
            let switcherList;
 | 
			
		||||
            dom.querySelector('#qr--modal-switcher').addEventListener('click', (evt)=>{
 | 
			
		||||
                if (switcherList) {
 | 
			
		||||
                    switcherList.remove();
 | 
			
		||||
                    switcherList = null;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                const list = document.createElement('ul'); {
 | 
			
		||||
                    switcherList = list;
 | 
			
		||||
                    list.classList.add('qr--modal-switcherList');
 | 
			
		||||
                    const makeList = (qrs)=>{
 | 
			
		||||
                        const setItem = document.createElement('li'); {
 | 
			
		||||
                            setItem.classList.add('qr--modal-switcherItem');
 | 
			
		||||
                            setItem.addEventListener('click', ()=>{
 | 
			
		||||
                                list.innerHTML = '';
 | 
			
		||||
                                for (const qrs of quickReplyApi.listSets()) {
 | 
			
		||||
                                    const item = document.createElement('li'); {
 | 
			
		||||
                                        item.classList.add('qr--modal-switcherItem');
 | 
			
		||||
                                        item.addEventListener('click', ()=>{
 | 
			
		||||
                                            list.innerHTML = '';
 | 
			
		||||
                                            makeList(quickReplyApi.getSetByName(qrs));
 | 
			
		||||
                                        });
 | 
			
		||||
                                        const lbl = document.createElement('div'); {
 | 
			
		||||
                                            lbl.classList.add('qr--label');
 | 
			
		||||
                                            lbl.textContent = qrs;
 | 
			
		||||
                                            item.append(lbl);
 | 
			
		||||
                                        }
 | 
			
		||||
                                        list.append(item);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
                            const lbl = document.createElement('div'); {
 | 
			
		||||
                                lbl.classList.add('qr--label');
 | 
			
		||||
                                lbl.textContent = 'Switch QR Sets...';
 | 
			
		||||
                                setItem.append(lbl);
 | 
			
		||||
                            }
 | 
			
		||||
                            list.append(setItem);
 | 
			
		||||
                        }
 | 
			
		||||
                        for (const qr of qrs.qrList.toSorted((a,b)=>a.label.toLowerCase().localeCompare(b.label.toLowerCase()))) {
 | 
			
		||||
                            const item = document.createElement('li'); {
 | 
			
		||||
                                item.classList.add('qr--modal-switcherItem');
 | 
			
		||||
                                if (qr == this) item.classList.add('qr--current');
 | 
			
		||||
                                else item.addEventListener('click', ()=>{
 | 
			
		||||
                                    this.editorPopup.completeAffirmative();
 | 
			
		||||
                                    qr.showEditor();
 | 
			
		||||
                                });
 | 
			
		||||
                                const lbl = document.createElement('div'); {
 | 
			
		||||
                                    lbl.classList.add('qr--label');
 | 
			
		||||
                                    lbl.textContent = qr.label;
 | 
			
		||||
                                    item.append(lbl);
 | 
			
		||||
                                }
 | 
			
		||||
                                const id = document.createElement('div'); {
 | 
			
		||||
                                    id.classList.add('qr--id');
 | 
			
		||||
                                    id.textContent = qr.id.toString();
 | 
			
		||||
                                    item.append(id);
 | 
			
		||||
                                }
 | 
			
		||||
                                const mes = document.createElement('div'); {
 | 
			
		||||
                                    mes.classList.add('qr--message');
 | 
			
		||||
                                    mes.textContent = qr.message;
 | 
			
		||||
                                    item.append(mes);
 | 
			
		||||
                                }
 | 
			
		||||
                                list.append(item);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    };
 | 
			
		||||
                    makeList(quickReplyApi.getSetByQr(this));
 | 
			
		||||
                }
 | 
			
		||||
                label.parentElement.append(list);
 | 
			
		||||
            });
 | 
			
		||||
            /**@type {HTMLInputElement}*/
 | 
			
		||||
            const title = dom.querySelector('#qr--modal-title');
 | 
			
		||||
            title.value = this.title;
 | 
			
		||||
 
 | 
			
		||||
@@ -456,32 +456,106 @@
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
  gap: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label {
 | 
			
		||||
  flex: 1 1 1px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label.qr--fit {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label.qr--fit,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label.qr--fit {
 | 
			
		||||
  flex: 0 0 auto;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--inputGroup {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--inputGroup,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--inputGroup {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: baseline;
 | 
			
		||||
  gap: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--inputGroup input {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--inputGroup input,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--inputGroup input {
 | 
			
		||||
  flex: 1 1 auto;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--labelText {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--labelText,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--labelText {
 | 
			
		||||
  flex: 1 1 auto;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--labelHint {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--labelHint,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--labelHint {
 | 
			
		||||
  flex: 1 1 auto;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label input {
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label input,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label input {
 | 
			
		||||
  flex: 0 0 auto;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList {
 | 
			
		||||
  background-color: var(--stcdx--bgColor);
 | 
			
		||||
  border: 1px solid var(--SmartThemeBorderColor);
 | 
			
		||||
  backdrop-filter: blur(var(--SmartThemeBlurStrength));
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  font-size: smaller;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 100%;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0.5em;
 | 
			
		||||
  max-height: 50vh;
 | 
			
		||||
  list-style: none;
 | 
			
		||||
  z-index: 40000;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--modal-switcherItem,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--modal-switcherItem {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  gap: 1em;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  opacity: 0.75;
 | 
			
		||||
  transition: 200ms;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--modal-switcherItem:hover,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--modal-switcherItem:hover {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--modal-switcherItem.qr--current,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--modal-switcherItem.qr--current {
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--modal-switcherItem.qr--current .qr--label,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--modal-switcherItem.qr--current .qr--label,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--modal-switcherItem.qr--current .qr--id,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--modal-switcherItem.qr--current .qr--id {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--label,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--label {
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--id,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--id {
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--id:before,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--id:before {
 | 
			
		||||
  content: "[";
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--id:after,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--id:after {
 | 
			
		||||
  content: "]";
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--modal-switcherList .qr--message,
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > .label .qr--modal-switcherList .qr--message {
 | 
			
		||||
  height: 1lh;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer {
 | 
			
		||||
  flex: 1 1 auto;
 | 
			
		||||
  display: flex;
 | 
			
		||||
 
 | 
			
		||||
@@ -527,10 +527,11 @@
 | 
			
		||||
					display: flex;
 | 
			
		||||
					flex-direction: row;
 | 
			
		||||
					gap: 0.5em;
 | 
			
		||||
					> label {
 | 
			
		||||
					> label, > .label {
 | 
			
		||||
						flex: 1 1 1px;
 | 
			
		||||
						display: flex;
 | 
			
		||||
						flex-direction: column;
 | 
			
		||||
                        position: relative;
 | 
			
		||||
                        &.qr--fit {
 | 
			
		||||
                            flex: 0 0 auto;
 | 
			
		||||
                            justify-content: center;
 | 
			
		||||
@@ -552,6 +553,56 @@
 | 
			
		||||
						input {
 | 
			
		||||
							flex: 0 0 auto;
 | 
			
		||||
						}
 | 
			
		||||
                        .qr--modal-switcherList {
 | 
			
		||||
                            background-color: var(--stcdx--bgColor);
 | 
			
		||||
                            border: 1px solid var(--SmartThemeBorderColor);
 | 
			
		||||
                            backdrop-filter: blur(var(--SmartThemeBlurStrength));
 | 
			
		||||
                            border-radius: 10px;
 | 
			
		||||
                            font-size: smaller;
 | 
			
		||||
                            position: absolute;
 | 
			
		||||
                            top: 100%;
 | 
			
		||||
                            left: 0;
 | 
			
		||||
                            right: 0;
 | 
			
		||||
                            overflow: auto;
 | 
			
		||||
                            margin: 0;
 | 
			
		||||
                            padding: 0.5em;
 | 
			
		||||
                            max-height: 50vh;
 | 
			
		||||
                            list-style: none;
 | 
			
		||||
                            z-index: 40000;
 | 
			
		||||
                            max-width: 100%;
 | 
			
		||||
                            .qr--modal-switcherItem {
 | 
			
		||||
                                display: flex;
 | 
			
		||||
                                gap: 1em;
 | 
			
		||||
                                text-align: left;
 | 
			
		||||
                                opacity: 0.75;
 | 
			
		||||
                                transition: 200ms;
 | 
			
		||||
                                cursor: pointer;
 | 
			
		||||
                                &:hover {
 | 
			
		||||
                                    opacity: 1;
 | 
			
		||||
                                }
 | 
			
		||||
                                &.qr--current {
 | 
			
		||||
                                    opacity: 1;
 | 
			
		||||
                                    .qr--label, .qr--id {
 | 
			
		||||
                                        font-weight: bold;
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            .qr--label {
 | 
			
		||||
                                white-space: nowrap;;
 | 
			
		||||
                            }
 | 
			
		||||
                            .qr--id {
 | 
			
		||||
                                opacity: 0.5;
 | 
			
		||||
                                &:before { content: "["; }
 | 
			
		||||
                                &:after { content: "]"; }
 | 
			
		||||
                            }
 | 
			
		||||
                            .qr--message {
 | 
			
		||||
                                height: 1lh;
 | 
			
		||||
                                overflow: hidden;
 | 
			
		||||
                                text-overflow: ellipsis;
 | 
			
		||||
                                white-space: nowrap;
 | 
			
		||||
                                opacity: 0.5;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				> .qr--modal-messageContainer {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user