Merge pull request #4117 from SillyTavern/goodbye-isSaveWorldInfoDisabled Add skip save checks to all on-init event handlers

fd80474d4772f859cf080028a921eeb3fc29c821

RossAscends <124905043+RossAscends@users.noreply.github.com>

Signed
1 files changed, +61 -71Ignore whitespace
public/scripts/world-info.js+61 -71
@@ -86,7 +86,6 @@ const saveSettingsDebounced = debounce(() => {
8686}, debounce_timeout.relaxed);
8787const sortFn = (a, b) => b.order - a.order;
8888let updateEditor = (navigation, flashOnNav = true) => { console.debug('Triggered WI navigation', navigation, flashOnNav); };
89-let isSaveWorldInfoDisabled = false;
9089
9190// Do not optimize. updateEditor is a function that is updated by the displayWorldEntries with new data.
9291export const worldInfoFilter = new FilterHelper(() => updateEditor());
@@ -2102,8 +2101,6 @@ async function displayWorldEntries(name, data, navigation = navigation_option.no
21022101 showNavigator: true,
21032102 callback: async function (/** @type {object[]} */ page) {
21042103 try {
2105- // Prevent saveWorldInfo from firing timeouts while rendering the list
2106- isSaveWorldInfoDisabled = true;
21072104 clearEntryList(worldEntriesList);
21082105
21092106 const keywordHeaders = await renderTemplateAsync('worldInfoKeywordHeaders');
@@ -2131,8 +2128,6 @@ async function displayWorldEntries(name, data, navigation = navigation_option.no
21312128 worldEntriesList.append(blocks);
21322129 } catch (error) {
21332130 console.error('Error while rendering WI entries:', error);
2134- } finally {
2135- isSaveWorldInfoDisabled = false;
21362131 }
21372132 },
21382133 afterSizeSelectorChange: function (e) {
@@ -2635,14 +2630,14 @@ function handleMatchCheckboxHelper({ template, entry, fieldName, data, name }) {
26352630 const key = originalWIDataKeyMap[fieldName];
26362631 const checkBoxElem = template.find(`input[type="checkbox"][name="${fieldName}"]`);
26372632 checkBoxElem.data('uid', entry.uid);
26382633 checkBoxElem.on('input', async function (_, { noSave = false } = {}) {
26392634 const uid = $(this).data('uid');
26402635 const value = $(this).prop('checked');
26412636 data.entries[uid][fieldName] = value;
26422637 setWIOriginalDataValue(data, uid, key, data.entries[uid][fieldName]);
26432638 !noSave && await saveWorldInfo(name, data);
26442639 });
26452640 checkBoxElem.prop('checked', !!entry[fieldName]).trigger('input', { noSave: true });
26462641}
26472642
26482643/**
@@ -2736,7 +2731,7 @@ function handleCharacterFilterChangeHelper({ characterFilter, data, entry, name,
27362731 */
27372732function handleProbabilityInputHelper({ probabilityInput, data, entry, name, setWIOriginalDataValue, saveWorldInfo }) {
27382733 probabilityInput.data('uid', entry.uid);
27392734 probabilityInput.on('input', async function (_, { noSave = false } = {}) {
27402735 const uid = $(this).data('uid');
27412736 const value = Number($(this).val());
27422737 data.entries[uid].probability = !isNaN(value) ? value : null;
@@ -2747,9 +2742,9 @@ function handleProbabilityInputHelper({ probabilityInput, data, entry, name, set
27472742 }
27482743 }
27492744 setWIOriginalDataValue(data, uid, 'extensions.probability', data.entries[uid].probability);
27502745 !noSave && await saveWorldInfo(name, data);
27512746 });
27522747 probabilityInput.val(entry.probability).trigger('input', { noSave: true });
27532748 probabilityInput.css('width', 'calc(3em + 15px)');
27542749}
27552750
@@ -2758,12 +2753,12 @@ function handleProbabilityInputHelper({ probabilityInput, data, entry, name, set
27582753 */
27592754function handleProbabilityToggleHelper({ probabilityToggle, data, entry, name, probabilityInput, setWIOriginalDataValue, saveWorldInfo }) {
27602755 probabilityToggle.data('uid', entry.uid);
27612756 probabilityToggle.on('input', async function (_, { noSave = false } = {}) {
27622757 const uid = $(this).data('uid');
27632758 const value = $(this).prop('checked');
27642759 data.entries[uid].useProbability = value;
27652760 const probabilityContainer = $(this).closest('.world_entry').find('.probabilityContainer');
27662761 !noSave && await saveWorldInfo(name, data);
27672762 value ? probabilityContainer.show() : probabilityContainer.hide();
27682763 if (value && data.entries[uid].probability === null) {
27692764 data.entries[uid].probability = 100;
@@ -2771,9 +2766,9 @@ function handleProbabilityToggleHelper({ probabilityToggle, data, entry, name, p
27712766 if (!value) {
27722767 data.entries[uid].probability = null;
27732768 }
27742769 probabilityInput.val(data.entries[uid].probability).trigger('input', { noSave });
27752770 });
27762771 probabilityToggle.prop('checked', true).trigger('input', { noSave: true });
27772772 probabilityToggle.parent().hide();
27782773}
27792774
@@ -2782,14 +2777,14 @@ function handleProbabilityToggleHelper({ probabilityToggle, data, entry, name, p
27822777 */
27832778function handleBooleanSelectHelper({ selectElem, entry, entryKey, data, name, setWIOriginalDataValue, saveWorldInfo }) {
27842779 selectElem.data('uid', entry.uid);
27852780 selectElem.on('input', async function (_, { noSave = false } = {}) {
27862781 const uid = $(this).data('uid');
27872782 const value = $(this).val();
27882783 data.entries[uid][entryKey] = value === 'null' ? null : value === 'true';
27892784 setWIOriginalDataValue(data, uid, `extensions.${entryKey.replace(/[A-Z]/g, m => `_${m.toLowerCase()}`)}`, data.entries[uid][entryKey]);
27902785 !noSave && await saveWorldInfo(name, data);
27912786 });
27922787 selectElem.val((entry[entryKey] === null || entry[entryKey] === undefined) ? 'null' : entry[entryKey] ? 'true' : 'false').trigger('input', { noSave: true });
27932788}
27942789
27952790/**
@@ -2797,7 +2792,7 @@ function handleBooleanSelectHelper({ selectElem, entry, entryKey, data, name, se
27972792 */
27982793function handleNumberInputHelper({ inputElem, entry, entryKey, data, name, setWIOriginalDataValue, saveWorldInfo, min, max, clamp = false }) {
27992794 inputElem.data('uid', entry.uid);
28002795 inputElem.on('input', async function (_, { noSave = false } = {}) {
28012796 const uid = $(this).data('uid');
28022797 let value = Number($(this).val());
28032798 if (clamp) {
@@ -2811,9 +2806,9 @@ function handleNumberInputHelper({ inputElem, entry, entryKey, data, name, setWI
28112806 }
28122807 data.entries[uid][entryKey] = !isNaN(value) ? value : null;
28132808 setWIOriginalDataValue(data, uid, `extensions.${entryKey.replace(/[A-Z]/g, m => `_${m.toLowerCase()}`)}`, data.entries[uid][entryKey]);
28142809 !noSave && await saveWorldInfo(name, data);
28152810 });
28162811 inputElem.val(entry[entryKey] ?? (clamp ? min : '')).trigger('input', { noSave: true });
28172812}
28182813
28192814/**
@@ -2824,7 +2819,7 @@ function handleEntryStateSelectorHelper({ entryStateSelector, entry, data, name,
28242819 entryStateSelector.on('click', function (event) {
28252820 event.stopPropagation();
28262821 });
28272822 entryStateSelector.on('input', async function (_, { noSave = false } = {}) {
28282823 const uid = entry.uid;
28292824 const value = $(this).val();
28302825 switch (value) {
@@ -2847,10 +2842,10 @@ function handleEntryStateSelectorHelper({ entryStateSelector, entry, data, name,
28472842 setWIOriginalDataValue(data, uid, 'extensions.vectorized', true);
28482843 break;
28492844 }
28502845 !noSave && await saveWorldInfo(name, data);
28512846 });
28522847 const entryState = () => entry.constant === true ? 'constant' : entry.vectorized === true ? 'vectorized' : 'normal';
28532848 entryStateSelector.find(`option[value=${entryState()}]`).prop('selected', true).trigger('input', { noSave: true });
28542849}
28552850
28562851/**
@@ -2892,28 +2887,28 @@ export async function getWorldEntry(name, data, entry) {
28922887 // Comment
28932888 const commentInput = headerTemplate.find('textarea[name="comment"]');
28942889 commentInput.data('uid', entry.uid);
28952890 commentInput.on('input', async function (_, { skipReset = false, noSave = false } = {}) {
28962891 const uid = $(this).data('uid');
28972892 const value = $(this).val();
28982893 !skipReset && await resetScrollHeight(this);
28992894 data.entries[uid].comment = value;
29002895 setWIOriginalDataValue(data, uid, 'comment', data.entries[uid].comment);
29012896 !noSave && await saveWorldInfo(name, data);
29022897 });
29032898 commentInput.val(entry.comment).trigger('input', { skipReset: true, noSave: true });
29042899
29052900 // Order
29062901 const orderInput = headerTemplate.find('input[name="order"]');
29072902 orderInput.data('uid', entry.uid);
29082903 orderInput.on('input', async function (_, { noSave = false } = {}) {
29092904 const uid = $(this).data('uid');
29102905 const value = Number($(this).val());
29112906 data.entries[uid].order = !isNaN(value) ? value : 0;
29122907 updatePosOrdDisplayHelper({ template: headerTemplate, data, uid });
29132908 setWIOriginalDataValue(data, uid, 'insertion_order', data.entries[uid].order);
29142909 !noSave && await saveWorldInfo(name, data);
29152910 });
29162911 orderInput.val(entry.order).trigger('input', { noSave: true });
29172912 orderInput.css('width', 'calc(3em + 15px)');
29182913
29192914 // Probability
@@ -2932,7 +2927,7 @@ export async function getWorldEntry(name, data, entry) {
29322927 const positionInput = headerTemplate.find('select[name="position"]');
29332928 positionInput.data('uid', entry.uid);
29342929 positionInput.on('click', e => e.stopPropagation());
29352930 positionInput.on('input', async function (_, { noSave = false } = {}) {
29362931 const uid = $(this).data('uid');
29372932 const value = Number($(this).val());
29382933 data.entries[uid].position = !isNaN(value) ? value : 0;
@@ -2951,10 +2946,10 @@ export async function getWorldEntry(name, data, entry) {
29512946 setWIOriginalDataValue(data, uid, 'position', data.entries[uid].position == 0 ? 'before_char' : 'after_char');
29522947 setWIOriginalDataValue(data, uid, 'extensions.position', data.entries[uid].position);
29532948 setWIOriginalDataValue(data, uid, 'extensions.role', data.entries[uid].role);
29542949 !noSave && await saveWorldInfo(name, data);
29552950 });
29562951 const roleValue = entry.position === world_info_position.atDepth ? String(entry.role ?? extension_prompt_roles.SYSTEM) : '';
29572952 headerTemplate.find(`select[name="position"] option[value="${entry.position}"][data-role="${roleValue}"]`).prop('selected', true).trigger('input', { noSave: true });
29582953
29592954 // Tri-state selector
29602955 handleEntryStateSelectorHelper({
@@ -3098,39 +3093,39 @@ export async function getWorldEntry(name, data, entry) {
30983093 // Comment toggle
30993094 const commentToggle = editTemplate.find('input[name="addMemo"]');
31003095 commentToggle.data('uid', entry.uid);
31013096 commentToggle.on('input', async function (_, { noSave = false } = {}) {
31023097 const uid = $(this).data('uid');
31033098 const value = $(this).prop('checked');
31043099 const commentContainer = $(this).closest('.world_entry').find('.commentContainer');
31053100 data.entries[uid].addMemo = value;
31063101 !noSave && await saveWorldInfo(name, data);
31073102 value ? commentContainer.show() : commentContainer.hide();
31083103 });
31093104 commentToggle.prop('checked', true).trigger('input', { noSave: true });
31103105 commentToggle.parent().hide();
31113106
31123107 // Logic AND/NOT
31133108 const selectiveLogicDropdown = editTemplate.find('select[name="entryLogicType"]');
31143109 selectiveLogicDropdown.data('uid', entry.uid);
31153110 selectiveLogicDropdown.on('click', e => e.stopPropagation());
31163111 selectiveLogicDropdown.on('input', async function (_, { noSave = false } = {}) {
31173112 const uid = $(this).data('uid');
31183113 const value = Number($(this).val());
31193114 data.entries[uid].selectiveLogic = !isNaN(value) ? value : world_info_logic.AND_ANY;
31203115 setWIOriginalDataValue(data, uid, 'selectiveLogic', data.entries[uid].selectiveLogic);
31213116 !noSave && await saveWorldInfo(name, data);
31223117 });
31233118 editTemplate.find(`select[name="entryLogicType"] option[value=${entry.selectiveLogic}]`).prop('selected', true).trigger('input', { noSave: true });
31243119
31253120 // Selective
31263121 const selectiveInput = editTemplate.find('input[name="selective"]');
31273122 selectiveInput.data('uid', entry.uid);
31283123 selectiveInput.on('input', async function (_, { noSave = false } = {}) {
31293124 const uid = $(this).data('uid');
31303125 const value = $(this).prop('checked');
31313126 data.entries[uid].selective = value;
31323127 setWIOriginalDataValue(data, uid, 'selective', data.entries[uid].selective);
31333128 !noSave && await saveWorldInfo(name, data);
31343129 const keysecondary = $(this).closest('.world_entry').find('.keysecondary');
31353130 const keysecondarytextpole = $(this).closest('.world_entry').find('.keysecondarytextpole');
31363131 const keyprimaryselect = $(this).closest('.world_entry').find('.keyprimaryselect');
@@ -3138,7 +3133,7 @@ export async function getWorldEntry(name, data, entry) {
31383133 keysecondarytextpole.css('height', keyprimaryHeight + 'px');
31393134 value ? keysecondary.show() : keysecondary.hide();
31403135 });
31413136 selectiveInput.prop('checked', true).trigger('input', { noSave: true });
31423137 selectiveInput.parent().hide();
31433138
31443139 // Character filter
@@ -3146,7 +3141,7 @@ export async function getWorldEntry(name, data, entry) {
31463141 characterFilterLabel.text(entry.characterFilter?.isExclude ? 'Exclude Character(s)' : 'Filter to Character(s)');
31473142 const characterExclusionInput = editTemplate.find('input[name="character_exclusion"]');
31483143 characterExclusionInput.data('uid', entry.uid);
31493144 characterExclusionInput.on('input', async function (_, { noSave = false } = {}) {
31503145 const uid = $(this).data('uid');
31513146 const value = $(this).prop('checked');
31523147 characterFilterLabel.text(value ? 'Exclude Character(s)' : 'Filter to Character(s)');
@@ -3167,9 +3162,9 @@ export async function getWorldEntry(name, data, entry) {
31673162 }
31683163 }
31693164 setWIOriginalDataValue(data, uid, 'character_filter', data.entries[uid].characterFilter);
31703165 !noSave && await saveWorldInfo(name, data);
31713166 });
31723167 characterExclusionInput.prop('checked', entry.characterFilter?.isExclude ?? false).trigger('input', { noSave: true });
31733168
31743169 const characterFilter = editTemplate.find('select[name="characterFilter"]');
31753170 characterFilter.data('uid', entry.uid);
@@ -3189,21 +3184,21 @@ export async function getWorldEntry(name, data, entry) {
31893184 const contentInput = editTemplate.find('textarea[name="content"]');
31903185 contentInput.data('uid', entry.uid);
31913186 contentInput.attr('id', contentInputId);
31923187 contentInput.on('input', async function (_, { skipCount, noSave } = {}) {
31933188 const uid = $(this).data('uid');
31943189 const value = $(this).val();
31953190 data.entries[uid].content = value;
31963191 setWIOriginalDataValue(data, uid, 'content', data.entries[uid].content);
31973192 !noSave && await saveWorldInfo(name, data);
31983193 if (!skipCount) countTokensDebounced(counter, value);
31993194 });
32003195 contentInput.val(entry.content).trigger('input', { skipCount: true, noSave: true });
32013196 editTemplate.find('.editor_maximize').attr('data-for', contentInputId);
32023197
32033198 // Scan depth
32043199 const scanDepthInput = editTemplate.find('input[name="scanDepth"]');
32053200 scanDepthInput.data('uid', entry.uid);
32063201 scanDepthInput.on('input', async function (_, { noSave = false } = {}) {
32073202 const uid = $(this).data('uid');
32083203 const isEmpty = $(this).val() === '';
32093204 const value = Number($(this).val());
@@ -3219,34 +3214,34 @@ export async function getWorldEntry(name, data, entry) {
32193214 }
32203215 data.entries[uid].scanDepth = !isEmpty && !isNaN(value) && value >= 0 && value <= MAX_SCAN_DEPTH ? Math.floor(value) : null;
32213216 setWIOriginalDataValue(data, uid, 'extensions.scan_depth', data.entries[uid].scanDepth);
32223217 !noSave && await saveWorldInfo(name, data);
32233218 });
32243219 scanDepthInput.val(entry.scanDepth ?? null).trigger('input', { noSave: true });
32253220
32263221 // Group
32273222 const groupInput = editTemplate.find('input[name="group"]');
32283223 groupInput.data('uid', entry.uid);
32293224 groupInput.on('input', async function (_, { noSave = false } = {}) {
32303225 const uid = $(this).data('uid');
32313226 const value = String($(this).val()).trim();
32323227 data.entries[uid].group = value;
32333228 setWIOriginalDataValue(data, uid, 'extensions.group', data.entries[uid].group);
32343229 !noSave && await saveWorldInfo(name, data);
32353230 });
32363231 groupInput.val(entry.group ?? '').trigger('input', { noSave: true });
32373232 setTimeout(() => createEntryInputAutocomplete(groupInput, getInclusionGroupCallback(data), { allowMultiple: true }), 1);
32383233
32393234 // Inclusion priority
32403235 const groupOverrideInput = editTemplate.find('input[name="groupOverride"]');
32413236 groupOverrideInput.data('uid', entry.uid);
32423237 groupOverrideInput.on('input', async function (_, { noSave = false } = {}) {
32433238 const uid = $(this).data('uid');
32443239 const value = $(this).prop('checked');
32453240 data.entries[uid].groupOverride = value;
32463241 setWIOriginalDataValue(data, uid, 'extensions.group_override', data.entries[uid].groupOverride);
32473242 !noSave && await saveWorldInfo(name, data);
32483243 });
32493244 groupOverrideInput.prop('checked', entry.groupOverride).trigger('input', { noSave: true });
32503245
32513246 // Group weight
32523247 handleNumberInputHelper({
@@ -3281,17 +3276,17 @@ export async function getWorldEntry(name, data, entry) {
32813276 delayUntilRecursionInput.data('uid', entry.uid);
32823277 const delayUntilRecursionLevelInput = editTemplate.find('input[name="delayUntilRecursionLevel"]');
32833278 delayUntilRecursionLevelInput.data('uid', entry.uid);
32843279 delayUntilRecursionInput.on('input', async function (_, { noSave = false } = {}) {
32853280 const uid = $(this).data('uid');
32863281 const toggled = $(this).prop('checked');
32873282 const value = toggled ? data.entries[uid].delayUntilRecursion || true : false;
32883283 if (!toggled) delayUntilRecursionLevelInput.val('');
32893284 data.entries[uid].delayUntilRecursion = value;
32903285 setWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion);
32913286 !noSave && await saveWorldInfo(name, data);
32923287 });
32933288 delayUntilRecursionInput.prop('checked', entry.delayUntilRecursion).trigger('input', { noSave: true });
32943289 delayUntilRecursionLevelInput.on('input', async function (_, { noSave = false } = {}) {
32953290 const uid = $(this).data('uid');
32963291 const content = $(this).val();
32973292 const value = content === '' ? (typeof data.entries[uid].delayUntilRecursion === 'boolean' ? data.entries[uid].delayUntilRecursion : true)
@@ -3300,9 +3295,9 @@ export async function getWorldEntry(name, data, entry) {
33003295 : false;
33013296 data.entries[uid].delayUntilRecursion = value;
33023297 setWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion);
33033298 !noSave && await saveWorldInfo(name, data);
33043299 });
33053300 delayUntilRecursionLevelInput.val(['number', 'string'].includes(typeof entry.delayUntilRecursion) ? entry.delayUntilRecursion : '').trigger('input', { noSave: true });
33063301
33073302 // Boolean selects
33083303 handleBooleanSelectHelper({
@@ -3329,14 +3324,14 @@ export async function getWorldEntry(name, data, entry) {
33293324 // Automation ID
33303325 const automationIdInput = editTemplate.find('input[name="automationId"]');
33313326 automationIdInput.data('uid', entry.uid);
33323327 automationIdInput.on('input', async function (_, { noSave = false } = {}) {
33333328 const uid = $(this).data('uid');
33343329 const value = $(this).val();
33353330 data.entries[uid].automationId = value;
33363331 setWIOriginalDataValue(data, uid, 'extensions.automation_id', data.entries[uid].automationId);
33373332 !noSave && await saveWorldInfo(name, data);
33383333 });
33393334 automationIdInput.val(entry.automationId ?? '').trigger('input', { noSave: true });
33403335 setTimeout(() => createEntryInputAutocomplete(automationIdInput, getAutomationIdCallback(data)), 1);
33413336
33423337 countTokensDebounced(counter, contentInput.val());
@@ -3588,11 +3583,6 @@ async function _save(name, data) {
35883583 * @return {Promise<void>} A promise that resolves when the world info is saved
35893584 */
35903585export async function saveWorldInfo(name, data, immediately = false) {
3591- // Saving is temporarily disabled
3592- if (isSaveWorldInfoDisabled) {
3593- return;
3594- }
3595-
35963586 if (!name || !data) {
35973587 return;
35983588 }