Add settings.json-backed KV string storage Fixes #3461, #3443
| @@ -270,6 +270,7 @@ import { initBulkEdit } from './scripts/bulk-edit.js'; | |||
| 270 | import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; | 270 | import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; |
| 271 | import { getContext } from './scripts/st-context.js'; | 271 | import { getContext } from './scripts/st-context.js'; |
| 272 | import { extractReasoningFromData, initReasoning, PromptReasoning, updateReasoningTimeUI } from './scripts/reasoning.js'; | 272 | import { extractReasoningFromData, initReasoning, PromptReasoning, updateReasoningTimeUI } from './scripts/reasoning.js'; |
| 273 | import { accountStorage } from './scripts/util/AccountStorage.js'; | ||
| 273 | 274 | ||
| 274 | // API OBJECT FOR EXTERNAL WIRING | 275 | // API OBJECT FOR EXTERNAL WIRING |
| 275 | globalThis.SillyTavern = { | 276 | globalThis.SillyTavern = { |
| @@ -419,7 +420,7 @@ DOMPurify.addHook('uponSanitizeElement', (node, _, config) => { | |||
| 419 | const entityId = getCurrentEntityId(); | 420 | const entityId = getCurrentEntityId(); |
| 420 | const warningShownKey = `mediaWarningShown:${entityId}`; | 421 | const warningShownKey = `mediaWarningShown:${entityId}`; |
| 421 | 422 | ||
| 422 | if (localStorage.getItem(warningShownKey) === null) { | 423 | if (accountStorage.getItem(warningShownKey) === null) { |
| 423 | const warningToast = toastr.warning( | 424 | const warningToast = toastr.warning( |
| 424 | t`Use the 'Ext. Media' button to allow it. Click on this message to dismiss.`, | 425 | t`Use the 'Ext. Media' button to allow it. Click on this message to dismiss.`, |
| 425 | t`External media has been blocked`, | 426 | t`External media has been blocked`, |
| @@ -430,7 +431,7 @@ DOMPurify.addHook('uponSanitizeElement', (node, _, config) => { | |||
| 430 | }, | 431 | }, |
| 431 | ); | 432 | ); |
| 432 | 433 | ||
| 433 | localStorage.setItem(warningShownKey, 'true'); | 434 | accountStorage.setItem(warningShownKey, 'true'); |
| 434 | } | 435 | } |
| 435 | } | 436 | } |
| 436 | }); | 437 | }); |
| @@ -1490,7 +1491,7 @@ export async function printCharacters(fullRefresh = false) { | |||
| 1490 | 1491 | ||
| 1491 | $('#rm_print_characters_pagination').pagination({ | 1492 | $('#rm_print_characters_pagination').pagination({ |
| 1492 | dataSource: entities, | 1493 | dataSource: entities, |
| 1493 | pageSize: Number(localStorage.getItem(storageKey)) || per_page_default, | 1494 | pageSize: Number(accountStorage.getItem(storageKey)) || per_page_default, |
| 1494 | sizeChangerOptions: [10, 25, 50, 100, 250, 500, 1000], | 1495 | sizeChangerOptions: [10, 25, 50, 100, 250, 500, 1000], |
| 1495 | pageRange: 1, | 1496 | pageRange: 1, |
| 1496 | pageNumber: saveCharactersPage || 1, | 1497 | pageNumber: saveCharactersPage || 1, |
| @@ -1534,7 +1535,7 @@ export async function printCharacters(fullRefresh = false) { | |||
| 1534 | eventSource.emit(event_types.CHARACTER_PAGE_LOADED); | 1535 | eventSource.emit(event_types.CHARACTER_PAGE_LOADED); |
| 1535 | }, | 1536 | }, |
| 1536 | afterSizeSelectorChange: function (e) { | 1537 | afterSizeSelectorChange: function (e) { |
| 1537 | localStorage.setItem(storageKey, e.target.value); | 1538 | accountStorage.setItem(storageKey, e.target.value); |
| 1538 | }, | 1539 | }, |
| 1539 | afterPaging: function (e) { | 1540 | afterPaging: function (e) { |
| 1540 | saveCharactersPage = e; | 1541 | saveCharactersPage = e; |
| @@ -6902,10 +6903,11 @@ export async function getSettings() { | |||
| 6902 | $('#your_name').val(name1); | 6903 | $('#your_name').val(name1); |
| 6903 | } | 6904 | } |
| 6904 | 6905 | ||
| 6906 | accountStorage.init(settings?.accountStorage); | ||
| 6905 | await setUserControls(data.enable_accounts); | 6907 | await setUserControls(data.enable_accounts); |
| 6906 | 6908 | ||
| 6907 | // Allow subscribers to mutate settings | 6909 | // Allow subscribers to mutate settings |
| 6908 | eventSource.emit(event_types.SETTINGS_LOADED_BEFORE, settings); | 6910 | await eventSource.emit(event_types.SETTINGS_LOADED_BEFORE, settings); |
| 6909 | 6911 | ||
| 6910 | //Load KoboldAI settings | 6912 | //Load KoboldAI settings |
| 6911 | koboldai_setting_names = data.koboldai_setting_names; | 6913 | koboldai_setting_names = data.koboldai_setting_names; |
| @@ -7094,6 +7096,7 @@ export async function saveSettings(loopCounter = 0) { | |||
| 7094 | url: '/api/settings/save', | 7096 | url: '/api/settings/save', |
| 7095 | data: JSON.stringify({ | 7097 | data: JSON.stringify({ |
| 7096 | firstRun: firstRun, | 7098 | firstRun: firstRun, |
| 7099 | accountStorage: accountStorage.state, | ||
| 7097 | currentVersion: currentVersion, | 7100 | currentVersion: currentVersion, |
| 7098 | username: name1, | 7101 | username: name1, |
| 7099 | active_character: active_character, | 7102 | active_character: active_character, |
| @@ -7549,7 +7552,7 @@ export function select_rm_info(type, charId, previousCharId = null) { | |||
| 7549 | } | 7552 | } |
| 7550 | 7553 | ||
| 7551 | try { | 7554 | try { |
| 7552 | const perPage = Number(localStorage.getItem('Characters_PerPage')) || per_page_default; | 7555 | const perPage = Number(accountStorage.getItem('Characters_PerPage')) || per_page_default; |
| 7553 | const page = Math.floor(charIndex / perPage) + 1; | 7556 | const page = Math.floor(charIndex / perPage) + 1; |
| 7554 | const selector = `#rm_print_characters_block [title*="${avatarFileName}"]`; | 7557 | const selector = `#rm_print_characters_block [title*="${avatarFileName}"]`; |
| 7555 | $('#rm_print_characters_pagination').pagination('go', page); | 7558 | $('#rm_print_characters_pagination').pagination('go', page); |
| @@ -7581,7 +7584,7 @@ export function select_rm_info(type, charId, previousCharId = null) { | |||
| 7581 | return; | 7584 | return; |
| 7582 | } | 7585 | } |
| 7583 | 7586 | ||
| 7584 | const perPage = Number(localStorage.getItem('Characters_PerPage')) || per_page_default; | 7587 | const perPage = Number(accountStorage.getItem('Characters_PerPage')) || per_page_default; |
| 7585 | const page = Math.floor(charIndex / perPage) + 1; | 7588 | const page = Math.floor(charIndex / perPage) + 1; |
| 7586 | $('#rm_print_characters_pagination').pagination('go', page); | 7589 | $('#rm_print_characters_pagination').pagination('go', page); |
| 7587 | const selector = `#rm_print_characters_block [grid="${charId}"]`; | 7590 | const selector = `#rm_print_characters_block [grid="${charId}"]`; |
| @@ -9650,8 +9653,8 @@ function addDebugFunctions() { | |||
| 9650 | }); | 9653 | }); |
| 9651 | 9654 | ||
| 9652 | registerDebugFunction('toggleRegenerateWarning', 'Toggle Ctrl+Enter regeneration confirmation', 'Toggle the warning when regenerating a message with a Ctrl+Enter hotkey.', () => { | 9655 | registerDebugFunction('toggleRegenerateWarning', 'Toggle Ctrl+Enter regeneration confirmation', 'Toggle the warning when regenerating a message with a Ctrl+Enter hotkey.', () => { |
| 9653 | localStorage.setItem('RegenerateWithCtrlEnter', localStorage.getItem('RegenerateWithCtrlEnter') === 'true' ? 'false' : 'true'); | 9656 | accountStorage.setItem('RegenerateWithCtrlEnter', accountStorage.getItem('RegenerateWithCtrlEnter') === 'true' ? 'false' : 'true'); |
| 9654 | toastr.info('Regenerate warning is now ' + (localStorage.getItem('RegenerateWithCtrlEnter') === 'true' ? 'disabled' : 'enabled')); | 9657 | toastr.info('Regenerate warning is now ' + (accountStorage.getItem('RegenerateWithCtrlEnter') === 'true' ? 'disabled' : 'enabled')); |
| 9655 | }); | 9658 | }); |
| 9656 | 9659 | ||
| 9657 | registerDebugFunction('copySetup', 'Copy ST setup to clipboard [WIP]', 'Useful data when reporting bugs', async () => { | 9660 | registerDebugFunction('copySetup', 'Copy ST setup to clipboard [WIP]', 'Useful data when reporting bugs', async () => { |
| @@ -27,7 +27,6 @@ import { | |||
| 27 | send_on_enter_options, | 27 | send_on_enter_options, |
| 28 | } from './power-user.js'; | 28 | } from './power-user.js'; |
| 29 | 29 | ||
| 30 | import { LoadLocal, SaveLocal, LoadLocalBool } from './f-localStorage.js'; | ||
| 31 | import { selected_group, is_group_generating, openGroupById } from './group-chats.js'; | 30 | import { selected_group, is_group_generating, openGroupById } from './group-chats.js'; |
| 32 | import { getTagKeyForEntity, applyTagsOnCharacterSelect } from './tags.js'; | 31 | import { getTagKeyForEntity, applyTagsOnCharacterSelect } from './tags.js'; |
| 33 | import { | 32 | import { |
| @@ -41,6 +40,7 @@ import { textgen_types, textgenerationwebui_settings as textgen_settings, getTex | |||
| 41 | import { debounce_timeout } from './constants.js'; | 40 | import { debounce_timeout } from './constants.js'; |
| 42 | 41 | ||
| 43 | import { Popup } from './popup.js'; | 42 | import { Popup } from './popup.js'; |
| 43 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 44 | 44 | ||
| 45 | var RPanelPin = document.getElementById('rm_button_panel_pin'); | 45 | var RPanelPin = document.getElementById('rm_button_panel_pin'); |
| 46 | var LPanelPin = document.getElementById('lm_button_panel_pin'); | 46 | var LPanelPin = document.getElementById('lm_button_panel_pin'); |
| @@ -409,19 +409,19 @@ function RA_autoconnect(PrevApi) { | |||
| 409 | function OpenNavPanels() { | 409 | function OpenNavPanels() { |
| 410 | if (!isMobile()) { | 410 | if (!isMobile()) { |
| 411 | //auto-open R nav if locked and previously open | 411 | //auto-open R nav if locked and previously open |
| 412 | if (LoadLocalBool('NavLockOn') == true && LoadLocalBool('NavOpened') == true) { | 412 | if (accountStorage.getItem('NavLockOn') == 'true' && accountStorage.getItem('NavOpened') == 'true') { |
| 413 | //console.log("RA -- clicking right nav to open"); | 413 | //console.log("RA -- clicking right nav to open"); |
| 414 | $('#rightNavDrawerIcon').click(); | 414 | $('#rightNavDrawerIcon').click(); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | //auto-open L nav if locked and previously open | 417 | //auto-open L nav if locked and previously open |
| 418 | if (LoadLocalBool('LNavLockOn') == true && LoadLocalBool('LNavOpened') == true) { | 418 | if (accountStorage.getItem('LNavLockOn') == 'true' && accountStorage.getItem('LNavOpened') == 'true') { |
| 419 | console.debug('RA -- clicking left nav to open'); | 419 | console.debug('RA -- clicking left nav to open'); |
| 420 | $('#leftNavDrawerIcon').click(); | 420 | $('#leftNavDrawerIcon').click(); |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | //auto-open WI if locked and previously open | 423 | //auto-open WI if locked and previously open |
| 424 | if (LoadLocalBool('WINavLockOn') == true && LoadLocalBool('WINavOpened') == true) { | 424 | if (accountStorage.getItem('WINavLockOn') == 'true' && accountStorage.getItem('WINavOpened') == 'true') { |
| 425 | console.debug('RA -- clicking WI to open'); | 425 | console.debug('RA -- clicking WI to open'); |
| 426 | $('#WIDrawerIcon').click(); | 426 | $('#WIDrawerIcon').click(); |
| 427 | } | 427 | } |
| @@ -434,7 +434,7 @@ function restoreUserInput() { | |||
| 434 | return; | 434 | return; |
| 435 | } | 435 | } |
| 436 | 436 | ||
| 437 | const userInput = LoadLocal('userInput'); | 437 | const userInput = localStorage.getItem('userInput'); |
| 438 | if (userInput) { | 438 | if (userInput) { |
| 439 | $('#send_textarea').val(userInput)[0].dispatchEvent(new Event('input', { bubbles: true })); | 439 | $('#send_textarea').val(userInput)[0].dispatchEvent(new Event('input', { bubbles: true })); |
| 440 | } | 440 | } |
| @@ -442,7 +442,8 @@ function restoreUserInput() { | |||
| 442 | 442 | ||
| 443 | function saveUserInput() { | 443 | function saveUserInput() { |
| 444 | const userInput = String($('#send_textarea').val()); | 444 | const userInput = String($('#send_textarea').val()); |
| 445 | SaveLocal('userInput', userInput); | 445 | localStorage.setItem('userInput', userInput); |
| 446 | console.debug('User Input -- ', userInput); | ||
| 446 | } | 447 | } |
| 447 | const saveUserInputDebounced = debounce(saveUserInput); | 448 | const saveUserInputDebounced = debounce(saveUserInput); |
| 448 | 449 | ||
| @@ -739,7 +740,7 @@ export function initRossMods() { | |||
| 739 | 740 | ||
| 740 | //toggle pin class when lock toggle clicked | 741 | //toggle pin class when lock toggle clicked |
| 741 | $(RPanelPin).on('click', function () { | 742 | $(RPanelPin).on('click', function () { |
| 742 | SaveLocal('NavLockOn', $(RPanelPin).prop('checked')); | 743 | accountStorage.setItem('NavLockOn', $(RPanelPin).prop('checked')); |
| 743 | if ($(RPanelPin).prop('checked') == true) { | 744 | if ($(RPanelPin).prop('checked') == true) { |
| 744 | //console.log('adding pin class to right nav'); | 745 | //console.log('adding pin class to right nav'); |
| 745 | $(RightNavPanel).addClass('pinnedOpen'); | 746 | $(RightNavPanel).addClass('pinnedOpen'); |
| @@ -757,7 +758,7 @@ export function initRossMods() { | |||
| 757 | } | 758 | } |
| 758 | }); | 759 | }); |
| 759 | $(LPanelPin).on('click', function () { | 760 | $(LPanelPin).on('click', function () { |
| 760 | SaveLocal('LNavLockOn', $(LPanelPin).prop('checked')); | 761 | accountStorage.setItem('LNavLockOn', $(LPanelPin).prop('checked')); |
| 761 | if ($(LPanelPin).prop('checked') == true) { | 762 | if ($(LPanelPin).prop('checked') == true) { |
| 762 | //console.log('adding pin class to Left nav'); | 763 | //console.log('adding pin class to Left nav'); |
| 763 | $(LeftNavPanel).addClass('pinnedOpen'); | 764 | $(LeftNavPanel).addClass('pinnedOpen'); |
| @@ -776,7 +777,7 @@ export function initRossMods() { | |||
| 776 | }); | 777 | }); |
| 777 | 778 | ||
| 778 | $(WIPanelPin).on('click', function () { | 779 | $(WIPanelPin).on('click', function () { |
| 779 | SaveLocal('WINavLockOn', $(WIPanelPin).prop('checked')); | 780 | accountStorage.setItem('WINavLockOn', $(WIPanelPin).prop('checked')); |
| 780 | if ($(WIPanelPin).prop('checked') == true) { | 781 | if ($(WIPanelPin).prop('checked') == true) { |
| 781 | console.debug('adding pin class to WI'); | 782 | console.debug('adding pin class to WI'); |
| 782 | $(WorldInfo).addClass('pinnedOpen'); | 783 | $(WorldInfo).addClass('pinnedOpen'); |
| @@ -796,8 +797,8 @@ export function initRossMods() { | |||
| 796 | }); | 797 | }); |
| 797 | 798 | ||
| 798 | // read the state of right Nav Lock and apply to rightnav classlist | 799 | // read the state of right Nav Lock and apply to rightnav classlist |
| 799 | $(RPanelPin).prop('checked', LoadLocalBool('NavLockOn')); | 800 | $(RPanelPin).prop('checked', accountStorage.getItem('NavLockOn') == 'true'); |
| 800 | if (LoadLocalBool('NavLockOn') == true) { | 801 | if (accountStorage.getItem('NavLockOn') == 'true') { |
| 801 | //console.log('setting pin class via local var'); | 802 | //console.log('setting pin class via local var'); |
| 802 | $(RightNavPanel).addClass('pinnedOpen'); | 803 | $(RightNavPanel).addClass('pinnedOpen'); |
| 803 | $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); | 804 | $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); |
| @@ -808,8 +809,8 @@ export function initRossMods() { | |||
| 808 | $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); | 809 | $(RightNavDrawerIcon).addClass('drawerPinnedOpen'); |
| 809 | } | 810 | } |
| 810 | // read the state of left Nav Lock and apply to leftnav classlist | 811 | // read the state of left Nav Lock and apply to leftnav classlist |
| 811 | $(LPanelPin).prop('checked', LoadLocalBool('LNavLockOn')); | 812 | $(LPanelPin).prop('checked', accountStorage.getItem('LNavLockOn') === 'true'); |
| 812 | if (LoadLocalBool('LNavLockOn') == true) { | 813 | if (accountStorage.getItem('LNavLockOn') == 'true') { |
| 813 | //console.log('setting pin class via local var'); | 814 | //console.log('setting pin class via local var'); |
| 814 | $(LeftNavPanel).addClass('pinnedOpen'); | 815 | $(LeftNavPanel).addClass('pinnedOpen'); |
| 815 | $(LeftNavDrawerIcon).addClass('drawerPinnedOpen'); | 816 | $(LeftNavDrawerIcon).addClass('drawerPinnedOpen'); |
| @@ -821,8 +822,8 @@ export function initRossMods() { | |||
| 821 | } | 822 | } |
| 822 | 823 | ||
| 823 | // read the state of left Nav Lock and apply to leftnav classlist | 824 | // read the state of left Nav Lock and apply to leftnav classlist |
| 824 | $(WIPanelPin).prop('checked', LoadLocalBool('WINavLockOn')); | 825 | $(WIPanelPin).prop('checked', accountStorage.getItem('WINavLockOn') === 'true'); |
| 825 | if (LoadLocalBool('WINavLockOn') == true) { | 826 | if (accountStorage.getItem('WINavLockOn') == 'true') { |
| 826 | //console.log('setting pin class via local var'); | 827 | //console.log('setting pin class via local var'); |
| 827 | $(WorldInfo).addClass('pinnedOpen'); | 828 | $(WorldInfo).addClass('pinnedOpen'); |
| 828 | $(WIDrawerIcon).addClass('drawerPinnedOpen'); | 829 | $(WIDrawerIcon).addClass('drawerPinnedOpen'); |
| @@ -837,22 +838,22 @@ export function initRossMods() { | |||
| 837 | //save state of Right nav being open or closed | 838 | //save state of Right nav being open or closed |
| 838 | $('#rightNavDrawerIcon').on('click', function () { | 839 | $('#rightNavDrawerIcon').on('click', function () { |
| 839 | if (!$('#rightNavDrawerIcon').hasClass('openIcon')) { | 840 | if (!$('#rightNavDrawerIcon').hasClass('openIcon')) { |
| 840 | SaveLocal('NavOpened', 'true'); | 841 | accountStorage.setItem('NavOpened', 'true'); |
| 841 | } else { SaveLocal('NavOpened', 'false'); } | 842 | } else { accountStorage.setItem('NavOpened', 'false'); } |
| 842 | }); | 843 | }); |
| 843 | 844 | ||
| 844 | //save state of Left nav being open or closed | 845 | //save state of Left nav being open or closed |
| 845 | $('#leftNavDrawerIcon').on('click', function () { | 846 | $('#leftNavDrawerIcon').on('click', function () { |
| 846 | if (!$('#leftNavDrawerIcon').hasClass('openIcon')) { | 847 | if (!$('#leftNavDrawerIcon').hasClass('openIcon')) { |
| 847 | SaveLocal('LNavOpened', 'true'); | 848 | accountStorage.setItem('LNavOpened', 'true'); |
| 848 | } else { SaveLocal('LNavOpened', 'false'); } | 849 | } else { accountStorage.setItem('LNavOpened', 'false'); } |
| 849 | }); | 850 | }); |
| 850 | 851 | ||
| 851 | //save state of Left nav being open or closed | 852 | //save state of Left nav being open or closed |
| 852 | $('#WorldInfo').on('click', function () { | 853 | $('#WorldInfo').on('click', function () { |
| 853 | if (!$('#WorldInfo').hasClass('openIcon')) { | 854 | if (!$('#WorldInfo').hasClass('openIcon')) { |
| 854 | SaveLocal('WINavOpened', 'true'); | 855 | accountStorage.setItem('WINavOpened', 'true'); |
| 855 | } else { SaveLocal('WINavOpened', 'false'); } | 856 | } else { accountStorage.setItem('WINavOpened', 'false'); } |
| 856 | }); | 857 | }); |
| 857 | 858 | ||
| 858 | var chatbarInFocus = false; | 859 | var chatbarInFocus = false; |
| @@ -868,8 +869,8 @@ export function initRossMods() { | |||
| 868 | OpenNavPanels(); | 869 | OpenNavPanels(); |
| 869 | }, 300); | 870 | }, 300); |
| 870 | 871 | ||
| 871 | $(SelectedCharacterTab).click(function () { SaveLocal('SelectedNavTab', 'rm_button_selected_ch'); }); | 872 | $(SelectedCharacterTab).click(function () { accountStorage.setItem('SelectedNavTab', 'rm_button_selected_ch'); }); |
| 872 | $('#rm_button_characters').click(function () { SaveLocal('SelectedNavTab', 'rm_button_characters'); }); | 873 | $('#rm_button_characters').click(function () { accountStorage.setItem('SelectedNavTab', 'rm_button_characters'); }); |
| 873 | 874 | ||
| 874 | // when a char is selected from the list, save them as the auto-load character for next page load | 875 | // when a char is selected from the list, save them as the auto-load character for next page load |
| 875 | 876 | ||
| @@ -1077,7 +1078,7 @@ export function initRossMods() { | |||
| 1077 | } | 1078 | } |
| 1078 | else if (is_send_press == false) { | 1079 | else if (is_send_press == false) { |
| 1079 | const skipConfirmKey = 'RegenerateWithCtrlEnter'; | 1080 | const skipConfirmKey = 'RegenerateWithCtrlEnter'; |
| 1080 | const skipConfirm = LoadLocalBool(skipConfirmKey); | 1081 | const skipConfirm = accountStorage.getItem(skipConfirmKey) === 'true'; |
| 1081 | function doRegenerate() { | 1082 | function doRegenerate() { |
| 1082 | console.debug('Regenerating with Ctrl+Enter'); | 1083 | console.debug('Regenerating with Ctrl+Enter'); |
| 1083 | $('#option_regenerate').trigger('click'); | 1084 | $('#option_regenerate').trigger('click'); |
| @@ -1097,7 +1098,7 @@ export function initRossMods() { | |||
| 1097 | return; | 1098 | return; |
| 1098 | } | 1099 | } |
| 1099 | 1100 | ||
| 1100 | SaveLocal(skipConfirmKey, regenerateWithCtrlEnter); | 1101 | accountStorage.setItem(skipConfirmKey, String(regenerateWithCtrlEnter)); |
| 1101 | doRegenerate(); | 1102 | doRegenerate(); |
| 1102 | } | 1103 | } |
| 1103 | return; | 1104 | return; |
| @@ -45,6 +45,7 @@ import { DragAndDropHandler } from './dragdrop.js'; | |||
| 45 | import { renderTemplateAsync } from './templates.js'; | 45 | import { renderTemplateAsync } from './templates.js'; |
| 46 | import { t } from './i18n.js'; | 46 | import { t } from './i18n.js'; |
| 47 | import { humanizedDateTime } from './RossAscends-mods.js'; | 47 | import { humanizedDateTime } from './RossAscends-mods.js'; |
| 48 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 48 | 49 | ||
| 49 | /** | 50 | /** |
| 50 | * @typedef {Object} FileAttachment | 51 | * @typedef {Object} FileAttachment |
| @@ -1078,8 +1079,8 @@ async function openAttachmentManager() { | |||
| 1078 | renderAttachments(); | 1079 | renderAttachments(); |
| 1079 | }); | 1080 | }); |
| 1080 | 1081 | ||
| 1081 | let sortField = localStorage.getItem('DataBank_sortField') || 'created'; | 1082 | let sortField = accountStorage.getItem('DataBank_sortField') || 'created'; |
| 1082 | let sortOrder = localStorage.getItem('DataBank_sortOrder') || 'desc'; | 1083 | let sortOrder = accountStorage.getItem('DataBank_sortOrder') || 'desc'; |
| 1083 | let filterString = ''; | 1084 | let filterString = ''; |
| 1084 | 1085 | ||
| 1085 | const template = $(await renderExtensionTemplateAsync('attachments', 'manager', {})); | 1086 | const template = $(await renderExtensionTemplateAsync('attachments', 'manager', {})); |
| @@ -1095,8 +1096,8 @@ async function openAttachmentManager() { | |||
| 1095 | 1096 | ||
| 1096 | sortField = this.selectedOptions[0].dataset.sortField; | 1097 | sortField = this.selectedOptions[0].dataset.sortField; |
| 1097 | sortOrder = this.selectedOptions[0].dataset.sortOrder; | 1098 | sortOrder = this.selectedOptions[0].dataset.sortOrder; |
| 1098 | localStorage.setItem('DataBank_sortField', sortField); | 1099 | accountStorage.setItem('DataBank_sortField', sortField); |
| 1099 | localStorage.setItem('DataBank_sortOrder', sortOrder); | 1100 | accountStorage.setItem('DataBank_sortOrder', sortOrder); |
| 1100 | renderAttachments(); | 1101 | renderAttachments(); |
| 1101 | }); | 1102 | }); |
| 1102 | function handleBulkAction(action) { | 1103 | function handleBulkAction(action) { |
| @@ -9,6 +9,7 @@ import { getContext } from './st-context.js'; | |||
| 9 | import { isAdmin } from './user.js'; | 9 | import { isAdmin } from './user.js'; |
| 10 | import { t } from './i18n.js'; | 10 | import { t } from './i18n.js'; |
| 11 | import { debounce_timeout } from './constants.js'; | 11 | import { debounce_timeout } from './constants.js'; |
| 12 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 12 | 13 | ||
| 13 | export { | 14 | export { |
| 14 | getContext, | 15 | getContext, |
| @@ -714,7 +715,7 @@ async function showExtensionsDetails() { | |||
| 714 | htmlExternal.append(htmlLoading); | 715 | htmlExternal.append(htmlLoading); |
| 715 | 716 | ||
| 716 | const sortOrderKey = 'extensions_sortByName'; | 717 | const sortOrderKey = 'extensions_sortByName'; |
| 717 | const sortByName = localStorage.getItem(sortOrderKey) === 'true'; | 718 | const sortByName = accountStorage.getItem(sortOrderKey) === 'true'; |
| 718 | const sortFn = sortByName ? sortManifestsByName : sortManifestsByOrder; | 719 | const sortFn = sortByName ? sortManifestsByName : sortManifestsByOrder; |
| 719 | const extensions = Object.entries(manifests).sort((a, b) => sortFn(a[1], b[1])).map(getExtensionData); | 720 | const extensions = Object.entries(manifests).sort((a, b) => sortFn(a[1], b[1])).map(getExtensionData); |
| 720 | 721 | ||
| @@ -745,7 +746,7 @@ async function showExtensionsDetails() { | |||
| 745 | text: sortByName ? t`Sort: Display Name` : t`Sort: Loading Order`, | 746 | text: sortByName ? t`Sort: Display Name` : t`Sort: Loading Order`, |
| 746 | action: async () => { | 747 | action: async () => { |
| 747 | abortController.abort(); | 748 | abortController.abort(); |
| 748 | localStorage.setItem(sortOrderKey, sortByName ? 'false' : 'true'); | 749 | accountStorage.setItem(sortOrderKey, sortByName ? 'false' : 'true'); |
| 749 | await showExtensionsDetails(); | 750 | await showExtensionsDetails(); |
| 750 | }, | 751 | }, |
| 751 | }; | 752 | }; |
| @@ -1153,11 +1154,11 @@ async function checkForExtensionUpdates(force) { | |||
| 1153 | const currentDate = new Date().toDateString(); | 1154 | const currentDate = new Date().toDateString(); |
| 1154 | 1155 | ||
| 1155 | // Don't nag more than once a day | 1156 | // Don't nag more than once a day |
| 1156 | if (localStorage.getItem(STORAGE_NAG_KEY) === currentDate) { | 1157 | if (accountStorage.getItem(STORAGE_NAG_KEY) === currentDate) { |
| 1157 | return; | 1158 | return; |
| 1158 | } | 1159 | } |
| 1159 | 1160 | ||
| 1160 | localStorage.setItem(STORAGE_NAG_KEY, currentDate); | 1161 | accountStorage.setItem(STORAGE_NAG_KEY, currentDate); |
| 1161 | } | 1162 | } |
| 1162 | 1163 | ||
| 1163 | const isCurrentUserAdmin = isAdmin(); | 1164 | const isCurrentUserAdmin = isAdmin(); |
| @@ -8,6 +8,7 @@ import { getRequestHeaders, processDroppedFiles, eventSource, event_types } from | |||
| 8 | import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js'; | 8 | import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js'; |
| 9 | import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js'; | 9 | import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js'; |
| 10 | import { executeSlashCommands } from '../../slash-commands.js'; | 10 | import { executeSlashCommands } from '../../slash-commands.js'; |
| 11 | import { accountStorage } from '../../util/AccountStorage.js'; | ||
| 11 | import { flashHighlight, getStringHash, isValidUrl } from '../../utils.js'; | 12 | import { flashHighlight, getStringHash, isValidUrl } from '../../utils.js'; |
| 12 | export { MODULE_NAME }; | 13 | export { MODULE_NAME }; |
| 13 | 14 | ||
| @@ -432,14 +433,14 @@ jQuery(async () => { | |||
| 432 | connectButton.on('click', async function () { | 433 | connectButton.on('click', async function () { |
| 433 | const url = DOMPurify.sanitize(String(assetsJsonUrl.val())); | 434 | const url = DOMPurify.sanitize(String(assetsJsonUrl.val())); |
| 434 | const rememberKey = `Assets_SkipConfirm_${getStringHash(url)}`; | 435 | const rememberKey = `Assets_SkipConfirm_${getStringHash(url)}`; |
| 435 | const skipConfirm = localStorage.getItem(rememberKey) === 'true'; | 436 | const skipConfirm = accountStorage.getItem(rememberKey) === 'true'; |
| 436 | 437 | ||
| 437 | const confirmation = skipConfirm || await Popup.show.confirm('Loading Asset List', `<span>Are you sure you want to connect to the following url?</span><var>${url}</var>`, { | 438 | const confirmation = skipConfirm || await Popup.show.confirm('Loading Asset List', `<span>Are you sure you want to connect to the following url?</span><var>${url}</var>`, { |
| 438 | customInputs: [{ id: 'assets-remember', label: 'Don\'t ask again for this URL' }], | 439 | customInputs: [{ id: 'assets-remember', label: 'Don\'t ask again for this URL' }], |
| 439 | onClose: popup => { | 440 | onClose: popup => { |
| 440 | if (popup.result) { | 441 | if (popup.result) { |
| 441 | const rememberValue = popup.inputResults.get('assets-remember'); | 442 | const rememberValue = popup.inputResults.get('assets-remember'); |
| 442 | localStorage.setItem(rememberKey, String(rememberValue)); | 443 | accountStorage.setItem(rememberKey, String(rememberValue)); |
| 443 | } | 444 | } |
| 444 | }, | 445 | }, |
| 445 | }); | 446 | }); |
| @@ -10,6 +10,7 @@ import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; | |||
| 10 | import { download, getFileText, getSortableDelay, uuidv4 } from '../../utils.js'; | 10 | import { download, getFileText, getSortableDelay, uuidv4 } from '../../utils.js'; |
| 11 | import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js'; | 11 | import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js'; |
| 12 | import { t } from '../../i18n.js'; | 12 | import { t } from '../../i18n.js'; |
| 13 | import { accountStorage } from '../../util/AccountStorage.js'; | ||
| 13 | 14 | ||
| 14 | /** | 15 | /** |
| 15 | * @typedef {object} RegexScript | 16 | * @typedef {object} RegexScript |
| @@ -440,8 +441,8 @@ async function checkEmbeddedRegexScripts() { | |||
| 440 | if (avatar && !extension_settings.character_allowed_regex.includes(avatar)) { | 441 | if (avatar && !extension_settings.character_allowed_regex.includes(avatar)) { |
| 441 | const checkKey = `AlertRegex_${characters[chid].avatar}`; | 442 | const checkKey = `AlertRegex_${characters[chid].avatar}`; |
| 442 | 443 | ||
| 443 | if (!localStorage.getItem(checkKey)) { | 444 | if (!accountStorage.getItem(checkKey)) { |
| 444 | localStorage.setItem(checkKey, 'true'); | 445 | accountStorage.setItem(checkKey, 'true'); |
| 445 | const template = await renderExtensionTemplateAsync('regex', 'embeddedScripts', {}); | 446 | const template = await renderExtensionTemplateAsync('regex', 'embeddedScripts', {}); |
| 446 | const result = await callGenericPopup(template, POPUP_TYPE.CONFIRM, '', { okButton: 'Yes' }); | 447 | const result = await callGenericPopup(template, POPUP_TYPE.CONFIRM, '', { okButton: 'Yes' }); |
| 447 | 448 | ||
| @@ -1,27 +0,0 @@ | |||
| 1 | ////////////////// LOCAL STORAGE HANDLING ///////////////////// | ||
| 2 | |||
| 3 | export function SaveLocal(target, val) { | ||
| 4 | localStorage.setItem(target, val); | ||
| 5 | console.debug('SaveLocal -- ' + target + ' : ' + val); | ||
| 6 | } | ||
| 7 | export function LoadLocal(target) { | ||
| 8 | console.debug('LoadLocal -- ' + target); | ||
| 9 | return localStorage.getItem(target); | ||
| 10 | |||
| 11 | } | ||
| 12 | export function LoadLocalBool(target) { | ||
| 13 | let result = localStorage.getItem(target) === 'true'; | ||
| 14 | return result; | ||
| 15 | } | ||
| 16 | export function CheckLocal() { | ||
| 17 | console.log('----------local storage---------'); | ||
| 18 | var i; | ||
| 19 | for (i = 0; i < localStorage.length; i++) { | ||
| 20 | console.log(localStorage.key(i) + ' : ' + localStorage.getItem(localStorage.key(i))); | ||
| 21 | } | ||
| 22 | console.log('------------------------------'); | ||
| 23 | } | ||
| 24 | |||
| 25 | export function ClearLocal() { localStorage.clear(); console.log('Removed All Local Storage'); } | ||
| 26 | |||
| 27 | ///////////////////////////////////////////////////////////////////////// | ||
| @@ -78,6 +78,7 @@ import { FILTER_TYPES, FilterHelper } from './filters.js'; | |||
| 78 | import { isExternalMediaAllowed } from './chats.js'; | 78 | import { isExternalMediaAllowed } from './chats.js'; |
| 79 | import { POPUP_TYPE, Popup, callGenericPopup } from './popup.js'; | 79 | import { POPUP_TYPE, Popup, callGenericPopup } from './popup.js'; |
| 80 | import { t } from './i18n.js'; | 80 | import { t } from './i18n.js'; |
| 81 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 81 | 82 | ||
| 82 | export { | 83 | export { |
| 83 | selected_group, | 84 | selected_group, |
| @@ -1309,10 +1310,10 @@ function printGroupCandidates() { | |||
| 1309 | formatNavigator: PAGINATION_TEMPLATE, | 1310 | formatNavigator: PAGINATION_TEMPLATE, |
| 1310 | showNavigator: true, | 1311 | showNavigator: true, |
| 1311 | showSizeChanger: true, | 1312 | showSizeChanger: true, |
| 1312 | pageSize: Number(localStorage.getItem(storageKey)) || 5, | 1313 | pageSize: Number(accountStorage.getItem(storageKey)) || 5, |
| 1313 | sizeChangerOptions: [5, 10, 25, 50, 100, 200, 500, 1000], | 1314 | sizeChangerOptions: [5, 10, 25, 50, 100, 200, 500, 1000], |
| 1314 | afterSizeSelectorChange: function (e) { | 1315 | afterSizeSelectorChange: function (e) { |
| 1315 | localStorage.setItem(storageKey, e.target.value); | 1316 | accountStorage.setItem(storageKey, e.target.value); |
| 1316 | }, | 1317 | }, |
| 1317 | callback: function (data) { | 1318 | callback: function (data) { |
| 1318 | $('#rm_group_add_members').empty(); | 1319 | $('#rm_group_add_members').empty(); |
| @@ -1336,10 +1337,10 @@ function printGroupMembers() { | |||
| 1336 | formatNavigator: PAGINATION_TEMPLATE, | 1337 | formatNavigator: PAGINATION_TEMPLATE, |
| 1337 | showNavigator: true, | 1338 | showNavigator: true, |
| 1338 | showSizeChanger: true, | 1339 | showSizeChanger: true, |
| 1339 | pageSize: Number(localStorage.getItem(storageKey)) || 5, | 1340 | pageSize: Number(accountStorage.getItem(storageKey)) || 5, |
| 1340 | sizeChangerOptions: [5, 10, 25, 50, 100, 200, 500, 1000], | 1341 | sizeChangerOptions: [5, 10, 25, 50, 100, 200, 500, 1000], |
| 1341 | afterSizeSelectorChange: function (e) { | 1342 | afterSizeSelectorChange: function (e) { |
| 1342 | localStorage.setItem(storageKey, e.target.value); | 1343 | accountStorage.setItem(storageKey, e.target.value); |
| 1343 | }, | 1344 | }, |
| 1344 | callback: function (data) { | 1345 | callback: function (data) { |
| 1345 | $('.rm_group_members').empty(); | 1346 | $('.rm_group_members').empty(); |
| @@ -73,6 +73,7 @@ import { SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js | |||
| 73 | import { Popup, POPUP_RESULT } from './popup.js'; | 73 | import { Popup, POPUP_RESULT } from './popup.js'; |
| 74 | import { t } from './i18n.js'; | 74 | import { t } from './i18n.js'; |
| 75 | import { ToolManager } from './tool-calling.js'; | 75 | import { ToolManager } from './tool-calling.js'; |
| 76 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 76 | 77 | ||
| 77 | export { | 78 | export { |
| 78 | openai_messages_count, | 79 | openai_messages_count, |
| @@ -414,7 +415,7 @@ async function validateReverseProxy() { | |||
| 414 | throw err; | 415 | throw err; |
| 415 | } | 416 | } |
| 416 | const rememberKey = `Proxy_SkipConfirm_${getStringHash(oai_settings.reverse_proxy)}`; | 417 | const rememberKey = `Proxy_SkipConfirm_${getStringHash(oai_settings.reverse_proxy)}`; |
| 417 | const skipConfirm = localStorage.getItem(rememberKey) === 'true'; | 418 | const skipConfirm = accountStorage.getItem(rememberKey) === 'true'; |
| 418 | 419 | ||
| 419 | const confirmation = skipConfirm || await Popup.show.confirm(t`Connecting To Proxy`, await renderTemplateAsync('proxyConnectionWarning', { proxyURL: DOMPurify.sanitize(oai_settings.reverse_proxy) })); | 420 | const confirmation = skipConfirm || await Popup.show.confirm(t`Connecting To Proxy`, await renderTemplateAsync('proxyConnectionWarning', { proxyURL: DOMPurify.sanitize(oai_settings.reverse_proxy) })); |
| 420 | 421 | ||
| @@ -425,7 +426,7 @@ async function validateReverseProxy() { | |||
| 425 | throw new Error('Proxy connection denied.'); | 426 | throw new Error('Proxy connection denied.'); |
| 426 | } | 427 | } |
| 427 | 428 | ||
| 428 | localStorage.setItem(rememberKey, String(true)); | 429 | accountStorage.setItem(rememberKey, String(true)); |
| 429 | } | 430 | } |
| 430 | 431 | ||
| 431 | /** | 432 | /** |
| @@ -25,6 +25,7 @@ import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js'; | |||
| 25 | import { t } from './i18n.js'; | 25 | import { t } from './i18n.js'; |
| 26 | import { openWorldInfoEditor, world_names } from './world-info.js'; | 26 | import { openWorldInfoEditor, world_names } from './world-info.js'; |
| 27 | import { renderTemplateAsync } from './templates.js'; | 27 | import { renderTemplateAsync } from './templates.js'; |
| 28 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 28 | 29 | ||
| 29 | let savePersonasPage = 0; | 30 | let savePersonasPage = 0; |
| 30 | const GRID_STORAGE_KEY = 'Personas_GridView'; | 31 | const GRID_STORAGE_KEY = 'Personas_GridView'; |
| @@ -34,7 +35,7 @@ export let user_avatar = ''; | |||
| 34 | export const personasFilter = new FilterHelper(debounce(getUserAvatars, debounce_timeout.quick)); | 35 | export const personasFilter = new FilterHelper(debounce(getUserAvatars, debounce_timeout.quick)); |
| 35 | 36 | ||
| 36 | function switchPersonaGridView() { | 37 | function switchPersonaGridView() { |
| 37 | const state = localStorage.getItem(GRID_STORAGE_KEY) === 'true'; | 38 | const state = accountStorage.getItem(GRID_STORAGE_KEY) === 'true'; |
| 38 | $('#user_avatar_block').toggleClass('gridView', state); | 39 | $('#user_avatar_block').toggleClass('gridView', state); |
| 39 | } | 40 | } |
| 40 | 41 | ||
| @@ -182,7 +183,7 @@ export async function getUserAvatars(doRender = true, openPageAt = '') { | |||
| 182 | 183 | ||
| 183 | const storageKey = 'Personas_PerPage'; | 184 | const storageKey = 'Personas_PerPage'; |
| 184 | const listId = '#user_avatar_block'; | 185 | const listId = '#user_avatar_block'; |
| 185 | const perPage = Number(localStorage.getItem(storageKey)) || 5; | 186 | const perPage = Number(accountStorage.getItem(storageKey)) || 5; |
| 186 | 187 | ||
| 187 | $('#persona_pagination_container').pagination({ | 188 | $('#persona_pagination_container').pagination({ |
| 188 | dataSource: entities, | 189 | dataSource: entities, |
| @@ -205,7 +206,7 @@ export async function getUserAvatars(doRender = true, openPageAt = '') { | |||
| 205 | highlightSelectedAvatar(); | 206 | highlightSelectedAvatar(); |
| 206 | }, | 207 | }, |
| 207 | afterSizeSelectorChange: function (e) { | 208 | afterSizeSelectorChange: function (e) { |
| 208 | localStorage.setItem(storageKey, e.target.value); | 209 | accountStorage.setItem(storageKey, e.target.value); |
| 209 | }, | 210 | }, |
| 210 | afterPaging: function (e) { | 211 | afterPaging: function (e) { |
| 211 | savePersonasPage = e; | 212 | savePersonasPage = e; |
| @@ -1132,8 +1133,8 @@ export function initPersonas() { | |||
| 1132 | saveSettingsDebounced(); | 1133 | saveSettingsDebounced(); |
| 1133 | }); | 1134 | }); |
| 1134 | $('#persona_grid_toggle').on('click', () => { | 1135 | $('#persona_grid_toggle').on('click', () => { |
| 1135 | const state = localStorage.getItem(GRID_STORAGE_KEY) === 'true'; | 1136 | const state = accountStorage.getItem(GRID_STORAGE_KEY) === 'true'; |
| 1136 | localStorage.setItem(GRID_STORAGE_KEY, String(!state)); | 1137 | accountStorage.setItem(GRID_STORAGE_KEY, String(!state)); |
| 1137 | switchPersonaGridView(); | 1138 | switchPersonaGridView(); |
| 1138 | }); | 1139 | }); |
| 1139 | 1140 | ||
| @@ -54,6 +54,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom | |||
| 54 | import { POPUP_TYPE, callGenericPopup } from './popup.js'; | 54 | import { POPUP_TYPE, callGenericPopup } from './popup.js'; |
| 55 | import { loadSystemPrompts } from './sysprompt.js'; | 55 | import { loadSystemPrompts } from './sysprompt.js'; |
| 56 | import { fuzzySearchCategories } from './filters.js'; | 56 | import { fuzzySearchCategories } from './filters.js'; |
| 57 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 57 | 58 | ||
| 58 | export { | 59 | export { |
| 59 | loadPowerUserSettings, | 60 | loadPowerUserSettings, |
| @@ -2019,7 +2020,7 @@ export function renderStoryString(params) { | |||
| 2019 | */ | 2020 | */ |
| 2020 | function validateStoryString(storyString, params) { | 2021 | function validateStoryString(storyString, params) { |
| 2021 | /** @type {{hashCache: {[hash: string]: {fieldsWarned: {[key: string]: boolean}}}}} */ | 2022 | /** @type {{hashCache: {[hash: string]: {fieldsWarned: {[key: string]: boolean}}}}} */ |
| 2022 | const cache = JSON.parse(localStorage.getItem(storage_keys.storyStringValidationCache)) ?? { hashCache: {} }; | 2023 | const cache = JSON.parse(accountStorage.getItem(storage_keys.storyStringValidationCache)) ?? { hashCache: {} }; |
| 2023 | 2024 | ||
| 2024 | const hash = getStringHash(storyString); | 2025 | const hash = getStringHash(storyString); |
| 2025 | 2026 | ||
| @@ -2056,7 +2057,7 @@ function validateStoryString(storyString, params) { | |||
| 2056 | toastr.warning(`The story string does not contain the following fields, but they would contain content: ${fieldsList}`, 'Story String Validation'); | 2057 | toastr.warning(`The story string does not contain the following fields, but they would contain content: ${fieldsList}`, 'Story String Validation'); |
| 2057 | } | 2058 | } |
| 2058 | 2059 | ||
| 2059 | localStorage.setItem(storage_keys.storyStringValidationCache, JSON.stringify(cache)); | 2060 | accountStorage.setItem(storage_keys.storyStringValidationCache, JSON.stringify(cache)); |
| 2060 | } | 2061 | } |
| 2061 | 2062 | ||
| 2062 | 2063 | ||
| @@ -75,6 +75,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom | |||
| 75 | import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js'; | 75 | import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js'; |
| 76 | import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js'; | 76 | import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js'; |
| 77 | import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; | 77 | import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; |
| 78 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 78 | export { | 79 | export { |
| 79 | executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand, | 80 | executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand, |
| 80 | }; | 81 | }; |
| @@ -3606,9 +3607,9 @@ export async function sendMessageAs(args, text) { | |||
| 3606 | 3607 | ||
| 3607 | if (!name) { | 3608 | if (!name) { |
| 3608 | const namelessWarningKey = 'sendAsNamelessWarningShown'; | 3609 | const namelessWarningKey = 'sendAsNamelessWarningShown'; |
| 3609 | if (localStorage.getItem(namelessWarningKey) !== 'true') { | 3610 | if (accountStorage.getItem(namelessWarningKey) !== 'true') { |
| 3610 | toastr.warning('To avoid confusion, please use /sendas name="Character Name"', 'Name defaulted to {{char}}', { timeOut: 10000 }); | 3611 | toastr.warning('To avoid confusion, please use /sendas name="Character Name"', 'Name defaulted to {{char}}', { timeOut: 10000 }); |
| 3611 | localStorage.setItem(namelessWarningKey, 'true'); | 3612 | accountStorage.setItem(namelessWarningKey, 'true'); |
| 3612 | } | 3613 | } |
| 3613 | name = name2; | 3614 | name = name2; |
| 3614 | } | 3615 | } |
| @@ -68,12 +68,14 @@ import { tag_map, tags } from './tags.js'; | |||
| 68 | import { textgenerationwebui_settings } from './textgen-settings.js'; | 68 | import { textgenerationwebui_settings } from './textgen-settings.js'; |
| 69 | import { tokenizers, getTextTokens, getTokenCount, getTokenCountAsync, getTokenizerModel } from './tokenizers.js'; | 69 | import { tokenizers, getTextTokens, getTokenCount, getTokenCountAsync, getTokenizerModel } from './tokenizers.js'; |
| 70 | import { ToolManager } from './tool-calling.js'; | 70 | import { ToolManager } from './tool-calling.js'; |
| 71 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 71 | import { timestampToMoment, uuidv4 } from './utils.js'; | 72 | import { timestampToMoment, uuidv4 } from './utils.js'; |
| 72 | import { getGlobalVariable, getLocalVariable, setGlobalVariable, setLocalVariable } from './variables.js'; | 73 | import { getGlobalVariable, getLocalVariable, setGlobalVariable, setLocalVariable } from './variables.js'; |
| 73 | import { convertCharacterBook, loadWorldInfo, saveWorldInfo, updateWorldInfoList } from './world-info.js'; | 74 | import { convertCharacterBook, loadWorldInfo, saveWorldInfo, updateWorldInfoList } from './world-info.js'; |
| 74 | 75 | ||
| 75 | export function getContext() { | 76 | export function getContext() { |
| 76 | return { | 77 | return { |
| 78 | accountStorage, | ||
| 77 | chat, | 79 | chat, |
| 78 | characters, | 80 | characters, |
| 79 | groups, | 81 | groups, |
| @@ -6,6 +6,7 @@ import { tokenizers } from './tokenizers.js'; | |||
| 6 | import { renderTemplateAsync } from './templates.js'; | 6 | import { renderTemplateAsync } from './templates.js'; |
| 7 | import { POPUP_TYPE, callGenericPopup } from './popup.js'; | 7 | import { POPUP_TYPE, callGenericPopup } from './popup.js'; |
| 8 | import { t } from './i18n.js'; | 8 | import { t } from './i18n.js'; |
| 9 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 9 | 10 | ||
| 10 | let mancerModels = []; | 11 | let mancerModels = []; |
| 11 | let togetherModels = []; | 12 | let togetherModels = []; |
| @@ -336,7 +337,7 @@ export async function loadFeatherlessModels(data) { | |||
| 336 | populateClassSelection(data); | 337 | populateClassSelection(data); |
| 337 | 338 | ||
| 338 | // Retrieve the stored number of items per page or default to 10 | 339 | // Retrieve the stored number of items per page or default to 10 |
| 339 | const perPage = Number(localStorage.getItem(storageKey)) || 10; | 340 | const perPage = Number(accountStorage.getItem(storageKey)) || 10; |
| 340 | 341 | ||
| 341 | // Initialize pagination | 342 | // Initialize pagination |
| 342 | applyFiltersAndSort(); | 343 | applyFiltersAndSort(); |
| @@ -412,7 +413,7 @@ export async function loadFeatherlessModels(data) { | |||
| 412 | }, | 413 | }, |
| 413 | afterSizeSelectorChange: function (e) { | 414 | afterSizeSelectorChange: function (e) { |
| 414 | const newPerPage = e.target.value; | 415 | const newPerPage = e.target.value; |
| 415 | localStorage.setItem('Models_PerPage', newPerPage); | 416 | accountStorage.setItem(storageKey, newPerPage); |
| 416 | setupPagination(models, Number(newPerPage), featherlessCurrentPage); // Use the stored current page number | 417 | setupPagination(models, Number(newPerPage), featherlessCurrentPage); // Use the stored current page number |
| 417 | }, | 418 | }, |
| 418 | }); | 419 | }); |
| @@ -513,7 +514,7 @@ export async function loadFeatherlessModels(data) { | |||
| 513 | const currentModelIndex = filteredModels.findIndex(x => x.id === textgen_settings.featherless_model); | 514 | const currentModelIndex = filteredModels.findIndex(x => x.id === textgen_settings.featherless_model); |
| 514 | featherlessCurrentPage = currentModelIndex >= 0 ? (currentModelIndex / perPage) + 1 : 1; | 515 | featherlessCurrentPage = currentModelIndex >= 0 ? (currentModelIndex / perPage) + 1 : 1; |
| 515 | 516 | ||
| 516 | setupPagination(filteredModels, Number(localStorage.getItem(storageKey)) || perPage, featherlessCurrentPage); | 517 | setupPagination(filteredModels, Number(accountStorage.getItem(storageKey)) || perPage, featherlessCurrentPage); |
| 517 | } | 518 | } |
| 518 | 519 | ||
| 519 | // Required to keep the /model command function | 520 | // Required to keep the /model command function |
| @@ -0,0 +1,116 @@ | |||
| 1 | import { saveSettingsDebounced } from '../../script.js'; | ||
| 2 | |||
| 3 | const MIGRATED_MARKER = '__migrated'; | ||
| 4 | const MIGRATABLE_KEYS = [ | ||
| 5 | /^AlertRegex_/, | ||
| 6 | /^AlertWI_/, | ||
| 7 | /^Assets_SkipConfirm_/, | ||
| 8 | /^Characters_PerPage$/, | ||
| 9 | /^DataBank_sortField$/, | ||
| 10 | /^DataBank_sortOrder$/, | ||
| 11 | /^extension_update_nag$/, | ||
| 12 | /^extensions_sortByName$/, | ||
| 13 | /^FeatherlessModels_PerPage$/, | ||
| 14 | /^GroupMembers_PerPage$/, | ||
| 15 | /^GroupCandidates_PerPage$/, | ||
| 16 | /^LNavLockOn$/, | ||
| 17 | /^LNavOpened$/, | ||
| 18 | /^mediaWarningShown:/, | ||
| 19 | /^NavLockOn$/, | ||
| 20 | /^NavOpened$/, | ||
| 21 | /^Personas_PerPage$/, | ||
| 22 | /^Personas_GridView$/, | ||
| 23 | /^Proxy_SkipConfirm_/, | ||
| 24 | /^RegenerateWithCtrlEnter$/, | ||
| 25 | /^SelectedNavTab$/, | ||
| 26 | /^sendAsNamelessWarningShown$/, | ||
| 27 | /^StoryStringValidationCache$/, | ||
| 28 | /^WINavOpened$/, | ||
| 29 | /^WI_PerPage$/, | ||
| 30 | /^world_info_sort_order$/, | ||
| 31 | ]; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Provides access to account storage of arbitrary key-value pairs. | ||
| 35 | */ | ||
| 36 | class AccountStorage { | ||
| 37 | constructor() { | ||
| 38 | this.state = {}; | ||
| 39 | this.ready = false; | ||
| 40 | } | ||
| 41 | |||
| 42 | #migrateLocalStorage() { | ||
| 43 | for (let i = 0; i < globalThis.localStorage.length; i++) { | ||
| 44 | const key = globalThis.localStorage.key(i); | ||
| 45 | const value = globalThis.localStorage.getItem(key); | ||
| 46 | |||
| 47 | if (MIGRATABLE_KEYS.some(k => k.test(key))) { | ||
| 48 | this.state[key] = value; | ||
| 49 | globalThis.localStorage.removeItem(key); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Initialize the account storage. | ||
| 56 | * @param {Object} state Initial state | ||
| 57 | */ | ||
| 58 | init(state) { | ||
| 59 | if (state && typeof state === 'object') { | ||
| 60 | this.state = Object.assign(this.state, state); | ||
| 61 | } | ||
| 62 | |||
| 63 | if (!Object.hasOwn(this.state, MIGRATED_MARKER)) { | ||
| 64 | this.#migrateLocalStorage(); | ||
| 65 | this.state[MIGRATED_MARKER] = 1; | ||
| 66 | saveSettingsDebounced(); | ||
| 67 | } | ||
| 68 | |||
| 69 | this.ready = true; | ||
| 70 | } | ||
| 71 | |||
| 72 | /** | ||
| 73 | * Get the value of a key in account storage. | ||
| 74 | * @param {string} key Key to get | ||
| 75 | * @returns {string|null} Value of the key | ||
| 76 | */ | ||
| 77 | getItem(key) { | ||
| 78 | if (!this.ready) { | ||
| 79 | console.warn(`AccountStorage not ready (trying to read from ${key})`); | ||
| 80 | } | ||
| 81 | |||
| 82 | return Object.hasOwn(this.state, key) ? String(this.state[key]) : null; | ||
| 83 | } | ||
| 84 | |||
| 85 | /** | ||
| 86 | * Set a key in account storage. | ||
| 87 | * @param {string} key Key to set | ||
| 88 | * @param {string} value Value to set | ||
| 89 | */ | ||
| 90 | setItem(key, value) { | ||
| 91 | if (!this.ready) { | ||
| 92 | console.warn(`AccountStorage not ready (trying to write to ${key})`); | ||
| 93 | } | ||
| 94 | |||
| 95 | this.state[key] = String(value); | ||
| 96 | saveSettingsDebounced(); | ||
| 97 | } | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Remove a key from account storage. | ||
| 101 | * @param {string} key Key to remove | ||
| 102 | */ | ||
| 103 | removeItem(key) { | ||
| 104 | if (!this.ready) { | ||
| 105 | console.warn(`AccountStorage not ready (trying to remove ${key})`); | ||
| 106 | } | ||
| 107 | |||
| 108 | delete this.state[key]; | ||
| 109 | saveSettingsDebounced(); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Account storage instance. | ||
| 115 | */ | ||
| 116 | export const accountStorage = new AccountStorage(); | ||
| @@ -21,6 +21,7 @@ import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js'; | |||
| 21 | import { StructuredCloneMap } from './util/StructuredCloneMap.js'; | 21 | import { StructuredCloneMap } from './util/StructuredCloneMap.js'; |
| 22 | import { renderTemplateAsync } from './templates.js'; | 22 | import { renderTemplateAsync } from './templates.js'; |
| 23 | import { t } from './i18n.js'; | 23 | import { t } from './i18n.js'; |
| 24 | import { accountStorage } from './util/AccountStorage.js'; | ||
| 24 | 25 | ||
| 25 | export const world_info_insertion_strategy = { | 26 | export const world_info_insertion_strategy = { |
| 26 | evenly: 0, | 27 | evenly: 0, |
| @@ -872,7 +873,7 @@ export function setWorldInfoSettings(settings, data) { | |||
| 872 | $('#world_editor_select').append(`<option value='${i}'>${item}</option>`); | 873 | $('#world_editor_select').append(`<option value='${i}'>${item}</option>`); |
| 873 | }); | 874 | }); |
| 874 | 875 | ||
| 875 | $('#world_info_sort_order').val(localStorage.getItem(SORT_ORDER_KEY) || '0'); | 876 | $('#world_info_sort_order').val(accountStorage.getItem(SORT_ORDER_KEY) || '0'); |
| 876 | $('#world_info').trigger('change'); | 877 | $('#world_info').trigger('change'); |
| 877 | $('#world_editor_select').trigger('change'); | 878 | $('#world_editor_select').trigger('change'); |
| 878 | 879 | ||
| @@ -1947,13 +1948,13 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | |||
| 1947 | if (typeof navigation === 'number' && Number(navigation) >= 0) { | 1948 | if (typeof navigation === 'number' && Number(navigation) >= 0) { |
| 1948 | const data = getDataArray(); | 1949 | const data = getDataArray(); |
| 1949 | const uidIndex = data.findIndex(x => x.uid === navigation); | 1950 | const uidIndex = data.findIndex(x => x.uid === navigation); |
| 1950 | const perPage = Number(localStorage.getItem(storageKey)) || perPageDefault; | 1951 | const perPage = Number(accountStorage.getItem(storageKey)) || perPageDefault; |
| 1951 | startPage = Math.floor(uidIndex / perPage) + 1; | 1952 | startPage = Math.floor(uidIndex / perPage) + 1; |
| 1952 | } | 1953 | } |
| 1953 | 1954 | ||
| 1954 | $('#world_info_pagination').pagination({ | 1955 | $('#world_info_pagination').pagination({ |
| 1955 | dataSource: getDataArray, | 1956 | dataSource: getDataArray, |
| 1956 | pageSize: Number(localStorage.getItem(storageKey)) || perPageDefault, | 1957 | pageSize: Number(accountStorage.getItem(storageKey)) || perPageDefault, |
| 1957 | sizeChangerOptions: [10, 25, 50, 100, 500, 1000], | 1958 | sizeChangerOptions: [10, 25, 50, 100, 500, 1000], |
| 1958 | showSizeChanger: true, | 1959 | showSizeChanger: true, |
| 1959 | pageRange: 1, | 1960 | pageRange: 1, |
| @@ -1983,7 +1984,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | |||
| 1983 | worldEntriesList.append(blocks); | 1984 | worldEntriesList.append(blocks); |
| 1984 | }, | 1985 | }, |
| 1985 | afterSizeSelectorChange: function (e) { | 1986 | afterSizeSelectorChange: function (e) { |
| 1986 | localStorage.setItem(storageKey, e.target.value); | 1987 | accountStorage.setItem(storageKey, e.target.value); |
| 1987 | }, | 1988 | }, |
| 1988 | afterPaging: function () { | 1989 | afterPaging: function () { |
| 1989 | $('#world_popup_entries_list textarea[name="comment"]').each(function () { | 1990 | $('#world_popup_entries_list textarea[name="comment"]').each(function () { |
| @@ -2188,7 +2189,7 @@ function verifyWorldInfoSearchSortRule() { | |||
| 2188 | // If search got cleared, we make sure to hide the option and go back to the one before | 2189 | // If search got cleared, we make sure to hide the option and go back to the one before |
| 2189 | if (!searchTerm && !isHidden) { | 2190 | if (!searchTerm && !isHidden) { |
| 2190 | searchOption.attr('hidden', ''); | 2191 | searchOption.attr('hidden', ''); |
| 2191 | selector.val(localStorage.getItem(SORT_ORDER_KEY) || '0'); | 2192 | selector.val(accountStorage.getItem(SORT_ORDER_KEY) || '0'); |
| 2192 | } | 2193 | } |
| 2193 | } | 2194 | } |
| 2194 | 2195 | ||
| @@ -4753,8 +4754,8 @@ export function checkEmbeddedWorld(chid) { | |||
| 4753 | // Only show the alert once per character | 4754 | // Only show the alert once per character |
| 4754 | const checkKey = `AlertWI_${characters[chid].avatar}`; | 4755 | const checkKey = `AlertWI_${characters[chid].avatar}`; |
| 4755 | const worldName = characters[chid]?.data?.extensions?.world; | 4756 | const worldName = characters[chid]?.data?.extensions?.world; |
| 4756 | if (!localStorage.getItem(checkKey) && (!worldName || !world_names.includes(worldName))) { | 4757 | if (!accountStorage.getItem(checkKey) && (!worldName || !world_names.includes(worldName))) { |
| 4757 | localStorage.setItem(checkKey, 'true'); | 4758 | accountStorage.setItem(checkKey, 'true'); |
| 4758 | 4759 | ||
| 4759 | if (power_user.world_import_dialog) { | 4760 | if (power_user.world_import_dialog) { |
| 4760 | const html = `<h3>This character has an embedded World/Lorebook.</h3> | 4761 | const html = `<h3>This character has an embedded World/Lorebook.</h3> |
| @@ -5198,7 +5199,7 @@ jQuery(() => { | |||
| 5198 | $('#world_info_sort_order').on('change', function () { | 5199 | $('#world_info_sort_order').on('change', function () { |
| 5199 | const value = String($(this).find(':selected').val()); | 5200 | const value = String($(this).find(':selected').val()); |
| 5200 | // Save sort order, but do not save search sorting, as this is a temporary sorting option | 5201 | // Save sort order, but do not save search sorting, as this is a temporary sorting option |
| 5201 | if (value !== 'search') localStorage.setItem(SORT_ORDER_KEY, value); | 5202 | if (value !== 'search') accountStorage.setItem(SORT_ORDER_KEY, value); |
| 5202 | updateEditor(navigation_option.none); | 5203 | updateEditor(navigation_option.none); |
| 5203 | }); | 5204 | }); |
| 5204 | 5205 | ||