mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
* set isForced to true on input
* make floating auto-complete follow horizontal scrolling
* add callable closure vars
* changes to /let and /var for callable closures
* fix error message
* fix scope for closure arguments
* if should return the pipe result from closures
* use /run to call closures and no arguments on immediate closures
* throw exception from QRs window-function if no match
* when to show autocomplete vs info only
* autocomplete positioning
* autocomplete styling
* add theming to autocomplete (theme, dark, light)
* improve autocomplete show/hide logic and editor selection
* use blur tint color instead of chat tint color and use blur setting
* cleanup and docs
* use scope macros for QR args
* add enter to select autocomplete
* fix no executor found
* cleanup and comment
* fix alias list in help string
* fallback to empty string piped value if null or undefined
* fix typo
* blur textarea on ctrl+enter execute (and refocus after)
* stop executeSlashCommand if parser throws
* move /let and /var callbacks into functions
* switch textarea to monospace when value starts with slash
* add double pipe a pipe breaker
* fix /? slash
* remove some logging
* add "/:name" as shorthand for "/run name" after all
* move shit around
* fix error message
* use testRunShorthandEnd
* use parseQuotedValue and parseValue to determine name for "/:"
QR labels and set names can include spaces
* add some adjustments to make autocomplete work properly
some hint in there about "/:" would still be nice
* add autocomplete style selector
* only strip quotes from subcommand if they are at both ends
* fix JSDoc
* escaping
* allow open quotes on dry run
* throwing shit at the wall for /: autocomplete
* escapes only for symbols
* clean up autocomplete
* improve performance
* fix scope macros
* remove unescaping of pipes
* fix macros in scope copy
* fix "/? slash"
* don't run parser for getNameAt if text has not changed
* fix options filter
* re-enable blur listener
* restore selection on non-replace select
* fix for escaping first character of value
* add support for {{pipe}} and {{var::}} closures
* add index support to var macro
* add scoped var macro to macro help
* more escape fixes
* reduce autocomplete render debounce
* cleanup
* restore old escape handling and parser flag for strict escaping
* fix "no match" autocomplete message
* add dummy commands for comments and parser flag
* fix type annotations
* somewhat safer macro replacements
* fix autocomplete select on blank / "no match"
* fix cutting off handled part in substitution
* add parser flag REPLACE_GETVAR
Replaces all {{getvar::}} and {{getglobalvar::}} macros with {{var::}}.
Inserts a series of command executors before the command with the macros that:
- save {{pipe}} to a var
- call /getvar or /getglobalvar to get the variable used in the macro
- call /let to save the retrieved variable
- return the saved {{pipe}} value
This helps to avoid double-substitutions when the var values contain text that could be interpreted as macros.
* remove old parser
* fix send on enter when no match
* deal with pipes in quoted values (loose escaping)
* add default parser flags to user settings
* allow quoted values in unnamed argument
* set parser flag without explicit state to "on"
* add click hint on parser error toast
* dirty more detailed cmd defs
* remove name from unnamed arg
* move autocomplete into class and floating with details
* replace jQuery's trigger('input') on #send_textarea with native events because jQuery does not dispatch the native event
* fix ctrl+space
* fix arrow navigation
* add comments
* fix pointer block
* add static fromProps
* fix up dummy commands
* migrate all commands to addCommandObject
* remove commented comment command
* fix alias in details
* add range as argument type
* switch to addCommandObject
* switch to addCommandObject
* fix height
* fix floating details position on left
* re-enable blur event
* use auto width for full details on floating autocomplete
* auto-size floating full details
* fix typo
* re-enable blur listener
* don't prevent enter when selected item is fully typed out
* add autocomplete details tooltips
* add language to slash command examples
* move makeItem into option and command and fix click select
* use autocomplete parts in /? slash
* fix alias formatting
* add language to slash command examples
* fix details position on initial input history
* small screen styles
* replace registerSlashCommand with detailed declarations
* put name on first line
* add missing returns
* fix missing comma
* fix alias display in autocomplete list
* remove args from help string
* move parser settings to its own section
* jsdoc
* hljs stscript lang
* add hljs to autocomplete help examples
* add missing import
* apply autocomplete colors to stscript codeblocks (hljs)
* add fromProps
* cache autocomplete elements
* towards generic autocomplete
* remove unused imports
* fix blanks
* add return types
* re-enable blur
* fix blank check
* Caption messages by id
* add aborting command execution
* fix return type
* fix chat input font reset
* add slash command progress indicator
* add missing return
* mark registerSlashCommand deprecated
* why??
* separate abort logic for commands
* remove parsing of quoted values from unnamed arg
* add adjustable autocomplete width
* revert stop button pulse
* add progress and pause/abort to QR editor
* add resize event on autocomplete width change
* add key= argument to all get vars
* refactoring
* introduce NamedArgumentAsignment
* add TODOs
* refactoring
* record start and end of named arg assignment
* refactoring
* prevent duplicate calls to show
* refactoring
* remove macro ac
* add secondary autocomplete and enum descriptions
* add syntax highlighting to QR editor
* add enum descriptions to /while
* add /let key=... to scope variable names
* add unnamed argument assignment class and unnamed argument splitting
* fix QR editor style
* remove dash before autocomplete help text
* add autocomplete for unnamed enums
* fix remaining dom after holding backslash
* fix for unnamed enums
* fix autocomplete for /parser-flag
* add parser-flag enum help
* fix type annotations
* fix autocomplete result for /:
* add colored autocomplete type icons
* collapse second line autocomplete help if empty
* mark optional named args in autocomplete
* fix when what
* remove duplicate debug buttons
* dispatch input on autocomplete select
* prevent grow from editor syntax layer
* add auto-adjust qr editor caret color
* remove text-shadow from autocomplete
* join value strings in /let and /var
* add /abort syntax highlight
* fix attempting secondary result when there is none
* rename settings headers and split autocomplete / stscript
* add parser flag tooltips
* add tooltips to chat width stops
* fix typo
* return clone of help item
* fix enum string
* don't make optional notice for autocomplete arguments smaller
* avoid scrollbar in chat input
* add rudimentary macro autocomplete
* strip macro from helptext
* finally remove closure delimiters around root
* cleanup
* fix index stuff for removed closure delimiters
* fix type hint
* add child commands to progress indicator
* include sub-separator in macro autocomplete
* remove all mentions of interruptsGeneration and purge
* remove unused imports
* fix syntax highlight with newline at end of input
* cleanup select pointer events
* coalesce onProgress call
* add regex to STscript syntax highlighting
* fix closure end
* fix autocomplete type icon alignment
* adjustments for small screens
* fix removing wrong element
* add missing "at=" arg to /sys, /comment, /sendas
* add font scale setting for autocomplete
* add target=_blank for parser flag links
* fix for searching enums
* remove REGEXP_MODE from hljs
just causes trouble
* fix autocomplete in closures
* fix typo
* fix type hint
* Get rid of scroll bar on load
* Add type hint for /send name argument. Fix 'at' types
* Add 'negative' arg hint to /sd command
* reenable blur event
* Allow /summarize to process any text
* Compact layout of script toggles
* Expand CSS by default
* fix double ranger indicator and adjust to narrow container
* make custom css input fill available vertical space
* reduce scroll lag
* use default cursor on scrollbar
* Clean-up module loading in index.html
* fix tab indent with hljs
---------
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
501 lines
15 KiB
JavaScript
501 lines
15 KiB
JavaScript
import { callPopup, chat_metadata, eventSource, event_types, generateQuietPrompt, getCurrentChatId, getRequestHeaders, getThumbnailUrl, saveSettingsDebounced } from '../script.js';
|
|
import { saveMetadataDebounced } from './extensions.js';
|
|
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
|
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
|
import { flashHighlight, stringFormat } from './utils.js';
|
|
|
|
const BG_METADATA_KEY = 'custom_background';
|
|
const LIST_METADATA_KEY = 'chat_backgrounds';
|
|
|
|
export let background_settings = {
|
|
name: '__transparent.png',
|
|
url: generateUrlParameter('__transparent.png', false),
|
|
};
|
|
|
|
export function loadBackgroundSettings(settings) {
|
|
let backgroundSettings = settings.background;
|
|
if (!backgroundSettings || !backgroundSettings.name || !backgroundSettings.url) {
|
|
backgroundSettings = background_settings;
|
|
}
|
|
setBackground(backgroundSettings.name, backgroundSettings.url);
|
|
}
|
|
|
|
/**
|
|
* Sets the background for the current chat and adds it to the list of custom backgrounds.
|
|
* @param {{url: string, path:string}} backgroundInfo
|
|
*/
|
|
function forceSetBackground(backgroundInfo) {
|
|
saveBackgroundMetadata(backgroundInfo.url);
|
|
setCustomBackground();
|
|
|
|
const list = chat_metadata[LIST_METADATA_KEY] || [];
|
|
const bg = backgroundInfo.path;
|
|
list.push(bg);
|
|
chat_metadata[LIST_METADATA_KEY] = list;
|
|
saveMetadataDebounced();
|
|
getChatBackgroundsList();
|
|
highlightNewBackground(bg);
|
|
highlightLockedBackground();
|
|
}
|
|
|
|
async function onChatChanged() {
|
|
if (hasCustomBackground()) {
|
|
setCustomBackground();
|
|
}
|
|
else {
|
|
unsetCustomBackground();
|
|
}
|
|
|
|
getChatBackgroundsList();
|
|
highlightLockedBackground();
|
|
}
|
|
|
|
function getChatBackgroundsList() {
|
|
const list = chat_metadata[LIST_METADATA_KEY];
|
|
const listEmpty = !Array.isArray(list) || list.length === 0;
|
|
|
|
$('#bg_custom_content').empty();
|
|
$('#bg_chat_hint').toggle(listEmpty);
|
|
|
|
if (listEmpty) {
|
|
return;
|
|
}
|
|
|
|
for (const bg of list) {
|
|
const template = getBackgroundFromTemplate(bg, true);
|
|
$('#bg_custom_content').append(template);
|
|
}
|
|
}
|
|
|
|
function getBackgroundPath(fileUrl) {
|
|
return `backgrounds/${fileUrl}`;
|
|
}
|
|
|
|
function highlightLockedBackground() {
|
|
$('.bg_example').removeClass('locked');
|
|
|
|
const lockedBackground = chat_metadata[BG_METADATA_KEY];
|
|
|
|
if (!lockedBackground) {
|
|
return;
|
|
}
|
|
|
|
$('.bg_example').each(function () {
|
|
const url = $(this).data('url');
|
|
if (url === lockedBackground) {
|
|
$(this).addClass('locked');
|
|
}
|
|
});
|
|
}
|
|
|
|
function onLockBackgroundClick(e) {
|
|
e.stopPropagation();
|
|
|
|
const chatName = getCurrentChatId();
|
|
|
|
if (!chatName) {
|
|
toastr.warning('Select a chat to lock the background for it');
|
|
return;
|
|
}
|
|
|
|
const relativeBgImage = getUrlParameter(this);
|
|
|
|
saveBackgroundMetadata(relativeBgImage);
|
|
setCustomBackground();
|
|
highlightLockedBackground();
|
|
}
|
|
|
|
function onUnlockBackgroundClick(e) {
|
|
e.stopPropagation();
|
|
removeBackgroundMetadata();
|
|
unsetCustomBackground();
|
|
highlightLockedBackground();
|
|
}
|
|
|
|
function hasCustomBackground() {
|
|
return chat_metadata[BG_METADATA_KEY];
|
|
}
|
|
|
|
function saveBackgroundMetadata(file) {
|
|
chat_metadata[BG_METADATA_KEY] = file;
|
|
saveMetadataDebounced();
|
|
}
|
|
|
|
function removeBackgroundMetadata() {
|
|
delete chat_metadata[BG_METADATA_KEY];
|
|
saveMetadataDebounced();
|
|
}
|
|
|
|
function setCustomBackground() {
|
|
const file = chat_metadata[BG_METADATA_KEY];
|
|
|
|
// bg already set
|
|
if (document.getElementById('bg_custom').style.backgroundImage == file) {
|
|
return;
|
|
}
|
|
|
|
$('#bg_custom').css('background-image', file);
|
|
}
|
|
|
|
function unsetCustomBackground() {
|
|
$('#bg_custom').css('background-image', 'none');
|
|
}
|
|
|
|
function onSelectBackgroundClick() {
|
|
const isCustom = $(this).attr('custom') === 'true';
|
|
const relativeBgImage = getUrlParameter(this);
|
|
|
|
// if clicked on upload button
|
|
if (!relativeBgImage) {
|
|
return;
|
|
}
|
|
|
|
// Automatically lock the background if it's custom or other background is locked
|
|
if (hasCustomBackground() || isCustom) {
|
|
saveBackgroundMetadata(relativeBgImage);
|
|
setCustomBackground();
|
|
highlightLockedBackground();
|
|
}
|
|
highlightLockedBackground();
|
|
|
|
const customBg = window.getComputedStyle(document.getElementById('bg_custom')).backgroundImage;
|
|
|
|
// Custom background is set. Do not override the layer below
|
|
if (customBg !== 'none') {
|
|
return;
|
|
}
|
|
|
|
const bgFile = $(this).attr('bgfile');
|
|
const backgroundUrl = getBackgroundPath(bgFile);
|
|
|
|
// Fetching to browser memory to reduce flicker
|
|
fetch(backgroundUrl).then(() => {
|
|
setBackground(bgFile, relativeBgImage);
|
|
}).catch(() => {
|
|
console.log('Background could not be set: ' + backgroundUrl);
|
|
});
|
|
}
|
|
|
|
async function onCopyToSystemBackgroundClick(e) {
|
|
e.stopPropagation();
|
|
const bgNames = await getNewBackgroundName(this);
|
|
|
|
if (!bgNames) {
|
|
return;
|
|
}
|
|
|
|
const bgFile = await fetch(bgNames.oldBg);
|
|
|
|
if (!bgFile.ok) {
|
|
toastr.warning('Failed to copy background');
|
|
return;
|
|
}
|
|
|
|
const blob = await bgFile.blob();
|
|
const file = new File([blob], bgNames.newBg);
|
|
const formData = new FormData();
|
|
formData.set('avatar', file);
|
|
|
|
uploadBackground(formData);
|
|
|
|
const list = chat_metadata[LIST_METADATA_KEY] || [];
|
|
const index = list.indexOf(bgNames.oldBg);
|
|
list.splice(index, 1);
|
|
saveMetadataDebounced();
|
|
getChatBackgroundsList();
|
|
}
|
|
|
|
/**
|
|
* Gets the new background name from the user.
|
|
* @param {Element} referenceElement
|
|
* @returns {Promise<{oldBg: string, newBg: string}>}
|
|
* */
|
|
async function getNewBackgroundName(referenceElement) {
|
|
const exampleBlock = $(referenceElement).closest('.bg_example');
|
|
const isCustom = exampleBlock.attr('custom') === 'true';
|
|
const oldBg = exampleBlock.attr('bgfile');
|
|
|
|
if (!oldBg) {
|
|
console.debug('no bgfile');
|
|
return;
|
|
}
|
|
|
|
const fileExtension = oldBg.split('.').pop();
|
|
const fileNameBase = isCustom ? oldBg.split('/').pop() : oldBg;
|
|
const oldBgExtensionless = fileNameBase.replace(`.${fileExtension}`, '');
|
|
const newBgExtensionless = await callPopup('<h3>Enter new background name:</h3>', 'input', oldBgExtensionless);
|
|
|
|
if (!newBgExtensionless) {
|
|
console.debug('no new_bg_extensionless');
|
|
return;
|
|
}
|
|
|
|
const newBg = `${newBgExtensionless}.${fileExtension}`;
|
|
|
|
if (oldBgExtensionless === newBgExtensionless) {
|
|
console.debug('new_bg === old_bg');
|
|
return;
|
|
}
|
|
|
|
return { oldBg, newBg };
|
|
}
|
|
|
|
async function onRenameBackgroundClick(e) {
|
|
e.stopPropagation();
|
|
|
|
const bgNames = await getNewBackgroundName(this);
|
|
|
|
if (!bgNames) {
|
|
return;
|
|
}
|
|
|
|
const data = { old_bg: bgNames.oldBg, new_bg: bgNames.newBg };
|
|
const response = await fetch('/api/backgrounds/rename', {
|
|
method: 'POST',
|
|
headers: getRequestHeaders(),
|
|
body: JSON.stringify(data),
|
|
cache: 'no-cache',
|
|
});
|
|
|
|
if (response.ok) {
|
|
await getBackgrounds();
|
|
highlightNewBackground(bgNames.newBg);
|
|
} else {
|
|
toastr.warning('Failed to rename background');
|
|
}
|
|
}
|
|
|
|
async function onDeleteBackgroundClick(e) {
|
|
e.stopPropagation();
|
|
const bgToDelete = $(this).closest('.bg_example');
|
|
const url = bgToDelete.data('url');
|
|
const isCustom = bgToDelete.attr('custom') === 'true';
|
|
const confirm = await callPopup('<h3>Delete the background?</h3>', 'confirm');
|
|
const bg = bgToDelete.attr('bgfile');
|
|
|
|
if (confirm) {
|
|
// If it's not custom, it's a built-in background. Delete it from the server
|
|
if (!isCustom) {
|
|
delBackground(bg);
|
|
} else {
|
|
const list = chat_metadata[LIST_METADATA_KEY] || [];
|
|
const index = list.indexOf(bg);
|
|
list.splice(index, 1);
|
|
}
|
|
|
|
const siblingSelector = '.bg_example:not(#form_bg_download)';
|
|
const nextBg = bgToDelete.next(siblingSelector);
|
|
const prevBg = bgToDelete.prev(siblingSelector);
|
|
const anyBg = $(siblingSelector);
|
|
|
|
if (nextBg.length > 0) {
|
|
nextBg.trigger('click');
|
|
} else if (prevBg.length > 0) {
|
|
prevBg.trigger('click');
|
|
} else {
|
|
$(anyBg[Math.floor(Math.random() * anyBg.length)]).trigger('click');
|
|
}
|
|
|
|
bgToDelete.remove();
|
|
|
|
if (url === chat_metadata[BG_METADATA_KEY]) {
|
|
removeBackgroundMetadata();
|
|
unsetCustomBackground();
|
|
highlightLockedBackground();
|
|
}
|
|
|
|
if (isCustom) {
|
|
getChatBackgroundsList();
|
|
saveMetadataDebounced();
|
|
}
|
|
}
|
|
}
|
|
|
|
const autoBgPrompt = 'Pause your roleplay and choose a location ONLY from the provided list that is the most suitable for the current scene. Do not output any other text:\n{0}';
|
|
|
|
async function autoBackgroundCommand() {
|
|
/** @type {HTMLElement[]} */
|
|
const bgTitles = Array.from(document.querySelectorAll('#bg_menu_content .BGSampleTitle'));
|
|
const options = bgTitles.map(x => ({ element: x, text: x.innerText.trim() })).filter(x => x.text.length > 0);
|
|
if (options.length == 0) {
|
|
toastr.warning('No backgrounds to choose from. Please upload some images to the "backgrounds" folder.');
|
|
return;
|
|
}
|
|
|
|
const list = options.map(option => `- ${option.text}`).join('\n');
|
|
const prompt = stringFormat(autoBgPrompt, list);
|
|
const reply = await generateQuietPrompt(prompt, false, false);
|
|
const fuse = new Fuse(options, { keys: ['text'] });
|
|
const bestMatch = fuse.search(reply, { limit: 1 });
|
|
|
|
if (bestMatch.length == 0) {
|
|
toastr.warning('No match found. Please try again.');
|
|
return;
|
|
}
|
|
|
|
console.debug('Automatically choosing background:', bestMatch);
|
|
bestMatch[0].item.element.click();
|
|
}
|
|
|
|
export async function getBackgrounds() {
|
|
const response = await fetch('/api/backgrounds/all', {
|
|
method: 'POST',
|
|
headers: getRequestHeaders(),
|
|
body: JSON.stringify({
|
|
'': '',
|
|
}),
|
|
});
|
|
if (response.ok) {
|
|
const getData = await response.json();
|
|
//background = getData;
|
|
//console.log(getData.length);
|
|
$('#bg_menu_content').children('div').remove();
|
|
for (const bg of getData) {
|
|
const template = getBackgroundFromTemplate(bg, false);
|
|
$('#bg_menu_content').append(template);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the CSS URL of the background
|
|
* @param {Element} block
|
|
* @returns {string} URL of the background
|
|
*/
|
|
function getUrlParameter(block) {
|
|
return $(block).closest('.bg_example').data('url');
|
|
}
|
|
|
|
function generateUrlParameter(bg, isCustom) {
|
|
return isCustom ? `url("${encodeURI(bg)}")` : `url("${getBackgroundPath(bg)}")`;
|
|
}
|
|
|
|
/**
|
|
* Instantiates a background template
|
|
* @param {string} bg Path to background
|
|
* @param {boolean} isCustom Whether the background is custom
|
|
* @returns {JQuery<HTMLElement>} Background template
|
|
*/
|
|
function getBackgroundFromTemplate(bg, isCustom) {
|
|
const template = $('#background_template .bg_example').clone();
|
|
const thumbPath = isCustom ? bg : getThumbnailUrl('bg', bg);
|
|
const url = generateUrlParameter(bg, isCustom);
|
|
const title = isCustom ? bg.split('/').pop() : bg;
|
|
const friendlyTitle = title.slice(0, title.lastIndexOf('.'));
|
|
template.attr('title', title);
|
|
template.attr('bgfile', bg);
|
|
template.attr('custom', String(isCustom));
|
|
template.data('url', url);
|
|
template.css('background-image', `url('${thumbPath}')`);
|
|
template.find('.BGSampleTitle').text(friendlyTitle);
|
|
return template;
|
|
}
|
|
|
|
async function setBackground(bg, url) {
|
|
$('#bg1').css('background-image', url);
|
|
background_settings.name = bg;
|
|
background_settings.url = url;
|
|
saveSettingsDebounced();
|
|
}
|
|
|
|
async function delBackground(bg) {
|
|
await fetch('/api/backgrounds/delete', {
|
|
method: 'POST',
|
|
headers: getRequestHeaders(),
|
|
body: JSON.stringify({
|
|
bg: bg,
|
|
}),
|
|
});
|
|
}
|
|
|
|
function onBackgroundUploadSelected() {
|
|
const form = $('#form_bg_download').get(0);
|
|
|
|
if (!(form instanceof HTMLFormElement)) {
|
|
console.error('form_bg_download is not a form');
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData(form);
|
|
uploadBackground(formData);
|
|
form.reset();
|
|
}
|
|
|
|
/**
|
|
* Uploads a background to the server
|
|
* @param {FormData} formData
|
|
*/
|
|
function uploadBackground(formData) {
|
|
jQuery.ajax({
|
|
type: 'POST',
|
|
url: '/api/backgrounds/upload',
|
|
data: formData,
|
|
beforeSend: function () {
|
|
},
|
|
cache: false,
|
|
contentType: false,
|
|
processData: false,
|
|
success: async function (bg) {
|
|
setBackground(bg, generateUrlParameter(bg, false));
|
|
await getBackgrounds();
|
|
highlightNewBackground(bg);
|
|
},
|
|
error: function (jqXHR, exception) {
|
|
console.log(exception);
|
|
console.log(jqXHR);
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {string} bg
|
|
*/
|
|
function highlightNewBackground(bg) {
|
|
const newBg = $(`.bg_example[bgfile="${bg}"]`);
|
|
const scrollOffset = newBg.offset().top - newBg.parent().offset().top;
|
|
$('#Backgrounds').scrollTop(scrollOffset);
|
|
flashHighlight(newBg);
|
|
}
|
|
|
|
function onBackgroundFilterInput() {
|
|
const filterValue = String($(this).val()).toLowerCase();
|
|
$('#bg_menu_content > div').each(function () {
|
|
const $bgContent = $(this);
|
|
if ($bgContent.attr('title').toLowerCase().includes(filterValue)) {
|
|
$bgContent.show();
|
|
} else {
|
|
$bgContent.hide();
|
|
}
|
|
});
|
|
}
|
|
|
|
export function initBackgrounds() {
|
|
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
|
|
eventSource.on(event_types.FORCE_SET_BACKGROUND, forceSetBackground);
|
|
$(document).on('click', '.bg_example', onSelectBackgroundClick);
|
|
$(document).on('click', '.bg_example_lock', onLockBackgroundClick);
|
|
$(document).on('click', '.bg_example_unlock', onUnlockBackgroundClick);
|
|
$(document).on('click', '.bg_example_edit', onRenameBackgroundClick);
|
|
$(document).on('click', '.bg_example_cross', onDeleteBackgroundClick);
|
|
$(document).on('click', '.bg_example_copy', onCopyToSystemBackgroundClick);
|
|
$('#auto_background').on('click', autoBackgroundCommand);
|
|
$('#add_bg_button').on('change', onBackgroundUploadSelected);
|
|
$('#bg-filter').on('input', onBackgroundFilterInput);
|
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'lockbg',
|
|
callback: onLockBackgroundClick,
|
|
aliases: ['bglock'],
|
|
helpString: 'Locks a background for the currently selected chat',
|
|
}));
|
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'unlockbg',
|
|
callback: onUnlockBackgroundClick,
|
|
aliases: ['bgunlock'],
|
|
helpString: 'Unlocks a background for the currently selected chat',
|
|
}));
|
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'autobg',
|
|
callback: autoBackgroundCommand,
|
|
aliases: ['bgauto'],
|
|
helpString: 'Automatically changes the background based on the chat context using the AI request prompt',
|
|
}));
|
|
|
|
}
|