mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	add font-awesome icons to QR buttons
This commit is contained in:
		@@ -2,9 +2,19 @@
 | 
			
		||||
	<div id="qr--main">
 | 
			
		||||
		<h3 data-i18n="Labels and Message">Labels and Message</h3>
 | 
			
		||||
		<div class="qr--labels">
 | 
			
		||||
			<label class="qr--fit">
 | 
			
		||||
				<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>
 | 
			
		||||
				<span class="qr--labelText" data-i18n="Label">Label</span>
 | 
			
		||||
				<input type="text" class="text_pole" id="qr--modal-label">
 | 
			
		||||
				<div class="qr--inputGroup">
 | 
			
		||||
					<label class="checkbox_label" title="Show label even if an icon is assigned">
 | 
			
		||||
						<input type="checkbox" id="qr--modal-showLabel">
 | 
			
		||||
						Show
 | 
			
		||||
					</label>
 | 
			
		||||
					<input type="text" class="text_pole" id="qr--modal-label">
 | 
			
		||||
				</div>
 | 
			
		||||
			</label>
 | 
			
		||||
			<label>
 | 
			
		||||
				<span class="qr--labelText" data-i18n="Title">Title</span>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ import { SlashCommandExecutor } from '../../../slash-commands/SlashCommandExecut
 | 
			
		||||
import { SlashCommandParser } from '../../../slash-commands/SlashCommandParser.js';
 | 
			
		||||
import { SlashCommandParserError } from '../../../slash-commands/SlashCommandParserError.js';
 | 
			
		||||
import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js';
 | 
			
		||||
import { debounce, getSortableDelay } from '../../../utils.js';
 | 
			
		||||
import { debounce, getSortableDelay, showFontAwesomePicker } from '../../../utils.js';
 | 
			
		||||
import { log, warn } from '../index.js';
 | 
			
		||||
import { QuickReplyContextLink } from './QuickReplyContextLink.js';
 | 
			
		||||
import { QuickReplySet } from './QuickReplySet.js';
 | 
			
		||||
@@ -27,31 +27,35 @@ export class QuickReply {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**@type {Number}*/ id;
 | 
			
		||||
    /**@type {String}*/ label = '';
 | 
			
		||||
    /**@type {String}*/ title = '';
 | 
			
		||||
    /**@type {String}*/ message = '';
 | 
			
		||||
    /**@type {number}*/ id;
 | 
			
		||||
    /**@type {string}*/ icon;
 | 
			
		||||
    /**@type {string}*/ label = '';
 | 
			
		||||
    /**@type {boolean}*/ showLabel = false;
 | 
			
		||||
    /**@type {string}*/ title = '';
 | 
			
		||||
    /**@type {string}*/ message = '';
 | 
			
		||||
 | 
			
		||||
    /**@type {QuickReplyContextLink[]}*/ contextList;
 | 
			
		||||
 | 
			
		||||
    /**@type {Boolean}*/ preventAutoExecute = true;
 | 
			
		||||
    /**@type {Boolean}*/ isHidden = false;
 | 
			
		||||
    /**@type {Boolean}*/ executeOnStartup = false;
 | 
			
		||||
    /**@type {Boolean}*/ executeOnUser = false;
 | 
			
		||||
    /**@type {Boolean}*/ executeOnAi = false;
 | 
			
		||||
    /**@type {Boolean}*/ executeOnChatChange = false;
 | 
			
		||||
    /**@type {Boolean}*/ executeOnGroupMemberDraft = false;
 | 
			
		||||
    /**@type {String}*/ automationId = '';
 | 
			
		||||
    /**@type {boolean}*/ preventAutoExecute = true;
 | 
			
		||||
    /**@type {boolean}*/ isHidden = false;
 | 
			
		||||
    /**@type {boolean}*/ executeOnStartup = false;
 | 
			
		||||
    /**@type {boolean}*/ executeOnUser = false;
 | 
			
		||||
    /**@type {boolean}*/ executeOnAi = false;
 | 
			
		||||
    /**@type {boolean}*/ executeOnChatChange = false;
 | 
			
		||||
    /**@type {boolean}*/ executeOnGroupMemberDraft = false;
 | 
			
		||||
    /**@type {string}*/ automationId = '';
 | 
			
		||||
 | 
			
		||||
    /**@type {Function}*/ onExecute;
 | 
			
		||||
    /**@type {function}*/ onExecute;
 | 
			
		||||
    /**@type {(qr:QuickReply)=>AsyncGenerator<SlashCommandClosureResult|{closure:SlashCommandClosure, executor:SlashCommandExecutor|SlashCommandClosureResult}, SlashCommandClosureResult, boolean>}*/ onDebug;
 | 
			
		||||
    /**@type {Function}*/ onDelete;
 | 
			
		||||
    /**@type {Function}*/ onUpdate;
 | 
			
		||||
    /**@type {function}*/ onDelete;
 | 
			
		||||
    /**@type {function}*/ onUpdate;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**@type {HTMLElement}*/ dom;
 | 
			
		||||
    /**@type {HTMLElement}*/ domIcon;
 | 
			
		||||
    /**@type {HTMLElement}*/ domLabel;
 | 
			
		||||
    /**@type {HTMLElement}*/ settingsDom;
 | 
			
		||||
    /**@type {HTMLElement}*/ settingsDomIcon;
 | 
			
		||||
    /**@type {HTMLInputElement}*/ settingsDomLabel;
 | 
			
		||||
    /**@type {HTMLTextAreaElement}*/ settingsDomMessage;
 | 
			
		||||
 | 
			
		||||
@@ -89,6 +93,14 @@ export class QuickReply {
 | 
			
		||||
    updateRender() {
 | 
			
		||||
        if (!this.dom) return;
 | 
			
		||||
        this.dom.title = this.title || this.message;
 | 
			
		||||
        if (this.icon) {
 | 
			
		||||
            this.domIcon.classList.remove('qr--hidden');
 | 
			
		||||
            if (this.showLabel) this.domLabel.classList.remove('qr--hidden');
 | 
			
		||||
            else this.domLabel.classList.add('qr--hidden');
 | 
			
		||||
        } else {
 | 
			
		||||
            this.domIcon.classList.add('qr--hidden');
 | 
			
		||||
            this.domLabel.classList.remove('qr--hidden');
 | 
			
		||||
        }
 | 
			
		||||
        this.domLabel.textContent = this.label;
 | 
			
		||||
        this.dom.classList[this.hasContext ? 'add' : 'remove']('qr--hasCtx');
 | 
			
		||||
    }
 | 
			
		||||
@@ -119,9 +131,18 @@ export class QuickReply {
 | 
			
		||||
                    }
 | 
			
		||||
                    this.execute();
 | 
			
		||||
                });
 | 
			
		||||
                const icon = document.createElement('div'); {
 | 
			
		||||
                    this.domIcon = icon;
 | 
			
		||||
                    icon.classList.add('qr--button-icon');
 | 
			
		||||
                    icon.classList.add('fa-solid');
 | 
			
		||||
                    if (!this.icon) icon.classList.add('qr--hidden');
 | 
			
		||||
                    else icon.classList.add(this.icon);
 | 
			
		||||
                    root.append(icon);
 | 
			
		||||
                }
 | 
			
		||||
                const lbl = document.createElement('div'); {
 | 
			
		||||
                    this.domLabel = lbl;
 | 
			
		||||
                    lbl.classList.add('qr--button-label');
 | 
			
		||||
                    if (this.icon && !this.showLabel) lbl.classList.add('qr--hidden');
 | 
			
		||||
                    lbl.textContent = this.label;
 | 
			
		||||
                    root.append(lbl);
 | 
			
		||||
                }
 | 
			
		||||
@@ -160,6 +181,21 @@ export class QuickReply {
 | 
			
		||||
                }
 | 
			
		||||
                const lblContainer = document.createElement('div'); {
 | 
			
		||||
                    lblContainer.classList.add('qr--set-itemLabelContainer');
 | 
			
		||||
                    const icon = document.createElement('div'); {
 | 
			
		||||
                        this.settingsDomIcon = icon;
 | 
			
		||||
                        icon.title = 'Click to change icon';
 | 
			
		||||
                        icon.classList.add('qr--set-itemIcon');
 | 
			
		||||
                        icon.classList.add('menu_button');
 | 
			
		||||
                        if (this.icon) {
 | 
			
		||||
                            icon.classList.add('fa-solid');
 | 
			
		||||
                            icon.classList.add(this.icon);
 | 
			
		||||
                        }
 | 
			
		||||
                        icon.addEventListener('click', async()=>{
 | 
			
		||||
                            let value = await showFontAwesomePicker();
 | 
			
		||||
                            this.updateIcon(value);
 | 
			
		||||
                        });
 | 
			
		||||
                        lblContainer.append(icon);
 | 
			
		||||
                    }
 | 
			
		||||
                    const lbl = document.createElement('input'); {
 | 
			
		||||
                        this.settingsDomLabel = lbl;
 | 
			
		||||
                        lbl.classList.add('qr--set-itemLabel');
 | 
			
		||||
@@ -227,6 +263,35 @@ export class QuickReply {
 | 
			
		||||
            const popupResult = this.editorPopup.show();
 | 
			
		||||
 | 
			
		||||
            // basics
 | 
			
		||||
            /**@type {HTMLElement}*/
 | 
			
		||||
            const icon = dom.querySelector('#qr--modal-icon');
 | 
			
		||||
            if (this.icon) {
 | 
			
		||||
                icon.classList.add('fa-solid');
 | 
			
		||||
                icon.classList.add(this.icon);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                icon.textContent = '…';
 | 
			
		||||
            }
 | 
			
		||||
            icon.addEventListener('click', async()=>{
 | 
			
		||||
                let value = await showFontAwesomePicker();
 | 
			
		||||
                if (value === null) return;
 | 
			
		||||
                if (this.icon) icon.classList.remove(this.icon);
 | 
			
		||||
                if (value == '') {
 | 
			
		||||
                    icon.classList.remove('fa-solid');
 | 
			
		||||
                    icon.textContent = '…';
 | 
			
		||||
                } else {
 | 
			
		||||
                    icon.textContent = '';
 | 
			
		||||
                    icon.classList.add('fa-solid');
 | 
			
		||||
                    icon.classList.add(value);
 | 
			
		||||
                }
 | 
			
		||||
                this.updateIcon(value);
 | 
			
		||||
            });
 | 
			
		||||
            /**@type {HTMLInputElement}*/
 | 
			
		||||
            const showLabel = dom.querySelector('#qr--modal-showLabel');
 | 
			
		||||
            showLabel.checked = this.showLabel;
 | 
			
		||||
            showLabel.addEventListener('click', ()=>{
 | 
			
		||||
                this.updateShowLabel(showLabel.checked);
 | 
			
		||||
            });
 | 
			
		||||
            /**@type {HTMLInputElement}*/
 | 
			
		||||
            const label = dom.querySelector('#qr--modal-label');
 | 
			
		||||
            label.value = this.label;
 | 
			
		||||
@@ -523,7 +588,7 @@ export class QuickReply {
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            };
 | 
			
		||||
            const addCtxItem = (/**@type {QuickReplyContextLink}*/link, /**@type {Number}*/idx) => {
 | 
			
		||||
            const addCtxItem = (/**@type {QuickReplyContextLink}*/link, /**@type {number}*/idx) => {
 | 
			
		||||
                /**@type {HTMLElement} */
 | 
			
		||||
                // @ts-ignore
 | 
			
		||||
                const itemDom = tpl.content.querySelector('.qr--ctxItem').cloneNode(true); {
 | 
			
		||||
@@ -1309,6 +1374,46 @@ export class QuickReply {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {string} value
 | 
			
		||||
     */
 | 
			
		||||
    updateIcon(value) {
 | 
			
		||||
        if (this.onUpdate) {
 | 
			
		||||
            if (value === null) return;
 | 
			
		||||
            if (this.settingsDomIcon) {
 | 
			
		||||
                if (this.icon != value) {
 | 
			
		||||
                    if (value == '') {
 | 
			
		||||
                        if (this.icon) {
 | 
			
		||||
                            this.settingsDomIcon.classList.remove(this.icon);
 | 
			
		||||
                        }
 | 
			
		||||
                        this.settingsDomIcon.classList.remove('fa-solid');
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (this.icon) {
 | 
			
		||||
                            this.settingsDomIcon.classList.remove(this.icon);
 | 
			
		||||
                        } else {
 | 
			
		||||
                            this.settingsDomIcon.classList.add('fa-solid');
 | 
			
		||||
                        }
 | 
			
		||||
                        this.settingsDomIcon.classList.add(value);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this.icon = value;
 | 
			
		||||
            this.updateRender();
 | 
			
		||||
            this.onUpdate(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {boolean} value
 | 
			
		||||
     */
 | 
			
		||||
    updateShowLabel(value) {
 | 
			
		||||
        if (this.onUpdate) {
 | 
			
		||||
            this.showLabel = value;
 | 
			
		||||
            this.updateRender();
 | 
			
		||||
            this.onUpdate(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {string} value
 | 
			
		||||
     */
 | 
			
		||||
@@ -1387,6 +1492,8 @@ export class QuickReply {
 | 
			
		||||
    toJSON() {
 | 
			
		||||
        return {
 | 
			
		||||
            id: this.id,
 | 
			
		||||
            icon: this.icon,
 | 
			
		||||
            showLabel: this.showLabel,
 | 
			
		||||
            label: this.label,
 | 
			
		||||
            title: this.title,
 | 
			
		||||
            message: this.message,
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,14 @@
 | 
			
		||||
  opacity: 1;
 | 
			
		||||
  filter: brightness(1.2);
 | 
			
		||||
}
 | 
			
		||||
#qr--bar > .qr--buttons .qr--button .qr--hidden,
 | 
			
		||||
#qr--popout > .qr--body > .qr--buttons .qr--button .qr--hidden {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
#qr--bar > .qr--buttons .qr--button .qr--button-icon,
 | 
			
		||||
#qr--popout > .qr--body > .qr--buttons .qr--button .qr--button-icon {
 | 
			
		||||
  margin: 0 0.5em;
 | 
			
		||||
}
 | 
			
		||||
#qr--bar > .qr--buttons .qr--button > .qr--button-expander,
 | 
			
		||||
#qr--popout > .qr--body > .qr--buttons .qr--button > .qr--button-expander {
 | 
			
		||||
  display: none;
 | 
			
		||||
@@ -195,6 +203,13 @@
 | 
			
		||||
#qr--settings #qr--set-qrList .qr--set-qrListContents > .qr--set-item > .drag-handle {
 | 
			
		||||
  padding: 0.75em;
 | 
			
		||||
}
 | 
			
		||||
#qr--settings #qr--set-qrList .qr--set-qrListContents > .qr--set-item .qr--set-itemLabelContainer {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
}
 | 
			
		||||
#qr--settings #qr--set-qrList .qr--set-qrListContents > .qr--set-item .qr--set-itemLabelContainer .qr--set-itemIcon:not(.fa-solid) {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
#qr--settings #qr--set-qrList .qr--set-qrListContents > .qr--set-item .qr--set-itemLabel,
 | 
			
		||||
#qr--settings #qr--set-qrList .qr--set-qrListContents > .qr--set-item .qr--action {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
@@ -314,13 +329,24 @@
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
.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--fit {
 | 
			
		||||
  flex: 0 0 auto;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label .qr--inputGroup {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  gap: 0.5em;
 | 
			
		||||
}
 | 
			
		||||
.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--labelHint {
 | 
			
		||||
.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 > input {
 | 
			
		||||
.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 {
 | 
			
		||||
  flex: 0 0 auto;
 | 
			
		||||
}
 | 
			
		||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer {
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,13 @@
 | 
			
		||||
                filter: brightness(1.2);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .qr--hidden {
 | 
			
		||||
                display: none;
 | 
			
		||||
            }
 | 
			
		||||
            .qr--button-icon {
 | 
			
		||||
                margin: 0 0.5em;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            >.qr--button-expander {
 | 
			
		||||
                display: none;
 | 
			
		||||
            }
 | 
			
		||||
@@ -242,6 +249,14 @@
 | 
			
		||||
                    padding: 0.75em;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                .qr--set-itemLabelContainer {
 | 
			
		||||
                    display: flex;
 | 
			
		||||
                    align-items: center;
 | 
			
		||||
                    .qr--set-itemIcon:not(.fa-solid) {
 | 
			
		||||
                        display: none;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                .qr--set-itemLabel,
 | 
			
		||||
                .qr--action {
 | 
			
		||||
                    margin: 0;
 | 
			
		||||
@@ -387,13 +402,24 @@
 | 
			
		||||
						flex: 1 1 1px;
 | 
			
		||||
						display: flex;
 | 
			
		||||
						flex-direction: column;
 | 
			
		||||
						> .qr--labelText {
 | 
			
		||||
                        &.qr--fit {
 | 
			
		||||
                            flex: 0 0 auto;
 | 
			
		||||
                            justify-content: center;
 | 
			
		||||
                        }
 | 
			
		||||
                        .qr--inputGroup {
 | 
			
		||||
                            display: flex;
 | 
			
		||||
                            gap: 0.5em;
 | 
			
		||||
                            input {
 | 
			
		||||
                                flex: 1 1 auto;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
						.qr--labelText {
 | 
			
		||||
							flex: 1 1 auto;
 | 
			
		||||
						}
 | 
			
		||||
						> .qr--labelHint {
 | 
			
		||||
						.qr--labelHint {
 | 
			
		||||
							flex: 1 1 auto;
 | 
			
		||||
						}
 | 
			
		||||
						> input {
 | 
			
		||||
						input {
 | 
			
		||||
							flex: 0 0 auto;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user