Replace ajax with fetch (#4241) * Replace ajax with fetch Fix type errors in power-user / group-chats modules * Fix single sprite upload * Return empty object on failed upload
Signed| @@ -73,4 +73,10 @@ declare global { | |||
| 73 | * @param args - The arguments for the conversion function. | 73 | * @param args - The arguments for the conversion function. |
| 74 | */ | 74 | */ |
| 75 | function convertVideoToAnimatedWebp(args: ConvertVideoArgs): Promise<Uint8Array>; | 75 | function convertVideoToAnimatedWebp(args: ConvertVideoArgs): Promise<Uint8Array>; |
| 76 | |||
| 77 | interface ColorPickerEvent extends JQuery.ChangeEvent<HTMLElement> { | ||
| 78 | detail: { | ||
| 79 | rgba: string; | ||
| 80 | }; | ||
| 81 | } | ||
| 76 | } | 82 | } |
| @@ -784,11 +784,17 @@ export let active_group = ''; | |||
| 784 | 784 | ||
| 785 | export const entitiesFilter = new FilterHelper(printCharactersDebounced); | 785 | export const entitiesFilter = new FilterHelper(printCharactersDebounced); |
| 786 | 786 | ||
| 787 | export function getRequestHeaders() { | 787 | export function getRequestHeaders({ omitContentType = false } = {}) { |
| 788 | return { | 788 | const headers = { |
| 789 | 'Content-Type': 'application/json', | 789 | 'Content-Type': 'application/json', |
| 790 | 'X-CSRF-Token': token, | 790 | 'X-CSRF-Token': token, |
| 791 | }; | 791 | }; |
| 792 | |||
| 793 | if (omitContentType) { | ||
| 794 | delete headers['Content-Type']; | ||
| 795 | } | ||
| 796 | |||
| 797 | return headers; | ||
| 792 | } | 798 | } |
| 793 | 799 | ||
| 794 | export function getSlideToggleOptions() { | 800 | export function getSlideToggleOptions() { |
| @@ -7078,50 +7084,51 @@ export async function saveSettings(loopCounter = 0) { | |||
| 7078 | TempResponseLength.restore(null); | 7084 | TempResponseLength.restore(null); |
| 7079 | } | 7085 | } |
| 7080 | 7086 | ||
| 7081 | //console.log('Entering settings with name1 = '+name1); | 7087 | const payload = { |
| 7082 | return jQuery.ajax({ | 7088 | firstRun: firstRun, |
| 7083 | type: 'POST', | 7089 | accountStorage: accountStorage.getState(), |
| 7084 | url: '/api/settings/save', | 7090 | currentVersion: currentVersion, |
| 7085 | data: JSON.stringify({ | 7091 | username: name1, |
| 7086 | firstRun: firstRun, | 7092 | active_character: active_character, |
| 7087 | accountStorage: accountStorage.getState(), | 7093 | active_group: active_group, |
| 7088 | currentVersion: currentVersion, | 7094 | user_avatar: user_avatar, |
| 7089 | username: name1, | 7095 | amount_gen: amount_gen, |
| 7090 | active_character: active_character, | 7096 | max_context: max_context, |
| 7091 | active_group: active_group, | 7097 | main_api: main_api, |
| 7092 | user_avatar: user_avatar, | 7098 | world_info_settings: getWorldInfoSettings(), |
| 7093 | amount_gen: amount_gen, | 7099 | textgenerationwebui_settings: textgen_settings, |
| 7094 | max_context: max_context, | 7100 | swipes: swipes, |
| 7095 | main_api: main_api, | 7101 | horde_settings: horde_settings, |
| 7096 | world_info_settings: getWorldInfoSettings(), | 7102 | power_user: power_user, |
| 7097 | textgenerationwebui_settings: textgen_settings, | 7103 | extension_settings: extension_settings, |
| 7098 | swipes: swipes, | 7104 | tags: tags, |
| 7099 | horde_settings: horde_settings, | 7105 | tag_map: tag_map, |
| 7100 | power_user: power_user, | 7106 | nai_settings: nai_settings, |
| 7101 | extension_settings: extension_settings, | 7107 | kai_settings: kai_settings, |
| 7102 | tags: tags, | 7108 | oai_settings: oai_settings, |
| 7103 | tag_map: tag_map, | 7109 | background: background_settings, |
| 7104 | nai_settings: nai_settings, | 7110 | proxies: proxies, |
| 7105 | kai_settings: kai_settings, | 7111 | selected_proxy: selected_proxy, |
| 7106 | oai_settings: oai_settings, | 7112 | }; |
| 7107 | background: background_settings, | 7113 | |
| 7108 | proxies: proxies, | 7114 | try { |
| 7109 | selected_proxy: selected_proxy, | 7115 | const result = await fetch('/api/settings/save', { |
| 7110 | }, null, 4), | 7116 | method: 'POST', |
| 7111 | beforeSend: function () { }, | 7117 | headers: getRequestHeaders(), |
| 7112 | cache: false, | 7118 | body: JSON.stringify(payload), |
| 7113 | dataType: 'json', | 7119 | cache: 'no-cache', |
| 7114 | contentType: 'application/json', | 7120 | }); |
| 7115 | //processData: false, | 7121 | |
| 7116 | success: async function (data) { | 7122 | if (!result.ok) { |
| 7117 | eventSource.emit(event_types.SETTINGS_UPDATED); | 7123 | throw new Error(`Failed to save settings: ${result.statusText}`); |
| 7118 | }, | 7124 | } |
| 7119 | error: function (jqXHR, exception) { | 7125 | |
| 7120 | toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Settings could not be saved`); | 7126 | settings = payload; |
| 7121 | console.log(exception); | 7127 | await eventSource.emit(event_types.SETTINGS_UPDATED); |
| 7122 | console.log(jqXHR); | 7128 | } catch (error) { |
| 7123 | }, | 7129 | console.error('Error saving settings:', error); |
| 7124 | }); | 7130 | toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Settings could not be saved`); |
| 7131 | } | ||
| 7125 | } | 7132 | } |
| 7126 | 7133 | ||
| 7127 | /** | 7134 | /** |
| @@ -8079,12 +8086,10 @@ export async function saveChatConditional() { | |||
| 8079 | * @param {EventTarget} eventTarget Event target to trigger the event on. | 8086 | * @param {EventTarget} eventTarget Event target to trigger the event on. |
| 8080 | */ | 8087 | */ |
| 8081 | async function importCharacterChat(formData, eventTarget) { | 8088 | async function importCharacterChat(formData, eventTarget) { |
| 8082 | const headers = getRequestHeaders(); | ||
| 8083 | delete headers['Content-Type']; | ||
| 8084 | const fetchResult = await fetch('/api/chats/import', { | 8089 | const fetchResult = await fetch('/api/chats/import', { |
| 8085 | method: 'POST', | 8090 | method: 'POST', |
| 8086 | body: formData, | 8091 | body: formData, |
| 8087 | headers: headers, | 8092 | headers: getRequestHeaders({ omitContentType: true }), |
| 8088 | cache: 'no-cache', | 8093 | cache: 'no-cache', |
| 8089 | }); | 8094 | }); |
| 8090 | 8095 | ||
| @@ -8388,8 +8393,7 @@ async function createOrEditCharacter(e) { | |||
| 8388 | formData.set('avatar', convertedFile); | 8393 | formData.set('avatar', convertedFile); |
| 8389 | } | 8394 | } |
| 8390 | 8395 | ||
| 8391 | const headers = getRequestHeaders(); | 8396 | const headers = getRequestHeaders({ omitContentType: true }); |
| 8392 | delete headers['Content-Type']; | ||
| 8393 | 8397 | ||
| 8394 | if ($('#form_create').attr('actiontype') == 'createcharacter') { | 8398 | if ($('#form_create').attr('actiontype') == 'createcharacter') { |
| 8395 | if (String($('#character_name_pole').val()).length === 0) { | 8399 | if (String($('#character_name_pole').val()).length === 0) { |
| @@ -9013,32 +9017,38 @@ async function importCharacter(file, { preserveFileName = '', importTags = false | |||
| 9013 | formData.append('file_type', format); | 9017 | formData.append('file_type', format); |
| 9014 | if (preserveFileName) formData.append('preserved_name', preserveFileName); | 9018 | if (preserveFileName) formData.append('preserved_name', preserveFileName); |
| 9015 | 9019 | ||
| 9016 | const data = await jQuery.ajax({ | 9020 | try { |
| 9017 | type: 'POST', | 9021 | const result = await fetch('/api/characters/import', { |
| 9018 | url: '/api/characters/import', | 9022 | method: 'POST', |
| 9019 | data: formData, | 9023 | body: formData, |
| 9020 | async: true, | 9024 | headers: getRequestHeaders({ omitContentType: true }), |
| 9021 | cache: false, | 9025 | cache: 'no-cache', |
| 9022 | contentType: false, | 9026 | }); |
| 9023 | processData: false, | ||
| 9024 | }); | ||
| 9025 | 9027 | ||
| 9026 | if (data.error) { | 9028 | if (!result.ok) { |
| 9027 | toastr.error(t`The file is likely invalid or corrupted.`, t`Could not import character`); | 9029 | throw new Error(`Failed to import character: ${result.statusText}`); |
| 9028 | return; | 9030 | } |
| 9029 | } | ||
| 9030 | 9031 | ||
| 9031 | if (data.file_name !== undefined) { | 9032 | const data = await result.json(); |
| 9032 | $('#character_search_bar').val('').trigger('input'); | ||
| 9033 | 9033 | ||
| 9034 | toastr.success(t`Character Created: ${String(data.file_name).replace('.png', '')}`); | 9034 | if (data.error) { |
| 9035 | let avatarFileName = `${data.file_name}.png`; | 9035 | throw new Error(`Server returned an error: ${data.error}`); |
| 9036 | if (importTags) { | 9036 | } |
| 9037 | await importCharactersTags([avatarFileName]); | ||
| 9038 | 9037 | ||
| 9039 | selectImportedChar(data.file_name); | 9038 | if (data.file_name !== undefined) { |
| 9039 | $('#character_search_bar').val('').trigger('input'); | ||
| 9040 | |||
| 9041 | toastr.success(t`Character Created: ${String(data.file_name).replace('.png', '')}`); | ||
| 9042 | let avatarFileName = `${data.file_name}.png`; | ||
| 9043 | if (importTags) { | ||
| 9044 | await importCharactersTags([avatarFileName]); | ||
| 9045 | selectImportedChar(data.file_name); | ||
| 9046 | } | ||
| 9047 | return avatarFileName; | ||
| 9040 | } | 9048 | } |
| 9041 | return avatarFileName; | 9049 | } catch (error) { |
| 9050 | console.error('Error importing character', error); | ||
| 9051 | toastr.error(t`The file is likely invalid or corrupted.`, t`Could not import character`); | ||
| 9042 | } | 9052 | } |
| 9043 | } | 9053 | } |
| 9044 | 9054 | ||
| @@ -636,12 +636,9 @@ async function uploadBackground(formData) { | |||
| 636 | return; | 636 | return; |
| 637 | } | 637 | } |
| 638 | 638 | ||
| 639 | const headers = getRequestHeaders(); | ||
| 640 | delete headers['Content-Type']; | ||
| 641 | |||
| 642 | const response = await fetch('/api/backgrounds/upload', { | 639 | const response = await fetch('/api/backgrounds/upload', { |
| 643 | method: 'POST', | 640 | method: 'POST', |
| 644 | headers: headers, | 641 | headers: getRequestHeaders({ omitContentType: true }), |
| 645 | body: formData, | 642 | body: formData, |
| 646 | cache: 'no-cache', | 643 | cache: 'no-cache', |
| 647 | }); | 644 | }); |
| @@ -1758,27 +1758,38 @@ async function onExpressionFallbackChanged() { | |||
| 1758 | saveSettingsDebounced(); | 1758 | saveSettingsDebounced(); |
| 1759 | } | 1759 | } |
| 1760 | 1760 | ||
| 1761 | /** | ||
| 1762 | * Handles the file upload process for a sprite image. | ||
| 1763 | * @param {string} url URL to upload the file to | ||
| 1764 | * @param {FormData} formData FormData object containing the file and other data to upload | ||
| 1765 | * @returns {Promise<any>} - The response data from the server | ||
| 1766 | */ | ||
| 1761 | async function handleFileUpload(url, formData) { | 1767 | async function handleFileUpload(url, formData) { |
| 1762 | try { | 1768 | try { |
| 1763 | const data = await jQuery.ajax({ | 1769 | const result = await fetch(url, { |
| 1764 | type: 'POST', | 1770 | method: 'POST', |
| 1765 | url: url, | 1771 | headers: getRequestHeaders({ omitContentType: true }), |
| 1766 | data: formData, | 1772 | body: formData, |
| 1767 | beforeSend: function () { }, | 1773 | cache: 'no-cache', |
| 1768 | cache: false, | ||
| 1769 | contentType: false, | ||
| 1770 | processData: false, | ||
| 1771 | }); | 1774 | }); |
| 1772 | 1775 | ||
| 1776 | if (!result.ok) { | ||
| 1777 | throw new Error(`Upload failed with status ${result.status}`); | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | const data = await result.json(); | ||
| 1781 | |||
| 1773 | // Refresh sprites list | 1782 | // Refresh sprites list |
| 1774 | const name = formData.get('name'); | 1783 | const name = formData.get('name').toString(); |
| 1775 | delete spriteCache[name]; | 1784 | delete spriteCache[name]; |
| 1776 | await fetchImagesNoCache(); | 1785 | await fetchImagesNoCache(); |
| 1777 | await validateImages(name); | 1786 | await validateImages(name); |
| 1778 | 1787 | ||
| 1779 | return data; | 1788 | return data ?? {}; |
| 1780 | } catch (error) { | 1789 | } catch (error) { |
| 1790 | console.error('Error uploading image:', error); | ||
| 1781 | toastr.error('Failed to upload image'); | 1791 | toastr.error('Failed to upload image'); |
| 1792 | return {}; | ||
| 1782 | } | 1793 | } |
| 1783 | } | 1794 | } |
| 1784 | 1795 | ||
| @@ -1996,7 +2007,11 @@ async function onClickExpressionUploadPackButton() { | |||
| 1996 | const uploadToast = toastr.info('Please wait...', 'Upload is processing', { timeOut: 0, extendedTimeOut: 0 }); | 2007 | const uploadToast = toastr.info('Please wait...', 'Upload is processing', { timeOut: 0, extendedTimeOut: 0 }); |
| 1997 | const { count } = await handleFileUpload('/api/sprites/upload-zip', formData); | 2008 | const { count } = await handleFileUpload('/api/sprites/upload-zip', formData); |
| 1998 | toastr.clear(uploadToast); | 2009 | toastr.clear(uploadToast); |
| 1999 | toastr.success(`Uploaded ${count} image(s) for ${name}`); | 2010 | |
| 2011 | // Only show success message if at least one image was uploaded | ||
| 2012 | if (count) { | ||
| 2013 | toastr.success(`Uploaded ${count} image(s) for ${name}`); | ||
| 2014 | } | ||
| 2000 | 2015 | ||
| 2001 | // Reset the input | 2016 | // Reset the input |
| 2002 | e.target.form.reset(); | 2017 | e.target.form.reset(); |
| @@ -311,7 +311,7 @@ export function getGroupNames() { | |||
| 311 | * @returns {number|Object} 0-based character ID or key-value object if full is true | 311 | * @returns {number|Object} 0-based character ID or key-value object if full is true |
| 312 | */ | 312 | */ |
| 313 | export function findGroupMemberId(arg, full = false) { | 313 | export function findGroupMemberId(arg, full = false) { |
| 314 | arg = arg?.trim(); | 314 | arg = arg?.toString()?.trim(); |
| 315 | 315 | ||
| 316 | if (!arg) { | 316 | if (!arg) { |
| 317 | console.warn('WARN: No argument provided for findGroupMemberId'); | 317 | console.warn('WARN: No argument provided for findGroupMemberId'); |
| @@ -1358,7 +1358,7 @@ function isGroupMember(group, avatarId) { | |||
| 1358 | } | 1358 | } |
| 1359 | } | 1359 | } |
| 1360 | 1360 | ||
| 1361 | function getGroupCharacters({ doFilter, onlyMembers } = {}) { | 1361 | function getGroupCharacters({ doFilter = false, onlyMembers = false } = {}) { |
| 1362 | function sortMembersFn(a, b) { | 1362 | function sortMembersFn(a, b) { |
| 1363 | const membersArray = thisGroup?.members ?? newGroupMembers; | 1363 | const membersArray = thisGroup?.members ?? newGroupMembers; |
| 1364 | const aIndex = membersArray.indexOf(a.item.avatar); | 1364 | const aIndex = membersArray.indexOf(a.item.avatar); |
| @@ -1757,7 +1757,7 @@ async function onGroupActionClick(event) { | |||
| 1757 | 1757 | ||
| 1758 | function updateFavButtonState(state) { | 1758 | function updateFavButtonState(state) { |
| 1759 | fav_grp_checked = state; | 1759 | fav_grp_checked = state; |
| 1760 | $('#rm_group_fav').val(fav_grp_checked); | 1760 | $('#rm_group_fav').val(String(fav_grp_checked)); |
| 1761 | $('#group_favorite_button').toggleClass('fav_on', fav_grp_checked); | 1761 | $('#group_favorite_button').toggleClass('fav_on', fav_grp_checked); |
| 1762 | $('#group_favorite_button').toggleClass('fav_off', !fav_grp_checked); | 1762 | $('#group_favorite_button').toggleClass('fav_off', !fav_grp_checked); |
| 1763 | } | 1763 | } |
| @@ -2047,11 +2047,9 @@ export async function deleteGroupChat(groupId, chatId) { | |||
| 2047 | * @param {EventTarget} eventTarget Element that triggered the import | 2047 | * @param {EventTarget} eventTarget Element that triggered the import |
| 2048 | */ | 2048 | */ |
| 2049 | export async function importGroupChat(formData, eventTarget) { | 2049 | export async function importGroupChat(formData, eventTarget) { |
| 2050 | const headers = getRequestHeaders(); | ||
| 2051 | delete headers['Content-Type']; | ||
| 2052 | const fetchResult = await fetch('/api/chats/group/import', { | 2050 | const fetchResult = await fetch('/api/chats/group/import', { |
| 2053 | method: 'POST', | 2051 | method: 'POST', |
| 2054 | headers: headers, | 2052 | headers: getRequestHeaders({ omitContentType: true }), |
| 2055 | body: formData, | 2053 | body: formData, |
| 2056 | cache: 'no-cache', | 2054 | cache: 'no-cache', |
| 2057 | }); | 2055 | }); |
| @@ -317,12 +317,9 @@ async function uploadUserAvatar(url, name) { | |||
| 317 | formData.append('overwrite_name', name); | 317 | formData.append('overwrite_name', name); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | const headers = getRequestHeaders(); | ||
| 321 | delete headers['Content-Type']; | ||
| 322 | |||
| 323 | await fetch('/api/avatars/upload', { | 320 | await fetch('/api/avatars/upload', { |
| 324 | method: 'POST', | 321 | method: 'POST', |
| 325 | headers: headers, | 322 | headers: getRequestHeaders({ omitContentType: true }), |
| 326 | cache: 'no-cache', | 323 | cache: 'no-cache', |
| 327 | body: formData, | 324 | body: formData, |
| 328 | }); | 325 | }); |
| @@ -368,12 +365,9 @@ async function changeUserAvatar(e) { | |||
| 368 | formData.set('avatar', convertedFile); | 365 | formData.set('avatar', convertedFile); |
| 369 | } | 366 | } |
| 370 | 367 | ||
| 371 | const headers = getRequestHeaders(); | ||
| 372 | delete headers['Content-Type']; | ||
| 373 | |||
| 374 | const response = await fetch(url, { | 368 | const response = await fetch(url, { |
| 375 | method: 'POST', | 369 | method: 'POST', |
| 376 | headers: headers, | 370 | headers: getRequestHeaders({ omitContentType:true }), |
| 377 | cache: 'no-cache', | 371 | cache: 'no-cache', |
| 378 | body: formData, | 372 | body: formData, |
| 379 | }); | 373 | }); |
| @@ -61,18 +61,6 @@ import { accountStorage } from './util/AccountStorage.js'; | |||
| 61 | import { DEFAULT_REASONING_TEMPLATE, loadReasoningTemplates } from './reasoning.js'; | 61 | import { DEFAULT_REASONING_TEMPLATE, loadReasoningTemplates } from './reasoning.js'; |
| 62 | import { bindModelTemplates } from './chat-templates.js'; | 62 | import { bindModelTemplates } from './chat-templates.js'; |
| 63 | 63 | ||
| 64 | export { | ||
| 65 | loadPowerUserSettings, | ||
| 66 | loadMovingUIState, | ||
| 67 | collapseNewlines, | ||
| 68 | playMessageSound, | ||
| 69 | fixMarkdown, | ||
| 70 | power_user, | ||
| 71 | send_on_enter_options, | ||
| 72 | getContextSettings, | ||
| 73 | applyPowerUserSettings, | ||
| 74 | }; | ||
| 75 | |||
| 76 | export const toastPositionClasses = [ | 64 | export const toastPositionClasses = [ |
| 77 | 'toast-top-left', | 65 | 'toast-top-left', |
| 78 | 'toast-top-center', | 66 | 'toast-top-center', |
| @@ -108,7 +96,7 @@ export const chat_styles = { | |||
| 108 | DOCUMENT: 2, | 96 | DOCUMENT: 2, |
| 109 | }; | 97 | }; |
| 110 | 98 | ||
| 111 | const send_on_enter_options = { | 99 | export const send_on_enter_options = { |
| 112 | DISABLED: -1, | 100 | DISABLED: -1, |
| 113 | AUTO: 0, | 101 | AUTO: 0, |
| 114 | ENABLED: 1, | 102 | ENABLED: 1, |
| @@ -126,7 +114,7 @@ export const persona_description_positions = { | |||
| 126 | NONE: 9, | 114 | NONE: 9, |
| 127 | }; | 115 | }; |
| 128 | 116 | ||
| 129 | let power_user = { | 117 | export const power_user = { |
| 130 | charListGrid: false, | 118 | charListGrid: false, |
| 131 | tokenizer: tokenizers.BEST_MATCH, | 119 | tokenizer: tokenizers.BEST_MATCH, |
| 132 | token_padding: 64, | 120 | token_padding: 64, |
| @@ -370,7 +358,7 @@ const debug_functions = []; | |||
| 370 | 358 | ||
| 371 | const setHotswapsDebounced = debounce(favsToHotswap); | 359 | const setHotswapsDebounced = debounce(favsToHotswap); |
| 372 | 360 | ||
| 373 | function playMessageSound() { | 361 | export function playMessageSound() { |
| 374 | if (!power_user.play_message_sound) { | 362 | if (!power_user.play_message_sound) { |
| 375 | return; | 363 | return; |
| 376 | } | 364 | } |
| @@ -395,7 +383,7 @@ function playMessageSound() { | |||
| 395 | * @example | 383 | * @example |
| 396 | * collapseNewlines("\n\n\n"); // "\n" | 384 | * collapseNewlines("\n\n\n"); // "\n" |
| 397 | */ | 385 | */ |
| 398 | function collapseNewlines(x) { | 386 | export function collapseNewlines(x) { |
| 399 | return x.replaceAll(/\n+/g, '\n'); | 387 | return x.replaceAll(/\n+/g, '\n'); |
| 400 | } | 388 | } |
| 401 | 389 | ||
| @@ -416,7 +404,7 @@ function collapseNewlines(x) { | |||
| 416 | * // and you HAVE to handle the cases where multiple pairs of asterisks exist in the same line | 404 | * // and you HAVE to handle the cases where multiple pairs of asterisks exist in the same line |
| 417 | * "^example * text* * harder problem *\n" // "^example *text* *harder problem*\n" | 405 | * "^example * text* * harder problem *\n" // "^example *text* *harder problem*\n" |
| 418 | */ | 406 | */ |
| 419 | function fixMarkdown(text, forDisplay) { | 407 | export function fixMarkdown(text, forDisplay) { |
| 420 | // Find pairs of formatting characters and capture the text in between them | 408 | // Find pairs of formatting characters and capture the text in between them |
| 421 | const format = /([*_]{1,2})([\s\S]*?)\1/gm; | 409 | const format = /([*_]{1,2})([\s\S]*?)\1/gm; |
| 422 | let matches = []; | 410 | let matches = []; |
| @@ -862,13 +850,13 @@ async function CreateZenSliders(elmnt) { | |||
| 862 | }) | 850 | }) |
| 863 | //trigger slider changes when user clicks away | 851 | //trigger slider changes when user clicks away |
| 864 | .on('mouseup blur', function () { | 852 | .on('mouseup blur', function () { |
| 865 | let manualInput = parseFloat(handle.text()).toFixed(decimals); | 853 | let manualInput = parseFloat(parseFloat(handle.text()).toFixed(decimals)); |
| 866 | if (isManualInput) { | 854 | if (isManualInput) { |
| 867 | //disallow manual inputs outside acceptable range | 855 | //disallow manual inputs outside acceptable range |
| 868 | if (manualInput >= sliderMin && manualInput <= sliderMax) { | 856 | if (manualInput >= sliderMin && manualInput <= sliderMax) { |
| 869 | //if value is ok, assign to slider and update handle text and position | 857 | //if value is ok, assign to slider and update handle text and position |
| 870 | newSlider.val(manualInput); | 858 | newSlider.val(manualInput); |
| 871 | handleSlideEvent.call(newSlider, null, { value: parseFloat(manualInput) }, 'manual'); | 859 | handleSlideEvent.call(newSlider, null, { value: manualInput }, 'manual'); |
| 872 | valueBeforeManualInput = manualInput; | 860 | valueBeforeManualInput = manualInput; |
| 873 | } else { | 861 | } else { |
| 874 | //if value not ok, warn and reset to last known valid value | 862 | //if value not ok, warn and reset to last known valid value |
| @@ -890,13 +878,13 @@ async function CreateZenSliders(elmnt) { | |||
| 890 | 878 | ||
| 891 | function handleSlideEvent(event, ui, type) { | 879 | function handleSlideEvent(event, ui, type) { |
| 892 | var handle = $(this).find('.ui-slider-handle'); | 880 | var handle = $(this).find('.ui-slider-handle'); |
| 893 | var numVal = Number(ui.value).toFixed(decimals); | 881 | var numVal = parseFloat(Number(ui.value).toFixed(decimals)); |
| 894 | offVal = Number(offVal).toFixed(decimals); | 882 | offVal = parseFloat(Number(offVal).toFixed(decimals)); |
| 895 | allVal = Number(allVal).toFixed(decimals); | 883 | allVal = parseFloat(Number(allVal).toFixed(decimals)); |
| 896 | console.log(numVal, sliderMin, sliderMax, numVal > sliderMax, numVal < sliderMin); | 884 | console.log(numVal, sliderMin, sliderMax, numVal > sliderMax, numVal < sliderMin); |
| 897 | if (numVal > sliderMax) { numVal = sliderMax; } | 885 | if (numVal > sliderMax) { numVal = sliderMax; } |
| 898 | if (numVal < sliderMin) { numVal = sliderMin; } | 886 | if (numVal < sliderMin) { numVal = sliderMin; } |
| 899 | var stepNumber = ((ui.value - sliderMin) / stepScale).toFixed(0); | 887 | var stepNumber = parseFloat(((ui.value - sliderMin) / stepScale).toFixed(0)); |
| 900 | var handleText = (ui.value); | 888 | var handleText = (ui.value); |
| 901 | var leftMargin = (stepNumber / numSteps) * 50 * -1; | 889 | var leftMargin = (stepNumber / numSteps) * 50 * -1; |
| 902 | var perStepPercent = 1 / numSteps; //how far in % each step should be on the slider | 890 | var perStepPercent = 1 / numSteps; //how far in % each step should be on the slider |
| @@ -1035,10 +1023,9 @@ function applyAvatarStyle() { | |||
| 1035 | } | 1023 | } |
| 1036 | 1024 | ||
| 1037 | function applyChatDisplay() { | 1025 | function applyChatDisplay() { |
| 1038 | 1026 | if ([null, undefined].includes(power_user.chat_display)) { | |
| 1039 | if (!power_user.chat_display === (null || undefined)) { | ||
| 1040 | console.debug('applyChatDisplay: saw no chat display type defined'); | 1027 | console.debug('applyChatDisplay: saw no chat display type defined'); |
| 1041 | return; | 1028 | power_user.chat_display = chat_styles.DEFAULT; |
| 1042 | } | 1029 | } |
| 1043 | console.debug(`poweruser.chat_display ${power_user.chat_display}`); | 1030 | console.debug(`poweruser.chat_display ${power_user.chat_display}`); |
| 1044 | $('#chat_display').val(power_user.chat_display).prop('selected', true); | 1031 | $('#chat_display').val(power_user.chat_display).prop('selected', true); |
| @@ -1417,7 +1404,7 @@ async function showDebugMenu() { | |||
| 1417 | callGenericPopup(template, POPUP_TYPE.TEXT, '', { wide: true, large: true, allowVerticalScrolling: true }); | 1404 | callGenericPopup(template, POPUP_TYPE.TEXT, '', { wide: true, large: true, allowVerticalScrolling: true }); |
| 1418 | } | 1405 | } |
| 1419 | 1406 | ||
| 1420 | function applyPowerUserSettings() { | 1407 | export function applyPowerUserSettings() { |
| 1421 | switchUiMode(); | 1408 | switchUiMode(); |
| 1422 | applyFontScale('forced'); | 1409 | applyFontScale('forced'); |
| 1423 | applyThemeColor(); | 1410 | applyThemeColor(); |
| @@ -1496,7 +1483,7 @@ function getExampleMessagesBehavior() { | |||
| 1496 | } | 1483 | } |
| 1497 | 1484 | ||
| 1498 | //MARK: loadPowerUser | 1485 | //MARK: loadPowerUser |
| 1499 | async function loadPowerUserSettings(settings, data) { | 1486 | export async function loadPowerUserSettings(settings, data) { |
| 1500 | const defaultStscript = JSON.parse(JSON.stringify(power_user.stscript)); | 1487 | const defaultStscript = JSON.parse(JSON.stringify(power_user.stscript)); |
| 1501 | // Load from settings.json | 1488 | // Load from settings.json |
| 1502 | if (settings.power_user !== undefined) { | 1489 | if (settings.power_user !== undefined) { |
| @@ -1552,15 +1539,15 @@ async function loadPowerUserSettings(settings, data) { | |||
| 1552 | context_presets = data.context; | 1539 | context_presets = data.context; |
| 1553 | } | 1540 | } |
| 1554 | 1541 | ||
| 1555 | if (power_user.chat_display === '') { | 1542 | if (typeof power_user.chat_display !== 'number') { |
| 1556 | power_user.chat_display = chat_styles.DEFAULT; | 1543 | power_user.chat_display = chat_styles.DEFAULT; |
| 1557 | } | 1544 | } |
| 1558 | 1545 | ||
| 1559 | if (power_user.waifuMode === '') { | 1546 | if (typeof power_user.waifuMode !== 'boolean') { |
| 1560 | power_user.waifuMode = false; | 1547 | power_user.waifuMode = false; |
| 1561 | } | 1548 | } |
| 1562 | 1549 | ||
| 1563 | if (power_user.chat_width === '') { | 1550 | if (typeof power_user.chat_width !== 'number') { |
| 1564 | power_user.chat_width = 50; | 1551 | power_user.chat_width = 50; |
| 1565 | } | 1552 | } |
| 1566 | 1553 | ||
| @@ -1618,8 +1605,8 @@ async function loadPowerUserSettings(settings, data) { | |||
| 1618 | $('#auto_scroll_chat_to_bottom').prop('checked', power_user.auto_scroll_chat_to_bottom); | 1605 | $('#auto_scroll_chat_to_bottom').prop('checked', power_user.auto_scroll_chat_to_bottom); |
| 1619 | $('#bogus_folders').prop('checked', power_user.bogus_folders); | 1606 | $('#bogus_folders').prop('checked', power_user.bogus_folders); |
| 1620 | $('#zoomed_avatar_magnification').prop('checked', power_user.zoomed_avatar_magnification); | 1607 | $('#zoomed_avatar_magnification').prop('checked', power_user.zoomed_avatar_magnification); |
| 1621 | $(`#tokenizer option[value="${power_user.tokenizer}"]`).attr('selected', true); | 1608 | $(`#tokenizer option[value="${power_user.tokenizer}"]`).prop('selected', true); |
| 1622 | $(`#send_on_enter option[value=${power_user.send_on_enter}]`).attr('selected', true); | 1609 | $(`#send_on_enter option[value=${power_user.send_on_enter}]`).prop('selected', true); |
| 1623 | $('#confirm_message_delete').prop('checked', power_user.confirm_message_delete !== undefined ? !!power_user.confirm_message_delete : true); | 1610 | $('#confirm_message_delete').prop('checked', power_user.confirm_message_delete !== undefined ? !!power_user.confirm_message_delete : true); |
| 1624 | $('#spoiler_free_mode').prop('checked', power_user.spoiler_free_mode); | 1611 | $('#spoiler_free_mode').prop('checked', power_user.spoiler_free_mode); |
| 1625 | $('#collapse-newlines-checkbox').prop('checked', power_user.collapse_newlines); | 1612 | $('#collapse-newlines-checkbox').prop('checked', power_user.collapse_newlines); |
| @@ -1655,8 +1642,8 @@ async function loadPowerUserSettings(settings, data) { | |||
| 1655 | $('#enableZenSliders').prop('checked', power_user.enableZenSliders).trigger('input'); | 1642 | $('#enableZenSliders').prop('checked', power_user.enableZenSliders).trigger('input'); |
| 1656 | $('#enableLabMode').prop('checked', power_user.enableLabMode).trigger('input', { fromInit: true }); | 1643 | $('#enableLabMode').prop('checked', power_user.enableLabMode).trigger('input', { fromInit: true }); |
| 1657 | $(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop('checked', true); | 1644 | $(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop('checked', true); |
| 1658 | $(`#chat_display option[value=${power_user.chat_display}]`).attr('selected', true).trigger('change'); | 1645 | $(`#chat_display option[value=${power_user.chat_display}]`).prop('selected', true).trigger('change'); |
| 1659 | $(`#toastr_position option[value=${power_user.toastr_position}]`).attr('selected', true).trigger('change'); | 1646 | $(`#toastr_position option[value=${power_user.toastr_position}]`).prop('selected', true).trigger('change'); |
| 1660 | $('#chat_width_slider').val(power_user.chat_width); | 1647 | $('#chat_width_slider').val(power_user.chat_width); |
| 1661 | $('#token_padding').val(power_user.token_padding); | 1648 | $('#token_padding').val(power_user.token_padding); |
| 1662 | $('#aux_field').val(power_user.aux_field); | 1649 | $('#aux_field').val(power_user.aux_field); |
| @@ -1763,7 +1750,7 @@ function loadCharListState() { | |||
| 1763 | document.body.classList.toggle('charListGrid', power_user.charListGrid); | 1750 | document.body.classList.toggle('charListGrid', power_user.charListGrid); |
| 1764 | } | 1751 | } |
| 1765 | 1752 | ||
| 1766 | function loadMovingUIState() { | 1753 | export function loadMovingUIState() { |
| 1767 | if (!isMobile() | 1754 | if (!isMobile() |
| 1768 | && power_user.movingUIState | 1755 | && power_user.movingUIState |
| 1769 | && power_user.movingUI === true) { | 1756 | && power_user.movingUI === true) { |
| @@ -1853,7 +1840,7 @@ function switchMaxContextSize() { | |||
| 1853 | } | 1840 | } |
| 1854 | 1841 | ||
| 1855 | // Fetch a compiled object of all preset settings | 1842 | // Fetch a compiled object of all preset settings |
| 1856 | function getContextSettings() { | 1843 | export function getContextSettings() { |
| 1857 | let compiledSettings = {}; | 1844 | let compiledSettings = {}; |
| 1858 | 1845 | ||
| 1859 | contextControls.forEach((control) => { | 1846 | contextControls.forEach((control) => { |
| @@ -2397,7 +2384,7 @@ async function saveTheme(name = undefined, theme = undefined) { | |||
| 2397 | } | 2384 | } |
| 2398 | else { | 2385 | else { |
| 2399 | themes[themeIndex] = theme; | 2386 | themes[themeIndex] = theme; |
| 2400 | $(`#themes option[value="${name}"]`).attr('selected', true); | 2387 | $(`#themes option[value="${name}"]`).prop('selected', true); |
| 2401 | } | 2388 | } |
| 2402 | 2389 | ||
| 2403 | power_user.theme = name; | 2390 | power_user.theme = name; |
| @@ -2504,7 +2491,7 @@ async function saveMovingUI() { | |||
| 2504 | } | 2491 | } |
| 2505 | else { | 2492 | else { |
| 2506 | movingUIPresets[movingUIPresetIndex] = movingUIPreset; | 2493 | movingUIPresets[movingUIPresetIndex] = movingUIPreset; |
| 2507 | $(`#movingUIPresets option[value="${name}"]`).attr('selected', true); | 2494 | $(`#movingUIPresets option[value="${name}"]`).prop('selected', true); |
| 2508 | } | 2495 | } |
| 2509 | 2496 | ||
| 2510 | power_user.movingUIPreset = name; | 2497 | power_user.movingUIPreset = name; |
| @@ -3162,7 +3149,7 @@ jQuery(() => { | |||
| 3162 | }); | 3149 | }); |
| 3163 | 3150 | ||
| 3164 | const reportZoomLevelDebounced = debounce(() => { | 3151 | const reportZoomLevelDebounced = debounce(() => { |
| 3165 | const zoomLevel = Number(window.devicePixelRatio).toFixed(2) || 1; | 3152 | const zoomLevel = parseFloat(Number(window.devicePixelRatio).toFixed(2)) || 1; |
| 3166 | const winWidth = window.innerWidth; | 3153 | const winWidth = window.innerWidth; |
| 3167 | const winHeight = window.innerHeight; | 3154 | const winHeight = window.innerHeight; |
| 3168 | const originalWidth = winWidth * zoomLevel; | 3155 | const originalWidth = winWidth * zoomLevel; |
| @@ -3187,8 +3174,8 @@ jQuery(() => { | |||
| 3187 | 3174 | ||
| 3188 | //attempt to scale movingUI elements naturally across window resizing/zooms | 3175 | //attempt to scale movingUI elements naturally across window resizing/zooms |
| 3189 | //this will still break if the zoom level causes mobile styles to come into play. | 3176 | //this will still break if the zoom level causes mobile styles to come into play. |
| 3190 | const scaleY = Number(window.innerHeight / coreTruthWinHeight).toFixed(4); | 3177 | const scaleY = parseFloat(Number(window.innerHeight / coreTruthWinHeight).toFixed(4)); |
| 3191 | const scaleX = Number(window.innerWidth / coreTruthWinWidth).toFixed(4); | 3178 | const scaleX = parseFloat(Number(window.innerWidth / coreTruthWinWidth).toFixed(4)); |
| 3192 | 3179 | ||
| 3193 | if (Object.keys(power_user.movingUIState).length > 0) { | 3180 | if (Object.keys(power_user.movingUIState).length > 0) { |
| 3194 | for (var elmntName of Object.keys(power_user.movingUIState)) { | 3181 | for (var elmntName of Object.keys(power_user.movingUIState)) { |
| @@ -3362,7 +3349,7 @@ jQuery(() => { | |||
| 3362 | }); | 3349 | }); |
| 3363 | 3350 | ||
| 3364 | $('#waifuMode').on('change', () => { | 3351 | $('#waifuMode').on('change', () => { |
| 3365 | power_user.waifuMode = $('#waifuMode').prop('checked'); | 3352 | power_user.waifuMode = !!$('#waifuMode').prop('checked'); |
| 3366 | switchWaifuMode(); | 3353 | switchWaifuMode(); |
| 3367 | saveSettingsDebounced(); | 3354 | saveSettingsDebounced(); |
| 3368 | }); | 3355 | }); |
| @@ -3410,7 +3397,7 @@ jQuery(() => { | |||
| 3410 | 3397 | ||
| 3411 | $('#chat_width_slider').on('input', function (e, data) { | 3398 | $('#chat_width_slider').on('input', function (e, data) { |
| 3412 | const applyMode = data?.forced ? 'forced' : 'normal'; | 3399 | const applyMode = data?.forced ? 'forced' : 'normal'; |
| 3413 | power_user.chat_width = Number(e.target.value); | 3400 | power_user.chat_width = Number($(this).val()); |
| 3414 | applyChatWidth(applyMode); | 3401 | applyChatWidth(applyMode); |
| 3415 | saveSettingsDebounced(); | 3402 | saveSettingsDebounced(); |
| 3416 | setHotswapsDebounced(); | 3403 | setHotswapsDebounced(); |
| @@ -3440,81 +3427,81 @@ jQuery(() => { | |||
| 3440 | 3427 | ||
| 3441 | $('input[name="font_scale"]').on('input', async function (e, data) { | 3428 | $('input[name="font_scale"]').on('input', async function (e, data) { |
| 3442 | const applyMode = data?.forced ? 'forced' : 'normal'; | 3429 | const applyMode = data?.forced ? 'forced' : 'normal'; |
| 3443 | power_user.font_scale = Number(e.target.value); | 3430 | power_user.font_scale = Number($(this).val()); |
| 3444 | $('#font_scale_counter').val(power_user.font_scale); | 3431 | $('#font_scale_counter').val(power_user.font_scale); |
| 3445 | applyFontScale(applyMode); | 3432 | applyFontScale(applyMode); |
| 3446 | saveSettingsDebounced(); | 3433 | saveSettingsDebounced(); |
| 3447 | }); | 3434 | }); |
| 3448 | 3435 | ||
| 3449 | $('input[name="blur_strength"]').on('input', async function (e) { | 3436 | $('input[name="blur_strength"]').on('input', async function (e) { |
| 3450 | power_user.blur_strength = Number(e.target.value); | 3437 | power_user.blur_strength = Number($(this).val()); |
| 3451 | $('#blur_strength_counter').val(power_user.blur_strength); | 3438 | $('#blur_strength_counter').val(power_user.blur_strength); |
| 3452 | applyBlurStrength(); | 3439 | applyBlurStrength(); |
| 3453 | saveSettingsDebounced(); | 3440 | saveSettingsDebounced(); |
| 3454 | }); | 3441 | }); |
| 3455 | 3442 | ||
| 3456 | $('input[name="shadow_width"]').on('input', async function (e) { | 3443 | $('input[name="shadow_width"]').on('input', async function (e) { |
| 3457 | power_user.shadow_width = Number(e.target.value); | 3444 | power_user.shadow_width = Number($(this).val()); |
| 3458 | $('#shadow_width_counter').val(power_user.shadow_width); | 3445 | $('#shadow_width_counter').val(power_user.shadow_width); |
| 3459 | applyShadowWidth(); | 3446 | applyShadowWidth(); |
| 3460 | saveSettingsDebounced(); | 3447 | saveSettingsDebounced(); |
| 3461 | }); | 3448 | }); |
| 3462 | 3449 | ||
| 3463 | $('#main-text-color-picker').on('change', (evt) => { | 3450 | $('#main-text-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3464 | power_user.main_text_color = evt.detail.rgba; | 3451 | power_user.main_text_color = evt.detail.rgba; |
| 3465 | applyThemeColor('main'); | 3452 | applyThemeColor('main'); |
| 3466 | saveSettingsDebounced(); | 3453 | saveSettingsDebounced(); |
| 3467 | }); | 3454 | }); |
| 3468 | 3455 | ||
| 3469 | $('#italics-color-picker').on('change', (evt) => { | 3456 | $('#italics-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3470 | power_user.italics_text_color = evt.detail.rgba; | 3457 | power_user.italics_text_color = evt.detail.rgba; |
| 3471 | applyThemeColor('italics'); | 3458 | applyThemeColor('italics'); |
| 3472 | saveSettingsDebounced(); | 3459 | saveSettingsDebounced(); |
| 3473 | }); | 3460 | }); |
| 3474 | 3461 | ||
| 3475 | $('#underline-color-picker').on('change', (evt) => { | 3462 | $('#underline-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3476 | power_user.underline_text_color = evt.detail.rgba; | 3463 | power_user.underline_text_color = evt.detail.rgba; |
| 3477 | applyThemeColor('underline'); | 3464 | applyThemeColor('underline'); |
| 3478 | saveSettingsDebounced(); | 3465 | saveSettingsDebounced(); |
| 3479 | }); | 3466 | }); |
| 3480 | 3467 | ||
| 3481 | $('#quote-color-picker').on('change', (evt) => { | 3468 | $('#quote-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3482 | power_user.quote_text_color = evt.detail.rgba; | 3469 | power_user.quote_text_color = evt.detail.rgba; |
| 3483 | applyThemeColor('quote'); | 3470 | applyThemeColor('quote'); |
| 3484 | saveSettingsDebounced(); | 3471 | saveSettingsDebounced(); |
| 3485 | }); | 3472 | }); |
| 3486 | 3473 | ||
| 3487 | $('#blur-tint-color-picker').on('change', (evt) => { | 3474 | $('#blur-tint-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3488 | power_user.blur_tint_color = evt.detail.rgba; | 3475 | power_user.blur_tint_color = evt.detail.rgba; |
| 3489 | applyThemeColor('blurTint'); | 3476 | applyThemeColor('blurTint'); |
| 3490 | saveSettingsDebounced(); | 3477 | saveSettingsDebounced(); |
| 3491 | }); | 3478 | }); |
| 3492 | 3479 | ||
| 3493 | $('#chat-tint-color-picker').on('change', (evt) => { | 3480 | $('#chat-tint-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3494 | power_user.chat_tint_color = evt.detail.rgba; | 3481 | power_user.chat_tint_color = evt.detail.rgba; |
| 3495 | applyThemeColor('chatTint'); | 3482 | applyThemeColor('chatTint'); |
| 3496 | saveSettingsDebounced(); | 3483 | saveSettingsDebounced(); |
| 3497 | }); | 3484 | }); |
| 3498 | 3485 | ||
| 3499 | $('#user-mes-blur-tint-color-picker').on('change', (evt) => { | 3486 | $('#user-mes-blur-tint-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3500 | power_user.user_mes_blur_tint_color = evt.detail.rgba; | 3487 | power_user.user_mes_blur_tint_color = evt.detail.rgba; |
| 3501 | applyThemeColor('userMesBlurTint'); | 3488 | applyThemeColor('userMesBlurTint'); |
| 3502 | saveSettingsDebounced(); | 3489 | saveSettingsDebounced(); |
| 3503 | }); | 3490 | }); |
| 3504 | 3491 | ||
| 3505 | $('#bot-mes-blur-tint-color-picker').on('change', (evt) => { | 3492 | $('#bot-mes-blur-tint-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3506 | power_user.bot_mes_blur_tint_color = evt.detail.rgba; | 3493 | power_user.bot_mes_blur_tint_color = evt.detail.rgba; |
| 3507 | applyThemeColor('botMesBlurTint'); | 3494 | applyThemeColor('botMesBlurTint'); |
| 3508 | saveSettingsDebounced(); | 3495 | saveSettingsDebounced(); |
| 3509 | }); | 3496 | }); |
| 3510 | 3497 | ||
| 3511 | $('#shadow-color-picker').on('change', (evt) => { | 3498 | $('#shadow-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3512 | power_user.shadow_color = evt.detail.rgba; | 3499 | power_user.shadow_color = evt.detail.rgba; |
| 3513 | applyThemeColor('shadow'); | 3500 | applyThemeColor('shadow'); |
| 3514 | saveSettingsDebounced(); | 3501 | saveSettingsDebounced(); |
| 3515 | }); | 3502 | }); |
| 3516 | 3503 | ||
| 3517 | $('#border-color-picker').on('change', (evt) => { | 3504 | $('#border-color-picker').on('change', (/** @type {ColorPickerEvent} */ evt) => { |
| 3518 | power_user.border_color = evt.detail.rgba; | 3505 | power_user.border_color = evt.detail.rgba; |
| 3519 | applyThemeColor('border'); | 3506 | applyThemeColor('border'); |
| 3520 | saveSettingsDebounced(); | 3507 | saveSettingsDebounced(); |
| @@ -577,12 +577,9 @@ async function createPermanentAssistant() { | |||
| 577 | console.warn('Error fetching system avatar. Fallback image will be used.', error); | 577 | console.warn('Error fetching system avatar. Fallback image will be used.', error); |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | const headers = getRequestHeaders(); | ||
| 581 | delete headers['Content-Type']; | ||
| 582 | |||
| 583 | const fetchResult = await fetch('/api/characters/create', { | 580 | const fetchResult = await fetch('/api/characters/create', { |
| 584 | method: 'POST', | 581 | method: 'POST', |
| 585 | headers: headers, | 582 | headers: getRequestHeaders({ omitContentType: true }), |
| 586 | body: formData, | 583 | body: formData, |
| 587 | cache: 'no-cache', | 584 | cache: 'no-cache', |
| 588 | }); | 585 | }); |
| @@ -5199,6 +5199,10 @@ export function onWorldInfoChange(args, text) { | |||
| 5199 | return ''; | 5199 | return ''; |
| 5200 | } | 5200 | } |
| 5201 | 5201 | ||
| 5202 | /** | ||
| 5203 | * Imports world info from a file. | ||
| 5204 | * @param {File} file File to import | ||
| 5205 | */ | ||
| 5202 | export async function importWorldInfo(file) { | 5206 | export async function importWorldInfo(file) { |
| 5203 | if (!file) { | 5207 | if (!file) { |
| 5204 | return; | 5208 | return; |
| @@ -5252,28 +5256,34 @@ export async function importWorldInfo(file) { | |||
| 5252 | return false; | 5256 | return false; |
| 5253 | } | 5257 | } |
| 5254 | 5258 | ||
| 5255 | jQuery.ajax({ | 5259 | try { |
| 5256 | type: 'POST', | 5260 | const result = await fetch('/api/worldinfo/import', { |
| 5257 | url: '/api/worldinfo/import', | 5261 | method: 'POST', |
| 5258 | data: formData, | 5262 | headers: getRequestHeaders({ omitContentType: true }), |
| 5259 | beforeSend: () => { }, | 5263 | body: formData, |
| 5260 | cache: false, | 5264 | cache: 'no-cache', |
| 5261 | contentType: false, | 5265 | }); |
| 5262 | processData: false, | 5266 | |
| 5263 | success: async function (data) { | 5267 | if (!result.ok) { |
| 5264 | if (data.name) { | 5268 | throw new Error(`Failed to import world info: ${result.statusText}`); |
| 5265 | await updateWorldInfoList(); | 5269 | } |
| 5266 | 5270 | ||
| 5267 | const newIndex = world_names.indexOf(data.name); | 5271 | const data = await result.json(); |
| 5268 | if (newIndex >= 0) { | ||
| 5269 | $('#world_editor_select').val(newIndex).trigger('change'); | ||
| 5270 | } | ||
| 5271 | 5272 | ||
| 5272 | toastr.success(`World Info "${data.name}" imported successfully!`); | 5273 | if (data.name) { |
| 5274 | await updateWorldInfoList(); | ||
| 5275 | |||
| 5276 | const newIndex = world_names.indexOf(data.name); | ||
| 5277 | if (newIndex >= 0) { | ||
| 5278 | $('#world_editor_select').val(newIndex).trigger('change'); | ||
| 5273 | } | 5279 | } |
| 5274 | }, | 5280 | |
| 5275 | error: (_jqXHR, _exception) => { }, | 5281 | toastr.success(t`World Info "${data.name}" imported successfully!`); |
| 5276 | }); | 5282 | } |
| 5283 | } catch (error) { | ||
| 5284 | console.error('Error importing world info:', error); | ||
| 5285 | toastr.error(t`Failed to import World Info`); | ||
| 5286 | } | ||
| 5277 | } | 5287 | } |
| 5278 | 5288 | ||
| 5279 | /** | 5289 | /** |
| @@ -216,7 +216,7 @@ router.post('/upload-zip', async (request, response) => { | |||
| 216 | 216 | ||
| 217 | // Remove uploaded ZIP file | 217 | // Remove uploaded ZIP file |
| 218 | fs.unlinkSync(spritePackPath); | 218 | fs.unlinkSync(spritePackPath); |
| 219 | return response.send({ count: sprites.length }); | 219 | return response.send({ ok: true, count: sprites.length }); |
| 220 | } catch (error) { | 220 | } catch (error) { |
| 221 | console.error(error); | 221 | console.error(error); |
| 222 | return response.sendStatus(500); | 222 | return response.sendStatus(500); |
| @@ -262,7 +262,7 @@ router.post('/upload', async (request, response) => { | |||
| 262 | fs.cpSync(spritePath, pathToFile); | 262 | fs.cpSync(spritePath, pathToFile); |
| 263 | // Remove uploaded file | 263 | // Remove uploaded file |
| 264 | fs.unlinkSync(spritePath); | 264 | fs.unlinkSync(spritePath); |
| 265 | return response.sendStatus(200); | 265 | return response.send({ ok: true }); |
| 266 | } catch (error) { | 266 | } catch (error) { |
| 267 | console.error(error); | 267 | console.error(error); |
| 268 | return response.sendStatus(500); | 268 | return response.sendStatus(500); |