Merge branch 'staging' into macro-register

This commit is contained in:
Cohee
2024-06-26 21:54:00 +03:00
23 changed files with 284 additions and 170 deletions

View File

@ -36,9 +36,6 @@ label[for="extensions_autoconnect"] {
.extensions_info { .extensions_info {
text-align: left; text-align: left;
max-height: 100%;
overflow-y: auto;
padding-right: 1em;
} }
.extensions_info h3 { .extensions_info h3 {

View File

@ -115,12 +115,10 @@ dialog {
background-color: var(--crimson-hover); background-color: var(--crimson-hover);
} }
.menu_button.popup-button-custom {
/* Custom buttons should not scale to smallest size, otherwise they will always break to multiline */
width: unset;
}
.popup-controls .menu_button { .popup-controls .menu_button {
/* Popup buttons should not scale to smallest size, otherwise they will always break to multiline if multiple words */
width: unset;
/* Fix weird animation issue with fonts on brightness filter */ /* Fix weird animation issue with fonts on brightness filter */
backface-visibility: hidden; backface-visibility: hidden;
transform: translateZ(0); transform: translateZ(0);

6
public/img/manual.svg Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M13.3252 3.05011L8.66765 20.4323L10.5995 20.9499L15.257 3.56775L13.3252 3.05011Z" />
<path d="M7.61222 18.3608L8.97161 16.9124L8.9711 16.8933L3.87681 12.1121L8.66724 7.00798L7.20892 5.63928L1.0498 12.2017L7.61222 18.3608Z" />
<path d="M16.3883 18.3608L15.0289 16.9124L15.0294 16.8933L20.1237 12.1121L15.3333 7.00798L16.7916 5.63928L22.9507 12.2017L16.3883 18.3608Z" />
</svg>

After

Width:  |  Height:  |  Size: 514 B

View File

@ -6400,9 +6400,6 @@
</div> </div>
</div> </div>
</template> </template>
<div id="rawPromptPopup" class="list-group">
<div id="rawPromptWrapper" class="tokenItemizingSubclass"></div>
</div>
<div id="user_avatar_template" class="template_element"> <div id="user_avatar_template" class="template_element">
<div class="avatar-container"> <div class="avatar-container">
<div imgfile="" class="avatar"> <div imgfile="" class="avatar">

View File

@ -228,7 +228,7 @@ import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, de
import { initPresetManager } from './scripts/preset-manager.js'; import { initPresetManager } from './scripts/preset-manager.js';
import { MacrosParser, evaluateMacros } from './scripts/macros.js'; import { MacrosParser, evaluateMacros } from './scripts/macros.js';
import { currentUser, setUserControls } from './scripts/user.js'; import { currentUser, setUserControls } from './scripts/user.js';
import { POPUP_TYPE, Popup, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js'; import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js';
import { renderTemplate, renderTemplateAsync } from './scripts/templates.js'; import { renderTemplate, renderTemplateAsync } from './scripts/templates.js';
import { ScraperManager } from './scripts/scrapers.js'; import { ScraperManager } from './scripts/scrapers.js';
import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js'; import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js';
@ -513,9 +513,6 @@ let optionsPopper = Popper.createPopper(document.getElementById('options_button'
let exportPopper = Popper.createPopper(document.getElementById('export_button'), document.getElementById('export_format_popup'), { let exportPopper = Popper.createPopper(document.getElementById('export_button'), document.getElementById('export_format_popup'), {
placement: 'left', placement: 'left',
}); });
let rawPromptPopper = Popper.createPopper(document.getElementById('dialogue_popup'), document.getElementById('rawPromptPopup'), {
placement: 'right',
});
// Saved here for performance reasons // Saved here for performance reasons
const messageTemplate = $('#message_template .mes'); const messageTemplate = $('#message_template .mes');
@ -4890,14 +4887,44 @@ async function promptItemize(itemizedPrompts, requestedMesId) {
const params = await itemizedParams(itemizedPrompts, thisPromptSet); const params = await itemizedParams(itemizedPrompts, thisPromptSet);
if (params.this_main_api == 'openai') { const template = params.this_main_api == 'openai'
const template = await renderTemplateAsync('itemizationChat', params); ? await renderTemplateAsync('itemizationChat', params)
callPopup(template, 'text'); : await renderTemplateAsync('itemizationText', params);
} else { const popup = new Popup(template, POPUP_TYPE.TEXT);
const template = await renderTemplateAsync('itemizationText', params);
callPopup(template, 'text'); popup.dlg.querySelector('#copyPromptToClipboard').addEventListener('click', function () {
} let rawPrompt = itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt;
let rawPromptValues = rawPrompt;
if (Array.isArray(rawPrompt)) {
rawPromptValues = rawPrompt.map(x => x.content).join('\n');
}
navigator.clipboard.writeText(rawPromptValues);
toastr.info('Copied!');
});
popup.dlg.querySelector('#showRawPrompt').addEventListener('click', function () {
//console.log(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt);
console.log(PromptArrayItemForRawPromptDisplay);
console.log(itemizedPrompts);
console.log(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt);
let rawPrompt = itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt;
let rawPromptValues = rawPrompt;
if (Array.isArray(rawPrompt)) {
rawPromptValues = rawPrompt.map(x => x.content).join('\n');
}
//let DisplayStringifiedPrompt = JSON.stringify(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt).replace(/\n+/g, '<br>');
const rawPromptWrapper = document.getElementById('rawPromptWrapper');
rawPromptWrapper.innerText = rawPromptValues;
$('#rawPromptPopup').slideToggle();
});
await popup.show();
} }
function setInContextMessages(lastmsg, type) { function setInContextMessages(lastmsg, type) {
@ -9184,13 +9211,6 @@ jQuery(async function () {
if (popup_type == 'alternate_greeting' && menu_type !== 'create') { if (popup_type == 'alternate_greeting' && menu_type !== 'create') {
createOrEditCharacter(); createOrEditCharacter();
} }
if (popup_type === 'del_group') {
const groupId = $('#dialogue_popup').data('group_id');
if (groupId) {
deleteGroup(groupId);
}
}
//Make a new chat for selected character //Make a new chat for selected character
if ( if (
popup_type == 'new_chat' && popup_type == 'new_chat' &&
@ -9224,9 +9244,6 @@ jQuery(async function () {
} }
} }
rawPromptPopper.update();
$('#rawPromptPopup').hide();
if (dialogueResolve) { if (dialogueResolve) {
if (popup_type == 'input') { if (popup_type == 'input') {
dialogueResolve($('#dialogue_popup_input').val()); dialogueResolve($('#dialogue_popup_input').val());
@ -9817,45 +9834,14 @@ jQuery(async function () {
}); });
} }
$(document).on('pointerup', '.mes_prompt', function () { $(document).on('pointerup', '.mes_prompt', async function () {
let mesIdForItemization = $(this).closest('.mes').attr('mesId'); let mesIdForItemization = $(this).closest('.mes').attr('mesId');
console.log(`looking for mesID: ${mesIdForItemization}`); console.log(`looking for mesID: ${mesIdForItemization}`);
if (itemizedPrompts.length !== undefined && itemizedPrompts.length !== 0) { if (itemizedPrompts.length !== undefined && itemizedPrompts.length !== 0) {
promptItemize(itemizedPrompts, mesIdForItemization); await promptItemize(itemizedPrompts, mesIdForItemization);
} }
}); });
$(document).on('pointerup', '#copyPromptToClipboard', function () {
let rawPrompt = itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt;
let rawPromptValues = rawPrompt;
if (Array.isArray(rawPrompt)) {
rawPromptValues = rawPrompt.map(x => x.content).join('\n');
}
navigator.clipboard.writeText(rawPromptValues);
toastr.info('Copied!', '', { timeOut: 2000 });
});
$(document).on('pointerup', '#showRawPrompt', function () {
//console.log(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt);
console.log(PromptArrayItemForRawPromptDisplay);
console.log(itemizedPrompts);
console.log(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt);
let rawPrompt = itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt;
let rawPromptValues = rawPrompt;
if (Array.isArray(rawPrompt)) {
rawPromptValues = rawPrompt.map(x => x.content).join('\n');
}
//let DisplayStringifiedPrompt = JSON.stringify(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt).replace(/\n+/g, '<br>');
$('#rawPromptWrapper').text(rawPromptValues);
rawPromptPopper.update();
$('#rawPromptPopup').toggle();
});
//******************** //********************
//***Message Editor*** //***Message Editor***
$(document).on('click', '.mes_edit', async function () { $(document).on('click', '.mes_edit', async function () {
@ -10060,7 +10046,7 @@ jQuery(async function () {
}); });
$(document).on('click', '.mes_edit_copy', async function () { $(document).on('click', '.mes_edit_copy', async function () {
const confirmation = await callPopup('Create a copy of this message?', 'confirm'); const confirmation = await callGenericPopup('Create a copy of this message?', POPUP_TYPE.CONFIRM);
if (!confirmation) { if (!confirmation) {
return; return;
} }
@ -10086,24 +10072,33 @@ jQuery(async function () {
$(document).on('click', '.mes_edit_delete', async function (event, customData) { $(document).on('click', '.mes_edit_delete', async function (event, customData) {
const fromSlashCommand = customData?.fromSlashCommand || false; const fromSlashCommand = customData?.fromSlashCommand || false;
const swipeExists = (!Array.isArray(chat[this_edit_mes_id].swipes) || chat[this_edit_mes_id].swipes.length <= 1 || chat[this_edit_mes_id].is_user || parseInt(this_edit_mes_id) !== chat.length - 1); const canDeleteSwipe = (Array.isArray(chat[this_edit_mes_id].swipes) && chat[this_edit_mes_id].swipes.length > 1 && !chat[this_edit_mes_id].is_user && parseInt(this_edit_mes_id) === chat.length - 1);
let deleteOnlySwipe = false;
if (power_user.confirm_message_delete && fromSlashCommand !== true) { if (power_user.confirm_message_delete && fromSlashCommand !== true) {
const confirmation = swipeExists ? await callPopup('Are you sure you want to delete this message?', 'confirm') const result = await callGenericPopup('Are you sure you want to delete this message?', POPUP_TYPE.CONFIRM, null, {
: await callPopup('<h3>Delete this...</h3> <select id=\'del_type\'><option value=\'swipe\'>Swipe</option><option value=\'message\'>Message</option></select>', 'confirm'); okButton: canDeleteSwipe ? 'Delete Swipe' : 'Delete Message',
if (!confirmation) { cancelButton: 'Cancel',
customButtons: canDeleteSwipe ? ['Delete Message'] : null,
});
if (!result) {
return; return;
} }
deleteOnlySwipe = canDeleteSwipe && result === 1; // Default button, not the custom one
} }
const mes = $(this).closest('.mes'); const messageElement = $(this).closest('.mes');
if (!messageElement) {
if (!mes) {
return; return;
} }
if ($('#del_type').val() === 'swipe') { if (deleteOnlySwipe) {
const swipe_id = chat[this_edit_mes_id]['swipe_id']; const message = chat[this_edit_mes_id];
chat[this_edit_mes_id]['swipes'].splice(swipe_id, 1); const swipe_id = message.swipe_id;
message.swipes.splice(swipe_id, 1);
if (Array.isArray(message.swipe_info) && message.swipe_info.length) {
message.swipe_info.splice(swipe_id, 1);
}
if (swipe_id > 0) { if (swipe_id > 0) {
$('.swipe_left:last').click(); $('.swipe_left:last').click();
} else { } else {
@ -10111,7 +10106,7 @@ jQuery(async function () {
} }
} else { } else {
chat.splice(this_edit_mes_id, 1); chat.splice(this_edit_mes_id, 1);
mes.remove(); messageElement.remove();
} }
let startFromZero = Number(this_edit_mes_id) === 0; let startFromZero = Number(this_edit_mes_id) === 0;

View File

@ -16,7 +16,6 @@ import {
eventSource, eventSource,
menu_type, menu_type,
substituteParams, substituteParams,
callPopup,
sendTextareaMessage, sendTextareaMessage,
} from '../script.js'; } from '../script.js';
@ -1004,20 +1003,21 @@ export function initRossMods() {
if (skipConfirm) { if (skipConfirm) {
doRegenerate(); doRegenerate();
} else { } else {
const popupText = ` Popup.show.confirm('Regenerate Message', `
<div class="marginBot10">Are you sure you want to regenerate the latest message?</div> <span>Are you sure you want to regenerate the latest message?</span>
<label class="checkbox_label justifyCenter" for="regenerateWithCtrlEnter"> <label class="checkbox_label justifyCenter marginTop10" for="regenerateWithCtrlEnter">
<input type="checkbox" id="regenerateWithCtrlEnter"> <input type="checkbox" id="regenerateWithCtrlEnter">
Don't ask again Don't ask again
</label>`; </label>`, {
callPopup(popupText, 'confirm').then(result => { onClose: (popup) => {
if (!result) { if (!popup.result) {
return; return;
} }
const regenerateWithCtrlEnter = $('#regenerateWithCtrlEnter').prop('checked'); const regenerateWithCtrlEnter = $('#regenerateWithCtrlEnter').prop('checked');
SaveLocal(skipConfirmKey, regenerateWithCtrlEnter); SaveLocal(skipConfirmKey, regenerateWithCtrlEnter);
doRegenerate(); doRegenerate();
}); },
})
} }
return; return;
} else { } else {

View File

@ -504,7 +504,7 @@ function addExtensionScript(name, manifest) {
* @param {boolean} isDisabled - Whether the extension is disabled or not. * @param {boolean} isDisabled - Whether the extension is disabled or not.
* @param {boolean} isExternal - Whether the extension is external or not. * @param {boolean} isExternal - Whether the extension is external or not.
* @param {string} checkboxClass - The class for the checkbox HTML element. * @param {string} checkboxClass - The class for the checkbox HTML element.
* @return {string} - The HTML string that represents the extension. * @return {Promise<string>} - The HTML string that represents the extension.
*/ */
async function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal, checkboxClass) { async function generateExtensionHtml(name, manifest, isActive, isDisabled, isExternal, checkboxClass) {
const displayName = manifest.display_name; const displayName = manifest.display_name;
@ -556,8 +556,10 @@ async function generateExtensionHtml(name, manifest, isActive, isDisabled, isExt
} else if (!isDisabled) { // Neither active nor disabled } else if (!isDisabled) { // Neither active nor disabled
const requirements = new Set(manifest.requires); const requirements = new Set(manifest.requires);
modules.forEach(x => requirements.delete(x)); modules.forEach(x => requirements.delete(x));
const requirementsString = DOMPurify.sanitize([...requirements].join(', ')); if (requirements.size > 0) {
extensionHtml += `<p>Missing modules: <span class="failure">${requirementsString}</span></p>`; const requirementsString = DOMPurify.sanitize([...requirements].join(', '));
extensionHtml += `<p>Missing modules: <span class="failure">${requirementsString}</span></p>`;
}
} }
return extensionHtml; return extensionHtml;
@ -642,7 +644,7 @@ async function showExtensionsDetails() {
popup.complete(POPUP_RESULT.AFFIRMATIVE); popup.complete(POPUP_RESULT.AFFIRMATIVE);
}, },
}; };
const popup = new Popup(`<div class="extensions_info">${html}</div>`, POPUP_TYPE.TEXT, '', { okButton: 'Close', wide: true, large: true, customButtons: [updateAllButton] }); const popup = new Popup(`<div class="extensions_info">${html}</div>`, POPUP_TYPE.TEXT, '', { okButton: 'Close', wide: true, large: true, customButtons: [updateAllButton], allowVerticalScrolling: true });
popupPromise = popup.show(); popupPromise = popup.show();
} catch (error) { } catch (error) {
toastr.error('Error loading extensions. See browser console for details.'); toastr.error('Error loading extensions. See browser console for details.');

View File

@ -1,10 +1,11 @@
import { callPopup, main_api } from '../../../script.js'; import { main_api } from '../../../script.js';
import { getContext } from '../../extensions.js'; import { getContext } from '../../extensions.js';
import { SlashCommand } from '../../slash-commands/SlashCommand.js'; import { SlashCommand } from '../../slash-commands/SlashCommand.js';
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
import { getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, tokenizers } from '../../tokenizers.js'; import { getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, tokenizers } from '../../tokenizers.js';
import { resetScrollHeight, debounce } from '../../utils.js'; import { resetScrollHeight, debounce } from '../../utils.js';
import { debounce_timeout } from '../../constants.js'; import { debounce_timeout } from '../../constants.js';
import { POPUP_TYPE, callGenericPopup } from '../../popup.js';
function rgb2hex(rgb) { function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
@ -63,8 +64,7 @@ async function doTokenCounter() {
}, debounce_timeout.relaxed); }, debounce_timeout.relaxed);
dialog.find('#token_counter_textarea').on('input', () => countDebounced()); dialog.find('#token_counter_textarea').on('input', () => countDebounced());
$('#dialogue_popup').addClass('wide_dialogue_popup'); callGenericPopup(dialog, POPUP_TYPE.TEXT, '', { wide: true, large: true, allowVerticalScrolling: true });
callPopup(dialog, 'text', '', { wide: true, large: true });
} }
/** /**

View File

@ -1,7 +1,6 @@
export { translate }; export { translate };
import { import {
callPopup,
eventSource, eventSource,
event_types, event_types,
getRequestHeaders, getRequestHeaders,
@ -11,6 +10,7 @@ import {
updateMessageBlock, updateMessageBlock,
} from '../../../script.js'; } from '../../../script.js';
import { extension_settings, getContext, renderExtensionTemplateAsync } from '../../extensions.js'; import { extension_settings, getContext, renderExtensionTemplateAsync } from '../../extensions.js';
import { POPUP_TYPE, callGenericPopup } from '../../popup.js';
import { findSecret, secret_state, writeSecret } from '../../secrets.js'; import { findSecret, secret_state, writeSecret } from '../../secrets.js';
import { SlashCommand } from '../../slash-commands/SlashCommand.js'; import { SlashCommand } from '../../slash-commands/SlashCommand.js';
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
@ -510,7 +510,7 @@ async function onTranslateChatClick() {
async function onTranslationsClearClick() { async function onTranslationsClearClick() {
const popupHtml = await renderExtensionTemplateAsync('translate', 'deleteConfirmation'); const popupHtml = await renderExtensionTemplateAsync('translate', 'deleteConfirmation');
const confirm = await callPopup(popupHtml, 'confirm'); const confirm = await callGenericPopup(popupHtml, POPUP_TYPE.CONFIRM);
if (!confirm) { if (!confirm) {
return; return;
@ -598,7 +598,7 @@ jQuery(async () => {
$(document).on('click', '.mes_translate', onMessageTranslateClick); $(document).on('click', '.mes_translate', onMessageTranslateClick);
$('#translate_key_button').on('click', async () => { $('#translate_key_button').on('click', async () => {
const optionText = $('#translation_provider option:selected').text(); const optionText = $('#translation_provider option:selected').text();
const key = await callPopup(`<h3>${optionText} API Key</h3>`, 'input'); const key = await callGenericPopup(`<h3>${optionText} API Key</h3>`, POPUP_TYPE.INPUT);
if (key == false) { if (key == false) {
return; return;
@ -621,7 +621,7 @@ jQuery(async () => {
const secretKey = extension_settings.translate.provider + '_url'; const secretKey = extension_settings.translate.provider + '_url';
const savedUrl = secret_state[secretKey] ? await findSecret(secretKey) : ''; const savedUrl = secret_state[secretKey] ? await findSecret(secretKey) : '';
const url = await callPopup(popupText, 'input', savedUrl); const url = await callGenericPopup(popupText, POPUP_TYPE.INPUT, savedUrl);
if (url == false || url == '') { if (url == false || url == '') {
return; return;

View File

@ -1,4 +1,4 @@
import { callPopup, cancelTtsPlay, eventSource, event_types, isStreamingEnabled, name2, saveSettingsDebounced, substituteParams } from '../../../script.js'; import { cancelTtsPlay, eventSource, event_types, isStreamingEnabled, name2, saveSettingsDebounced, substituteParams } from '../../../script.js';
import { ModuleWorkerWrapper, doExtrasFetch, extension_settings, getApiUrl, getContext, modules, renderExtensionTemplateAsync } from '../../extensions.js'; import { ModuleWorkerWrapper, doExtrasFetch, extension_settings, getApiUrl, getContext, modules, renderExtensionTemplateAsync } from '../../extensions.js';
import { delay, escapeRegex, getBase64Async, getStringHash, onlyUnique } from '../../utils.js'; import { delay, escapeRegex, getBase64Async, getStringHash, onlyUnique } from '../../utils.js';
import { EdgeTtsProvider } from './edge.js'; import { EdgeTtsProvider } from './edge.js';
@ -21,6 +21,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '
import { debounce_timeout } from '../../constants.js'; import { debounce_timeout } from '../../constants.js';
import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js'; import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
import { POPUP_TYPE, callGenericPopup } from '../../popup.js';
export { talkingAnimation }; export { talkingAnimation };
const UPDATE_INTERVAL = 1000; const UPDATE_INTERVAL = 1000;
@ -310,7 +311,7 @@ async function onTtsVoicesClick() {
popupText = 'Could not load voices list. Check your API key.'; popupText = 'Could not load voices list. Check your API key.';
} }
callPopup(popupText, 'text'); callGenericPopup(popupText, POPUP_TYPE.TEXT, '', { allowVerticalScrolling: true });
} }
function updateUiAudioPlayState() { function updateUiAudioPlayState() {

View File

@ -24,7 +24,6 @@ import {
characters, characters,
default_avatar, default_avatar,
addOneMessage, addOneMessage,
callPopup,
clearChat, clearChat,
Generate, Generate,
select_rm_info, select_rm_info,
@ -75,7 +74,7 @@ import {
import { printTagList, createTagMapFromList, applyTagsOnCharacterSelect, tag_map, applyTagsOnGroupSelect } from './tags.js'; import { printTagList, createTagMapFromList, applyTagsOnCharacterSelect, tag_map, applyTagsOnGroupSelect } from './tags.js';
import { FILTER_TYPES, FilterHelper } from './filters.js'; import { FILTER_TYPES, FilterHelper } from './filters.js';
import { isExternalMediaAllowed } from './chats.js'; import { isExternalMediaAllowed } from './chats.js';
import { POPUP_TYPE, callGenericPopup } from './popup.js'; import { POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
export { export {
selected_group, selected_group,
@ -1300,14 +1299,20 @@ function isGroupMemberDisabled(avatarId) {
return Boolean(thisGroup && thisGroup.disabled_members.includes(avatarId)); return Boolean(thisGroup && thisGroup.disabled_members.includes(avatarId));
} }
function onDeleteGroupClick() { async function onDeleteGroupClick() {
if (!openGroupId) {
toastr.warning('Currently no group selected.');
return;
}
if (is_group_generating) { if (is_group_generating) {
toastr.warning('Not so fast! Wait for the characters to stop typing before deleting the group.'); toastr.warning('Not so fast! Wait for the characters to stop typing before deleting the group.');
return; return;
} }
$('#dialogue_popup').data('group_id', openGroupId); const confirm = await Popup.show.confirm('Delete the group?', '<p>This will also delete all your chats with that group. If you want to delete a single conversation, select a "View past chats" option in the lower left menu.</p>');
callPopup('<h3>Delete the group?</h3><p>This will also delete all your chats with that group. If you want to delete a single conversation, select a "View past chats" option in the lower left menu.</p>', 'del_group'); if (confirm) {
deleteGroup(openGroupId);
}
} }
async function onFavoriteGroupClick() { async function onFavoriteGroupClick() {
@ -1476,8 +1481,7 @@ async function uploadGroupAvatar(event) {
} }
async function restoreGroupAvatar() { async function restoreGroupAvatar() {
const confirm = await callPopup('<h3>Are you sure you want to restore the group avatar?</h3> Your custom image will be deleted, and a collage will be used instead.', 'confirm'); const confirm = await Popup.show.confirm('Are you sure you want to restore the group avatar?', 'Your custom image will be deleted, and a collage will be used instead.');
if (!confirm) { if (!confirm) {
return; return;
} }

View File

@ -590,7 +590,37 @@ function selectCurrentPersona() {
} }
} }
async function lockUserNameToChat() { /**
* Checks if the persona is locked for the current chat.
* @returns {boolean} Whether the persona is locked
*/
function isPersonaLocked() {
return !!chat_metadata['persona'];
}
/**
* Locks or unlocks the persona for the current chat.
* @param {boolean} state Desired lock state
* @returns {Promise<void>}
*/
export async function setPersonaLockState(state) {
return state ? await lockPersona() : await unlockPersona();
}
/**
* Toggle the persona lock state for the current chat.
* @returns {Promise<void>}
*/
export async function togglePersonaLock() {
return isPersonaLocked()
? await unlockPersona()
: await lockPersona();
}
/**
* Unlock the persona for the current chat.
*/
async function unlockPersona() {
if (chat_metadata['persona']) { if (chat_metadata['persona']) {
console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`); console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`);
delete chat_metadata['persona']; delete chat_metadata['persona'];
@ -599,9 +629,13 @@ async function lockUserNameToChat() {
toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked'); toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked');
} }
updateUserLockIcon(); updateUserLockIcon();
return;
} }
}
/**
* Lock the persona for the current chat.
*/
async function lockPersona() {
if (!(user_avatar in power_user.personas)) { if (!(user_avatar in power_user.personas)) {
console.log(`Creating a new persona ${user_avatar}`); console.log(`Creating a new persona ${user_avatar}`);
if (power_user.persona_show_notifications) { if (power_user.persona_show_notifications) {
@ -625,6 +659,7 @@ async function lockUserNameToChat() {
updateUserLockIcon(); updateUserLockIcon();
} }
async function deleteUserAvatar(e) { async function deleteUserAvatar(e) {
e?.stopPropagation(); e?.stopPropagation();
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile'); const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
@ -973,7 +1008,7 @@ export function initPersonas() {
$(document).on('click', '.bind_user_name', bindUserNameToPersona); $(document).on('click', '.bind_user_name', bindUserNameToPersona);
$(document).on('click', '.set_default_persona', setDefaultPersona); $(document).on('click', '.set_default_persona', setDefaultPersona);
$(document).on('click', '.delete_avatar', deleteUserAvatar); $(document).on('click', '.delete_avatar', deleteUserAvatar);
$('#lock_user_name').on('click', lockUserNameToChat); $('#lock_user_name').on('click', togglePersonaLock);
$('#create_dummy_persona').on('click', createDummyPersona); $('#create_dummy_persona').on('click', createDummyPersona);
$('#persona_description').on('input', onPersonaDescriptionInput); $('#persona_description').on('input', onPersonaDescriptionInput);
$('#persona_description_position').on('input', onPersonaDescriptionPositionInput); $('#persona_description_position').on('input', onPersonaDescriptionPositionInput);

View File

@ -74,6 +74,22 @@ const showPopupHelper = {
const value = await popup.show(); const value = await popup.show();
return value ? String(value) : null; return value ? String(value) : null;
}, },
/**
* Asynchronously displays a confirmation popup with the given header and text, returning the clicked result button value.
*
* @param {string} header - The header text for the popup.
* @param {string} text - The main text for the popup.
* @param {PopupOptions} [popupOptions={}] - Options for the popup.
* @return {Promise<POPUP_RESULT>} A Promise that resolves with the result of the user's interaction.
*/
confirm: async (header, text, popupOptions = {}) => {
const content = PopupUtils.BuildTextWithHeader(header, text);
const popup = new Popup(content, POPUP_TYPE.CONFIRM, null, popupOptions);
const result = await popup.show();
if (typeof result === 'string' || typeof result === 'boolean') throw new Error(`Invalid popup result. CONFIRM popups only support numbers, or null. Result: ${result}`);
return result;
}
}; };
export class Popup { export class Popup {

View File

@ -2,7 +2,6 @@ import {
saveSettingsDebounced, saveSettingsDebounced,
scrollChatToBottom, scrollChatToBottom,
characters, characters,
callPopup,
reloadMarkdownProcessor, reloadMarkdownProcessor,
reloadCurrentChat, reloadCurrentChat,
getRequestHeaders, getRequestHeaders,
@ -48,6 +47,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashComma
import { AUTOCOMPLETE_WIDTH } from './autocomplete/AutoComplete.js'; import { AUTOCOMPLETE_WIDTH } from './autocomplete/AutoComplete.js';
import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
import { POPUP_TYPE, callGenericPopup } from './popup.js';
export { export {
loadPowerUserSettings, loadPowerUserSettings,
@ -1432,7 +1432,7 @@ export function registerDebugFunction(functionId, name, description, func) {
async function showDebugMenu() { async function showDebugMenu() {
const template = await renderTemplateAsync('debug', { functions: debug_functions }); const template = await renderTemplateAsync('debug', { functions: debug_functions });
callPopup(template, 'text', '', { wide: true, large: true }); callGenericPopup(template, POPUP_TYPE.TEXT, '', { wide: true, large: true, allowVerticalScrolling: true });
} }
switchUiMode(); switchUiMode();
@ -2207,7 +2207,8 @@ async function deleteTheme() {
return; return;
} }
const confirm = await callPopup(`Are you sure you want to delete the theme "${themeName}"?`, 'confirm', '', { okButton: 'Yes' }); const template = $(await renderTemplateAsync('themeDelete', { themeName }));
const confirm = await callGenericPopup(template, POPUP_TYPE.CONFIRM);
if (!confirm) { if (!confirm) {
return; return;
@ -2269,7 +2270,8 @@ async function importTheme(file) {
} }
if (typeof parsed.custom_css === 'string' && parsed.custom_css.includes('@import')) { if (typeof parsed.custom_css === 'string' && parsed.custom_css.includes('@import')) {
const confirm = await callPopup('This theme contains @import lines in the Custom CSS. Press "Yes" to proceed.', 'confirm', '', { okButton: 'Yes' }); const template = $(await renderTemplateAsync('themeImportWarning'));
const confirm = await callGenericPopup(template, POPUP_TYPE.CONFIRM);
if (!confirm) { if (!confirm) {
throw new Error('Theme contains @import lines'); throw new Error('Theme contains @import lines');
} }
@ -2294,11 +2296,13 @@ async function importTheme(file) {
*/ */
async function saveTheme(name = undefined, theme = undefined) { async function saveTheme(name = undefined, theme = undefined) {
if (typeof name !== 'string') { if (typeof name !== 'string') {
name = await callPopup('Enter a theme preset name:', 'input', power_user.theme); const newName = await callGenericPopup('Enter a theme preset name:', POPUP_TYPE.INPUT, power_user.theme);
if (!name) { if (!newName) {
return; return;
} }
name = String(newName);
} }
if (typeof theme !== 'object') { if (typeof theme !== 'object') {
@ -2396,7 +2400,7 @@ function getNewTheme(parsed) {
} }
async function saveMovingUI() { async function saveMovingUI() {
const name = await callPopup('Enter a name for the MovingUI Preset:', 'input'); const name = await callGenericPopup('Enter a name for the MovingUI Preset:', POPUP_TYPE.INPUT);
if (!name) { if (!name) {
return; return;

View File

@ -46,7 +46,7 @@ import { extension_settings, getContext, saveMetadataDebounced } from './extensi
import { getRegexedString, regex_placement } from './extensions/regex/engine.js'; import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
import { findGroupMemberId, getGroupMembers, groups, is_group_generating, openGroupById, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js'; import { findGroupMemberId, getGroupMembers, groups, is_group_generating, openGroupById, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js';
import { chat_completion_sources, oai_settings, setupChatCompletionPromptManager } from './openai.js'; import { chat_completion_sources, oai_settings, setupChatCompletionPromptManager } from './openai.js';
import { autoSelectPersona, retriggerFirstMessageOnEmptyChat, user_avatar } from './personas.js'; import { autoSelectPersona, retriggerFirstMessageOnEmptyChat, setPersonaLockState, togglePersonaLock, user_avatar } from './personas.js';
import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js'; import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
import { decodeTextTokens, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync } from './tokenizers.js'; import { decodeTextTokens, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync } from './tokenizers.js';
@ -118,9 +118,18 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
})); }));
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'lock', name: 'lock',
callback: bindCallback, callback: lockPersonaCallback,
aliases: ['bind'], aliases: ['bind'],
helpString: 'Locks/unlocks a persona (name and avatar) to the current chat', helpString: 'Locks/unlocks a persona (name and avatar) to the current chat',
unnamedArgumentList: [
SlashCommandArgument.fromProps({
description: 'state',
typeList: [ARGUMENT_TYPE.STRING],
isRequired: true,
defaultValue: 'toggle',
enumProvider: commonEnumProviders.boolean('onOffToggle'),
}),
],
})); }));
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'bg', name: 'bg',
@ -1998,6 +2007,9 @@ async function addSwipeCallback(_, arg) {
lastMessage.swipe_info = [{}]; lastMessage.swipe_info = [{}];
lastMessage.swipe_id = 0; lastMessage.swipe_id = 0;
} }
if (!Array.isArray(lastMessage.swipe_info)) {
lastMessage.swipe_info = lastMessage.swipes.map(() => ({}));
}
lastMessage.swipes.push(arg); lastMessage.swipes.push(arg);
lastMessage.swipe_info.push({ lastMessage.swipe_info.push({
@ -2573,8 +2585,23 @@ function syncCallback() {
return ''; return '';
} }
function bindCallback() { async function lockPersonaCallback(_args, value) {
$('#lock_user_name').trigger('click'); if (['toggle', 't', ''].includes(value.trim().toLowerCase())) {
await togglePersonaLock();
return '';
}
if (isTrueBoolean(value)) {
await setPersonaLockState(true);
return '';
}
if (isFalseBoolean(value)) {
await setPersonaLockState(false);
return '';
}
return ''; return '';
} }
@ -2700,9 +2727,26 @@ export async function sendMessageAs(args, text) {
bias: bias.trim().length ? bias : null, bias: bias.trim().length ? bias : null,
gen_id: Date.now(), gen_id: Date.now(),
isSmallSys: compact, isSmallSys: compact,
api: 'manual',
model: 'slash command',
}, },
}; };
message.swipe_id = 0;
message.swipes = [message.mes];
message.swipes_info = [{
send_date: message.send_date,
gen_started: null,
gen_finished: null,
extra: {
bias: message.extra.bias,
gen_id: message.extra.gen_id,
isSmallSys: compact,
api: 'manual',
model: 'slash command',
},
}];
const insertAt = Number(resolveVariable(args.at)); const insertAt = Number(resolveVariable(args.at));
if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) {
@ -2745,6 +2789,8 @@ export async function sendNarratorMessage(args, text) {
bias: bias.trim().length ? bias : null, bias: bias.trim().length ? bias : null,
gen_id: Date.now(), gen_id: Date.now(),
isSmallSys: compact, isSmallSys: compact,
api: 'manual',
model: 'slash command',
}, },
}; };
@ -2795,6 +2841,8 @@ export async function promptQuietForLoudResponse(who, text) {
extra: { extra: {
type: system_message_types.COMMENT, type: system_message_types.COMMENT,
gen_id: Date.now(), gen_id: Date.now(),
api: 'manual',
model: 'slash command',
}, },
}; };
@ -2823,6 +2871,8 @@ async function sendCommentMessage(args, text) {
type: system_message_types.COMMENT, type: system_message_types.COMMENT,
gen_id: Date.now(), gen_id: Date.now(),
isSmallSys: compact, isSmallSys: compact,
api: 'manual',
model: 'slash command',
}, },
}; };

View File

@ -1,25 +1,27 @@
<h3 data-i18n="Debug Menu">Debug Menu</h3> <div>
<div data-i18n="Debug Warning"> <h3 data-i18n="Debug Menu">Debug Menu</h3>
Functions in this category are for advanced users only. Don't click anything if you're not sure about the consequences. <div data-i18n="Debug Warning">
</div> Functions in this category are for advanced users only. Don't click anything if you're not sure about the consequences.
<table id="debug_table" class="responsiveTable"> </div>
{{#each functions}} <table id="debug_table" class="responsiveTable">
{{#with this}} {{#each functions}}
<tr> {{#with this}}
<td> <tr>
<div class="justifyLeft"> <td>
<b>{{this.name}}</b> <div class="justifyLeft">
</div> <b>{{this.name}}</b>
<div class="justifyLeft">
{{this.description}}
</div>
<div class="flex-container justifyCenter">
<div class="menu_button menu_button_icon" data-debug-function="{{this.functionId}}" data-i18n="Execute">
Execute
</div> </div>
</div> <div class="justifyLeft">
</td> {{this.description}}
</tr> </div>
{{/with}} <div class="flex-container justifyCenter">
{{/each}} <div class="menu_button menu_button_icon" data-debug-function="{{this.functionId}}" data-i18n="Execute">
</table> Execute
</div>
</div>
</td>
</tr>
{{/with}}
{{/each}}
</table>
</div>

View File

@ -127,3 +127,6 @@ API Used: {{this_main_api}}<br>
</div> </div>
</div> </div>
<hr> <hr>
<div id="rawPromptPopup" class="list-group">
<div id="rawPromptWrapper" class="tokenItemizingSubclass"></div>
</div>

View File

@ -107,3 +107,6 @@ API Used: {{this_main_api}}<br>
</div> </div>
</div> </div>
<hr> <hr>
<div id="rawPromptPopup" class="list-group">
<div id="rawPromptWrapper" class="tokenItemizingSubclass"></div>
</div>

View File

@ -0,0 +1,3 @@
<div>
Are you sure you want to delete the theme "{{themeName}}"?
</div>

View File

@ -0,0 +1,3 @@
<div>
This theme contains @import lines in the Custom CSS. Press "Yes" to proceed.
</div>

View File

@ -1,8 +1,9 @@
import { getContext } from './extensions.js'; import { getContext } from './extensions.js';
import { callPopup, getRequestHeaders } from '../script.js'; import { getRequestHeaders } from '../script.js';
import { isMobile } from './RossAscends-mods.js'; import { isMobile } from './RossAscends-mods.js';
import { collapseNewlines } from './power-user.js'; import { collapseNewlines } from './power-user.js';
import { debounce_timeout } from './constants.js'; import { debounce_timeout } from './constants.js';
import { Popup } from './popup.js';
/** /**
* Pagination status string template. * Pagination status string template.
@ -1821,7 +1822,7 @@ export async function checkOverwriteExistingData(type, existingNames, name, { in
return true; return true;
} }
const overwrite = interactive ? await callPopup(`<h3>${type} ${actionName}</h3><p>A ${type.toLowerCase()} with the same name already exists:<br />${existing}</p>Do you want to overwrite it?`, 'confirm') : false; const overwrite = interactive && await Popup.show.confirm(`${type} ${actionName}`, `<p>A ${type.toLowerCase()} with the same name already exists:<br />${existing}</p>Do you want to overwrite it?`);
if (!overwrite) { if (!overwrite) {
toastr.warning(`${type} ${actionName.toLowerCase()} cancelled. A ${type.toLowerCase()} with the same name already exists:<br />${existing}`, `${type} ${actionName}`, { escapeHtml: false }); toastr.warning(`${type} ${actionName.toLowerCase()} cancelled. A ${type.toLowerCase()} with the same name already exists:<br />${existing}`, `${type} ${actionName}`, { escapeHtml: false });
return false; return false;

View File

@ -16,6 +16,7 @@ import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandE
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
import { SlashCommandExecutor } from './slash-commands/SlashCommandExecutor.js'; import { SlashCommandExecutor } from './slash-commands/SlashCommandExecutor.js';
import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
import { Popup } from './popup.js';
export { export {
world_info, world_info,
@ -1684,8 +1685,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl
// Regardless of whether success is displayed or not. Make sure the delete button is available. // Regardless of whether success is displayed or not. Make sure the delete button is available.
// Do not put this code behind. // Do not put this code behind.
$('#world_popup_delete').off('click').on('click', async () => { $('#world_popup_delete').off('click').on('click', async () => {
const confirmation = await callPopup(`<h3>Delete the World/Lorebook: "${name}"?</h3>This action is irreversible!`, 'confirm'); const confirmation = await Popup.show.confirm(`Delete the World/Lorebook: "${name}"?`, `This action is irreversible!`);
if (!confirmation) { if (!confirmation) {
return; return;
} }
@ -1862,7 +1862,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl
$('#world_duplicate').off('click').on('click', async () => { $('#world_duplicate').off('click').on('click', async () => {
const tempName = getFreeWorldName(); const tempName = getFreeWorldName();
const finalName = await callPopup('<h3>Create a new World Info?</h3>Enter a name for the new file:', 'input', tempName); const finalName = await Popup.show.input('Create a new World Info?', 'Enter a name for the new file:', tempName);
if (finalName) { if (finalName) {
await saveWorldInfo(finalName, data, true); await saveWorldInfo(finalName, data, true);
@ -3190,7 +3190,7 @@ async function saveWorldInfo(name, data, immediately) {
async function renameWorldInfo(name, data) { async function renameWorldInfo(name, data) {
const oldName = name; const oldName = name;
const newName = await callPopup('<h3>Rename World Info</h3>Enter a new name:', 'input', oldName); const newName = await Popup.show.input('Rename World Info', 'Enter a new name:', oldName);
if (oldName === newName || !newName) { if (oldName === newName || !newName) {
console.debug('World info rename cancelled'); console.debug('World info rename cancelled');
@ -4138,11 +4138,9 @@ export async function importEmbeddedWorldInfo(skipPopup = false) {
} }
const bookName = characters[chid]?.data?.character_book?.name || `${characters[chid]?.name}'s Lorebook`; const bookName = characters[chid]?.data?.character_book?.name || `${characters[chid]?.name}'s Lorebook`;
const confirmationText = (`<h3>Are you sure you want to import "${bookName}"?</h3>`) + (world_names.includes(bookName) ? 'It will overwrite the World/Lorebook with the same name.' : '');
if (!skipPopup) { if (!skipPopup) {
const confirmation = await callPopup(confirmationText, 'confirm'); const confirmation = await Popup.show.confirm(`Are you sure you want to import "${bookName}"?`, world_names.includes(bookName) ? 'It will overwrite the World/Lorebook with the same name.' : '');
if (!confirmation) { if (!confirmation) {
return; return;
} }
@ -4382,7 +4380,7 @@ jQuery(() => {
$('#world_create_button').on('click', async () => { $('#world_create_button').on('click', async () => {
const tempName = getFreeWorldName(); const tempName = getFreeWorldName();
const finalName = await callPopup('<h3>Create a new World Info?</h3>Enter a name for the new file:', 'input', tempName); const finalName = await Popup.show.input('Create a new World Info', 'Enter a name for the new file:', tempName);
if (finalName) { if (finalName) {
await createNewWorldInfo(finalName, { interactive: true }); await createNewWorldInfo(finalName, { interactive: true });

View File

@ -82,7 +82,7 @@
/*base variable calculated in rems*/ /*base variable calculated in rems*/
--fontScale: 1; --fontScale: 1;
--mainFontSize: calc(var(--fontScale) * 15px); --mainFontSize: calc(var(--fontScale) * 15px);
--mainFontFamily: "Noto Sans", "Noto Color Emoji", sans-serif; --mainFontFamily: "Noto Sans", sans-serif;
--monoFontFamily: 'Noto Sans Mono', 'Courier New', Consolas, monospace; --monoFontFamily: 'Noto Sans Mono', 'Courier New', Consolas, monospace;
/* base variable for blur strength slider calculations */ /* base variable for blur strength slider calculations */
@ -256,10 +256,6 @@ input[type='checkbox']:focus-visible {
color: var(--SmartThemeEmColor); color: var(--SmartThemeEmColor);
} }
#rawPromptWrapper {
white-space: pre-wrap;
}
.tokenGraph { .tokenGraph {
border-radius: 10px; border-radius: 10px;
border: 1px solid var(--SmartThemeBorderColor); border: 1px solid var(--SmartThemeBorderColor);
@ -462,7 +458,7 @@ code {
kbd { kbd {
display: inline-block; display: inline-block;
padding: 2px 4px; padding: 2px 4px;
font-family: Consolas, monospace; font-family: var(--monoFontFamily);
white-space: nowrap; white-space: nowrap;
/* background-color: #eeeeee; */ /* background-color: #eeeeee; */
background-color: rgba(255, 255, 255, 0.9); background-color: rgba(255, 255, 255, 0.9);
@ -4367,8 +4363,7 @@ a {
text-decoration: none; text-decoration: none;
} }
#export_format_popup, #export_format_popup {
#rawPromptPopup {
display: none; display: none;
z-index: 9999; z-index: 9999;
} }
@ -4376,7 +4371,7 @@ a {
#rawPromptPopup { #rawPromptPopup {
inset: 0px auto auto 0px; inset: 0px auto auto 0px;
margin: 0px; margin: 0px;
transform: translate(909px, 47px); transform: translate(500px, 0px);
display: block; display: block;
overflow-wrap: break-word; overflow-wrap: break-word;
white-space: normal; white-space: normal;
@ -4395,7 +4390,8 @@ a {
display: none; display: none;
} }
#rawPopupWrapper { #rawPromptWrapper {
white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
width: 100%; width: 100%;
text-align: start; text-align: start;