Chore: Add code formatting conventions as eslint rules (#5158) * Add code formatting conventions as eslint rules * Improve formatting in addQuickReply
Signed| @@ -102,5 +102,28 @@ module.exports = { | |||
| 102 | // These rules should eventually be enabled. | 102 | // These rules should eventually be enabled. |
| 103 | 'no-async-promise-executor': 'off', | 103 | 'no-async-promise-executor': 'off', |
| 104 | 'no-inner-declarations': 'off', | 104 | 'no-inner-declarations': 'off', |
| 105 | 'brace-style': 'off', | ||
| 106 | // Additional formatting rules based on codebase conventions | ||
| 107 | 'array-bracket-spacing': ['error', 'never'], | ||
| 108 | 'computed-property-spacing': ['error', 'never'], | ||
| 109 | 'block-spacing': ['error', 'always'], | ||
| 110 | 'keyword-spacing': ['error', { before: true, after: true }], | ||
| 111 | 'space-before-blocks': ['error', 'always'], | ||
| 112 | 'space-before-function-paren': ['error', { anonymous: 'always', named: 'never', asyncArrow: 'always' }], | ||
| 113 | 'space-in-parens': ['error', 'never'], | ||
| 114 | 'comma-spacing': ['error', { before: false, after: true }], | ||
| 115 | 'key-spacing': ['error', { beforeColon: false, afterColon: true }], | ||
| 116 | 'func-call-spacing': ['error', 'never'], | ||
| 117 | 'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1, maxBOF: 0 }], | ||
| 118 | 'padded-blocks': ['error', 'never'], | ||
| 119 | 'no-whitespace-before-property': 'error', | ||
| 120 | 'space-unary-ops': ['error', { words: true, nonwords: false }], | ||
| 121 | 'arrow-spacing': ['error', { before: true, after: true }], | ||
| 122 | 'template-curly-spacing': ['error', 'never'], | ||
| 123 | 'rest-spread-spacing': ['error', 'never'], | ||
| 124 | 'generator-star-spacing': ['error', { before: false, after: true }], | ||
| 125 | 'yield-star-spacing': ['error', { before: false, after: true }], | ||
| 126 | 'template-tag-spacing': ['error', 'never'], | ||
| 127 | 'switch-colon-spacing': ['error', { after: true, before: false }], | ||
| 105 | }, | 128 | }, |
| 106 | }; | 129 | }; |
| @@ -2516,7 +2516,6 @@ export function addOneMessage(mes, { type = undefined, insertAfter = null, scrol | |||
| 2516 | * @returns {JQuery<HTMLElement>} Rendered HTMLElement. | 2516 | * @returns {JQuery<HTMLElement>} Rendered HTMLElement. |
| 2517 | */ | 2517 | */ |
| 2518 | export function updateMessageElement(mes, { messageId = chat.length - 1, messageElement = messageTemplate.clone(), adjustMediaScroll = SCROLL_BEHAVIOR.NONE } = {}) { | 2518 | export function updateMessageElement(mes, { messageId = chat.length - 1, messageElement = messageTemplate.clone(), adjustMediaScroll = SCROLL_BEHAVIOR.NONE } = {}) { |
| 2519 | |||
| 2520 | let avatarImg = getThumbnailUrl('persona', user_avatar); | 2519 | let avatarImg = getThumbnailUrl('persona', user_avatar); |
| 2521 | 2520 | ||
| 2522 | //for non-user messages | 2521 | //for non-user messages |
| @@ -3709,9 +3708,9 @@ class StreamingProcessor { | |||
| 3709 | } | 3708 | } |
| 3710 | 3709 | ||
| 3711 | /** | 3710 | /** |
| 3712 | * @returns {Generator<{ text: string, swipes: string[], logprobs: import('./scripts/logprobs.js').TokenLogprobs, toolCalls: any[], state: any }, void, void>} | 3711 | * @returns {AsyncGenerator<{ text: string, swipes: string[], logprobs: import('./scripts/logprobs.js').TokenLogprobs, toolCalls: any[], state: any }, void, void>} |
| 3713 | */ | 3712 | */ |
| 3714 | *nullStreamingGeneration() { | 3713 | async* nullStreamingGeneration() { |
| 3715 | throw new Error('Generation function for streaming is not hooked up'); | 3714 | throw new Error('Generation function for streaming is not hooked up'); |
| 3716 | } | 3715 | } |
| 3717 | 3716 | ||
| @@ -4862,7 +4861,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4862 | 4861 | ||
| 4863 | // Add quiet generation prompt at depth 0 | 4862 | // Add quiet generation prompt at depth 0 |
| 4864 | if (quiet_prompt && quiet_prompt.length) { | 4863 | if (quiet_prompt && quiet_prompt.length) { |
| 4865 | |||
| 4866 | // here name1 is forced for all quiet prompts..why? | 4864 | // here name1 is forced for all quiet prompts..why? |
| 4867 | const name = name1; | 4865 | const name = name1; |
| 4868 | //checks if we are in instruct, if so, formats the chat as such, otherwise just adds the quiet prompt | 4866 | //checks if we are in instruct, if so, formats the chat as such, otherwise just adds the quiet prompt |
| @@ -5399,7 +5397,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 5399 | if (!isAborted && power_user.auto_swipe && generatedTextFiltered(getMessage)) { | 5397 | if (!isAborted && power_user.auto_swipe && generatedTextFiltered(getMessage)) { |
| 5400 | is_send_press = false; | 5398 | is_send_press = false; |
| 5401 | return await swipe(null, SWIPE_DIRECTION.RIGHT, { source: SWIPE_SOURCE.AUTO_SWIPE, repeated: true, forceMesId: chat.length - 1 }); | 5399 | return await swipe(null, SWIPE_DIRECTION.RIGHT, { source: SWIPE_SOURCE.AUTO_SWIPE, repeated: true, forceMesId: chat.length - 1 }); |
| 5402 | |||
| 5403 | } | 5400 | } |
| 5404 | 5401 | ||
| 5405 | console.debug('/api/chats/save called by /Generate'); | 5402 | console.debug('/api/chats/save called by /Generate'); |
| @@ -6517,7 +6514,6 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title | |||
| 6517 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); | 6514 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); |
| 6518 | addOneMessage(chat[chat_id], { type: 'swipe' }); | 6515 | addOneMessage(chat[chat_id], { type: 'swipe' }); |
| 6519 | !fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type); | 6516 | !fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type); |
| 6520 | |||
| 6521 | } else { | 6517 | } else { |
| 6522 | console.debug('entering chat update routine for non-swipe post'); | 6518 | console.debug('entering chat update routine for non-swipe post'); |
| 6523 | const newMessage = {}; | 6519 | const newMessage = {}; |
| @@ -8247,7 +8243,6 @@ export async function getChatsFromFiles(data, isGroupChat) { | |||
| 8247 | currentChat.shift(); | 8243 | currentChat.shift(); |
| 8248 | } | 8244 | } |
| 8249 | chat_dict[file_name] = currentChat; | 8245 | chat_dict[file_name] = currentChat; |
| 8250 | |||
| 8251 | } catch (error) { | 8246 | } catch (error) { |
| 8252 | console.error(error); | 8247 | console.error(error); |
| 8253 | } | 8248 | } |
| @@ -9588,7 +9583,6 @@ export async function createOrEditCharacter(e) { | |||
| 9588 | select_rm_info('char_create', avatarId, oldSelectedChar); | 9583 | select_rm_info('char_create', avatarId, oldSelectedChar); |
| 9589 | 9584 | ||
| 9590 | crop_data = undefined; | 9585 | crop_data = undefined; |
| 9591 | |||
| 9592 | } catch (error) { | 9586 | } catch (error) { |
| 9593 | console.error('Error creating character', error); | 9587 | console.error('Error creating character', error); |
| 9594 | toastr.error(t`Failed to create character`); | 9588 | toastr.error(t`Failed to create character`); |
| @@ -9984,7 +9978,6 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 9984 | duration: 0, //used to be 100 //Disabled on Cohee's request. https://github.com/SillyTavern/SillyTavern/pull/4610/files#r2408731744 | 9978 | duration: 0, //used to be 100 //Disabled on Cohee's request. https://github.com/SillyTavern/SillyTavern/pull/4610/files#r2408731744 |
| 9985 | queue: false, | 9979 | queue: false, |
| 9986 | progress: function (animation, progress, remainingMs) { | 9980 | progress: function (animation, progress, remainingMs) { |
| 9987 | |||
| 9988 | if (is_animation_scroll) chatElement.scrollTop(getMessageBottomHeight(thisMesDiv)); | 9981 | if (is_animation_scroll) chatElement.scrollTop(getMessageBottomHeight(thisMesDiv)); |
| 9989 | }, | 9982 | }, |
| 9990 | complete: function () { | 9983 | complete: function () { |
| @@ -10001,7 +9994,6 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 10001 | * @param {boolean} [skipSwipeOut=false] | 9994 | * @param {boolean} [skipSwipeOut=false] |
| 10002 | */ | 9995 | */ |
| 10003 | async function animateSwipe(run_generate = false, skipSwipeOut = false) { | 9996 | async function animateSwipe(run_generate = false, skipSwipeOut = false) { |
| 10004 | |||
| 10005 | if (!skipSwipeOut) { | 9997 | if (!skipSwipeOut) { |
| 10006 | //Swipe out. | 9998 | //Swipe out. |
| 10007 | await animateSwipeTransition(mesId, { xEnd: `${swipeRange}px`, duration: swipeDuration }); | 9999 | await animateSwipeTransition(mesId, { xEnd: `${swipeRange}px`, duration: swipeDuration }); |
| @@ -10069,7 +10061,6 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 10069 | 10061 | ||
| 10070 | //If the swipe is not being deleted. | 10062 | //If the swipe is not being deleted. |
| 10071 | if (source != SWIPE_SOURCE.DELETE && source != SWIPE_SOURCE.BACK) { | 10063 | if (source != SWIPE_SOURCE.DELETE && source != SWIPE_SOURCE.BACK) { |
| 10072 | |||
| 10073 | // Make sure ad-hoc changes to extras are saved before swiping away | 10064 | // Make sure ad-hoc changes to extras are saved before swiping away |
| 10074 | syncMesToSwipe(mesId); | 10065 | syncMesToSwipe(mesId); |
| 10075 | 10066 | ||
| @@ -10382,7 +10373,6 @@ export async function doNewChat({ deleteCurrentChat = false } = {}) { | |||
| 10382 | await createOrEditCharacter(new CustomEvent('newChat')); | 10373 | await createOrEditCharacter(new CustomEvent('newChat')); |
| 10383 | if (deleteCurrentChat) await delChat(chat_file_for_del + '.jsonl'); | 10374 | if (deleteCurrentChat) await delChat(chat_file_for_del + '.jsonl'); |
| 10384 | } | 10375 | } |
| 10385 | |||
| 10386 | } | 10376 | } |
| 10387 | 10377 | ||
| 10388 | /** | 10378 | /** |
| @@ -11407,9 +11397,7 @@ jQuery(async function () { | |||
| 11407 | 11397 | ||
| 11408 | divchat.style.borderRadius = ''; | 11398 | divchat.style.borderRadius = ''; |
| 11409 | divchat.style.backgroundColor = ''; | 11399 | divchat.style.backgroundColor = ''; |
| 11410 | |||
| 11411 | } else { | 11400 | } else { |
| 11412 | |||
| 11413 | divchat.style.borderRadius = '10px'; // Adjust the value to control the roundness of the corners | 11401 | divchat.style.borderRadius = '10px'; // Adjust the value to control the roundness of the corners |
| 11414 | divchat.style.backgroundColor = ''; // Set the background color to your preference | 11402 | divchat.style.backgroundColor = ''; // Set the background color to your preference |
| 11415 | 11403 | ||
| @@ -101,7 +101,7 @@ class CharacterContextMenu { | |||
| 101 | * @param {number} characterId | 101 | * @param {number} characterId |
| 102 | * @returns {Promise<void>} | 102 | * @returns {Promise<void>} |
| 103 | */ | 103 | */ |
| 104 | static persona = async (characterId) => void(await convertCharacterToPersona(characterId)); | 104 | static persona = async (characterId) => void (await convertCharacterToPersona(characterId)); |
| 105 | 105 | ||
| 106 | /** | 106 | /** |
| 107 | * Delete one or more characters, | 107 | * Delete one or more characters, |
| @@ -754,7 +754,7 @@ class BulkEditOverlay { | |||
| 754 | 754 | ||
| 755 | handleContextMenuShow = (event) => { | 755 | handleContextMenuShow = (event) => { |
| 756 | event.preventDefault(); | 756 | event.preventDefault(); |
| 757 | const [x,y] = this.#getContextMenuPosition(event); | 757 | const [x, y] = this.#getContextMenuPosition(event); |
| 758 | CharacterContextMenu.show(x, y); | 758 | CharacterContextMenu.show(x, y); |
| 759 | this.#contextMenuOpen = true; | 759 | this.#contextMenuOpen = true; |
| 760 | }; | 760 | }; |
| @@ -986,7 +986,6 @@ class PromptManager { | |||
| 986 | * @returns {void} | 986 | * @returns {void} |
| 987 | */ | 987 | */ |
| 988 | addPrompt(prompt, identifier) { | 988 | addPrompt(prompt, identifier) { |
| 989 | |||
| 990 | if (typeof prompt !== 'object' || prompt === null) throw new Error('Object is not a prompt'); | 989 | if (typeof prompt !== 'object' || prompt === null) throw new Error('Object is not a prompt'); |
| 991 | 990 | ||
| 992 | const newPrompt = { | 991 | const newPrompt = { |
| @@ -1318,7 +1317,6 @@ class PromptManager { | |||
| 1318 | this.updatePromptByIdentifier(identifier, prompt); | 1317 | this.updatePromptByIdentifier(identifier, prompt); |
| 1319 | debouncedSaveServiceSettings().then(() => this.render()); | 1318 | debouncedSaveServiceSettings().then(() => this.render()); |
| 1320 | }); | 1319 | }); |
| 1321 | |||
| 1322 | } | 1320 | } |
| 1323 | 1321 | ||
| 1324 | /** | 1322 | /** |
| @@ -101,7 +101,6 @@ observer.observe(document.documentElement, observerConfig); | |||
| 101 | * @returns {string} - A human-readable string that represents the time spent generating characters. | 101 | * @returns {string} - A human-readable string that represents the time spent generating characters. |
| 102 | */ | 102 | */ |
| 103 | export function humanizeGenTime(total_gen_time) { | 103 | export function humanizeGenTime(total_gen_time) { |
| 104 | |||
| 105 | //convert time_spent to humanized format of "_ Hours, _ Minutes, _ Seconds" from milliseconds | 104 | //convert time_spent to humanized format of "_ Hours, _ Minutes, _ Seconds" from milliseconds |
| 106 | let time_spent = total_gen_time || 0; | 105 | let time_spent = total_gen_time || 0; |
| 107 | time_spent = Math.floor(time_spent / 1000); | 106 | time_spent = Math.floor(time_spent / 1000); |
| @@ -1274,8 +1273,6 @@ export function initRossMods() { | |||
| 1274 | } | 1273 | } |
| 1275 | 1274 | ||
| 1276 | 1275 | ||
| 1277 | |||
| 1278 | |||
| 1279 | if (event.ctrlKey && /^[1-9]$/.test(event.key)) { | 1276 | if (event.ctrlKey && /^[1-9]$/.test(event.key)) { |
| 1280 | // This will eventually be to trigger quick replies | 1277 | // This will eventually be to trigger quick replies |
| 1281 | // event.preventDefault(); | 1278 | // event.preventDefault(); |
| @@ -80,8 +80,6 @@ export class AutoComplete { | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | 82 | ||
| 83 | |||
| 84 | |||
| 85 | /** | 83 | /** |
| 86 | * @param {HTMLTextAreaElement|HTMLInputElement} textarea The textarea to receive autocomplete. | 84 | * @param {HTMLTextAreaElement|HTMLInputElement} textarea The textarea to receive autocomplete. |
| 87 | * @param {() => boolean} checkIfActivate Function should return true only if under the current conditions, autocomplete should display (e.g., for slash commands: autoComplete.text[0] == '/') | 85 | * @param {() => boolean} checkIfActivate Function should return true only if under the current conditions, autocomplete should display (e.g., for slash commands: autoComplete.text[0] == '/') |
| @@ -414,7 +412,6 @@ export class AutoComplete { | |||
| 414 | }); | 412 | }); |
| 415 | 413 | ||
| 416 | 414 | ||
| 417 | |||
| 418 | if (this.isForceHidden) { | 415 | if (this.isForceHidden) { |
| 419 | // hidden with escape | 416 | // hidden with escape |
| 420 | return this.hide(); | 417 | return this.hide(); |
| @@ -465,7 +462,6 @@ export class AutoComplete { | |||
| 465 | } | 462 | } |
| 466 | 463 | ||
| 467 | 464 | ||
| 468 | |||
| 469 | /** | 465 | /** |
| 470 | * Create updated DOM. | 466 | * Create updated DOM. |
| 471 | */ | 467 | */ |
| @@ -514,7 +510,6 @@ export class AutoComplete { | |||
| 514 | } | 510 | } |
| 515 | 511 | ||
| 516 | 512 | ||
| 517 | |||
| 518 | /** | 513 | /** |
| 519 | * Update position of DOM. | 514 | * Update position of DOM. |
| 520 | */ | 515 | */ |
| @@ -1,6 +1,3 @@ | |||
| 1 | |||
| 2 | |||
| 3 | |||
| 4 | export class AutoCompleteFuzzyScore { | 1 | export class AutoCompleteFuzzyScore { |
| 5 | /**@type {number}*/ start; | 2 | /**@type {number}*/ start; |
| 6 | /**@type {number}*/ longestConsecutive; | 3 | /**@type {number}*/ longestConsecutive; |
| @@ -2,7 +2,6 @@ import { AutoCompleteNameResultBase } from './AutoCompleteNameResultBase.js'; | |||
| 2 | import { AutoCompleteSecondaryNameResult } from './AutoCompleteSecondaryNameResult.js'; | 2 | import { AutoCompleteSecondaryNameResult } from './AutoCompleteSecondaryNameResult.js'; |
| 3 | 3 | ||
| 4 | 4 | ||
| 5 | |||
| 6 | export class AutoCompleteNameResult extends AutoCompleteNameResultBase { | 5 | export class AutoCompleteNameResult extends AutoCompleteNameResultBase { |
| 7 | /** | 6 | /** |
| 8 | * | 7 | * |
| @@ -1,14 +1,13 @@ | |||
| 1 | import { AutoCompleteOption } from './AutoCompleteOption.js'; | 1 | import { AutoCompleteOption } from './AutoCompleteOption.js'; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | |||
| 5 | export class AutoCompleteNameResultBase { | 4 | export class AutoCompleteNameResultBase { |
| 6 | /**@type {string} */ name; | 5 | /**@type {string} */ name; |
| 7 | /**@type {number} */ start; | 6 | /**@type {number} */ start; |
| 8 | /**@type {AutoCompleteOption[]} */ optionList = []; | 7 | /**@type {AutoCompleteOption[]} */ optionList = []; |
| 9 | /**@type {boolean} */ canBeQuoted = false; | 8 | /**@type {boolean} */ canBeQuoted = false; |
| 10 | /**@type {()=>string} */ makeNoMatchText = ()=>`No matches found for "${this.name}"`; | 9 | /**@type {()=>string} */ makeNoMatchText = () => `No matches found for "${this.name}"`; |
| 11 | /**@type {()=>string} */ makeNoOptionsText = ()=>'No options'; | 10 | /**@type {()=>string} */ makeNoOptionsText = () => 'No options'; |
| 12 | 11 | ||
| 13 | 12 | ||
| 14 | /** | 13 | /** |
| @@ -1,7 +1,6 @@ | |||
| 1 | import { AutoCompleteFuzzyScore } from './AutoCompleteFuzzyScore.js'; | 1 | import { AutoCompleteFuzzyScore } from './AutoCompleteFuzzyScore.js'; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | |||
| 5 | export class AutoCompleteOption { | 4 | export class AutoCompleteOption { |
| 6 | /** @type {string} */ name; | 5 | /** @type {string} */ name; |
| 7 | /** @type {string} */ typeIcon; | 6 | /** @type {string} */ typeIcon; |
| @@ -72,7 +71,7 @@ export class AutoCompleteOption { | |||
| 72 | name.classList.add('name'); | 71 | name.classList.add('name'); |
| 73 | name.classList.add('monospace'); | 72 | name.classList.add('monospace'); |
| 74 | name.textContent = noSlash ? '' : '/'; | 73 | name.textContent = noSlash ? '' : '/'; |
| 75 | key.split('').forEach(char=>{ | 74 | key.split('').forEach(char => { |
| 76 | const span = document.createElement('span'); { | 75 | const span = document.createElement('span'); { |
| 77 | span.textContent = char; | 76 | span.textContent = char; |
| 78 | name.append(span); | 77 | name.append(span); |
| @@ -55,7 +55,7 @@ function onSelectAllButtonClick() { | |||
| 55 | 55 | ||
| 56 | if (!atLeastOneSelected) { | 56 | if (!atLeastOneSelected) { |
| 57 | // If none was selected, trigger click on all to deselect all of them | 57 | // If none was selected, trigger click on all to deselect all of them |
| 58 | for(const character of characters) { | 58 | for (const character of characters) { |
| 59 | const checked = $(character).find('.bulk_select_checkbox:checked') ?? false; | 59 | const checked = $(character).find('.bulk_select_checkbox:checked') ?? false; |
| 60 | if (checked && character instanceof HTMLElement) { | 60 | if (checked && character instanceof HTMLElement) { |
| 61 | characterGroupOverlay.toggleSingleCharacter(character); | 61 | characterGroupOverlay.toggleSingleCharacter(character); |
| @@ -150,7 +150,6 @@ function onCfgMenuItemClick() { | |||
| 150 | setTimeout(function () { | 150 | setTimeout(function () { |
| 151 | $('#cfgConfig').hide(); | 151 | $('#cfgConfig').hide(); |
| 152 | }, animation_duration); | 152 | }, animation_duration); |
| 153 | |||
| 154 | } | 153 | } |
| 155 | //duplicate options menu close handler from script.js | 154 | //duplicate options menu close handler from script.js |
| 156 | //because this listener takes priority | 155 | //because this listener takes priority |
| @@ -199,7 +199,7 @@ class BackupsBrowser { | |||
| 199 | const deleteButton = document.createElement('div'); | 199 | const deleteButton = document.createElement('div'); |
| 200 | deleteButton.classList.add('right_menu_button', 'fa-solid', 'fa-trash'); | 200 | deleteButton.classList.add('right_menu_button', 'fa-solid', 'fa-trash'); |
| 201 | deleteButton.title = t`Delete backup`; | 201 | deleteButton.title = t`Delete backup`; |
| 202 | deleteButton.addEventListener('click',async () => { | 202 | deleteButton.addEventListener('click', async () => { |
| 203 | const isDeleted = await this.deleteBackup(backup.file_name); | 203 | const isDeleted = await this.deleteBackup(backup.file_name); |
| 204 | if (isDeleted) { | 204 | if (isDeleted) { |
| 205 | listItem.remove(); | 205 | listItem.remove(); |
| @@ -251,7 +251,6 @@ class DataMaidDialog { | |||
| 251 | categoryElement.remove(); | 251 | categoryElement.remove(); |
| 252 | this.displayEmptyPlaceholder(); | 252 | this.displayEmptyPlaceholder(); |
| 253 | }); | 253 | }); |
| 254 | |||
| 255 | }); | 254 | }); |
| 256 | categoryElement.querySelectorAll('.dataMaidItemDelete').forEach(button => { | 255 | categoryElement.querySelectorAll('.dataMaidItemDelete').forEach(button => { |
| 257 | button.addEventListener('click', async () => { | 256 | button.addEventListener('click', async () => { |
| @@ -94,8 +94,7 @@ async function downloadAssetsList(url) { | |||
| 94 | updateCurrentAssets().then(async function () { | 94 | updateCurrentAssets().then(async function () { |
| 95 | fetch(url, { cache: 'no-cache' }) | 95 | fetch(url, { cache: 'no-cache' }) |
| 96 | .then(response => response.json()) | 96 | .then(response => response.json()) |
| 97 | .then(async function(json) { | 97 | .then(async function (json) { |
| 98 | |||
| 99 | availableAssets = {}; | 98 | availableAssets = {}; |
| 100 | $('#assets_menu').empty(); | 99 | $('#assets_menu').empty(); |
| 101 | 100 | ||
| @@ -1414,7 +1414,6 @@ export async function getExpressionsList({ filterAvailable = false } = {}) { | |||
| 1414 | }); | 1414 | }); |
| 1415 | 1415 | ||
| 1416 | if (apiResult.ok) { | 1416 | if (apiResult.ok) { |
| 1417 | |||
| 1418 | const data = await apiResult.json(); | 1417 | const data = await apiResult.json(); |
| 1419 | expressionsList = data.labels; | 1418 | expressionsList = data.labels; |
| 1420 | return expressionsList; | 1419 | return expressionsList; |
| @@ -1488,7 +1487,6 @@ function chooseSpriteForExpression(spriteFolderName, expression, { prevExpressio | |||
| 1488 | } | 1487 | } |
| 1489 | 1488 | ||
| 1490 | return spriteFile; | 1489 | return spriteFile; |
| 1491 | |||
| 1492 | } | 1490 | } |
| 1493 | 1491 | ||
| 1494 | /** | 1492 | /** |
| @@ -2333,7 +2331,7 @@ function migrateSettings() { | |||
| 2333 | name: 'expression-folder-override', | 2331 | name: 'expression-folder-override', |
| 2334 | aliases: ['spriteoverride', 'costume'], | 2332 | aliases: ['spriteoverride', 'costume'], |
| 2335 | callback: setSpriteFolderCommand, | 2333 | callback: setSpriteFolderCommand, |
| 2336 | namedArgumentList:[ | 2334 | namedArgumentList: [ |
| 2337 | SlashCommandNamedArgument.fromProps({ | 2335 | SlashCommandNamedArgument.fromProps({ |
| 2338 | name: 'name', | 2336 | name: 'name', |
| 2339 | description: 'Character name to set a subfolder for. If not provided, the character who last sent a message will be used.', | 2337 | description: 'Character name to set a subfolder for. If not provided, the character who last sent a message will be used.', |
| @@ -791,7 +791,6 @@ async function listGalleryCommand(args) { | |||
| 791 | 791 | ||
| 792 | const items = await getGalleryItems(url); | 792 | const items = await getGalleryItems(url); |
| 793 | return JSON.stringify(items.map(it => it.src)); | 793 | return JSON.stringify(items.map(it => it.src)); |
| 794 | |||
| 795 | } catch (err) { | 794 | } catch (err) { |
| 796 | console.error(err); | 795 | console.error(err); |
| 797 | } | 796 | } |
| @@ -10,22 +10,18 @@ export class QuickReplyApi { | |||
| 10 | /** @type {SettingsUi} */ settingsUi; | 10 | /** @type {SettingsUi} */ settingsUi; |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | |||
| 14 | |||
| 15 | constructor(/** @type {QuickReplySettings} */settings, /** @type {SettingsUi} */settingsUi) { | 13 | constructor(/** @type {QuickReplySettings} */settings, /** @type {SettingsUi} */settingsUi) { |
| 16 | this.settings = settings; | 14 | this.settings = settings; |
| 17 | this.settingsUi = settingsUi; | 15 | this.settingsUi = settingsUi; |
| 18 | } | 16 | } |
| 19 | 17 | ||
| 20 | 18 | ||
| 21 | |||
| 22 | |||
| 23 | /** | 19 | /** |
| 24 | * @param {QuickReply} qr | 20 | * @param {QuickReply} qr |
| 25 | * @returns {QuickReplySet} | 21 | * @returns {QuickReplySet} |
| 26 | */ | 22 | */ |
| 27 | getSetByQr(qr) { | 23 | getSetByQr(qr) { |
| 28 | return QuickReplySet.list.find(it=>it.qrList.includes(qr)); | 24 | return QuickReplySet.list.find(it => it.qrList.includes(qr)); |
| 29 | } | 25 | } |
| 30 | 26 | ||
| 31 | /** | 27 | /** |
| @@ -48,13 +44,11 @@ export class QuickReplyApi { | |||
| 48 | getQrByLabel(setName, label) { | 44 | getQrByLabel(setName, label) { |
| 49 | const set = this.getSetByName(setName); | 45 | const set = this.getSetByName(setName); |
| 50 | if (!set) return; | 46 | if (!set) return; |
| 51 | if (Number.isInteger(label)) return set.qrList.find(it=>it.id == label); | 47 | if (Number.isInteger(label)) return set.qrList.find(it => it.id == label); |
| 52 | return set.qrList.find(it=>it.label == label); | 48 | return set.qrList.find(it => it.label == label); |
| 53 | } | 49 | } |
| 54 | 50 | ||
| 55 | 51 | ||
| 56 | |||
| 57 | |||
| 58 | /** | 52 | /** |
| 59 | * Executes a quick reply by its index and returns the result. | 53 | * Executes a quick reply by its index and returns the result. |
| 60 | * | 54 | * |
| @@ -63,7 +57,7 @@ export class QuickReplyApi { | |||
| 63 | */ | 57 | */ |
| 64 | async executeQuickReplyByIndex(idx) { | 58 | async executeQuickReplyByIndex(idx) { |
| 65 | const qr = [...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? [])] | 59 | const qr = [...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? [])] |
| 66 | .map(it=>it.set.qrList) | 60 | .map(it => it.set.qrList) |
| 67 | .flat()[idx] | 61 | .flat()[idx] |
| 68 | ; | 62 | ; |
| 69 | if (qr) { | 63 | if (qr) { |
| @@ -400,7 +394,7 @@ export class QuickReplyApi { | |||
| 400 | if (oldSet) { | 394 | if (oldSet) { |
| 401 | QuickReplySet.list.splice(QuickReplySet.list.indexOf(oldSet), 1, set); | 395 | QuickReplySet.list.splice(QuickReplySet.list.indexOf(oldSet), 1, set); |
| 402 | } else { | 396 | } else { |
| 403 | const idx = QuickReplySet.list.findIndex(it=>it.name.localeCompare(name) == 1); | 397 | const idx = QuickReplySet.list.findIndex(it => it.name.localeCompare(name) == 1); |
| 404 | if (idx > -1) { | 398 | if (idx > -1) { |
| 405 | QuickReplySet.list.splice(idx, 0, set); | 399 | QuickReplySet.list.splice(idx, 0, set); |
| 406 | } else { | 400 | } else { |
| @@ -460,7 +454,7 @@ export class QuickReplyApi { | |||
| 460 | * @returns array with the names of all quick reply sets | 454 | * @returns array with the names of all quick reply sets |
| 461 | */ | 455 | */ |
| 462 | listSets() { | 456 | listSets() { |
| 463 | return QuickReplySet.list.map(it=>it.name); | 457 | return QuickReplySet.list.map(it => it.name); |
| 464 | } | 458 | } |
| 465 | /** | 459 | /** |
| 466 | * Gets a list of all globally active quick reply sets. | 460 | * Gets a list of all globally active quick reply sets. |
| @@ -468,7 +462,7 @@ export class QuickReplyApi { | |||
| 468 | * @returns array with the names of all quick reply sets | 462 | * @returns array with the names of all quick reply sets |
| 469 | */ | 463 | */ |
| 470 | listGlobalSets() { | 464 | listGlobalSets() { |
| 471 | return this.settings.config.setList.map(it=>it.set.name); | 465 | return this.settings.config.setList.map(it => it.set.name); |
| 472 | } | 466 | } |
| 473 | /** | 467 | /** |
| 474 | * Gets a list of all quick reply sets activated by the current chat. | 468 | * Gets a list of all quick reply sets activated by the current chat. |
| @@ -476,7 +470,7 @@ export class QuickReplyApi { | |||
| 476 | * @returns array with the names of all quick reply sets | 470 | * @returns array with the names of all quick reply sets |
| 477 | */ | 471 | */ |
| 478 | listChatSets() { | 472 | listChatSets() { |
| 479 | return this.settings.chatConfig?.setList?.flatMap(it=>it.set.name) ?? []; | 473 | return this.settings.chatConfig?.setList?.flatMap(it => it.set.name) ?? []; |
| 480 | } | 474 | } |
| 481 | 475 | ||
| 482 | /** | 476 | /** |
| @@ -490,7 +484,7 @@ export class QuickReplyApi { | |||
| 490 | if (!set) { | 484 | if (!set) { |
| 491 | throw new Error(`No quick reply set with name "${name}" found.`); | 485 | throw new Error(`No quick reply set with name "${name}" found.`); |
| 492 | } | 486 | } |
| 493 | return set.qrList.map(it=>it.label); | 487 | return set.qrList.map(it => it.label); |
| 494 | } | 488 | } |
| 495 | 489 | ||
| 496 | /** | 490 | /** |
| @@ -14,8 +14,6 @@ import { selected_group } from '../../group-chats.js'; | |||
| 14 | export { debounceAsync }; | 14 | export { debounceAsync }; |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | |||
| 18 | |||
| 19 | const _VERBOSE = true; | 17 | const _VERBOSE = true; |
| 20 | export const debug = (...msg) => _VERBOSE ? console.debug('[QR2]', ...msg) : null; | 18 | export const debug = (...msg) => _VERBOSE ? console.debug('[QR2]', ...msg) : null; |
| 21 | export const log = (...msg) => _VERBOSE ? console.log('[QR2]', ...msg) : null; | 19 | export const log = (...msg) => _VERBOSE ? console.log('[QR2]', ...msg) : null; |
| @@ -54,8 +52,6 @@ let autoExec; | |||
| 54 | export let quickReplyApi; | 52 | export let quickReplyApi; |
| 55 | 53 | ||
| 56 | 54 | ||
| 57 | |||
| 58 | |||
| 59 | const loadSets = async () => { | 55 | const loadSets = async () => { |
| 60 | const response = await fetch('/api/settings/get', { | 56 | const response = await fetch('/api/settings/get', { |
| 61 | method: 'POST', | 57 | method: 'POST', |
| @@ -72,7 +68,7 @@ const loadSets = async () => { | |||
| 72 | set.disableSend = set.quickActionEnabled ?? false; | 68 | set.disableSend = set.quickActionEnabled ?? false; |
| 73 | set.placeBeforeInput = set.placeBeforeInputEnabled ?? false; | 69 | set.placeBeforeInput = set.placeBeforeInputEnabled ?? false; |
| 74 | set.injectInput = set.AutoInputInject ?? false; | 70 | set.injectInput = set.AutoInputInject ?? false; |
| 75 | set.qrList = set.quickReplySlots.map((slot,idx)=>{ | 71 | set.qrList = set.quickReplySlots.map((slot, idx) => { |
| 76 | const qr = {}; | 72 | const qr = {}; |
| 77 | qr.id = idx + 1; | 73 | qr.id = idx + 1; |
| 78 | qr.label = slot.label ?? ''; | 74 | qr.label = slot.label ?? ''; |
| @@ -87,7 +83,7 @@ const loadSets = async () => { | |||
| 87 | qr.executeOnNewChat = slot.autoExecute_newChat ?? false; | 83 | qr.executeOnNewChat = slot.autoExecute_newChat ?? false; |
| 88 | qr.executeBeforeGeneration = slot.autoExecute_beforeGeneration ?? false; | 84 | qr.executeBeforeGeneration = slot.autoExecute_beforeGeneration ?? false; |
| 89 | qr.automationId = slot.automationId ?? ''; | 85 | qr.automationId = slot.automationId ?? ''; |
| 90 | qr.contextList = (slot.contextMenu ?? []).map(it=>({ | 86 | qr.contextList = (slot.contextMenu ?? []).map(it => ({ |
| 91 | set: it.preset, | 87 | set: it.preset, |
| 92 | isChained: it.chain, | 88 | isChained: it.chain, |
| 93 | })); | 89 | })); |
| @@ -99,8 +95,8 @@ const loadSets = async () => { | |||
| 99 | } | 95 | } |
| 100 | } | 96 | } |
| 101 | // need to load QR lists after all sets are loaded to be able to resolve context menu entries | 97 | // need to load QR lists after all sets are loaded to be able to resolve context menu entries |
| 102 | setList.forEach((set, idx)=>{ | 98 | setList.forEach((set, idx) => { |
| 103 | QuickReplySet.list[idx].qrList = set.qrList.map(it=>QuickReply.from(it)); | 99 | QuickReplySet.list[idx].qrList = set.qrList.map(it => QuickReply.from(it)); |
| 104 | QuickReplySet.list[idx].init(); | 100 | QuickReplySet.list[idx].init(); |
| 105 | }); | 101 | }); |
| 106 | log('sets: ', QuickReplySet.list); | 102 | log('sets: ', QuickReplySet.list); |
| @@ -140,7 +136,7 @@ const executeIfReadyElseQueue = async (functionToCall, args) => { | |||
| 140 | await functionToCall(...args); | 136 | await functionToCall(...args); |
| 141 | } else { | 137 | } else { |
| 142 | log('queueing', { functionToCall, args }); | 138 | log('queueing', { functionToCall, args }); |
| 143 | executeQueue.push(async()=>await functionToCall(...args)); | 139 | executeQueue.push(async () => await functionToCall(...args)); |
| 144 | } | 140 | } |
| 145 | }; | 141 | }; |
| 146 | 142 | ||
| @@ -183,9 +179,9 @@ const init = async () => { | |||
| 183 | 179 | ||
| 184 | buttons = new ButtonUi(settings); | 180 | buttons = new ButtonUi(settings); |
| 185 | buttons.show(); | 181 | buttons.show(); |
| 186 | settings.onSave = ()=>buttons.refresh(); | 182 | settings.onSave = () => buttons.refresh(); |
| 187 | 183 | ||
| 188 | globalThis.executeQuickReplyByName = async(name, args = {}, options = {}) => { | 184 | globalThis.executeQuickReplyByName = async (name, args = {}, options = {}) => { |
| 189 | let qr = [ | 185 | let qr = [ |
| 190 | ...settings.config.setList, | 186 | ...settings.config.setList, |
| 191 | ...(settings.chatConfig?.setList ?? []), | 187 | ...(settings.chatConfig?.setList ?? []), |
| @@ -193,14 +189,14 @@ const init = async () => { | |||
| 193 | ] | 189 | ] |
| 194 | .map(it => it.set.qrList) | 190 | .map(it => it.set.qrList) |
| 195 | .flat() | 191 | .flat() |
| 196 | .find(it=>it.label == name) | 192 | .find(it => it.label == name) |
| 197 | ; | 193 | ; |
| 198 | if (!qr) { | 194 | if (!qr) { |
| 199 | let [setName, ...qrName] = name.split('.'); | 195 | let [setName, ...qrName] = name.split('.'); |
| 200 | qrName = qrName.join('.'); | 196 | qrName = qrName.join('.'); |
| 201 | let qrs = QuickReplySet.get(setName); | 197 | let qrs = QuickReplySet.get(setName); |
| 202 | if (qrs) { | 198 | if (qrs) { |
| 203 | qr = qrs.qrList.find(it=>it.label == qrName); | 199 | qr = qrs.qrList.find(it => it.label == qrName); |
| 204 | } | 200 | } |
| 205 | } | 201 | } |
| 206 | if (qr && qr.onExecute) { | 202 | if (qr && qr.onExecute) { |
| @@ -215,7 +211,7 @@ const init = async () => { | |||
| 215 | slash.init(); | 211 | slash.init(); |
| 216 | autoExec = new AutoExecuteHandler(settings); | 212 | autoExec = new AutoExecuteHandler(settings); |
| 217 | 213 | ||
| 218 | eventSource.on(event_types.APP_READY, async()=>await finalizeInit()); | 214 | eventSource.on(event_types.APP_READY, async () => await finalizeInit()); |
| 219 | 215 | ||
| 220 | globalThis.quickReplyApi = quickReplyApi; | 216 | globalThis.quickReplyApi = quickReplyApi; |
| 221 | }; | 217 | }; |
| @@ -275,14 +271,14 @@ const onChatChanged = async (chatIdx) => { | |||
| 275 | 271 | ||
| 276 | await autoExec.handleChatChanged(); | 272 | await autoExec.handleChatChanged(); |
| 277 | }; | 273 | }; |
| 278 | eventSource.on(event_types.CHAT_CHANGED, (...args)=>executeIfReadyElseQueue(onChatChanged, args)); | 274 | eventSource.on(event_types.CHAT_CHANGED, (...args) => executeIfReadyElseQueue(onChatChanged, args)); |
| 279 | eventSource.on(event_types.CHARACTER_DELETED, purgeCharacterQuickReplySets); | 275 | eventSource.on(event_types.CHARACTER_DELETED, purgeCharacterQuickReplySets); |
| 280 | eventSource.on(event_types.CHARACTER_RENAMED, updateCharacterQuickReplySets); | 276 | eventSource.on(event_types.CHARACTER_RENAMED, updateCharacterQuickReplySets); |
| 281 | 277 | ||
| 282 | const onUserMessage = async () => { | 278 | const onUserMessage = async () => { |
| 283 | await autoExec.handleUser(); | 279 | await autoExec.handleUser(); |
| 284 | }; | 280 | }; |
| 285 | eventSource.makeFirst(event_types.USER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onUserMessage, args)); | 281 | eventSource.makeFirst(event_types.USER_MESSAGE_RENDERED, (...args) => executeIfReadyElseQueue(onUserMessage, args)); |
| 286 | 282 | ||
| 287 | const onAiMessage = async (messageId) => { | 283 | const onAiMessage = async (messageId) => { |
| 288 | if (['...'].includes(chat[messageId]?.mes)) { | 284 | if (['...'].includes(chat[messageId]?.mes)) { |
| @@ -292,7 +288,7 @@ const onAiMessage = async (messageId) => { | |||
| 292 | 288 | ||
| 293 | await autoExec.handleAi(); | 289 | await autoExec.handleAi(); |
| 294 | }; | 290 | }; |
| 295 | eventSource.makeFirst(event_types.CHARACTER_MESSAGE_RENDERED, (...args)=>executeIfReadyElseQueue(onAiMessage, args)); | 291 | eventSource.makeFirst(event_types.CHARACTER_MESSAGE_RENDERED, (...args) => executeIfReadyElseQueue(onAiMessage, args)); |
| 296 | 292 | ||
| 297 | const onGroupMemberDraft = async () => { | 293 | const onGroupMemberDraft = async () => { |
| 298 | await autoExec.handleGroupMemberDraft(); | 294 | await autoExec.handleGroupMemberDraft(); |
| @@ -8,8 +8,6 @@ export class AutoExecuteHandler { | |||
| 8 | /** @type {Boolean[]}*/ preventAutoExecuteStack = []; | 8 | /** @type {Boolean[]}*/ preventAutoExecuteStack = []; |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | |||
| 12 | |||
| 13 | constructor(/** @type {QuickReplySettings} */settings) { | 11 | constructor(/** @type {QuickReplySettings} */settings) { |
| 14 | this.settings = settings; | 12 | this.settings = settings; |
| 15 | } | 13 | } |
| @@ -20,13 +18,11 @@ export class AutoExecuteHandler { | |||
| 20 | } | 18 | } |
| 21 | 19 | ||
| 22 | 20 | ||
| 23 | |||
| 24 | |||
| 25 | async performAutoExecute(/** @type {QuickReply[]} */qrList) { | 21 | async performAutoExecute(/** @type {QuickReply[]} */qrList) { |
| 26 | for (const qr of qrList) { | 22 | for (const qr of qrList) { |
| 27 | this.preventAutoExecuteStack.push(qr.preventAutoExecute); | 23 | this.preventAutoExecuteStack.push(qr.preventAutoExecute); |
| 28 | try { | 24 | try { |
| 29 | await qr.execute({ isAutoExecute:true }); | 25 | await qr.execute({ isAutoExecute: true }); |
| 30 | } catch (ex) { | 26 | } catch (ex) { |
| 31 | warn(ex); | 27 | warn(ex); |
| 32 | } finally { | 28 | } finally { |
| @@ -22,13 +22,11 @@ export class QuickReply { | |||
| 22 | * @param {{ id?: number; contextList?: any; }} props | 22 | * @param {{ id?: number; contextList?: any; }} props |
| 23 | */ | 23 | */ |
| 24 | static from(props) { | 24 | static from(props) { |
| 25 | props.contextList = (props.contextList ?? []).map((/** @type {any} */ it)=>QuickReplyContextLink.from(it)); | 25 | props.contextList = (props.contextList ?? []).map((/** @type {any} */ it) => QuickReplyContextLink.from(it)); |
| 26 | return Object.assign(new this(), props); | 26 | return Object.assign(new this(), props); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | |||
| 31 | |||
| 32 | /**@type {number}*/ id; | 30 | /**@type {number}*/ id; |
| 33 | /**@type {string}*/ icon; | 31 | /**@type {string}*/ icon; |
| 34 | /**@type {string}*/ label = ''; | 32 | /**@type {string}*/ label = ''; |
| @@ -89,8 +87,6 @@ export class QuickReply { | |||
| 89 | } | 87 | } |
| 90 | 88 | ||
| 91 | 89 | ||
| 92 | |||
| 93 | |||
| 94 | unrender() { | 90 | unrender() { |
| 95 | this.dom?.remove(); | 91 | this.dom?.remove(); |
| 96 | this.dom = null; | 92 | this.dom = null; |
| @@ -129,7 +125,7 @@ export class QuickReply { | |||
| 129 | menu.show(evt); | 125 | menu.show(evt); |
| 130 | } | 126 | } |
| 131 | }); | 127 | }); |
| 132 | root.addEventListener('click', (evt)=>{ | 128 | root.addEventListener('click', (evt) => { |
| 133 | if (evt.ctrlKey) { | 129 | if (evt.ctrlKey) { |
| 134 | this.showEditor(); | 130 | this.showEditor(); |
| 135 | return; | 131 | return; |
| @@ -169,8 +165,6 @@ export class QuickReply { | |||
| 169 | } | 165 | } |
| 170 | 166 | ||
| 171 | 167 | ||
| 172 | |||
| 173 | |||
| 174 | renderSettings(idx) { | 168 | renderSettings(idx) { |
| 175 | if (!this.settingsDom) { | 169 | if (!this.settingsDom) { |
| 176 | const item = document.createElement('div'); { | 170 | const item = document.createElement('div'); { |
| @@ -190,7 +184,7 @@ export class QuickReply { | |||
| 190 | addNew.classList.add('fa-solid'); | 184 | addNew.classList.add('fa-solid'); |
| 191 | addNew.classList.add('fa-plus'); | 185 | addNew.classList.add('fa-plus'); |
| 192 | addNew.title = 'Add quick reply'; | 186 | addNew.title = 'Add quick reply'; |
| 193 | addNew.addEventListener('click', ()=>this.onInsertBefore()); | 187 | addNew.addEventListener('click', () => this.onInsertBefore()); |
| 194 | actions.append(addNew); | 188 | actions.append(addNew); |
| 195 | } | 189 | } |
| 196 | const paste = document.createElement('div'); { | 190 | const paste = document.createElement('div'); { |
| @@ -201,7 +195,7 @@ export class QuickReply { | |||
| 201 | paste.classList.add('fa-solid'); | 195 | paste.classList.add('fa-solid'); |
| 202 | paste.classList.add('fa-paste'); | 196 | paste.classList.add('fa-paste'); |
| 203 | paste.title = 'Add quick reply from clipboard'; | 197 | paste.title = 'Add quick reply from clipboard'; |
| 204 | paste.addEventListener('click', async()=>{ | 198 | paste.addEventListener('click', async () => { |
| 205 | const text = await navigator.clipboard.readText(); | 199 | const text = await navigator.clipboard.readText(); |
| 206 | this.onInsertBefore(text); | 200 | this.onInsertBefore(text); |
| 207 | }); | 201 | }); |
| @@ -215,11 +209,11 @@ export class QuickReply { | |||
| 215 | importFile.classList.add('fa-solid'); | 209 | importFile.classList.add('fa-solid'); |
| 216 | importFile.classList.add('fa-file-import'); | 210 | importFile.classList.add('fa-file-import'); |
| 217 | importFile.title = 'Add quick reply from JSON file'; | 211 | importFile.title = 'Add quick reply from JSON file'; |
| 218 | importFile.addEventListener('click', async()=>{ | 212 | importFile.addEventListener('click', async () => { |
| 219 | const inp = document.createElement('input'); { | 213 | const inp = document.createElement('input'); { |
| 220 | inp.type = 'file'; | 214 | inp.type = 'file'; |
| 221 | inp.accept = '.json'; | 215 | inp.accept = '.json'; |
| 222 | inp.addEventListener('change', async()=>{ | 216 | inp.addEventListener('change', async () => { |
| 223 | if (inp.files.length > 0) { | 217 | if (inp.files.length > 0) { |
| 224 | for (const file of inp.files) { | 218 | for (const file of inp.files) { |
| 225 | const text = await file.text(); | 219 | const text = await file.text(); |
| @@ -256,7 +250,7 @@ export class QuickReply { | |||
| 256 | icon.classList.add('fa-solid'); | 250 | icon.classList.add('fa-solid'); |
| 257 | icon.classList.add(this.icon); | 251 | icon.classList.add(this.icon); |
| 258 | } | 252 | } |
| 259 | icon.addEventListener('click', async()=>{ | 253 | icon.addEventListener('click', async () => { |
| 260 | let value = await showFontAwesomePicker(); | 254 | let value = await showFontAwesomePicker(); |
| 261 | this.updateIcon(value); | 255 | this.updateIcon(value); |
| 262 | }); | 256 | }); |
| @@ -267,7 +261,7 @@ export class QuickReply { | |||
| 267 | lbl.classList.add('qr--set-itemLabel'); | 261 | lbl.classList.add('qr--set-itemLabel'); |
| 268 | lbl.classList.add('text_pole'); | 262 | lbl.classList.add('text_pole'); |
| 269 | lbl.value = this.label; | 263 | lbl.value = this.label; |
| 270 | lbl.addEventListener('input', ()=>this.updateLabel(lbl.value)); | 264 | lbl.addEventListener('input', () => this.updateLabel(lbl.value)); |
| 271 | lblContainer.append(lbl); | 265 | lblContainer.append(lbl); |
| 272 | } | 266 | } |
| 273 | itemContent.append(lblContainer); | 267 | itemContent.append(lblContainer); |
| @@ -283,7 +277,7 @@ export class QuickReply { | |||
| 283 | opt.classList.add('fa-solid'); | 277 | opt.classList.add('fa-solid'); |
| 284 | opt.textContent = '⁝'; | 278 | opt.textContent = '⁝'; |
| 285 | opt.title = 'Additional options:\n - large editor\n - context menu\n - auto-execution\n - tooltip'; | 279 | opt.title = 'Additional options:\n - large editor\n - context menu\n - auto-execution\n - tooltip'; |
| 286 | opt.addEventListener('click', ()=>this.showEditor()); | 280 | opt.addEventListener('click', () => this.showEditor()); |
| 287 | optContainer.append(opt); | 281 | optContainer.append(opt); |
| 288 | } | 282 | } |
| 289 | itemContent.append(optContainer); | 283 | itemContent.append(optContainer); |
| @@ -294,7 +288,7 @@ export class QuickReply { | |||
| 294 | mes.classList.add('qr--set-itemMessage'); | 288 | mes.classList.add('qr--set-itemMessage'); |
| 295 | mes.value = this.message; | 289 | mes.value = this.message; |
| 296 | //HACK need to use jQuery to catch the triggered event from the expanded editor | 290 | //HACK need to use jQuery to catch the triggered event from the expanded editor |
| 297 | $(mes).on('input', ()=>this.updateMessage(mes.value)); | 291 | $(mes).on('input', () => this.updateMessage(mes.value)); |
| 298 | itemContent.append(mes); | 292 | itemContent.append(mes); |
| 299 | } | 293 | } |
| 300 | const actions = document.createElement('div'); { | 294 | const actions = document.createElement('div'); { |
| @@ -306,7 +300,7 @@ export class QuickReply { | |||
| 306 | move.classList.add('fa-solid'); | 300 | move.classList.add('fa-solid'); |
| 307 | move.classList.add('fa-truck-arrow-right'); | 301 | move.classList.add('fa-truck-arrow-right'); |
| 308 | move.title = 'Move quick reply to other set'; | 302 | move.title = 'Move quick reply to other set'; |
| 309 | move.addEventListener('click', ()=>this.onTransfer(this)); | 303 | move.addEventListener('click', () => this.onTransfer(this)); |
| 310 | actions.append(move); | 304 | actions.append(move); |
| 311 | } | 305 | } |
| 312 | const copy = document.createElement('div'); { | 306 | const copy = document.createElement('div'); { |
| @@ -316,7 +310,7 @@ export class QuickReply { | |||
| 316 | copy.classList.add('fa-solid'); | 310 | copy.classList.add('fa-solid'); |
| 317 | copy.classList.add('fa-copy'); | 311 | copy.classList.add('fa-copy'); |
| 318 | copy.title = 'Copy quick reply to clipboard'; | 312 | copy.title = 'Copy quick reply to clipboard'; |
| 319 | copy.addEventListener('click', async()=>{ | 313 | copy.addEventListener('click', async () => { |
| 320 | await navigator.clipboard.writeText(JSON.stringify(this)); | 314 | await navigator.clipboard.writeText(JSON.stringify(this)); |
| 321 | copy.classList.add('qr--success'); | 315 | copy.classList.add('qr--success'); |
| 322 | await delay(3010); | 316 | await delay(3010); |
| @@ -331,7 +325,7 @@ export class QuickReply { | |||
| 331 | cut.classList.add('fa-solid'); | 325 | cut.classList.add('fa-solid'); |
| 332 | cut.classList.add('fa-cut'); | 326 | cut.classList.add('fa-cut'); |
| 333 | cut.title = 'Cut quick reply to clipboard (copy and remove)'; | 327 | cut.title = 'Cut quick reply to clipboard (copy and remove)'; |
| 334 | cut.addEventListener('click', async()=>{ | 328 | cut.addEventListener('click', async () => { |
| 335 | await navigator.clipboard.writeText(JSON.stringify(this)); | 329 | await navigator.clipboard.writeText(JSON.stringify(this)); |
| 336 | this.delete(); | 330 | this.delete(); |
| 337 | }); | 331 | }); |
| @@ -344,8 +338,8 @@ export class QuickReply { | |||
| 344 | exp.classList.add('fa-solid'); | 338 | exp.classList.add('fa-solid'); |
| 345 | exp.classList.add('fa-file-export'); | 339 | exp.classList.add('fa-file-export'); |
| 346 | exp.title = 'Export quick reply as file'; | 340 | exp.title = 'Export quick reply as file'; |
| 347 | exp.addEventListener('click', ()=>{ | 341 | exp.addEventListener('click', () => { |
| 348 | const blob = new Blob([JSON.stringify(this)], { type:'text' }); | 342 | const blob = new Blob([JSON.stringify(this)], { type: 'text' }); |
| 349 | const url = URL.createObjectURL(blob); | 343 | const url = URL.createObjectURL(blob); |
| 350 | const a = document.createElement('a'); { | 344 | const a = document.createElement('a'); { |
| 351 | a.href = url; | 345 | a.href = url; |
| @@ -363,7 +357,7 @@ export class QuickReply { | |||
| 363 | del.classList.add('fa-trash-can'); | 357 | del.classList.add('fa-trash-can'); |
| 364 | del.classList.add('redWarningBG'); | 358 | del.classList.add('redWarningBG'); |
| 365 | del.title = 'Remove Quick Reply\n---\nShift+Click to skip confirmation'; | 359 | del.title = 'Remove Quick Reply\n---\nShift+Click to skip confirmation'; |
| 366 | del.addEventListener('click', async(evt)=>{ | 360 | del.addEventListener('click', async (evt) => { |
| 367 | if (!evt.shiftKey) { | 361 | if (!evt.shiftKey) { |
| 368 | const result = await Popup.show.confirm( | 362 | const result = await Popup.show.confirm( |
| 369 | 'Remove Quick Reply', | 363 | 'Remove Quick Reply', |
| @@ -408,7 +402,7 @@ export class QuickReply { | |||
| 408 | else { | 402 | else { |
| 409 | icon.textContent = '…'; | 403 | icon.textContent = '…'; |
| 410 | } | 404 | } |
| 411 | icon.addEventListener('click', async()=>{ | 405 | icon.addEventListener('click', async () => { |
| 412 | let value = await showFontAwesomePicker(); | 406 | let value = await showFontAwesomePicker(); |
| 413 | if (value === null) return; | 407 | if (value === null) return; |
| 414 | if (this.icon) icon.classList.remove(this.icon); | 408 | if (this.icon) icon.classList.remove(this.icon); |
| @@ -425,18 +419,18 @@ export class QuickReply { | |||
| 425 | /**@type {HTMLInputElement}*/ | 419 | /**@type {HTMLInputElement}*/ |
| 426 | const showLabel = dom.querySelector('#qr--modal-showLabel'); | 420 | const showLabel = dom.querySelector('#qr--modal-showLabel'); |
| 427 | showLabel.checked = this.showLabel; | 421 | showLabel.checked = this.showLabel; |
| 428 | showLabel.addEventListener('click', ()=>{ | 422 | showLabel.addEventListener('click', () => { |
| 429 | this.updateShowLabel(showLabel.checked); | 423 | this.updateShowLabel(showLabel.checked); |
| 430 | }); | 424 | }); |
| 431 | /**@type {HTMLInputElement}*/ | 425 | /**@type {HTMLInputElement}*/ |
| 432 | const label = dom.querySelector('#qr--modal-label'); | 426 | const label = dom.querySelector('#qr--modal-label'); |
| 433 | label.value = this.label; | 427 | label.value = this.label; |
| 434 | label.addEventListener('input', ()=>{ | 428 | label.addEventListener('input', () => { |
| 435 | this.updateLabel(label.value); | 429 | this.updateLabel(label.value); |
| 436 | }); | 430 | }); |
| 437 | let switcherList; | 431 | let switcherList; |
| 438 | // @ts-ignore | 432 | // @ts-ignore |
| 439 | dom.querySelector('#qr--modal-switcher').addEventListener('click', (evt)=>{ | 433 | dom.querySelector('#qr--modal-switcher').addEventListener('click', (evt) => { |
| 440 | if (switcherList) { | 434 | if (switcherList) { |
| 441 | switcherList.remove(); | 435 | switcherList.remove(); |
| 442 | switcherList = null; | 436 | switcherList = null; |
| @@ -445,15 +439,15 @@ export class QuickReply { | |||
| 445 | const list = document.createElement('ul'); { | 439 | const list = document.createElement('ul'); { |
| 446 | switcherList = list; | 440 | switcherList = list; |
| 447 | list.classList.add('qr--modal-switcherList'); | 441 | list.classList.add('qr--modal-switcherList'); |
| 448 | const makeList = (qrs)=>{ | 442 | const makeList = (qrs) => { |
| 449 | const setItem = document.createElement('li'); { | 443 | const setItem = document.createElement('li'); { |
| 450 | setItem.classList.add('qr--modal-switcherItem'); | 444 | setItem.classList.add('qr--modal-switcherItem'); |
| 451 | setItem.addEventListener('click', ()=>{ | 445 | setItem.addEventListener('click', () => { |
| 452 | list.innerHTML = ''; | 446 | list.innerHTML = ''; |
| 453 | for (const qrs of quickReplyApi.listSets()) { | 447 | for (const qrs of quickReplyApi.listSets()) { |
| 454 | const item = document.createElement('li'); { | 448 | const item = document.createElement('li'); { |
| 455 | item.classList.add('qr--modal-switcherItem'); | 449 | item.classList.add('qr--modal-switcherItem'); |
| 456 | item.addEventListener('click', ()=>{ | 450 | item.addEventListener('click', () => { |
| 457 | list.innerHTML = ''; | 451 | list.innerHTML = ''; |
| 458 | makeList(quickReplyApi.getSetByName(qrs)); | 452 | makeList(quickReplyApi.getSetByName(qrs)); |
| 459 | }); | 453 | }); |
| @@ -484,7 +478,7 @@ export class QuickReply { | |||
| 484 | } | 478 | } |
| 485 | const addItem = document.createElement('li'); { | 479 | const addItem = document.createElement('li'); { |
| 486 | addItem.classList.add('qr--modal-switcherItem'); | 480 | addItem.classList.add('qr--modal-switcherItem'); |
| 487 | addItem.addEventListener('click', ()=>{ | 481 | addItem.addEventListener('click', () => { |
| 488 | const qr = quickReplyApi.getSetByQr(this).addQuickReply(); | 482 | const qr = quickReplyApi.getSetByQr(this).addQuickReply(); |
| 489 | this.editorPopup.completeAffirmative(); | 483 | this.editorPopup.completeAffirmative(); |
| 490 | qr.showEditor(); | 484 | qr.showEditor(); |
| @@ -505,11 +499,11 @@ export class QuickReply { | |||
| 505 | } | 499 | } |
| 506 | list.append(addItem); | 500 | list.append(addItem); |
| 507 | } | 501 | } |
| 508 | for (const qr of qrs.qrList.toSorted((a,b)=>a.label.toLowerCase().localeCompare(b.label.toLowerCase()))) { | 502 | for (const qr of qrs.qrList.toSorted((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase()))) { |
| 509 | const item = document.createElement('li'); { | 503 | const item = document.createElement('li'); { |
| 510 | item.classList.add('qr--modal-switcherItem'); | 504 | item.classList.add('qr--modal-switcherItem'); |
| 511 | if (qr == this) item.classList.add('qr--current'); | 505 | if (qr == this) item.classList.add('qr--current'); |
| 512 | else item.addEventListener('click', ()=>{ | 506 | else item.addEventListener('click', () => { |
| 513 | this.editorPopup.completeAffirmative(); | 507 | this.editorPopup.completeAffirmative(); |
| 514 | qr.showEditor(); | 508 | qr.showEditor(); |
| 515 | }); | 509 | }); |
| @@ -588,7 +582,7 @@ export class QuickReply { | |||
| 588 | }); | 582 | }); |
| 589 | }; | 583 | }; |
| 590 | const updateScrollDebounced = updateScroll; | 584 | const updateScrollDebounced = updateScroll; |
| 591 | const updateSyntaxEnabled = ()=>{ | 585 | const updateSyntaxEnabled = () => { |
| 592 | if (syntax.checked) { | 586 | if (syntax.checked) { |
| 593 | dom.querySelector('#qr--modal-messageHolder').classList.remove('qr--noSyntax'); | 587 | dom.querySelector('#qr--modal-messageHolder').classList.remove('qr--noSyntax'); |
| 594 | } else { | 588 | } else { |
| @@ -623,7 +617,7 @@ export class QuickReply { | |||
| 623 | // @ts-ignore | 617 | // @ts-ignore |
| 624 | if (navigator.keyboard) { | 618 | if (navigator.keyboard) { |
| 625 | // @ts-ignore | 619 | // @ts-ignore |
| 626 | navigator.keyboard.getLayoutMap().then(it=>dom.querySelector('#qr--modal-commentKey').textContent = it.get('Backslash')); | 620 | navigator.keyboard.getLayoutMap().then(it => dom.querySelector('#qr--modal-commentKey').textContent = it.get('Backslash')); |
| 627 | } else { | 621 | } else { |
| 628 | dom.querySelector('#qr--modal-commentKey').closest('small').remove(); | 622 | dom.querySelector('#qr--modal-commentKey').closest('small').remove(); |
| 629 | } | 623 | } |
| @@ -632,12 +626,12 @@ export class QuickReply { | |||
| 632 | const message = dom.querySelector('#qr--modal-message'); | 626 | const message = dom.querySelector('#qr--modal-message'); |
| 633 | this.editorMessage = message; | 627 | this.editorMessage = message; |
| 634 | message.value = this.message; | 628 | message.value = this.message; |
| 635 | const updateMessageDebounced = debounce((value)=>this.updateMessage(value), 10); | 629 | const updateMessageDebounced = debounce((value) => this.updateMessage(value), 10); |
| 636 | message.addEventListener('input', () => { | 630 | message.addEventListener('input', () => { |
| 637 | updateMessageDebounced(message.value); | 631 | updateMessageDebounced(message.value); |
| 638 | updateScrollDebounced(); | 632 | updateScrollDebounced(); |
| 639 | }, { passive:true }); | 633 | }, { passive: true }); |
| 640 | const getLineStart = ()=>{ | 634 | const getLineStart = () => { |
| 641 | const start = message.selectionStart; | 635 | const start = message.selectionStart; |
| 642 | let lineStart; | 636 | let lineStart; |
| 643 | if (start == 0 || message.value[start - 1] == '\n') { | 637 | if (start == 0 || message.value[start - 1] == '\n') { |
| @@ -651,7 +645,7 @@ export class QuickReply { | |||
| 651 | } | 645 | } |
| 652 | return lineStart; | 646 | return lineStart; |
| 653 | }; | 647 | }; |
| 654 | message.addEventListener('keydown', async(evt) => { | 648 | message.addEventListener('keydown', async (evt) => { |
| 655 | if (this.isExecuting) return; | 649 | if (this.isExecuting) return; |
| 656 | if (evt.key == 'Tab' && !evt.shiftKey && !evt.ctrlKey && !evt.altKey) { | 650 | if (evt.key == 'Tab' && !evt.shiftKey && !evt.ctrlKey && !evt.altKey) { |
| 657 | // increase indent | 651 | // increase indent |
| @@ -668,13 +662,13 @@ export class QuickReply { | |||
| 668 | document.execCommand('insertText', false, `\t${affectedLines.join('\n\t')}`); | 662 | document.execCommand('insertText', false, `\t${affectedLines.join('\n\t')}`); |
| 669 | message.selectionStart = start + 1; | 663 | message.selectionStart = start + 1; |
| 670 | message.selectionEnd = end + affectedLines.length; | 664 | message.selectionEnd = end + affectedLines.length; |
| 671 | message.dispatchEvent(new Event('input', { bubbles:true })); | 665 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 672 | } else if (!(ac.isReplaceable && ac.isActive)) { | 666 | } else if (!(ac.isReplaceable && ac.isActive)) { |
| 673 | evt.stopImmediatePropagation(); | 667 | evt.stopImmediatePropagation(); |
| 674 | evt.stopPropagation(); | 668 | evt.stopPropagation(); |
| 675 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history | 669 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history |
| 676 | document.execCommand('insertText', false, '\t'); | 670 | document.execCommand('insertText', false, '\t'); |
| 677 | message.dispatchEvent(new Event('input', { bubbles:true })); | 671 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 678 | } | 672 | } |
| 679 | } else if (evt.key == 'Tab' && evt.shiftKey && !evt.ctrlKey && !evt.altKey) { | 673 | } else if (evt.key == 'Tab' && evt.shiftKey && !evt.ctrlKey && !evt.altKey) { |
| 680 | // decrease indent | 674 | // decrease indent |
| @@ -686,7 +680,7 @@ export class QuickReply { | |||
| 686 | const lineStart = getLineStart(); | 680 | const lineStart = getLineStart(); |
| 687 | message.selectionStart = lineStart; | 681 | message.selectionStart = lineStart; |
| 688 | const affectedLines = message.value.substring(lineStart, end).split('\n'); | 682 | const affectedLines = message.value.substring(lineStart, end).split('\n'); |
| 689 | const newText = affectedLines.map(it=>it.replace(/^\t/, '')).join('\n'); | 683 | const newText = affectedLines.map(it => it.replace(/^\t/, '')).join('\n'); |
| 690 | const delta = affectedLines.join('\n').length - newText.length; | 684 | const delta = affectedLines.join('\n').length - newText.length; |
| 691 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history | 685 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history |
| 692 | if (delta > 0) { | 686 | if (delta > 0) { |
| @@ -697,7 +691,7 @@ export class QuickReply { | |||
| 697 | } | 691 | } |
| 698 | message.selectionStart = start - (affectedLines[0].startsWith('\t') ? 1 : 0); | 692 | message.selectionStart = start - (affectedLines[0].startsWith('\t') ? 1 : 0); |
| 699 | message.selectionEnd = end - delta; | 693 | message.selectionEnd = end - delta; |
| 700 | message.dispatchEvent(new Event('input', { bubbles:true })); | 694 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 701 | } else { | 695 | } else { |
| 702 | message.selectionStart = start; | 696 | message.selectionStart = start; |
| 703 | } | 697 | } |
| @@ -714,7 +708,7 @@ export class QuickReply { | |||
| 714 | document.execCommand('insertText', false, `\n${indent}`); | 708 | document.execCommand('insertText', false, `\n${indent}`); |
| 715 | message.selectionStart = start + 1 + indent.length; | 709 | message.selectionStart = start + 1 + indent.length; |
| 716 | message.selectionEnd = message.selectionStart; | 710 | message.selectionEnd = message.selectionStart; |
| 717 | message.dispatchEvent(new Event('input', { bubbles:true })); | 711 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 718 | } | 712 | } |
| 719 | } else if (evt.key == 'Enter' && evt.ctrlKey && !evt.shiftKey && !evt.altKey) { | 713 | } else if (evt.key == 'Enter' && evt.ctrlKey && !evt.shiftKey && !evt.altKey) { |
| 720 | if (executeShortcut.checked) { | 714 | if (executeShortcut.checked) { |
| @@ -751,7 +745,7 @@ export class QuickReply { | |||
| 751 | parser.parse(message.value, false); | 745 | parser.parse(message.value, false); |
| 752 | const start = message.selectionStart; | 746 | const start = message.selectionStart; |
| 753 | const end = message.selectionEnd; | 747 | const end = message.selectionEnd; |
| 754 | const comment = parser.commandIndex.findLast(it=>it.name == '*' && (it.start <= start && it.end >= start || it.start <= end && it.end >= end)); | 748 | const comment = parser.commandIndex.findLast(it => it.name == '*' && (it.start <= start && it.end >= start || it.start <= end && it.end >= end)); |
| 755 | if (comment) { | 749 | if (comment) { |
| 756 | // uncomment | 750 | // uncomment |
| 757 | let content = message.value.slice(comment.start + 1, comment.end - 1); | 751 | let content = message.value.slice(comment.start + 1, comment.end - 1); |
| @@ -778,15 +772,15 @@ export class QuickReply { | |||
| 778 | message.selectionStart = start + 3; | 772 | message.selectionStart = start + 3; |
| 779 | message.selectionEnd = end + 3; | 773 | message.selectionEnd = end + 3; |
| 780 | } | 774 | } |
| 781 | message.dispatchEvent(new Event('input', { bubbles:true })); | 775 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 782 | } | 776 | } |
| 783 | }); | 777 | }); |
| 784 | const ac = await setSlashCommandAutoComplete(message, true); | 778 | const ac = await setSlashCommandAutoComplete(message, true); |
| 785 | message.addEventListener('wheel', (evt)=>{ | 779 | message.addEventListener('wheel', (evt) => { |
| 786 | updateScrollDebounced(evt); | 780 | updateScrollDebounced(evt); |
| 787 | }); | 781 | }); |
| 788 | // @ts-ignore | 782 | // @ts-ignore |
| 789 | message.addEventListener('scroll', (evt)=>{ | 783 | message.addEventListener('scroll', (evt) => { |
| 790 | updateScrollDebounced(); | 784 | updateScrollDebounced(); |
| 791 | }); | 785 | }); |
| 792 | let preBreakPointStart; | 786 | let preBreakPointStart; |
| @@ -794,7 +788,7 @@ export class QuickReply { | |||
| 794 | /** | 788 | /** |
| 795 | * @param {SlashCommandBreakPoint} bp | 789 | * @param {SlashCommandBreakPoint} bp |
| 796 | */ | 790 | */ |
| 797 | const removeBreakpoint = (bp)=>{ | 791 | const removeBreakpoint = (bp) => { |
| 798 | // start at -1 because "/" is not included in start-end | 792 | // start at -1 because "/" is not included in start-end |
| 799 | let start = bp.start - 1; | 793 | let start = bp.start - 1; |
| 800 | // step left until forward slash "/" | 794 | // step left until forward slash "/" |
| @@ -812,7 +806,7 @@ export class QuickReply { | |||
| 812 | message.selectionEnd = end; | 806 | message.selectionEnd = end; |
| 813 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history | 807 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history |
| 814 | document.execCommand('insertText', false, ''); | 808 | document.execCommand('insertText', false, ''); |
| 815 | message.dispatchEvent(new Event('input', { bubbles:true })); | 809 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 816 | let postStart = preBreakPointStart; | 810 | let postStart = preBreakPointStart; |
| 817 | let postEnd = preBreakPointEnd; | 811 | let postEnd = preBreakPointEnd; |
| 818 | // set caret back to where it was | 812 | // set caret back to where it was |
| @@ -834,12 +828,12 @@ export class QuickReply { | |||
| 834 | // selection end was behind breakpoint: move back by length of removed string | 828 | // selection end was behind breakpoint: move back by length of removed string |
| 835 | postEnd = preBreakPointEnd - (end - start); | 829 | postEnd = preBreakPointEnd - (end - start); |
| 836 | } | 830 | } |
| 837 | return { start:postStart, end:postEnd }; | 831 | return { start: postStart, end: postEnd }; |
| 838 | }; | 832 | }; |
| 839 | /** | 833 | /** |
| 840 | * @param {SlashCommandExecutor} cmd | 834 | * @param {SlashCommandExecutor} cmd |
| 841 | */ | 835 | */ |
| 842 | const addBreakpoint = (cmd)=>{ | 836 | const addBreakpoint = (cmd) => { |
| 843 | // start at -1 because "/" is not included in start-end | 837 | // start at -1 because "/" is not included in start-end |
| 844 | let start = cmd.start - 1; | 838 | let start = cmd.start - 1; |
| 845 | let indent = ''; | 839 | let indent = ''; |
| @@ -860,16 +854,16 @@ export class QuickReply { | |||
| 860 | message.selectionEnd = start; | 854 | message.selectionEnd = start; |
| 861 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history | 855 | // document.execCommand is deprecated (and potentially buggy in some browsers) but the only way to retain undo-history |
| 862 | document.execCommand('insertText', false, breakpointText); | 856 | document.execCommand('insertText', false, breakpointText); |
| 863 | message.dispatchEvent(new Event('input', { bubbles:true })); | 857 | message.dispatchEvent(new Event('input', { bubbles: true })); |
| 864 | return breakpointText.length; | 858 | return breakpointText.length; |
| 865 | }; | 859 | }; |
| 866 | const toggleBreakpoint = ()=>{ | 860 | const toggleBreakpoint = () => { |
| 867 | const idx = message.selectionStart; | 861 | const idx = message.selectionStart; |
| 868 | let postStart = preBreakPointStart; | 862 | let postStart = preBreakPointStart; |
| 869 | let postEnd = preBreakPointEnd; | 863 | let postEnd = preBreakPointEnd; |
| 870 | const parser = new SlashCommandParser(); | 864 | const parser = new SlashCommandParser(); |
| 871 | parser.parse(message.value, false); | 865 | parser.parse(message.value, false); |
| 872 | const cmdIdx = parser.commandIndex.findLastIndex(it=>it.start <= idx); | 866 | const cmdIdx = parser.commandIndex.findLastIndex(it => it.start <= idx); |
| 873 | if (cmdIdx > -1) { | 867 | if (cmdIdx > -1) { |
| 874 | const cmd = parser.commandIndex[cmdIdx]; | 868 | const cmd = parser.commandIndex[cmdIdx]; |
| 875 | if (cmd instanceof SlashCommandBreakPoint) { | 869 | if (cmd instanceof SlashCommandBreakPoint) { |
| @@ -891,12 +885,12 @@ export class QuickReply { | |||
| 891 | message.selectionEnd = postEnd; | 885 | message.selectionEnd = postEnd; |
| 892 | } | 886 | } |
| 893 | }; | 887 | }; |
| 894 | message.addEventListener('pointerdown', (evt)=>{ | 888 | message.addEventListener('pointerdown', (evt) => { |
| 895 | if (!evt.ctrlKey || !evt.altKey) return; | 889 | if (!evt.ctrlKey || !evt.altKey) return; |
| 896 | preBreakPointStart = message.selectionStart; | 890 | preBreakPointStart = message.selectionStart; |
| 897 | preBreakPointEnd = message.selectionEnd; | 891 | preBreakPointEnd = message.selectionEnd; |
| 898 | }); | 892 | }); |
| 899 | message.addEventListener('pointerup', async(evt)=>{ | 893 | message.addEventListener('pointerup', async (evt) => { |
| 900 | if (!evt.ctrlKey || !evt.altKey || message.selectionStart != message.selectionEnd) return; | 894 | if (!evt.ctrlKey || !evt.altKey || message.selectionStart != message.selectionEnd) return; |
| 901 | toggleBreakpoint(); | 895 | toggleBreakpoint(); |
| 902 | }); | 896 | }); |
| @@ -910,11 +904,11 @@ export class QuickReply { | |||
| 910 | }); | 904 | }); |
| 911 | window.addEventListener('resize', resizeListener); | 905 | window.addEventListener('resize', resizeListener); |
| 912 | updateSyntaxEnabled(); | 906 | updateSyntaxEnabled(); |
| 913 | const updateSyntax = ()=>{ | 907 | const updateSyntax = () => { |
| 914 | if (messageSyntaxInner && syntax.checked) { | 908 | if (messageSyntaxInner && syntax.checked) { |
| 915 | morphdom( | 909 | morphdom( |
| 916 | messageSyntaxInner, | 910 | messageSyntaxInner, |
| 917 | `<div>${hljs.highlight(`${message.value}${message.value.slice(-1) == '\n' ? ' ' : ''}`, { language:'stscript', ignoreIllegals:true })?.value}</div>`, | 911 | `<div>${hljs.highlight(`${message.value}${message.value.slice(-1) == '\n' ? ' ' : ''}`, { language: 'stscript', ignoreIllegals: true })?.value}</div>`, |
| 918 | { childrenOnly: true }, | 912 | { childrenOnly: true }, |
| 919 | ); | 913 | ); |
| 920 | updateScrollDebounced(); | 914 | updateScrollDebounced(); |
| @@ -924,7 +918,7 @@ export class QuickReply { | |||
| 924 | const fpsTime = 1000 / 30; | 918 | const fpsTime = 1000 / 30; |
| 925 | let lastMessageValue = null; | 919 | let lastMessageValue = null; |
| 926 | let wasSyntax = null; | 920 | let wasSyntax = null; |
| 927 | const updateSyntaxLoop = ()=>{ | 921 | const updateSyntaxLoop = () => { |
| 928 | const now = Date.now(); | 922 | const now = Date.now(); |
| 929 | // fps limit | 923 | // fps limit |
| 930 | if (now - lastSyntaxUpdate < fpsTime) return requestAnimationFrame(updateSyntaxLoop); | 924 | if (now - lastSyntaxUpdate < fpsTime) return requestAnimationFrame(updateSyntaxLoop); |
| @@ -945,7 +939,7 @@ export class QuickReply { | |||
| 945 | updateSyntax(); | 939 | updateSyntax(); |
| 946 | requestAnimationFrame(updateSyntaxLoop); | 940 | requestAnimationFrame(updateSyntaxLoop); |
| 947 | }; | 941 | }; |
| 948 | requestAnimationFrame(()=>updateSyntaxLoop()); | 942 | requestAnimationFrame(() => updateSyntaxLoop()); |
| 949 | message.style.setProperty('text-shadow', 'none', 'important'); | 943 | message.style.setProperty('text-shadow', 'none', 'important'); |
| 950 | updateWrap(); | 944 | updateWrap(); |
| 951 | updateTabSize(); | 945 | updateTabSize(); |
| @@ -955,7 +949,7 @@ export class QuickReply { | |||
| 955 | const tpl = dom.querySelector('#qr--ctxItem'); | 949 | const tpl = dom.querySelector('#qr--ctxItem'); |
| 956 | const linkList = dom.querySelector('#qr--ctxEditor'); | 950 | const linkList = dom.querySelector('#qr--ctxEditor'); |
| 957 | const fillQrSetSelect = (/**@type {HTMLSelectElement}*/select, /**@type {QuickReplyContextLink}*/ link) => { | 951 | const fillQrSetSelect = (/**@type {HTMLSelectElement}*/select, /**@type {QuickReplyContextLink}*/ link) => { |
| 958 | [{ name: 'Select a QR set' }, ...QuickReplySet.list.toSorted((a,b)=>a.name.toLowerCase().localeCompare(b.name.toLowerCase()))].forEach(qrs => { | 952 | [{ name: 'Select a QR set' }, ...QuickReplySet.list.toSorted((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))].forEach(qrs => { |
| 959 | const opt = document.createElement('option'); { | 953 | const opt = document.createElement('option'); { |
| 960 | opt.value = qrs.name; | 954 | opt.value = qrs.name; |
| 961 | opt.textContent = qrs.name; | 955 | opt.textContent = qrs.name; |
| @@ -1002,7 +996,7 @@ export class QuickReply { | |||
| 1002 | addCtxItem(link, this.contextList.length - 1); | 996 | addCtxItem(link, this.contextList.length - 1); |
| 1003 | }); | 997 | }); |
| 1004 | const onContextSort = () => { | 998 | const onContextSort = () => { |
| 1005 | this.contextList = Array.from(linkList.querySelectorAll('.qr--ctxItem')).map((it,idx) => { | 999 | this.contextList = Array.from(linkList.querySelectorAll('.qr--ctxItem')).map((it, idx) => { |
| 1006 | const link = this.contextList[Number(it.getAttribute('data-order'))]; | 1000 | const link = this.contextList[Number(it.getAttribute('data-order'))]; |
| 1007 | it.setAttribute('data-order', String(idx)); | 1001 | it.setAttribute('data-order', String(idx)); |
| 1008 | return link; | 1002 | return link; |
| @@ -1019,63 +1013,63 @@ export class QuickReply { | |||
| 1019 | /**@type {HTMLInputElement}*/ | 1013 | /**@type {HTMLInputElement}*/ |
| 1020 | const preventAutoExecute = dom.querySelector('#qr--preventAutoExecute'); | 1014 | const preventAutoExecute = dom.querySelector('#qr--preventAutoExecute'); |
| 1021 | preventAutoExecute.checked = this.preventAutoExecute; | 1015 | preventAutoExecute.checked = this.preventAutoExecute; |
| 1022 | preventAutoExecute.addEventListener('click', ()=>{ | 1016 | preventAutoExecute.addEventListener('click', () => { |
| 1023 | this.preventAutoExecute = preventAutoExecute.checked; | 1017 | this.preventAutoExecute = preventAutoExecute.checked; |
| 1024 | this.updateContext(); | 1018 | this.updateContext(); |
| 1025 | }); | 1019 | }); |
| 1026 | /**@type {HTMLInputElement}*/ | 1020 | /**@type {HTMLInputElement}*/ |
| 1027 | const isHidden = dom.querySelector('#qr--isHidden'); | 1021 | const isHidden = dom.querySelector('#qr--isHidden'); |
| 1028 | isHidden.checked = this.isHidden; | 1022 | isHidden.checked = this.isHidden; |
| 1029 | isHidden.addEventListener('click', ()=>{ | 1023 | isHidden.addEventListener('click', () => { |
| 1030 | this.isHidden = isHidden.checked; | 1024 | this.isHidden = isHidden.checked; |
| 1031 | this.updateContext(); | 1025 | this.updateContext(); |
| 1032 | }); | 1026 | }); |
| 1033 | /**@type {HTMLInputElement}*/ | 1027 | /**@type {HTMLInputElement}*/ |
| 1034 | const executeOnStartup = dom.querySelector('#qr--executeOnStartup'); | 1028 | const executeOnStartup = dom.querySelector('#qr--executeOnStartup'); |
| 1035 | executeOnStartup.checked = this.executeOnStartup; | 1029 | executeOnStartup.checked = this.executeOnStartup; |
| 1036 | executeOnStartup.addEventListener('click', ()=>{ | 1030 | executeOnStartup.addEventListener('click', () => { |
| 1037 | this.executeOnStartup = executeOnStartup.checked; | 1031 | this.executeOnStartup = executeOnStartup.checked; |
| 1038 | this.updateContext(); | 1032 | this.updateContext(); |
| 1039 | }); | 1033 | }); |
| 1040 | /**@type {HTMLInputElement}*/ | 1034 | /**@type {HTMLInputElement}*/ |
| 1041 | const executeOnUser = dom.querySelector('#qr--executeOnUser'); | 1035 | const executeOnUser = dom.querySelector('#qr--executeOnUser'); |
| 1042 | executeOnUser.checked = this.executeOnUser; | 1036 | executeOnUser.checked = this.executeOnUser; |
| 1043 | executeOnUser.addEventListener('click', ()=>{ | 1037 | executeOnUser.addEventListener('click', () => { |
| 1044 | this.executeOnUser = executeOnUser.checked; | 1038 | this.executeOnUser = executeOnUser.checked; |
| 1045 | this.updateContext(); | 1039 | this.updateContext(); |
| 1046 | }); | 1040 | }); |
| 1047 | /**@type {HTMLInputElement}*/ | 1041 | /**@type {HTMLInputElement}*/ |
| 1048 | const executeOnAi = dom.querySelector('#qr--executeOnAi'); | 1042 | const executeOnAi = dom.querySelector('#qr--executeOnAi'); |
| 1049 | executeOnAi.checked = this.executeOnAi; | 1043 | executeOnAi.checked = this.executeOnAi; |
| 1050 | executeOnAi.addEventListener('click', ()=>{ | 1044 | executeOnAi.addEventListener('click', () => { |
| 1051 | this.executeOnAi = executeOnAi.checked; | 1045 | this.executeOnAi = executeOnAi.checked; |
| 1052 | this.updateContext(); | 1046 | this.updateContext(); |
| 1053 | }); | 1047 | }); |
| 1054 | /**@type {HTMLInputElement}*/ | 1048 | /**@type {HTMLInputElement}*/ |
| 1055 | const executeOnChatChange = dom.querySelector('#qr--executeOnChatChange'); | 1049 | const executeOnChatChange = dom.querySelector('#qr--executeOnChatChange'); |
| 1056 | executeOnChatChange.checked = this.executeOnChatChange; | 1050 | executeOnChatChange.checked = this.executeOnChatChange; |
| 1057 | executeOnChatChange.addEventListener('click', ()=>{ | 1051 | executeOnChatChange.addEventListener('click', () => { |
| 1058 | this.executeOnChatChange = executeOnChatChange.checked; | 1052 | this.executeOnChatChange = executeOnChatChange.checked; |
| 1059 | this.updateContext(); | 1053 | this.updateContext(); |
| 1060 | }); | 1054 | }); |
| 1061 | /**@type {HTMLInputElement}*/ | 1055 | /**@type {HTMLInputElement}*/ |
| 1062 | const executeOnGroupMemberDraft = dom.querySelector('#qr--executeOnGroupMemberDraft'); | 1056 | const executeOnGroupMemberDraft = dom.querySelector('#qr--executeOnGroupMemberDraft'); |
| 1063 | executeOnGroupMemberDraft.checked = this.executeOnGroupMemberDraft; | 1057 | executeOnGroupMemberDraft.checked = this.executeOnGroupMemberDraft; |
| 1064 | executeOnGroupMemberDraft.addEventListener('click', ()=>{ | 1058 | executeOnGroupMemberDraft.addEventListener('click', () => { |
| 1065 | this.executeOnGroupMemberDraft = executeOnGroupMemberDraft.checked; | 1059 | this.executeOnGroupMemberDraft = executeOnGroupMemberDraft.checked; |
| 1066 | this.updateContext(); | 1060 | this.updateContext(); |
| 1067 | }); | 1061 | }); |
| 1068 | /**@type {HTMLInputElement}*/ | 1062 | /**@type {HTMLInputElement}*/ |
| 1069 | const executeBeforeGeneration = dom.querySelector('#qr--executeBeforeGeneration'); | 1063 | const executeBeforeGeneration = dom.querySelector('#qr--executeBeforeGeneration'); |
| 1070 | executeBeforeGeneration.checked = this.executeBeforeGeneration; | 1064 | executeBeforeGeneration.checked = this.executeBeforeGeneration; |
| 1071 | executeBeforeGeneration.addEventListener('click', ()=>{ | 1065 | executeBeforeGeneration.addEventListener('click', () => { |
| 1072 | this.executeBeforeGeneration = executeBeforeGeneration.checked; | 1066 | this.executeBeforeGeneration = executeBeforeGeneration.checked; |
| 1073 | this.updateContext(); | 1067 | this.updateContext(); |
| 1074 | }); | 1068 | }); |
| 1075 | /**@type {HTMLInputElement}*/ | 1069 | /**@type {HTMLInputElement}*/ |
| 1076 | const executeOnNewChat = dom.querySelector('#qr--executeOnNewChat'); | 1070 | const executeOnNewChat = dom.querySelector('#qr--executeOnNewChat'); |
| 1077 | executeOnNewChat.checked = this.executeOnNewChat; | 1071 | executeOnNewChat.checked = this.executeOnNewChat; |
| 1078 | executeOnNewChat.addEventListener('click', ()=>{ | 1072 | executeOnNewChat.addEventListener('click', () => { |
| 1079 | this.executeOnNewChat = executeOnNewChat.checked; | 1073 | this.executeOnNewChat = executeOnNewChat.checked; |
| 1080 | this.updateContext(); | 1074 | this.updateContext(); |
| 1081 | }); | 1075 | }); |
| @@ -1102,13 +1096,13 @@ export class QuickReply { | |||
| 1102 | /**@type {HTMLElement}*/ | 1096 | /**@type {HTMLElement}*/ |
| 1103 | const executeBtn = dom.querySelector('#qr--modal-execute'); | 1097 | const executeBtn = dom.querySelector('#qr--modal-execute'); |
| 1104 | this.editorExecuteBtn = executeBtn; | 1098 | this.editorExecuteBtn = executeBtn; |
| 1105 | executeBtn.addEventListener('click', async()=>{ | 1099 | executeBtn.addEventListener('click', async () => { |
| 1106 | await this.executeFromEditor(); | 1100 | await this.executeFromEditor(); |
| 1107 | }); | 1101 | }); |
| 1108 | /**@type {HTMLElement}*/ | 1102 | /**@type {HTMLElement}*/ |
| 1109 | const executeBtnPause = dom.querySelector('#qr--modal-pause'); | 1103 | const executeBtnPause = dom.querySelector('#qr--modal-pause'); |
| 1110 | this.editorExecuteBtnPause = executeBtnPause; | 1104 | this.editorExecuteBtnPause = executeBtnPause; |
| 1111 | executeBtnPause.addEventListener('click', async()=>{ | 1105 | executeBtnPause.addEventListener('click', async () => { |
| 1112 | if (this.abortController) { | 1106 | if (this.abortController) { |
| 1113 | if (this.abortController.signal.paused) { | 1107 | if (this.abortController.signal.paused) { |
| 1114 | this.abortController.continue('Continue button clicked'); | 1108 | this.abortController.continue('Continue button clicked'); |
| @@ -1122,7 +1116,7 @@ export class QuickReply { | |||
| 1122 | /**@type {HTMLElement}*/ | 1116 | /**@type {HTMLElement}*/ |
| 1123 | const executeBtnStop = dom.querySelector('#qr--modal-stop'); | 1117 | const executeBtnStop = dom.querySelector('#qr--modal-stop'); |
| 1124 | this.editorExecuteBtnStop = executeBtnStop; | 1118 | this.editorExecuteBtnStop = executeBtnStop; |
| 1125 | executeBtnStop.addEventListener('click', async()=>{ | 1119 | executeBtnStop.addEventListener('click', async () => { |
| 1126 | this.abortController?.abort('Stop button clicked'); | 1120 | this.abortController?.abort('Stop button clicked'); |
| 1127 | }); | 1121 | }); |
| 1128 | 1122 | ||
| @@ -1131,49 +1125,49 @@ export class QuickReply { | |||
| 1131 | const inputMirror = dom.querySelector('#qr--modal-send_textarea'); | 1125 | const inputMirror = dom.querySelector('#qr--modal-send_textarea'); |
| 1132 | // @ts-ignore | 1126 | // @ts-ignore |
| 1133 | inputMirror.value = inputOg.value; | 1127 | inputMirror.value = inputOg.value; |
| 1134 | const inputOgMo = new MutationObserver(muts=>{ | 1128 | const inputOgMo = new MutationObserver(muts => { |
| 1135 | if (muts.find(it=>[...it.removedNodes].includes(inputMirror) || [...it.removedNodes].find(n=>n.contains(inputMirror)))) { | 1129 | if (muts.find(it => [...it.removedNodes].includes(inputMirror) || [...it.removedNodes].find(n => n.contains(inputMirror)))) { |
| 1136 | inputOg.removeEventListener('input', inputOgListener); | 1130 | inputOg.removeEventListener('input', inputOgListener); |
| 1137 | } | 1131 | } |
| 1138 | }); | 1132 | }); |
| 1139 | inputOgMo.observe(document.body, { childList:true }); | 1133 | inputOgMo.observe(document.body, { childList: true }); |
| 1140 | const inputOgListener = ()=>{ | 1134 | const inputOgListener = () => { |
| 1141 | // @ts-ignore | 1135 | // @ts-ignore |
| 1142 | inputMirror.value = inputOg.value; | 1136 | inputMirror.value = inputOg.value; |
| 1143 | }; | 1137 | }; |
| 1144 | inputOg.addEventListener('input', inputOgListener); | 1138 | inputOg.addEventListener('input', inputOgListener); |
| 1145 | inputMirror.addEventListener('input', ()=>{ | 1139 | inputMirror.addEventListener('input', () => { |
| 1146 | // @ts-ignore | 1140 | // @ts-ignore |
| 1147 | inputOg.value = inputMirror.value; | 1141 | inputOg.value = inputMirror.value; |
| 1148 | }); | 1142 | }); |
| 1149 | 1143 | ||
| 1150 | /**@type {HTMLElement}*/ | 1144 | /**@type {HTMLElement}*/ |
| 1151 | const resumeBtn = dom.querySelector('#qr--modal-resume'); | 1145 | const resumeBtn = dom.querySelector('#qr--modal-resume'); |
| 1152 | resumeBtn.addEventListener('click', ()=>{ | 1146 | resumeBtn.addEventListener('click', () => { |
| 1153 | this.debugController?.resume(); | 1147 | this.debugController?.resume(); |
| 1154 | }); | 1148 | }); |
| 1155 | /**@type {HTMLElement}*/ | 1149 | /**@type {HTMLElement}*/ |
| 1156 | const stepBtn = dom.querySelector('#qr--modal-step'); | 1150 | const stepBtn = dom.querySelector('#qr--modal-step'); |
| 1157 | stepBtn.addEventListener('click', ()=>{ | 1151 | stepBtn.addEventListener('click', () => { |
| 1158 | this.debugController?.step(); | 1152 | this.debugController?.step(); |
| 1159 | }); | 1153 | }); |
| 1160 | /**@type {HTMLElement}*/ | 1154 | /**@type {HTMLElement}*/ |
| 1161 | const stepIntoBtn = dom.querySelector('#qr--modal-stepInto'); | 1155 | const stepIntoBtn = dom.querySelector('#qr--modal-stepInto'); |
| 1162 | stepIntoBtn.addEventListener('click', ()=>{ | 1156 | stepIntoBtn.addEventListener('click', () => { |
| 1163 | this.debugController?.stepInto(); | 1157 | this.debugController?.stepInto(); |
| 1164 | }); | 1158 | }); |
| 1165 | /**@type {HTMLElement}*/ | 1159 | /**@type {HTMLElement}*/ |
| 1166 | const stepOutBtn = dom.querySelector('#qr--modal-stepOut'); | 1160 | const stepOutBtn = dom.querySelector('#qr--modal-stepOut'); |
| 1167 | stepOutBtn.addEventListener('click', ()=>{ | 1161 | stepOutBtn.addEventListener('click', () => { |
| 1168 | this.debugController?.stepOut(); | 1162 | this.debugController?.stepOut(); |
| 1169 | }); | 1163 | }); |
| 1170 | /**@type {HTMLElement}*/ | 1164 | /**@type {HTMLElement}*/ |
| 1171 | const minimizeBtn = dom.querySelector('#qr--modal-minimize'); | 1165 | const minimizeBtn = dom.querySelector('#qr--modal-minimize'); |
| 1172 | minimizeBtn.addEventListener('click', ()=>{ | 1166 | minimizeBtn.addEventListener('click', () => { |
| 1173 | this.editorDom.classList.add('qr--minimized'); | 1167 | this.editorDom.classList.add('qr--minimized'); |
| 1174 | }); | 1168 | }); |
| 1175 | const maximizeBtn = dom.querySelector('#qr--modal-maximize'); | 1169 | const maximizeBtn = dom.querySelector('#qr--modal-maximize'); |
| 1176 | maximizeBtn.addEventListener('click', ()=>{ | 1170 | maximizeBtn.addEventListener('click', () => { |
| 1177 | this.editorDom.classList.remove('qr--minimized'); | 1171 | this.editorDom.classList.remove('qr--minimized'); |
| 1178 | }); | 1172 | }); |
| 1179 | /**@type {boolean}*/ | 1173 | /**@type {boolean}*/ |
| @@ -1182,23 +1176,23 @@ export class QuickReply { | |||
| 1182 | let wStart; | 1176 | let wStart; |
| 1183 | /**@type {HTMLElement}*/ | 1177 | /**@type {HTMLElement}*/ |
| 1184 | const resizeHandle = dom.querySelector('#qr--resizeHandle'); | 1178 | const resizeHandle = dom.querySelector('#qr--resizeHandle'); |
| 1185 | resizeHandle.addEventListener('pointerdown', (evt)=>{ | 1179 | resizeHandle.addEventListener('pointerdown', (evt) => { |
| 1186 | if (isResizing) return; | 1180 | if (isResizing) return; |
| 1187 | isResizing = true; | 1181 | isResizing = true; |
| 1188 | evt.preventDefault(); | 1182 | evt.preventDefault(); |
| 1189 | resizeStart = evt.x; | 1183 | resizeStart = evt.x; |
| 1190 | // @ts-ignore | 1184 | // @ts-ignore |
| 1191 | wStart = dom.querySelector('#qr--qrOptions').offsetWidth; | 1185 | wStart = dom.querySelector('#qr--qrOptions').offsetWidth; |
| 1192 | const dragListener = debounce((evt)=>{ | 1186 | const dragListener = debounce((evt) => { |
| 1193 | const w = wStart + resizeStart - evt.x; | 1187 | const w = wStart + resizeStart - evt.x; |
| 1194 | // @ts-ignore | 1188 | // @ts-ignore |
| 1195 | dom.querySelector('#qr--qrOptions').style.setProperty('--width', `${w}px`); | 1189 | dom.querySelector('#qr--qrOptions').style.setProperty('--width', `${w}px`); |
| 1196 | }, 5); | 1190 | }, 5); |
| 1197 | window.addEventListener('pointerup', ()=>{ | 1191 | window.addEventListener('pointerup', () => { |
| 1198 | // @ts-ignore | 1192 | // @ts-ignore |
| 1199 | window.removeEventListener('pointermove', dragListener); | 1193 | window.removeEventListener('pointermove', dragListener); |
| 1200 | isResizing = false; | 1194 | isResizing = false; |
| 1201 | }, { once:true }); | 1195 | }, { once: true }); |
| 1202 | // @ts-ignore | 1196 | // @ts-ignore |
| 1203 | window.addEventListener('pointermove', dragListener); | 1197 | window.addEventListener('pointermove', dragListener); |
| 1204 | }); | 1198 | }); |
| @@ -1221,13 +1215,13 @@ export class QuickReply { | |||
| 1221 | } | 1215 | } |
| 1222 | this.clone.style.position = 'fixed'; | 1216 | this.clone.style.position = 'fixed'; |
| 1223 | this.clone.style.visibility = 'hidden'; | 1217 | this.clone.style.visibility = 'hidden'; |
| 1224 | const mo = new MutationObserver(muts=>{ | 1218 | const mo = new MutationObserver(muts => { |
| 1225 | if (muts.find(it=>[...it.removedNodes].includes(this.editorMessage) || [...it.removedNodes].find(n=>n.contains(this.editorMessage)))) { | 1219 | if (muts.find(it => [...it.removedNodes].includes(this.editorMessage) || [...it.removedNodes].find(n => n.contains(this.editorMessage)))) { |
| 1226 | this.clone?.remove(); | 1220 | this.clone?.remove(); |
| 1227 | this.clone = null; | 1221 | this.clone = null; |
| 1228 | } | 1222 | } |
| 1229 | }); | 1223 | }); |
| 1230 | mo.observe(document.body, { childList:true }); | 1224 | mo.observe(document.body, { childList: true }); |
| 1231 | } | 1225 | } |
| 1232 | document.body.append(this.clone); | 1226 | document.body.append(this.clone); |
| 1233 | this.clone.style.width = `${inputRect.width}px`; | 1227 | this.clone.style.width = `${inputRect.width}px`; |
| @@ -1258,7 +1252,7 @@ export class QuickReply { | |||
| 1258 | } | 1252 | } |
| 1259 | async executeFromEditor() { | 1253 | async executeFromEditor() { |
| 1260 | if (this.isExecuting) return; | 1254 | if (this.isExecuting) return; |
| 1261 | this.editorPopup.onClosing = ()=>false; | 1255 | this.editorPopup.onClosing = () => false; |
| 1262 | const uuidCheck = /^[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}$/; | 1256 | const uuidCheck = /^[0-9a-z]{8}(-[0-9a-z]{4}){3}-[0-9a-z]{12}$/; |
| 1263 | const oText = this.message; | 1257 | const oText = this.message; |
| 1264 | this.isExecuting = true; | 1258 | this.isExecuting = true; |
| @@ -1298,19 +1292,19 @@ export class QuickReply { | |||
| 1298 | }); | 1292 | }); |
| 1299 | }; | 1293 | }; |
| 1300 | const updateScrollDebounced = updateScroll; | 1294 | const updateScrollDebounced = updateScroll; |
| 1301 | syntax.addEventListener('wheel', (evt)=>{ | 1295 | syntax.addEventListener('wheel', (evt) => { |
| 1302 | updateScrollDebounced(evt); | 1296 | updateScrollDebounced(evt); |
| 1303 | }); | 1297 | }); |
| 1304 | // @ts-ignore | 1298 | // @ts-ignore |
| 1305 | syntax.addEventListener('scroll', (evt)=>{ | 1299 | syntax.addEventListener('scroll', (evt) => { |
| 1306 | updateScrollDebounced(); | 1300 | updateScrollDebounced(); |
| 1307 | }); | 1301 | }); |
| 1308 | try { | 1302 | try { |
| 1309 | this.abortController = new SlashCommandAbortController(); | 1303 | this.abortController = new SlashCommandAbortController(); |
| 1310 | this.debugController = new SlashCommandDebugController(); | 1304 | this.debugController = new SlashCommandDebugController(); |
| 1311 | this.debugController.onBreakPoint = async(closure, executor)=>{ | 1305 | this.debugController.onBreakPoint = async (closure, executor) => { |
| 1312 | this.editorDom.classList.add('qr--isPaused'); | 1306 | this.editorDom.classList.add('qr--isPaused'); |
| 1313 | syntax.innerHTML = hljs.highlight(`${closure.fullText}${closure.fullText.slice(-1) == '\n' ? ' ' : ''}`, { language:'stscript', ignoreIllegals:true })?.value; | 1307 | syntax.innerHTML = hljs.highlight(`${closure.fullText}${closure.fullText.slice(-1) == '\n' ? ' ' : ''}`, { language: 'stscript', ignoreIllegals: true })?.value; |
| 1314 | this.editorMessageLabel.innerHTML = ''; | 1308 | this.editorMessageLabel.innerHTML = ''; |
| 1315 | if (uuidCheck.test(closure.source)) { | 1309 | if (uuidCheck.test(closure.source)) { |
| 1316 | const p0 = document.createElement('span'); { | 1310 | const p0 = document.createElement('span'); { |
| @@ -1318,7 +1312,7 @@ export class QuickReply { | |||
| 1318 | this.editorMessageLabel.append(p0); | 1312 | this.editorMessageLabel.append(p0); |
| 1319 | } | 1313 | } |
| 1320 | const p1 = document.createElement('strong'); { | 1314 | const p1 = document.createElement('strong'); { |
| 1321 | p1.textContent = executor.source.slice(0,5); | 1315 | p1.textContent = executor.source.slice(0, 5); |
| 1322 | this.editorMessageLabel.append(p1); | 1316 | this.editorMessageLabel.append(p1); |
| 1323 | } | 1317 | } |
| 1324 | const p2 = document.createElement('span'); { | 1318 | const p2 = document.createElement('span'); { |
| @@ -1340,7 +1334,7 @@ export class QuickReply { | |||
| 1340 | /** | 1334 | /** |
| 1341 | * @param {SlashCommandScope} scope | 1335 | * @param {SlashCommandScope} scope |
| 1342 | */ | 1336 | */ |
| 1343 | const buildVars = (scope, isCurrent = false)=>{ | 1337 | const buildVars = (scope, isCurrent = false) => { |
| 1344 | if (!isCurrent) { | 1338 | if (!isCurrent) { |
| 1345 | ci--; | 1339 | ci--; |
| 1346 | } | 1340 | } |
| @@ -1358,7 +1352,7 @@ export class QuickReply { | |||
| 1358 | } | 1352 | } |
| 1359 | wrap.append(namedTitle); | 1353 | wrap.append(namedTitle); |
| 1360 | } | 1354 | } |
| 1361 | const keys = new Set([...Object.keys(this.debugController.namedArguments ?? {}), ...(executor.namedArgumentList ?? []).map(it=>it.name)]); | 1355 | const keys = new Set([...Object.keys(this.debugController.namedArguments ?? {}), ...(executor.namedArgumentList ?? []).map(it => it.name)]); |
| 1362 | for (const key of keys) { | 1356 | for (const key of keys) { |
| 1363 | if (key[0] == '_') continue; | 1357 | if (key[0] == '_') continue; |
| 1364 | const item = document.createElement('div'); { | 1358 | const item = document.createElement('div'); { |
| @@ -1371,7 +1365,7 @@ export class QuickReply { | |||
| 1371 | const vUnresolved = document.createElement('div'); { | 1365 | const vUnresolved = document.createElement('div'); { |
| 1372 | vUnresolved.classList.add('qr--val'); | 1366 | vUnresolved.classList.add('qr--val'); |
| 1373 | vUnresolved.classList.add('qr--singleCol'); | 1367 | vUnresolved.classList.add('qr--singleCol'); |
| 1374 | const val = executor.namedArgumentList.find(it=>it.name == key)?.value; | 1368 | const val = executor.namedArgumentList.find(it => it.name == key)?.value; |
| 1375 | if (val instanceof SlashCommandClosure) { | 1369 | if (val instanceof SlashCommandClosure) { |
| 1376 | vUnresolved.classList.add('qr--closure'); | 1370 | vUnresolved.classList.add('qr--closure'); |
| 1377 | vUnresolved.title = val.rawText; | 1371 | vUnresolved.title = val.rawText; |
| @@ -1437,7 +1431,7 @@ export class QuickReply { | |||
| 1437 | // @ts-ignore | 1431 | // @ts-ignore |
| 1438 | while (unnamed.length < executor.unnamedArgumentList?.length ?? 0) unnamed.push(undefined); | 1432 | while (unnamed.length < executor.unnamedArgumentList?.length ?? 0) unnamed.push(undefined); |
| 1439 | // @ts-ignore | 1433 | // @ts-ignore |
| 1440 | unnamed = unnamed.map((it,idx)=>[executor.unnamedArgumentList?.[idx], it]); | 1434 | unnamed = unnamed.map((it, idx) => [executor.unnamedArgumentList?.[idx], it]); |
| 1441 | // @ts-ignore | 1435 | // @ts-ignore |
| 1442 | for (const arg of unnamed) { | 1436 | for (const arg of unnamed) { |
| 1443 | i++; | 1437 | i++; |
| @@ -1511,7 +1505,7 @@ export class QuickReply { | |||
| 1511 | title.textContent = isCurrent ? 'Current Scope' : 'Parent Scope'; | 1505 | title.textContent = isCurrent ? 'Current Scope' : 'Parent Scope'; |
| 1512 | if (c.source == source) { | 1506 | if (c.source == source) { |
| 1513 | let hi; | 1507 | let hi; |
| 1514 | title.addEventListener('pointerenter', ()=>{ | 1508 | title.addEventListener('pointerenter', () => { |
| 1515 | const loc = this.getEditorPosition(Math.max(0, c.executorList[0].start - 1), c.executorList.slice(-1)[0].end, c.fullText); | 1509 | const loc = this.getEditorPosition(Math.max(0, c.executorList[0].start - 1), c.executorList.slice(-1)[0].end, c.fullText); |
| 1516 | const layer = syntax.getBoundingClientRect(); | 1510 | const layer = syntax.getBoundingClientRect(); |
| 1517 | hi = document.createElement('div'); | 1511 | hi = document.createElement('div'); |
| @@ -1522,7 +1516,7 @@ export class QuickReply { | |||
| 1522 | hi.style.height = `${loc.bottom - loc.top}px`; | 1516 | hi.style.height = `${loc.bottom - loc.top}px`; |
| 1523 | syntax.append(hi); | 1517 | syntax.append(hi); |
| 1524 | }); | 1518 | }); |
| 1525 | title.addEventListener('pointerleave', ()=>hi?.remove()); | 1519 | title.addEventListener('pointerleave', () => hi?.remove()); |
| 1526 | } | 1520 | } |
| 1527 | wrap.append(title); | 1521 | wrap.append(title); |
| 1528 | } | 1522 | } |
| @@ -1635,7 +1629,7 @@ export class QuickReply { | |||
| 1635 | } | 1629 | } |
| 1636 | return wrap; | 1630 | return wrap; |
| 1637 | }; | 1631 | }; |
| 1638 | const buildStack = ()=>{ | 1632 | const buildStack = () => { |
| 1639 | const wrap = document.createElement('div'); { | 1633 | const wrap = document.createElement('div'); { |
| 1640 | wrap.classList.add('qr--stack'); | 1634 | wrap.classList.add('qr--stack'); |
| 1641 | const title = document.createElement('div'); { | 1635 | const title = document.createElement('div'); { |
| @@ -1651,7 +1645,7 @@ export class QuickReply { | |||
| 1651 | item.classList.add('qr--item'); | 1645 | item.classList.add('qr--item'); |
| 1652 | if (executor.source == source) { | 1646 | if (executor.source == source) { |
| 1653 | let hi; | 1647 | let hi; |
| 1654 | item.addEventListener('pointerenter', ()=>{ | 1648 | item.addEventListener('pointerenter', () => { |
| 1655 | const loc = this.getEditorPosition(Math.max(0, executor.start - 1), executor.end, c.fullText); | 1649 | const loc = this.getEditorPosition(Math.max(0, executor.start - 1), executor.end, c.fullText); |
| 1656 | const layer = syntax.getBoundingClientRect(); | 1650 | const layer = syntax.getBoundingClientRect(); |
| 1657 | hi = document.createElement('div'); | 1651 | hi = document.createElement('div'); |
| @@ -1662,7 +1656,7 @@ export class QuickReply { | |||
| 1662 | hi.style.height = `${loc.bottom - loc.top}px`; | 1656 | hi.style.height = `${loc.bottom - loc.top}px`; |
| 1663 | syntax.append(hi); | 1657 | syntax.append(hi); |
| 1664 | }); | 1658 | }); |
| 1665 | item.addEventListener('pointerleave', ()=>hi?.remove()); | 1659 | item.addEventListener('pointerleave', () => hi?.remove()); |
| 1666 | } | 1660 | } |
| 1667 | const cmd = document.createElement('div'); { | 1661 | const cmd = document.createElement('div'); { |
| 1668 | cmd.classList.add('qr--cmd'); | 1662 | cmd.classList.add('qr--cmd'); |
| @@ -1678,7 +1672,7 @@ export class QuickReply { | |||
| 1678 | if (uuidCheck.test(executor.source)) { | 1672 | if (uuidCheck.test(executor.source)) { |
| 1679 | const p1 = document.createElement('span'); { | 1673 | const p1 = document.createElement('span'); { |
| 1680 | p1.classList.add('qr--fixed'); | 1674 | p1.classList.add('qr--fixed'); |
| 1681 | p1.textContent = executor.source.slice(0,5); | 1675 | p1.textContent = executor.source.slice(0, 5); |
| 1682 | src.append(p1); | 1676 | src.append(p1); |
| 1683 | } | 1677 | } |
| 1684 | const p2 = document.createElement('span'); { | 1678 | const p2 = document.createElement('span'); { |
| @@ -1756,7 +1750,7 @@ export class QuickReply { | |||
| 1756 | this.editorMessageLabel.innerHTML = ''; | 1750 | this.editorMessageLabel.innerHTML = ''; |
| 1757 | this.editorMessageLabel.textContent = 'Message / Command: '; | 1751 | this.editorMessageLabel.textContent = 'Message / Command: '; |
| 1758 | this.editorMessage.value = oText; | 1752 | this.editorMessage.value = oText; |
| 1759 | this.editorMessage.dispatchEvent(new Event('input', { bubbles:true })); | 1753 | this.editorMessage.dispatchEvent(new Event('input', { bubbles: true })); |
| 1760 | this.editorExecutePromise = null; | 1754 | this.editorExecutePromise = null; |
| 1761 | this.editorExecuteBtn.classList.remove('qr--busy'); | 1755 | this.editorExecuteBtn.classList.remove('qr--busy'); |
| 1762 | this.editorDom.classList.remove('qr--isExecuting'); | 1756 | this.editorDom.classList.remove('qr--isExecuting'); |
| @@ -1769,8 +1763,6 @@ export class QuickReply { | |||
| 1769 | } | 1763 | } |
| 1770 | 1764 | ||
| 1771 | 1765 | ||
| 1772 | |||
| 1773 | |||
| 1774 | delete() { | 1766 | delete() { |
| 1775 | if (this.onDelete) { | 1767 | if (this.onDelete) { |
| 1776 | this.unrender(); | 1768 | this.unrender(); |
| @@ -1870,7 +1862,7 @@ export class QuickReply { | |||
| 1870 | this.updateContext(); | 1862 | this.updateContext(); |
| 1871 | } | 1863 | } |
| 1872 | removeContextLink(setName) { | 1864 | removeContextLink(setName) { |
| 1873 | const idx = this.contextList.findIndex(it=>it.set.name == setName); | 1865 | const idx = this.contextList.findIndex(it => it.set.name == setName); |
| 1874 | if (idx > -1) { | 1866 | if (idx > -1) { |
| 1875 | this.contextList.splice(idx, 1); | 1867 | this.contextList.splice(idx, 1); |
| 1876 | this.updateContext(); | 1868 | this.updateContext(); |
| @@ -1908,8 +1900,6 @@ export class QuickReply { | |||
| 1908 | } | 1900 | } |
| 1909 | 1901 | ||
| 1910 | 1902 | ||
| 1911 | |||
| 1912 | |||
| 1913 | toJSON() { | 1903 | toJSON() { |
| 1914 | return { | 1904 | return { |
| 1915 | id: this.id, | 1905 | id: this.id, |
| @@ -13,25 +13,21 @@ export class QuickReplyConfig { | |||
| 13 | /**@type {HTMLElement}*/ setListDom; | 13 | /**@type {HTMLElement}*/ setListDom; |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | |||
| 17 | |||
| 18 | static from(props) { | 16 | static from(props) { |
| 19 | props.setList = props.setList?.map(it=>QuickReplySetLink.from(it))?.filter(it=>it.set) ?? []; | 17 | props.setList = props.setList?.map(it => QuickReplySetLink.from(it))?.filter(it => it.set) ?? []; |
| 20 | const instance = Object.assign(new this(), props); | 18 | const instance = Object.assign(new this(), props); |
| 21 | instance.init(); | 19 | instance.init(); |
| 22 | return instance; | 20 | return instance; |
| 23 | } | 21 | } |
| 24 | 22 | ||
| 25 | 23 | ||
| 26 | |||
| 27 | |||
| 28 | init() { | 24 | init() { |
| 29 | this.setList.forEach(it=>this.hookQuickReplyLink(it)); | 25 | this.setList.forEach(it => this.hookQuickReplyLink(it)); |
| 30 | } | 26 | } |
| 31 | 27 | ||
| 32 | 28 | ||
| 33 | hasSet(qrs) { | 29 | hasSet(qrs) { |
| 34 | return this.setList.find(it=>it.set == qrs) != null; | 30 | return this.setList.find(it => it.set == qrs) != null; |
| 35 | } | 31 | } |
| 36 | addSet(qrs, isVisible = true) { | 32 | addSet(qrs, isVisible = true) { |
| 37 | if (!this.hasSet(qrs)) { | 33 | if (!this.hasSet(qrs)) { |
| @@ -45,7 +41,7 @@ export class QuickReplyConfig { | |||
| 45 | } | 41 | } |
| 46 | } | 42 | } |
| 47 | removeSet(qrs) { | 43 | removeSet(qrs) { |
| 48 | const idx = this.setList.findIndex(it=>it.set == qrs); | 44 | const idx = this.setList.findIndex(it => it.set == qrs); |
| 49 | if (idx > -1) { | 45 | if (idx > -1) { |
| 50 | this.setList.splice(idx, 1); | 46 | this.setList.splice(idx, 1); |
| 51 | this.update(); | 47 | this.update(); |
| @@ -54,13 +50,11 @@ export class QuickReplyConfig { | |||
| 54 | } | 50 | } |
| 55 | 51 | ||
| 56 | 52 | ||
| 57 | |||
| 58 | |||
| 59 | renderSettingsInto(/**@type {HTMLElement}*/root) { | 53 | renderSettingsInto(/**@type {HTMLElement}*/root) { |
| 60 | /**@type {HTMLElement}*/ | 54 | /**@type {HTMLElement}*/ |
| 61 | this.setListDom = root.querySelector('.qr--setList'); | 55 | this.setListDom = root.querySelector('.qr--setList'); |
| 62 | root.querySelector('.qr--setListAdd').addEventListener('click', ()=>{ | 56 | root.querySelector('.qr--setListAdd').addEventListener('click', () => { |
| 63 | const newSet = QuickReplySet.list.find(qr=>!this.setList.find(qrl=>qrl.set == qr)); | 57 | const newSet = QuickReplySet.list.find(qr => !this.setList.find(qrl => qrl.set == qr)); |
| 64 | if (newSet) { | 58 | if (newSet) { |
| 65 | this.addSet(newSet); | 59 | this.addSet(newSet); |
| 66 | } else { | 60 | } else { |
| @@ -74,14 +68,14 @@ export class QuickReplyConfig { | |||
| 74 | // @ts-ignore | 68 | // @ts-ignore |
| 75 | $(this.setListDom).sortable({ | 69 | $(this.setListDom).sortable({ |
| 76 | delay: getSortableDelay(), | 70 | delay: getSortableDelay(), |
| 77 | stop: ()=>this.onSetListSort(), | 71 | stop: () => this.onSetListSort(), |
| 78 | }); | 72 | }); |
| 79 | this.setList.filter(it=>!it.set.isDeleted).forEach((qrl,idx)=>this.setListDom.append(qrl.renderSettings(idx))); | 73 | this.setList.filter(it => !it.set.isDeleted).forEach((qrl, idx) => this.setListDom.append(qrl.renderSettings(idx))); |
| 80 | } | 74 | } |
| 81 | 75 | ||
| 82 | 76 | ||
| 83 | onSetListSort() { | 77 | onSetListSort() { |
| 84 | this.setList = Array.from(this.setListDom.children).map((it,idx)=>{ | 78 | this.setList = Array.from(this.setListDom.children).map((it, idx) => { |
| 85 | const qrl = this.setList[Number(it.getAttribute('data-order'))]; | 79 | const qrl = this.setList[Number(it.getAttribute('data-order'))]; |
| 86 | qrl.index = idx; | 80 | qrl.index = idx; |
| 87 | it.setAttribute('data-order', String(idx)); | 81 | it.setAttribute('data-order', String(idx)); |
| @@ -91,15 +85,13 @@ export class QuickReplyConfig { | |||
| 91 | } | 85 | } |
| 92 | 86 | ||
| 93 | 87 | ||
| 94 | |||
| 95 | |||
| 96 | /** | 88 | /** |
| 97 | * @param {QuickReplySetLink} qrl | 89 | * @param {QuickReplySetLink} qrl |
| 98 | */ | 90 | */ |
| 99 | hookQuickReplyLink(qrl) { | 91 | hookQuickReplyLink(qrl) { |
| 100 | qrl.onDelete = ()=>this.deleteQuickReplyLink(qrl); | 92 | qrl.onDelete = () => this.deleteQuickReplyLink(qrl); |
| 101 | qrl.onUpdate = ()=>this.update(); | 93 | qrl.onUpdate = () => this.update(); |
| 102 | qrl.onRequestEditSet = ()=>this.requestEditSet(qrl.set); | 94 | qrl.onRequestEditSet = () => this.requestEditSet(qrl.set); |
| 103 | } | 95 | } |
| 104 | 96 | ||
| 105 | deleteQuickReplyLink(qrl) { | 97 | deleteQuickReplyLink(qrl) { |
| @@ -8,8 +8,6 @@ export class QuickReplyContextLink { | |||
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | |||
| 12 | |||
| 13 | /**@type {QuickReplySet}*/ set; | 11 | /**@type {QuickReplySet}*/ set; |
| 14 | /**@type {Boolean}*/ isChained = false; | 12 | /**@type {Boolean}*/ isChained = false; |
| 15 | 13 | ||
| @@ -24,7 +24,7 @@ export class QuickReplySet { | |||
| 24 | * @param {string} name - name of the QuickReplySet | 24 | * @param {string} name - name of the QuickReplySet |
| 25 | */ | 25 | */ |
| 26 | static get(name) { | 26 | static get(name) { |
| 27 | return this.list.find(it=>it.name == name); | 27 | return this.list.find(it => it.name == name); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /**@type {string}*/ name; | 30 | /**@type {string}*/ name; |
| @@ -42,11 +42,11 @@ export class QuickReplySet { | |||
| 42 | /**@type {HTMLElement}*/ settingsDom; | 42 | /**@type {HTMLElement}*/ settingsDom; |
| 43 | 43 | ||
| 44 | constructor() { | 44 | constructor() { |
| 45 | this.save = debounceAsync(()=>this.performSave(), 200); | 45 | this.save = debounceAsync(() => this.performSave(), 200); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | init() { | 48 | init() { |
| 49 | this.qrList.forEach(qr=>this.hookQuickReply(qr)); | 49 | this.qrList.forEach(qr => this.hookQuickReply(qr)); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | unrender() { | 52 | unrender() { |
| @@ -60,7 +60,7 @@ export class QuickReplySet { | |||
| 60 | this.dom = root; | 60 | this.dom = root; |
| 61 | root.classList.add('qr--buttons'); | 61 | root.classList.add('qr--buttons'); |
| 62 | this.updateColor(); | 62 | this.updateColor(); |
| 63 | this.qrList.filter(qr=>!qr.isHidden).forEach(qr=>{ | 63 | this.qrList.filter(qr => !qr.isHidden).forEach(qr => { |
| 64 | root.append(qr.render()); | 64 | root.append(qr.render()); |
| 65 | }); | 65 | }); |
| 66 | } | 66 | } |
| @@ -70,7 +70,7 @@ export class QuickReplySet { | |||
| 70 | rerender() { | 70 | rerender() { |
| 71 | if (!this.dom) return; | 71 | if (!this.dom) return; |
| 72 | this.dom.innerHTML = ''; | 72 | this.dom.innerHTML = ''; |
| 73 | this.qrList.filter(qr=>!qr.isHidden).forEach(qr=>{ | 73 | this.qrList.filter(qr => !qr.isHidden).forEach(qr => { |
| 74 | this.dom.append(qr.render()); | 74 | this.dom.append(qr.render()); |
| 75 | }); | 75 | }); |
| 76 | } | 76 | } |
| @@ -95,7 +95,7 @@ export class QuickReplySet { | |||
| 95 | if (!this.settingsDom) { | 95 | if (!this.settingsDom) { |
| 96 | this.settingsDom = document.createElement('div'); { | 96 | this.settingsDom = document.createElement('div'); { |
| 97 | this.settingsDom.classList.add('qr--set-qrListContents'); | 97 | this.settingsDom.classList.add('qr--set-qrListContents'); |
| 98 | this.qrList.forEach((qr,idx)=>{ | 98 | this.qrList.forEach((qr, idx) => { |
| 99 | this.renderSettingsItem(qr, idx); | 99 | this.renderSettingsItem(qr, idx); |
| 100 | }); | 100 | }); |
| 101 | } | 101 | } |
| @@ -138,12 +138,12 @@ export class QuickReplySet { | |||
| 138 | */ | 138 | */ |
| 139 | async executeWithOptions(qr, options = {}) { | 139 | async executeWithOptions(qr, options = {}) { |
| 140 | options = Object.assign({ | 140 | options = Object.assign({ |
| 141 | message:null, | 141 | message: null, |
| 142 | isAutoExecute:false, | 142 | isAutoExecute: false, |
| 143 | isEditor:false, | 143 | isEditor: false, |
| 144 | isRun:false, | 144 | isRun: false, |
| 145 | scope:null, | 145 | scope: null, |
| 146 | executionOptions:{}, | 146 | executionOptions: {}, |
| 147 | }, options); | 147 | }, options); |
| 148 | const execOptions = options.executionOptions; | 148 | const execOptions = options.executionOptions; |
| 149 | /**@type {HTMLTextAreaElement}*/ | 149 | /**@type {HTMLTextAreaElement}*/ |
| @@ -208,9 +208,8 @@ export class QuickReplySet { | |||
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | addQuickReply(data = {}) { | 210 | addQuickReply(data = {}) { |
| 211 | const id = Math.max(this.idIndex, this.qrList.reduce((max,qr)=>Math.max(max,qr.id),0)) + 1; | 211 | const id = Math.max(this.idIndex, this.qrList.reduce((max, qr) => Math.max(max, qr.id), 0)) + 1; |
| 212 | data.id = | 212 | data.id = this.idIndex = id + 1; |
| 213 | this.idIndex = id + 1; | ||
| 214 | const qr = QuickReply.from(data); | 213 | const qr = QuickReply.from(data); |
| 215 | this.qrList.push(qr); | 214 | this.qrList.push(qr); |
| 216 | this.hookQuickReply(qr); | 215 | this.hookQuickReply(qr); |
| @@ -257,11 +256,11 @@ export class QuickReplySet { | |||
| 257 | */ | 256 | */ |
| 258 | hookQuickReply(qr) { | 257 | hookQuickReply(qr) { |
| 259 | // @ts-ignore | 258 | // @ts-ignore |
| 260 | qr.onDebug = ()=>this.debug(qr); | 259 | qr.onDebug = () => this.debug(qr); |
| 261 | qr.onExecute = (_, options)=>this.executeWithOptions(qr, options); | 260 | qr.onExecute = (_, options) => this.executeWithOptions(qr, options); |
| 262 | qr.onDelete = ()=>this.removeQuickReply(qr); | 261 | qr.onDelete = () => this.removeQuickReply(qr); |
| 263 | qr.onUpdate = ()=>this.save(); | 262 | qr.onUpdate = () => this.save(); |
| 264 | qr.onInsertBefore = (qrJson)=>{ | 263 | qr.onInsertBefore = (qrJson) => { |
| 265 | this.addQuickReplyFromText(qrJson); | 264 | this.addQuickReplyFromText(qrJson); |
| 266 | const newQr = this.qrList.pop(); | 265 | const newQr = this.qrList.pop(); |
| 267 | this.qrList.splice(this.qrList.indexOf(qr), 0, newQr); | 266 | this.qrList.splice(this.qrList.indexOf(qr), 0, newQr); |
| @@ -270,7 +269,7 @@ export class QuickReplySet { | |||
| 270 | } | 269 | } |
| 271 | this.save(); | 270 | this.save(); |
| 272 | }; | 271 | }; |
| 273 | qr.onTransfer = async()=>{ | 272 | qr.onTransfer = async () => { |
| 274 | /**@type {HTMLSelectElement} */ | 273 | /**@type {HTMLSelectElement} */ |
| 275 | let sel; | 274 | let sel; |
| 276 | let isCopy = false; | 275 | let isCopy = false; |
| @@ -301,14 +300,14 @@ export class QuickReplySet { | |||
| 301 | sel.append(opt); | 300 | sel.append(opt); |
| 302 | } | 301 | } |
| 303 | } | 302 | } |
| 304 | sel.addEventListener('keyup', (evt)=>{ | 303 | sel.addEventListener('keyup', (evt) => { |
| 305 | if (evt.key == 'Shift') { | 304 | if (evt.key == 'Shift') { |
| 306 | // @ts-ignore | 305 | // @ts-ignore |
| 307 | (dlg.dom ?? dlg.dlg).classList.remove('qr--isCopy'); | 306 | (dlg.dom ?? dlg.dlg).classList.remove('qr--isCopy'); |
| 308 | return; | 307 | return; |
| 309 | } | 308 | } |
| 310 | }); | 309 | }); |
| 311 | sel.addEventListener('keydown', (evt)=>{ | 310 | sel.addEventListener('keydown', (evt) => { |
| 312 | if (evt.key == 'Shift') { | 311 | if (evt.key == 'Shift') { |
| 313 | // @ts-ignore | 312 | // @ts-ignore |
| 314 | (dlg.dom ?? dlg.dlg).classList.add('qr--isCopy'); | 313 | (dlg.dom ?? dlg.dlg).classList.add('qr--isCopy'); |
| @@ -330,12 +329,12 @@ export class QuickReplySet { | |||
| 330 | dom.append(hintP); | 329 | dom.append(hintP); |
| 331 | } | 330 | } |
| 332 | } | 331 | } |
| 333 | const dlg = new Popup(dom, POPUP_TYPE.CONFIRM, null, { okButton:'Transfer', cancelButton:'Cancel' }); | 332 | const dlg = new Popup(dom, POPUP_TYPE.CONFIRM, null, { okButton: 'Transfer', cancelButton: 'Cancel' }); |
| 334 | const copyBtn = document.createElement('div'); { | 333 | const copyBtn = document.createElement('div'); { |
| 335 | copyBtn.classList.add('qr--copy'); | 334 | copyBtn.classList.add('qr--copy'); |
| 336 | copyBtn.classList.add('menu_button'); | 335 | copyBtn.classList.add('menu_button'); |
| 337 | copyBtn.textContent = 'Copy'; | 336 | copyBtn.textContent = 'Copy'; |
| 338 | copyBtn.addEventListener('click', ()=>{ | 337 | copyBtn.addEventListener('click', () => { |
| 339 | isCopy = true; | 338 | isCopy = true; |
| 340 | dlg.completeAffirmative(); | 339 | dlg.completeAffirmative(); |
| 341 | }); | 340 | }); |
| @@ -346,7 +345,7 @@ export class QuickReplySet { | |||
| 346 | sel.focus(); | 345 | sel.focus(); |
| 347 | await prom; | 346 | await prom; |
| 348 | if (dlg.result == POPUP_RESULT.AFFIRMATIVE) { | 347 | if (dlg.result == POPUP_RESULT.AFFIRMATIVE) { |
| 349 | const qrs = QuickReplySet.list.find(it=>it.name == sel.value); | 348 | const qrs = QuickReplySet.list.find(it => it.name == sel.value); |
| 350 | qrs.addQuickReply(qr.toJSON()); | 349 | qrs.addQuickReply(qr.toJSON()); |
| 351 | if (!isCopy) { | 350 | if (!isCopy) { |
| 352 | qr.delete(); | 351 | qr.delete(); |
| @@ -9,8 +9,6 @@ export class QuickReplySetLink { | |||
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | |||
| 13 | |||
| 14 | /**@type {QuickReplySet}*/ set; | 12 | /**@type {QuickReplySet}*/ set; |
| 15 | /**@type {Boolean}*/ isVisible = true; | 13 | /**@type {Boolean}*/ isVisible = true; |
| 16 | 14 | ||
| @@ -23,8 +21,6 @@ export class QuickReplySetLink { | |||
| 23 | /**@type {HTMLElement}*/ settingsDom; | 21 | /**@type {HTMLElement}*/ settingsDom; |
| 24 | 22 | ||
| 25 | 23 | ||
| 26 | |||
| 27 | |||
| 28 | renderSettings(idx) { | 24 | renderSettings(idx) { |
| 29 | this.index = idx; | 25 | this.index = idx; |
| 30 | const item = document.createElement('div'); { | 26 | const item = document.createElement('div'); { |
| @@ -40,12 +36,12 @@ export class QuickReplySetLink { | |||
| 40 | const set = document.createElement('select'); { | 36 | const set = document.createElement('select'); { |
| 41 | set.classList.add('qr--set'); | 37 | set.classList.add('qr--set'); |
| 42 | // fix for jQuery sortable breaking childrens' touch events | 38 | // fix for jQuery sortable breaking childrens' touch events |
| 43 | set.addEventListener('touchstart', (evt)=>evt.stopPropagation()); | 39 | set.addEventListener('touchstart', (evt) => evt.stopPropagation()); |
| 44 | set.addEventListener('change', ()=>{ | 40 | set.addEventListener('change', () => { |
| 45 | this.set = QuickReplySet.get(set.value); | 41 | this.set = QuickReplySet.get(set.value); |
| 46 | this.update(); | 42 | this.update(); |
| 47 | }); | 43 | }); |
| 48 | QuickReplySet.list.toSorted((a,b)=>a.name.toLowerCase().localeCompare(b.name.toLowerCase())).forEach(qrs=>{ | 44 | QuickReplySet.list.toSorted((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).forEach(qrs => { |
| 49 | const opt = document.createElement('option'); { | 45 | const opt = document.createElement('option'); { |
| 50 | opt.value = qrs.name; | 46 | opt.value = qrs.name; |
| 51 | opt.textContent = qrs.name; | 47 | opt.textContent = qrs.name; |
| @@ -61,7 +57,7 @@ export class QuickReplySetLink { | |||
| 61 | const cb = document.createElement('input'); { | 57 | const cb = document.createElement('input'); { |
| 62 | cb.type = 'checkbox'; | 58 | cb.type = 'checkbox'; |
| 63 | cb.checked = this.isVisible; | 59 | cb.checked = this.isVisible; |
| 64 | cb.addEventListener('click', ()=>{ | 60 | cb.addEventListener('click', () => { |
| 65 | this.isVisible = cb.checked; | 61 | this.isVisible = cb.checked; |
| 66 | this.update(); | 62 | this.update(); |
| 67 | }); | 63 | }); |
| @@ -76,7 +72,7 @@ export class QuickReplySetLink { | |||
| 76 | edit.classList.add('fa-solid'); | 72 | edit.classList.add('fa-solid'); |
| 77 | edit.classList.add('fa-pencil'); | 73 | edit.classList.add('fa-pencil'); |
| 78 | edit.title = 'Edit quick reply set'; | 74 | edit.title = 'Edit quick reply set'; |
| 79 | edit.addEventListener('click', ()=>this.requestEditSet()); | 75 | edit.addEventListener('click', () => this.requestEditSet()); |
| 80 | item.append(edit); | 76 | item.append(edit); |
| 81 | } | 77 | } |
| 82 | const del = document.createElement('div'); { | 78 | const del = document.createElement('div'); { |
| @@ -86,7 +82,7 @@ export class QuickReplySetLink { | |||
| 86 | del.classList.add('fa-solid'); | 82 | del.classList.add('fa-solid'); |
| 87 | del.classList.add('fa-trash-can'); | 83 | del.classList.add('fa-trash-can'); |
| 88 | del.title = 'Remove quick reply set'; | 84 | del.title = 'Remove quick reply set'; |
| 89 | del.addEventListener('click', ()=>this.delete()); | 85 | del.addEventListener('click', () => this.delete()); |
| 90 | item.append(del); | 86 | item.append(del); |
| 91 | } | 87 | } |
| 92 | } | 88 | } |
| @@ -98,8 +94,6 @@ export class QuickReplySetLink { | |||
| 98 | } | 94 | } |
| 99 | 95 | ||
| 100 | 96 | ||
| 101 | |||
| 102 | |||
| 103 | update() { | 97 | update() { |
| 104 | if (this.onUpdate) { | 98 | if (this.onUpdate) { |
| 105 | this.onUpdate(this); | 99 | this.onUpdate(this); |
| @@ -118,8 +112,6 @@ export class QuickReplySetLink { | |||
| 118 | } | 112 | } |
| 119 | 113 | ||
| 120 | 114 | ||
| 121 | |||
| 122 | |||
| 123 | toJSON() { | 115 | toJSON() { |
| 124 | return { | 116 | return { |
| 125 | set: this.set.name, | 117 | set: this.set.name, |
| @@ -15,8 +15,6 @@ export class QuickReplySettings { | |||
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | |||
| 19 | |||
| 20 | /**@type {Boolean}*/ isEnabled = false; | 18 | /**@type {Boolean}*/ isEnabled = false; |
| 21 | /**@type {Boolean}*/ isCombined = false; | 19 | /**@type {Boolean}*/ isCombined = false; |
| 22 | /**@type {Boolean}*/ isPopout = false; | 20 | /**@type {Boolean}*/ isPopout = false; |
| @@ -50,8 +48,6 @@ export class QuickReplySettings { | |||
| 50 | /**@type {Function}*/ onRequestEditSet; | 48 | /**@type {Function}*/ onRequestEditSet; |
| 51 | 49 | ||
| 52 | 50 | ||
| 53 | |||
| 54 | |||
| 55 | init() { | 51 | init() { |
| 56 | this.hookConfig(this.config); | 52 | this.hookConfig(this.config); |
| 57 | this.hookConfig(this.chatConfig); | 53 | this.hookConfig(this.chatConfig); |
| @@ -60,8 +56,8 @@ export class QuickReplySettings { | |||
| 60 | 56 | ||
| 61 | hookConfig(config) { | 57 | hookConfig(config) { |
| 62 | if (config) { | 58 | if (config) { |
| 63 | config.onUpdate = ()=>this.save(); | 59 | config.onUpdate = () => this.save(); |
| 64 | config.onRequestEditSet = (qrs)=>this.requestEditSet(qrs); | 60 | config.onRequestEditSet = (qrs) => this.requestEditSet(qrs); |
| 65 | } | 61 | } |
| 66 | } | 62 | } |
| 67 | unhookConfig(config) { | 63 | unhookConfig(config) { |
| @@ -72,8 +68,6 @@ export class QuickReplySettings { | |||
| 72 | } | 68 | } |
| 73 | 69 | ||
| 74 | 70 | ||
| 75 | |||
| 76 | |||
| 77 | save() { | 71 | save() { |
| 78 | extension_settings.quickReplyV2 = this.toJSON(); | 72 | extension_settings.quickReplyV2 = this.toJSON(); |
| 79 | saveSettingsDebounced(); | 73 | saveSettingsDebounced(); |
| @@ -16,15 +16,11 @@ export class SlashCommandHandler { | |||
| 16 | /** @type {QuickReplyApi} */ api; | 16 | /** @type {QuickReplyApi} */ api; |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | |||
| 20 | |||
| 21 | constructor(/** @type {QuickReplyApi} */api) { | 19 | constructor(/** @type {QuickReplyApi} */api) { |
| 22 | this.api = api; | 20 | this.api = api; |
| 23 | } | 21 | } |
| 24 | 22 | ||
| 25 | 23 | ||
| 26 | |||
| 27 | |||
| 28 | init() { | 24 | init() { |
| 29 | function getExecutionIcons(/** @type {QuickReply} */ qr) { | 25 | function getExecutionIcons(/** @type {QuickReply} */ qr) { |
| 30 | let icons = ''; | 26 | let icons = ''; |
| @@ -56,7 +52,7 @@ export class SlashCommandHandler { | |||
| 56 | qrIds: (executor) => QuickReplySet.get(String(executor.namedArgumentList.find(x => x.name == 'set')?.value))?.qrList.map(qr => { | 52 | qrIds: (executor) => QuickReplySet.get(String(executor.namedArgumentList.find(x => x.name == 'set')?.value))?.qrList.map(qr => { |
| 57 | const icons = getExecutionIcons(qr); | 53 | const icons = getExecutionIcons(qr); |
| 58 | const message = `${qr.automationId ? `[${qr.automationId}]` : ''}${icons ? `[auto: ${icons}]` : ''} ${qr.title || qr.message}`.trim(); | 54 | const message = `${qr.automationId ? `[${qr.automationId}]` : ''}${icons ? `[auto: ${icons}]` : ''} ${qr.title || qr.message}`.trim(); |
| 59 | return new SlashCommandEnumValue(qr.label, message, enumTypes.enum, enumIcons.qr, null, ()=>qr.id.toString(), true); | 55 | return new SlashCommandEnumValue(qr.label, message, enumTypes.enum, enumIcons.qr, null, () => qr.id.toString(), true); |
| 60 | }) ?? [], | 56 | }) ?? [], |
| 61 | 57 | ||
| 62 | /** All QRs as a set.name string, to be able to execute, for example via the /run command */ | 58 | /** All QRs as a set.name string, to be able to execute, for example via the /run command */ |
| @@ -352,7 +348,7 @@ export class SlashCommandHandler { | |||
| 352 | return ''; | 348 | return ''; |
| 353 | }, | 349 | }, |
| 354 | returns: 'updated quick reply', | 350 | returns: 'updated quick reply', |
| 355 | namedArgumentList: [...qrUpdateArgs, ...qrArgs.map(it=>{ | 351 | namedArgumentList: [...qrUpdateArgs, ...qrArgs.map(it => { |
| 356 | if (it.name == 'label') { | 352 | if (it.name == 'label') { |
| 357 | const clone = SlashCommandNamedArgument.fromProps(it); | 353 | const clone = SlashCommandNamedArgument.fromProps(it); |
| 358 | clone.isRequired = false; | 354 | clone.isRequired = false; |
| @@ -691,16 +687,16 @@ export class SlashCommandHandler { | |||
| 691 | if (!args.from) throw new Error('/import requires from= to be set.'); | 687 | if (!args.from) throw new Error('/import requires from= to be set.'); |
| 692 | if (!value) throw new Error('/import requires the unnamed argument to be set.'); | 688 | if (!value) throw new Error('/import requires the unnamed argument to be set.'); |
| 693 | let qr = [...this.api.listGlobalSets(), ...this.api.listChatSets()] | 689 | let qr = [...this.api.listGlobalSets(), ...this.api.listChatSets()] |
| 694 | .map(it=>this.api.getSetByName(it)?.qrList ?? []) | 690 | .map(it => this.api.getSetByName(it)?.qrList ?? []) |
| 695 | .flat() | 691 | .flat() |
| 696 | .find(it=>it.label == args.from) | 692 | .find(it => it.label == args.from) |
| 697 | ; | 693 | ; |
| 698 | if (!qr) { | 694 | if (!qr) { |
| 699 | let [setName, ...qrNameParts] = args.from.split('.'); | 695 | let [setName, ...qrNameParts] = args.from.split('.'); |
| 700 | let qrName = qrNameParts.join('.'); | 696 | let qrName = qrNameParts.join('.'); |
| 701 | let qrs = QuickReplySet.get(setName); | 697 | let qrs = QuickReplySet.get(setName); |
| 702 | if (qrs) { | 698 | if (qrs) { |
| 703 | qr = qrs.qrList.find(it=>it.label == qrName); | 699 | qr = qrs.qrList.find(it => it.label == qrName); |
| 704 | } | 700 | } |
| 705 | } | 701 | } |
| 706 | if (qr) { | 702 | if (qr) { |
| @@ -709,23 +705,23 @@ export class SlashCommandHandler { | |||
| 709 | if (args._debugController) { | 705 | if (args._debugController) { |
| 710 | closure.source = args.from; | 706 | closure.source = args.from; |
| 711 | } | 707 | } |
| 712 | const testCandidates = (executor)=>{ | 708 | const testCandidates = (executor) => { |
| 713 | return ( | 709 | return ( |
| 714 | executor.namedArgumentList.find(arg=>arg.name == 'key') | 710 | executor.namedArgumentList.find(arg => arg.name == 'key') |
| 715 | && executor.unnamedArgumentList.length > 0 | 711 | && executor.unnamedArgumentList.length > 0 |
| 716 | && executor.unnamedArgumentList[0].value instanceof SlashCommandClosure | 712 | && executor.unnamedArgumentList[0].value instanceof SlashCommandClosure |
| 717 | ) || ( | 713 | ) || ( |
| 718 | !executor.namedArgumentList.find(arg=>arg.name == 'key') | 714 | !executor.namedArgumentList.find(arg => arg.name == 'key') |
| 719 | && executor.unnamedArgumentList.length > 1 | 715 | && executor.unnamedArgumentList.length > 1 |
| 720 | && executor.unnamedArgumentList[1].value instanceof SlashCommandClosure | 716 | && executor.unnamedArgumentList[1].value instanceof SlashCommandClosure |
| 721 | ); | 717 | ); |
| 722 | }; | 718 | }; |
| 723 | const candidates = closure.executorList | 719 | const candidates = closure.executorList |
| 724 | .filter(executor=>['let', 'var'].includes(executor.command.name)) | 720 | .filter(executor => ['let', 'var'].includes(executor.command.name)) |
| 725 | .filter(testCandidates) | 721 | .filter(testCandidates) |
| 726 | .map(executor=>({ | 722 | .map(executor => ({ |
| 727 | key: executor.namedArgumentList.find(arg=>arg.name == 'key')?.value ?? executor.unnamedArgumentList[0].value, | 723 | key: executor.namedArgumentList.find(arg => arg.name == 'key')?.value ?? executor.unnamedArgumentList[0].value, |
| 728 | value: executor.unnamedArgumentList[executor.namedArgumentList.find(arg=>arg.name == 'key') ? 0 : 1].value, | 724 | value: executor.unnamedArgumentList[executor.namedArgumentList.find(arg => arg.name == 'key') ? 0 : 1].value, |
| 729 | })) | 725 | })) |
| 730 | ; | 726 | ; |
| 731 | for (let i = 0; i < value.length; i++) { | 727 | for (let i = 0; i < value.length; i++) { |
| @@ -735,7 +731,7 @@ export class SlashCommandHandler { | |||
| 735 | dstName = value[i + 2]; | 731 | dstName = value[i + 2]; |
| 736 | i += 2; | 732 | i += 2; |
| 737 | } | 733 | } |
| 738 | const pick = candidates.find(it=>it.key == srcName); | 734 | const pick = candidates.find(it => it.key == srcName); |
| 739 | if (!pick) throw new Error(`No scoped closure named "${srcName}" found in "${args.from}"`); | 735 | if (!pick) throw new Error(`No scoped closure named "${srcName}" found in "${args.from}"`); |
| 740 | if (args._scope.existsVariableInScope(dstName)) { | 736 | if (args._scope.existsVariableInScope(dstName)) { |
| 741 | args._scope.setVariable(dstName, pick.value); | 737 | args._scope.setVariable(dstName, pick.value); |
| @@ -783,8 +779,6 @@ export class SlashCommandHandler { | |||
| 783 | } | 779 | } |
| 784 | 780 | ||
| 785 | 781 | ||
| 786 | |||
| 787 | |||
| 788 | getSetByName(name) { | 782 | getSetByName(name) { |
| 789 | const set = this.api.getSetByName(name); | 783 | const set = this.api.getSetByName(name); |
| 790 | if (!set) { | 784 | if (!set) { |
| @@ -802,8 +796,6 @@ export class SlashCommandHandler { | |||
| 802 | } | 796 | } |
| 803 | 797 | ||
| 804 | 798 | ||
| 805 | |||
| 806 | |||
| 807 | async executeQuickReplyByIndex(idx) { | 799 | async executeQuickReplyByIndex(idx) { |
| 808 | try { | 800 | try { |
| 809 | return await this.api.executeQuickReplyByIndex(idx); | 801 | return await this.api.executeQuickReplyByIndex(idx); |
| @@ -10,15 +10,11 @@ export class ButtonUi { | |||
| 10 | /**@type {HTMLElement}*/ popoutDom; | 10 | /**@type {HTMLElement}*/ popoutDom; |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | |||
| 14 | |||
| 15 | constructor(/**@type {QuickReplySettings}*/settings) { | 13 | constructor(/**@type {QuickReplySettings}*/settings) { |
| 16 | this.settings = settings; | 14 | this.settings = settings; |
| 17 | } | 15 | } |
| 18 | 16 | ||
| 19 | 17 | ||
| 20 | |||
| 21 | |||
| 22 | render() { | 18 | render() { |
| 23 | if (this.settings.isPopout) { | 19 | if (this.settings.isPopout) { |
| 24 | return this.renderPopout(); | 20 | return this.renderPopout(); |
| @@ -57,8 +53,6 @@ export class ButtonUi { | |||
| 57 | } | 53 | } |
| 58 | 54 | ||
| 59 | 55 | ||
| 60 | |||
| 61 | |||
| 62 | renderBar() { | 56 | renderBar() { |
| 63 | if (!this.dom) { | 57 | if (!this.dom) { |
| 64 | let buttonHolder; | 58 | let buttonHolder; |
| @@ -75,7 +69,7 @@ export class ButtonUi { | |||
| 75 | popout.classList.add('menu_button'); | 69 | popout.classList.add('menu_button'); |
| 76 | popout.classList.add('fa-solid'); | 70 | popout.classList.add('fa-solid'); |
| 77 | popout.classList.add('fa-window-restore'); | 71 | popout.classList.add('fa-window-restore'); |
| 78 | popout.addEventListener('click', ()=>{ | 72 | popout.addEventListener('click', () => { |
| 79 | this.settings.isPopout = true; | 73 | this.settings.isPopout = true; |
| 80 | this.refresh(); | 74 | this.refresh(); |
| 81 | this.settings.save(); | 75 | this.settings.save(); |
| @@ -91,8 +85,8 @@ export class ButtonUi { | |||
| 91 | } | 85 | } |
| 92 | } | 86 | } |
| 93 | [...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? []), ...(this.settings.charConfig?.setList ?? [])] | 87 | [...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? []), ...(this.settings.charConfig?.setList ?? [])] |
| 94 | .filter(link=>link.isVisible) | 88 | .filter(link => link.isVisible) |
| 95 | .forEach(link=>buttonHolder.append(link.set.render())) | 89 | .forEach(link => buttonHolder.append(link.set.render())) |
| 96 | ; | 90 | ; |
| 97 | } | 91 | } |
| 98 | } | 92 | } |
| @@ -100,8 +94,6 @@ export class ButtonUi { | |||
| 100 | } | 94 | } |
| 101 | 95 | ||
| 102 | 96 | ||
| 103 | |||
| 104 | |||
| 105 | renderPopout() { | 97 | renderPopout() { |
| 106 | if (!this.popoutDom) { | 98 | if (!this.popoutDom) { |
| 107 | let buttonHolder; | 99 | let buttonHolder; |
| @@ -130,7 +122,7 @@ export class ButtonUi { | |||
| 130 | close.classList.add('fa-solid'); | 122 | close.classList.add('fa-solid'); |
| 131 | close.classList.add('fa-circle-xmark'); | 123 | close.classList.add('fa-circle-xmark'); |
| 132 | close.classList.add('hoverglow'); | 124 | close.classList.add('hoverglow'); |
| 133 | close.addEventListener('click', ()=>{ | 125 | close.addEventListener('click', () => { |
| 134 | this.settings.isPopout = false; | 126 | this.settings.isPopout = false; |
| 135 | this.refresh(); | 127 | this.refresh(); |
| 136 | this.settings.save(); | 128 | this.settings.save(); |
| @@ -151,8 +143,8 @@ export class ButtonUi { | |||
| 151 | } | 143 | } |
| 152 | } | 144 | } |
| 153 | [...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? []), ...(this.settings.charConfig?.setList ?? [])] | 145 | [...this.settings.config.setList, ...(this.settings.chatConfig?.setList ?? []), ...(this.settings.charConfig?.setList ?? [])] |
| 154 | .filter(link=>link.isVisible) | 146 | .filter(link => link.isVisible) |
| 155 | .forEach(link=>buttonHolder.append(link.set.render())) | 147 | .forEach(link => buttonHolder.append(link.set.render())) |
| 156 | ; | 148 | ; |
| 157 | root.append(body); | 149 | root.append(body); |
| 158 | } | 150 | } |
| @@ -29,24 +29,18 @@ export class SettingsUi { | |||
| 29 | /**@type {HTMLSelectElement}*/ currentSet; | 29 | /**@type {HTMLSelectElement}*/ currentSet; |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | |||
| 33 | |||
| 34 | constructor(/**@type {QuickReplySettings}*/settings) { | 32 | constructor(/**@type {QuickReplySettings}*/settings) { |
| 35 | this.settings = settings; | 33 | this.settings = settings; |
| 36 | settings.onRequestEditSet = (qrs) => this.selectQrSet(qrs); | 34 | settings.onRequestEditSet = (qrs) => this.selectQrSet(qrs); |
| 37 | } | 35 | } |
| 38 | 36 | ||
| 39 | 37 | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | |||
| 44 | rerender() { | 38 | rerender() { |
| 45 | if (!this.dom) return; | 39 | if (!this.dom) return; |
| 46 | const content = this.dom.querySelector('.inline-drawer-content'); | 40 | const content = this.dom.querySelector('.inline-drawer-content'); |
| 47 | content.innerHTML = ''; | 41 | content.innerHTML = ''; |
| 48 | // @ts-ignore | 42 | // @ts-ignore |
| 49 | Array.from(this.template.querySelector('.inline-drawer-content').cloneNode(true).children).forEach(el=>{ | 43 | Array.from(this.template.querySelector('.inline-drawer-content').cloneNode(true).children).forEach(el => { |
| 50 | content.append(el); | 44 | content.append(el); |
| 51 | }); | 45 | }); |
| 52 | this.prepareDom(); | 46 | this.prepareDom(); |
| @@ -75,15 +69,15 @@ export class SettingsUi { | |||
| 75 | // general settings | 69 | // general settings |
| 76 | this.isEnabled = this.dom.querySelector('#qr--isEnabled'); | 70 | this.isEnabled = this.dom.querySelector('#qr--isEnabled'); |
| 77 | this.isEnabled.checked = this.settings.isEnabled; | 71 | this.isEnabled.checked = this.settings.isEnabled; |
| 78 | this.isEnabled.addEventListener('click', ()=>this.onIsEnabled()); | 72 | this.isEnabled.addEventListener('click', () => this.onIsEnabled()); |
| 79 | 73 | ||
| 80 | this.isCombined = this.dom.querySelector('#qr--isCombined'); | 74 | this.isCombined = this.dom.querySelector('#qr--isCombined'); |
| 81 | this.isCombined.checked = this.settings.isCombined; | 75 | this.isCombined.checked = this.settings.isCombined; |
| 82 | this.isCombined.addEventListener('click', ()=>this.onIsCombined()); | 76 | this.isCombined.addEventListener('click', () => this.onIsCombined()); |
| 83 | 77 | ||
| 84 | this.showPopoutButton = this.dom.querySelector('#qr--showPopoutButton'); | 78 | this.showPopoutButton = this.dom.querySelector('#qr--showPopoutButton'); |
| 85 | this.showPopoutButton.checked = this.settings.showPopoutButton; | 79 | this.showPopoutButton.checked = this.settings.showPopoutButton; |
| 86 | this.showPopoutButton.addEventListener('click', ()=>this.onShowPopoutButton()); | 80 | this.showPopoutButton.addEventListener('click', () => this.onShowPopoutButton()); |
| 87 | } | 81 | } |
| 88 | 82 | ||
| 89 | prepareGlobalSetList() { | 83 | prepareGlobalSetList() { |
| @@ -131,29 +125,29 @@ export class SettingsUi { | |||
| 131 | prepareQrEditor() { | 125 | prepareQrEditor() { |
| 132 | // qr editor | 126 | // qr editor |
| 133 | this.dom.querySelector('#qr--set-rename').addEventListener('click', async () => this.renameQrSet()); | 127 | this.dom.querySelector('#qr--set-rename').addEventListener('click', async () => this.renameQrSet()); |
| 134 | this.dom.querySelector('#qr--set-new').addEventListener('click', async()=>this.addQrSet()); | 128 | this.dom.querySelector('#qr--set-new').addEventListener('click', async () => this.addQrSet()); |
| 135 | /**@type {HTMLInputElement}*/ | 129 | /**@type {HTMLInputElement}*/ |
| 136 | const importFile = this.dom.querySelector('#qr--set-importFile'); | 130 | const importFile = this.dom.querySelector('#qr--set-importFile'); |
| 137 | importFile.addEventListener('change', async()=>{ | 131 | importFile.addEventListener('change', async () => { |
| 138 | await this.importQrSet(importFile.files); | 132 | await this.importQrSet(importFile.files); |
| 139 | importFile.value = null; | 133 | importFile.value = null; |
| 140 | }); | 134 | }); |
| 141 | this.dom.querySelector('#qr--set-import').addEventListener('click', ()=>importFile.click()); | 135 | this.dom.querySelector('#qr--set-import').addEventListener('click', () => importFile.click()); |
| 142 | this.dom.querySelector('#qr--set-export').addEventListener('click', async () => this.exportQrSet()); | 136 | this.dom.querySelector('#qr--set-export').addEventListener('click', async () => this.exportQrSet()); |
| 143 | this.dom.querySelector('#qr--set-duplicate').addEventListener('click', async () => this.duplicateQrSet()); | 137 | this.dom.querySelector('#qr--set-duplicate').addEventListener('click', async () => this.duplicateQrSet()); |
| 144 | this.dom.querySelector('#qr--set-delete').addEventListener('click', async()=>this.deleteQrSet()); | 138 | this.dom.querySelector('#qr--set-delete').addEventListener('click', async () => this.deleteQrSet()); |
| 145 | this.dom.querySelector('#qr--set-add').addEventListener('click', async()=>{ | 139 | this.dom.querySelector('#qr--set-add').addEventListener('click', async () => { |
| 146 | this.currentQrSet.addQuickReply(); | 140 | this.currentQrSet.addQuickReply(); |
| 147 | }); | 141 | }); |
| 148 | this.dom.querySelector('#qr--set-paste').addEventListener('click', async()=>{ | 142 | this.dom.querySelector('#qr--set-paste').addEventListener('click', async () => { |
| 149 | const text = await navigator.clipboard.readText(); | 143 | const text = await navigator.clipboard.readText(); |
| 150 | this.currentQrSet.addQuickReplyFromText(text); | 144 | this.currentQrSet.addQuickReplyFromText(text); |
| 151 | }); | 145 | }); |
| 152 | this.dom.querySelector('#qr--set-importQr').addEventListener('click', async()=>{ | 146 | this.dom.querySelector('#qr--set-importQr').addEventListener('click', async () => { |
| 153 | const inp = document.createElement('input'); { | 147 | const inp = document.createElement('input'); { |
| 154 | inp.type = 'file'; | 148 | inp.type = 'file'; |
| 155 | inp.accept = '.json'; | 149 | inp.accept = '.json'; |
| 156 | inp.addEventListener('change', async()=>{ | 150 | inp.addEventListener('change', async () => { |
| 157 | if (inp.files.length > 0) { | 151 | if (inp.files.length > 0) { |
| 158 | for (const file of inp.files) { | 152 | for (const file of inp.files) { |
| 159 | const text = await file.text(); | 153 | const text = await file.text(); |
| @@ -166,8 +160,8 @@ export class SettingsUi { | |||
| 166 | }); | 160 | }); |
| 167 | this.qrList = this.dom.querySelector('#qr--set-qrList'); | 161 | this.qrList = this.dom.querySelector('#qr--set-qrList'); |
| 168 | this.currentSet = this.dom.querySelector('#qr--set'); | 162 | this.currentSet = this.dom.querySelector('#qr--set'); |
| 169 | this.currentSet.addEventListener('change', ()=>this.onQrSetChange()); | 163 | this.currentSet.addEventListener('change', () => this.onQrSetChange()); |
| 170 | QuickReplySet.list.toSorted((a,b)=>a.name.toLowerCase().localeCompare(b.name.toLowerCase())).forEach(qrs=>{ | 164 | QuickReplySet.list.toSorted((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).forEach(qrs => { |
| 171 | const opt = document.createElement('option'); { | 165 | const opt = document.createElement('option'); { |
| 172 | opt.value = qrs.name; | 166 | opt.value = qrs.name; |
| 173 | opt.textContent = qrs.name; | 167 | opt.textContent = qrs.name; |
| @@ -175,19 +169,19 @@ export class SettingsUi { | |||
| 175 | } | 169 | } |
| 176 | }); | 170 | }); |
| 177 | this.disableSend = this.dom.querySelector('#qr--disableSend'); | 171 | this.disableSend = this.dom.querySelector('#qr--disableSend'); |
| 178 | this.disableSend.addEventListener('click', ()=>{ | 172 | this.disableSend.addEventListener('click', () => { |
| 179 | const qrs = this.currentQrSet; | 173 | const qrs = this.currentQrSet; |
| 180 | qrs.disableSend = this.disableSend.checked; | 174 | qrs.disableSend = this.disableSend.checked; |
| 181 | qrs.save(); | 175 | qrs.save(); |
| 182 | }); | 176 | }); |
| 183 | this.placeBeforeInput = this.dom.querySelector('#qr--placeBeforeInput'); | 177 | this.placeBeforeInput = this.dom.querySelector('#qr--placeBeforeInput'); |
| 184 | this.placeBeforeInput.addEventListener('click', ()=>{ | 178 | this.placeBeforeInput.addEventListener('click', () => { |
| 185 | const qrs = this.currentQrSet; | 179 | const qrs = this.currentQrSet; |
| 186 | qrs.placeBeforeInput = this.placeBeforeInput.checked; | 180 | qrs.placeBeforeInput = this.placeBeforeInput.checked; |
| 187 | qrs.save(); | 181 | qrs.save(); |
| 188 | }); | 182 | }); |
| 189 | this.injectInput = this.dom.querySelector('#qr--injectInput'); | 183 | this.injectInput = this.dom.querySelector('#qr--injectInput'); |
| 190 | this.injectInput.addEventListener('click', ()=>{ | 184 | this.injectInput.addEventListener('click', () => { |
| 191 | const qrs = this.currentQrSet; | 185 | const qrs = this.currentQrSet; |
| 192 | qrs.injectInput = this.injectInput.checked; | 186 | qrs.injectInput = this.injectInput.checked; |
| 193 | qrs.save(); | 187 | qrs.save(); |
| @@ -196,7 +190,7 @@ export class SettingsUi { | |||
| 196 | this.color = this.dom.querySelector('#qr--color'); | 190 | this.color = this.dom.querySelector('#qr--color'); |
| 197 | // @ts-ignore | 191 | // @ts-ignore |
| 198 | this.color.color = this.currentQrSet?.color ?? 'transparent'; | 192 | this.color.color = this.currentQrSet?.color ?? 'transparent'; |
| 199 | this.color.addEventListener('change', (evt)=>{ | 193 | this.color.addEventListener('change', (evt) => { |
| 200 | if (!this.dom.closest('body')) return; | 194 | if (!this.dom.closest('body')) return; |
| 201 | const qrs = this.currentQrSet; | 195 | const qrs = this.currentQrSet; |
| 202 | if (initialColorChange) { | 196 | if (initialColorChange) { |
| @@ -211,7 +205,7 @@ export class SettingsUi { | |||
| 211 | this.currentQrSet.updateColor(); | 205 | this.currentQrSet.updateColor(); |
| 212 | }); | 206 | }); |
| 213 | // @ts-ignore | 207 | // @ts-ignore |
| 214 | this.dom.querySelector('#qr--colorClear').addEventListener('click', (evt)=>{ | 208 | this.dom.querySelector('#qr--colorClear').addEventListener('click', (evt) => { |
| 215 | const qrs = this.currentQrSet; | 209 | const qrs = this.currentQrSet; |
| 216 | // @ts-ignore | 210 | // @ts-ignore |
| 217 | this.color.color = 'transparent'; | 211 | this.color.color = 'transparent'; |
| @@ -219,7 +213,7 @@ export class SettingsUi { | |||
| 219 | this.currentQrSet.updateColor(); | 213 | this.currentQrSet.updateColor(); |
| 220 | }); | 214 | }); |
| 221 | this.onlyBorderColor = this.dom.querySelector('#qr--onlyBorderColor'); | 215 | this.onlyBorderColor = this.dom.querySelector('#qr--onlyBorderColor'); |
| 222 | this.onlyBorderColor.addEventListener('click', ()=>{ | 216 | this.onlyBorderColor.addEventListener('click', () => { |
| 223 | const qrs = this.currentQrSet; | 217 | const qrs = this.currentQrSet; |
| 224 | qrs.onlyBorderColor = this.onlyBorderColor.checked; | 218 | qrs.onlyBorderColor = this.onlyBorderColor.checked; |
| 225 | qrs.save(); | 219 | qrs.save(); |
| @@ -242,7 +236,7 @@ export class SettingsUi { | |||
| 242 | $(qrsDom).sortable({ | 236 | $(qrsDom).sortable({ |
| 243 | delay: getSortableDelay(), | 237 | delay: getSortableDelay(), |
| 244 | handle: '.drag-handle', | 238 | handle: '.drag-handle', |
| 245 | stop: ()=>this.onQrListSort(), | 239 | stop: () => this.onQrListSort(), |
| 246 | }); | 240 | }); |
| 247 | } | 241 | } |
| 248 | 242 | ||
| @@ -256,8 +250,6 @@ export class SettingsUi { | |||
| 256 | } | 250 | } |
| 257 | 251 | ||
| 258 | 252 | ||
| 259 | |||
| 260 | |||
| 261 | async onIsEnabled() { | 253 | async onIsEnabled() { |
| 262 | this.settings.isEnabled = this.isEnabled.checked; | 254 | this.settings.isEnabled = this.isEnabled.checked; |
| 263 | this.settings.save(); | 255 | this.settings.save(); |
| @@ -274,7 +266,7 @@ export class SettingsUi { | |||
| 274 | } | 266 | } |
| 275 | 267 | ||
| 276 | async onGlobalSetListSort() { | 268 | async onGlobalSetListSort() { |
| 277 | this.settings.config.setList = Array.from(this.globalSetList.children).map((it,idx)=>{ | 269 | this.settings.config.setList = Array.from(this.globalSetList.children).map((it, idx) => { |
| 278 | const set = this.settings.config.setList[Number(it.getAttribute('data-order'))]; | 270 | const set = this.settings.config.setList[Number(it.getAttribute('data-order'))]; |
| 279 | it.setAttribute('data-order', String(idx)); | 271 | it.setAttribute('data-order', String(idx)); |
| 280 | return set; | 272 | return set; |
| @@ -283,7 +275,7 @@ export class SettingsUi { | |||
| 283 | } | 275 | } |
| 284 | 276 | ||
| 285 | async onChatSetListSort() { | 277 | async onChatSetListSort() { |
| 286 | this.settings.chatConfig.setList = Array.from(this.chatSetList.children).map((it,idx)=>{ | 278 | this.settings.chatConfig.setList = Array.from(this.chatSetList.children).map((it, idx) => { |
| 287 | const set = this.settings.chatConfig.setList[Number(it.getAttribute('data-order'))]; | 279 | const set = this.settings.chatConfig.setList[Number(it.getAttribute('data-order'))]; |
| 288 | it.setAttribute('data-order', String(idx)); | 280 | it.setAttribute('data-order', String(idx)); |
| 289 | return set; | 281 | return set; |
| @@ -292,14 +284,14 @@ export class SettingsUi { | |||
| 292 | } | 284 | } |
| 293 | 285 | ||
| 294 | updateOrder(list) { | 286 | updateOrder(list) { |
| 295 | Array.from(list.children).forEach((it,idx)=>{ | 287 | Array.from(list.children).forEach((it, idx) => { |
| 296 | it.setAttribute('data-order', idx); | 288 | it.setAttribute('data-order', idx); |
| 297 | }); | 289 | }); |
| 298 | } | 290 | } |
| 299 | 291 | ||
| 300 | async onQrListSort() { | 292 | async onQrListSort() { |
| 301 | this.currentQrSet.qrList = Array.from(this.qrList.querySelectorAll('.qr--set-item')).map((it,idx)=>{ | 293 | this.currentQrSet.qrList = Array.from(this.qrList.querySelectorAll('.qr--set-item')).map((it, idx) => { |
| 302 | const qr = this.currentQrSet.qrList.find(qr=>qr.id == Number(it.getAttribute('data-id'))); | 294 | const qr = this.currentQrSet.qrList.find(qr => qr.id == Number(it.getAttribute('data-id'))); |
| 303 | it.setAttribute('data-order', String(idx)); | 295 | it.setAttribute('data-order', String(idx)); |
| 304 | return qr; | 296 | return qr; |
| 305 | }); | 297 | }); |
| @@ -408,7 +400,7 @@ export class SettingsUi { | |||
| 408 | const qrs = new QuickReplySet(); | 400 | const qrs = new QuickReplySet(); |
| 409 | qrs.name = name; | 401 | qrs.name = name; |
| 410 | qrs.addQuickReply(); | 402 | qrs.addQuickReply(); |
| 411 | const idx = QuickReplySet.list.findIndex(it=>it.name.toLowerCase().localeCompare(name.toLowerCase()) == 1); | 403 | const idx = QuickReplySet.list.findIndex(it => it.name.toLowerCase().localeCompare(name.toLowerCase()) == 1); |
| 412 | if (idx > -1) { | 404 | if (idx > -1) { |
| 413 | QuickReplySet.list.splice(idx, 0, qrs); | 405 | QuickReplySet.list.splice(idx, 0, qrs); |
| 414 | } else { | 406 | } else { |
| @@ -448,7 +440,7 @@ export class SettingsUi { | |||
| 448 | } else { | 440 | } else { |
| 449 | /**@type {QuickReplySet}*/ | 441 | /**@type {QuickReplySet}*/ |
| 450 | const qrs = QuickReplySet.from(JSON.parse(JSON.stringify(props))); | 442 | const qrs = QuickReplySet.from(JSON.parse(JSON.stringify(props))); |
| 451 | qrs.qrList = props.qrList.map(it=>QuickReply.from(it)); | 443 | qrs.qrList = props.qrList.map(it => QuickReply.from(it)); |
| 452 | qrs.init(); | 444 | qrs.init(); |
| 453 | const oldQrs = QuickReplySet.get(props.name); | 445 | const oldQrs = QuickReplySet.get(props.name); |
| 454 | if (oldQrs) { | 446 | if (oldQrs) { |
| @@ -466,7 +458,7 @@ export class SettingsUi { | |||
| 466 | this.prepareCharacterSetList(); | 458 | this.prepareCharacterSetList(); |
| 467 | } | 459 | } |
| 468 | } else { | 460 | } else { |
| 469 | const idx = QuickReplySet.list.findIndex(it=>it.name.toLowerCase().localeCompare(qrs.name.toLowerCase()) == 1); | 461 | const idx = QuickReplySet.list.findIndex(it => it.name.toLowerCase().localeCompare(qrs.name.toLowerCase()) == 1); |
| 470 | if (idx > -1) { | 462 | if (idx > -1) { |
| 471 | QuickReplySet.list.splice(idx, 0, qrs); | 463 | QuickReplySet.list.splice(idx, 0, qrs); |
| 472 | } else { | 464 | } else { |
| @@ -496,7 +488,7 @@ export class SettingsUi { | |||
| 496 | } | 488 | } |
| 497 | 489 | ||
| 498 | exportQrSet() { | 490 | exportQrSet() { |
| 499 | const blob = new Blob([JSON.stringify(this.currentQrSet)], { type:'application/json' }); | 491 | const blob = new Blob([JSON.stringify(this.currentQrSet)], { type: 'application/json' }); |
| 500 | const url = URL.createObjectURL(blob); | 492 | const url = URL.createObjectURL(blob); |
| 501 | const a = document.createElement('a'); { | 493 | const a = document.createElement('a'); { |
| 502 | a.href = url; | 494 | a.href = url; |
| @@ -11,8 +11,6 @@ export class ContextMenu { | |||
| 11 | /**@type {HTMLElement}*/ menu; | 11 | /**@type {HTMLElement}*/ menu; |
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | |||
| 15 | |||
| 16 | constructor(/**@type {QuickReply}*/qr) { | 14 | constructor(/**@type {QuickReply}*/qr) { |
| 17 | // this.itemList = items; | 15 | // this.itemList = items; |
| 18 | this.itemList = this.build(qr).children; | 16 | this.itemList = this.build(qr).children; |
| @@ -104,8 +102,6 @@ export class ContextMenu { | |||
| 104 | } | 102 | } |
| 105 | 103 | ||
| 106 | 104 | ||
| 107 | |||
| 108 | |||
| 109 | show({ clientX, clientY }) { | 105 | show({ clientX, clientY }) { |
| 110 | if (this.isActive) return; | 106 | if (this.isActive) return; |
| 111 | this.isActive = true; | 107 | this.isActive = true; |
| @@ -15,8 +15,6 @@ export class MenuItem { | |||
| 15 | /**@type {function}*/ onExpand; | 15 | /**@type {function}*/ onExpand; |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | |||
| 19 | |||
| 20 | /** | 18 | /** |
| 21 | * | 19 | * |
| 22 | * @param {?string} icon | 20 | * @param {?string} icon |
| @@ -80,7 +78,6 @@ export class MenuItem { | |||
| 80 | } | 78 | } |
| 81 | item.addEventListener('mouseover', () => sub.show(item)); | 79 | item.addEventListener('mouseover', () => sub.show(item)); |
| 82 | item.addEventListener('mouseleave', () => sub.hide()); | 80 | item.addEventListener('mouseleave', () => sub.hide()); |
| 83 | |||
| 84 | } | 81 | } |
| 85 | } | 82 | } |
| 86 | } | 83 | } |
| @@ -9,8 +9,6 @@ export class SubMenu { | |||
| 9 | /**@type {HTMLElement}*/ root; | 9 | /**@type {HTMLElement}*/ root; |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | |||
| 13 | |||
| 14 | constructor(/**@type {MenuItem[]}*/items) { | 12 | constructor(/**@type {MenuItem[]}*/items) { |
| 15 | this.itemList = items; | 13 | this.itemList = items; |
| 16 | } | 14 | } |
| @@ -29,8 +27,6 @@ export class SubMenu { | |||
| 29 | } | 27 | } |
| 30 | 28 | ||
| 31 | 29 | ||
| 32 | |||
| 33 | |||
| 34 | show(/**@type {HTMLElement}*/parent) { | 30 | show(/**@type {HTMLElement}*/parent) { |
| 35 | if (this.isActive) return; | 31 | if (this.isActive) return; |
| 36 | this.isActive = true; | 32 | this.isActive = true; |
| @@ -1031,7 +1031,6 @@ function executeRegexScriptForDebugging(script, text) { | |||
| 1031 | const trailingText = text.substring(lastIndex); | 1031 | const trailingText = text.substring(lastIndex); |
| 1032 | outputText += trailingText; | 1032 | outputText += trailingText; |
| 1033 | highlightedOutput += escapeHtml(trailingText); | 1033 | highlightedOutput += escapeHtml(trailingText); |
| 1034 | |||
| 1035 | } catch (e) { | 1034 | } catch (e) { |
| 1036 | err = (err ? err + '; ' : '') + `Replace error: ${e.message}`; | 1035 | err = (err ? err + '; ' : '') + `Replace error: ${e.message}`; |
| 1037 | outputText = text; // Fallback | 1036 | outputText = text; // Fallback |
| @@ -115,5 +115,4 @@ jQuery(() => { | |||
| 115 | returns: 'number of tokens', | 115 | returns: 'number of tokens', |
| 116 | helpString: 'Counts the number of tokens in the current chat.', | 116 | helpString: 'Counts the number of tokens in the current chat.', |
| 117 | })); | 117 | })); |
| 118 | |||
| 119 | }); | 118 | }); |
| @@ -1043,7 +1043,6 @@ class AllTalkTtsProvider { | |||
| 1043 | // V2: Combine the endpoint with the relative path | 1043 | // V2: Combine the endpoint with the relative path |
| 1044 | return `${this.settings.provider_endpoint}${data.output_file_url}`; | 1044 | return `${this.settings.provider_endpoint}${data.output_file_url}`; |
| 1045 | } | 1045 | } |
| 1046 | |||
| 1047 | } catch (error) { | 1046 | } catch (error) { |
| 1048 | console.error('[fetchTtsGeneration] Exception caught:', error); | 1047 | console.error('[fetchTtsGeneration] Exception caught:', error); |
| 1049 | throw error; | 1048 | throw error; |
| @@ -239,7 +239,6 @@ class ChatterboxTtsProvider { | |||
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | this.setupEventListeners(); | 241 | this.setupEventListeners(); |
| 242 | |||
| 243 | } catch (error) { | 242 | } catch (error) { |
| 244 | console.error('Error loading Chatterbox settings:', error); | 243 | console.error('Error loading Chatterbox settings:', error); |
| 245 | this.updateStatus('Offline'); | 244 | this.updateStatus('Offline'); |
| @@ -518,7 +517,6 @@ class ChatterboxTtsProvider { | |||
| 518 | }); | 517 | }); |
| 519 | 518 | ||
| 520 | await audio.play(); | 519 | await audio.play(); |
| 521 | |||
| 522 | } catch (error) { | 520 | } catch (error) { |
| 523 | console.error('Error previewing voice:', error); | 521 | console.error('Error previewing voice:', error); |
| 524 | this.updateStatus('Ready'); | 522 | this.updateStatus('Ready'); |
| @@ -627,7 +625,6 @@ class ChatterboxTtsProvider { | |||
| 627 | 625 | ||
| 628 | // Return the response directly - SillyTavern expects a Response object | 626 | // Return the response directly - SillyTavern expects a Response object |
| 629 | return response; | 627 | return response; |
| 630 | |||
| 631 | } catch (error) { | 628 | } catch (error) { |
| 632 | console.error('Error in generateTts:', error); | 629 | console.error('Error in generateTts:', error); |
| 633 | this.updateStatus('Ready'); | 630 | this.updateStatus('Ready'); |
| @@ -160,7 +160,7 @@ class CoquiTtsProvider { | |||
| 160 | .then(response => response.json()) | 160 | .then(response => response.json()) |
| 161 | .then(json => { | 161 | .then(json => { |
| 162 | coquiApiModels = json; | 162 | coquiApiModels = json; |
| 163 | console.debug(DEBUG_PREFIX,'initialized coqui-api model list to', coquiApiModels); | 163 | console.debug(DEBUG_PREFIX, 'initialized coqui-api model list to', coquiApiModels); |
| 164 | /* | 164 | /* |
| 165 | $('#coqui_api_language') | 165 | $('#coqui_api_language') |
| 166 | .find('option') | 166 | .find('option') |
| @@ -180,7 +180,7 @@ class CoquiTtsProvider { | |||
| 180 | .then(response => response.json()) | 180 | .then(response => response.json()) |
| 181 | .then(json => { | 181 | .then(json => { |
| 182 | coquiApiModelsFull = json; | 182 | coquiApiModelsFull = json; |
| 183 | console.debug(DEBUG_PREFIX,'initialized coqui-api full model list to', coquiApiModelsFull); | 183 | console.debug(DEBUG_PREFIX, 'initialized coqui-api full model list to', coquiApiModelsFull); |
| 184 | /* | 184 | /* |
| 185 | $('#coqui_api_full_language') | 185 | $('#coqui_api_full_language') |
| 186 | .find('option') | 186 | .find('option') |
| @@ -197,7 +197,7 @@ class CoquiTtsProvider { | |||
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | // Perform a simple readiness check by trying to fetch voiceIds | 199 | // Perform a simple readiness check by trying to fetch voiceIds |
| 200 | async checkReady(){ | 200 | async checkReady() { |
| 201 | throwIfModuleMissing(); | 201 | throwIfModuleMissing(); |
| 202 | await this.fetchTtsVoiceObjects(); | 202 | await this.fetchTtsVoiceObjects(); |
| 203 | } | 203 | } |
| @@ -384,12 +384,12 @@ class CoquiTtsProvider { | |||
| 384 | .append('<option value="none">Select model language</option>') | 384 | .append('<option value="none">Select model language</option>') |
| 385 | .val('none'); | 385 | .val('none'); |
| 386 | 386 | ||
| 387 | for(let language in coquiApiModels) { | 387 | for (let language in coquiApiModels) { |
| 388 | let languageLabel = language; | 388 | let languageLabel = language; |
| 389 | if (language in languageLabels) | 389 | if (language in languageLabels) |
| 390 | languageLabel = languageLabels[language]; | 390 | languageLabel = languageLabels[language]; |
| 391 | $('#coqui_api_language').append(new Option(languageLabel,language)); | 391 | $('#coqui_api_language').append(new Option(languageLabel, language)); |
| 392 | console.log(DEBUG_PREFIX,'added language',languageLabel,'(',language,')'); | 392 | console.log(DEBUG_PREFIX, 'added language', languageLabel, '(', language, ')'); |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | $('#coqui_api_model_div').show(); | 395 | $('#coqui_api_model_div').show(); |
| @@ -406,12 +406,12 @@ class CoquiTtsProvider { | |||
| 406 | .append('<option value="none">Select model language</option>') | 406 | .append('<option value="none">Select model language</option>') |
| 407 | .val('none'); | 407 | .val('none'); |
| 408 | 408 | ||
| 409 | for(let language in coquiApiModelsFull) { | 409 | for (let language in coquiApiModelsFull) { |
| 410 | let languageLabel = language; | 410 | let languageLabel = language; |
| 411 | if (language in languageLabels) | 411 | if (language in languageLabels) |
| 412 | languageLabel = languageLabels[language]; | 412 | languageLabel = languageLabels[language]; |
| 413 | $('#coqui_api_language').append(new Option(languageLabel,language)); | 413 | $('#coqui_api_language').append(new Option(languageLabel, language)); |
| 414 | console.log(DEBUG_PREFIX,'added language',languageLabel,'(',language,')'); | 414 | console.log(DEBUG_PREFIX, 'added language', languageLabel, '(', language, ')'); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | $('#coqui_api_model_div').show(); | 417 | $('#coqui_api_model_div').show(); |
| @@ -450,8 +450,8 @@ class CoquiTtsProvider { | |||
| 450 | if (model_origin == 'coqui-api-full') | 450 | if (model_origin == 'coqui-api-full') |
| 451 | modelDict = coquiApiModelsFull; | 451 | modelDict = coquiApiModelsFull; |
| 452 | 452 | ||
| 453 | for(let model_dataset in modelDict[model_language]) | 453 | for (let model_dataset in modelDict[model_language]) |
| 454 | for(let model_name in modelDict[model_language][model_dataset]) { | 454 | for (let model_name in modelDict[model_language][model_dataset]) { |
| 455 | const model_id = model_dataset + '/' + model_name; | 455 | const model_id = model_dataset + '/' + model_name; |
| 456 | const model_label = model_name + ' (' + model_dataset + ' dataset)'; | 456 | const model_label = model_name + ' (' + model_dataset + ' dataset)'; |
| 457 | $('#coqui_api_model_name').append(new Option(model_label, model_id)); | 457 | $('#coqui_api_model_name').append(new Option(model_label, model_id)); |
| @@ -526,7 +526,7 @@ class CoquiTtsProvider { | |||
| 526 | 526 | ||
| 527 | // Check if already installed and propose to do it otherwise | 527 | // Check if already installed and propose to do it otherwise |
| 528 | const model_id = modelDict[model_language][model_dataset][model_name].id; | 528 | const model_id = modelDict[model_language][model_dataset][model_name].id; |
| 529 | console.debug(DEBUG_PREFIX,'Check if model is already installed',model_id); | 529 | console.debug(DEBUG_PREFIX, 'Check if model is already installed', model_id); |
| 530 | const result = await CoquiTtsProvider.checkmodel_state(model_id); | 530 | const result = await CoquiTtsProvider.checkmodel_state(model_id); |
| 531 | const resultJSON = await result.json(); | 531 | const resultJSON = await result.json(); |
| 532 | const model_state = resultJSON.model_state; | 532 | const model_state = resultJSON.model_state; |
| @@ -583,7 +583,6 @@ class CoquiTtsProvider { | |||
| 583 | $('#coqui_api_model_install_button').show(); | 583 | $('#coqui_api_model_install_button').show(); |
| 584 | return; | 584 | return; |
| 585 | } | 585 | } |
| 586 | |||
| 587 | } | 586 | } |
| 588 | 587 | ||
| 589 | 588 | ||
| @@ -110,15 +110,11 @@ class CosyVoiceProvider { | |||
| 110 | //#################// | 110 | //#################// |
| 111 | 111 | ||
| 112 | async getVoice(voiceName) { | 112 | async getVoice(voiceName) { |
| 113 | |||
| 114 | |||
| 115 | |||
| 116 | if (this.voices.length == 0) { | 113 | if (this.voices.length == 0) { |
| 117 | this.voices = await this.fetchTtsVoiceObjects(); | 114 | this.voices = await this.fetchTtsVoiceObjects(); |
| 118 | } | 115 | } |
| 119 | 116 | ||
| 120 | 117 | ||
| 121 | |||
| 122 | const match = this.voices.filter( | 118 | const match = this.voices.filter( |
| 123 | v => v.name == voiceName, | 119 | v => v.name == voiceName, |
| 124 | )[0]; | 120 | )[0]; |
| @@ -130,7 +126,6 @@ class CosyVoiceProvider { | |||
| 130 | } | 126 | } |
| 131 | 127 | ||
| 132 | 128 | ||
| 133 | |||
| 134 | async generateTts(text, voiceId) { | 129 | async generateTts(text, voiceId) { |
| 135 | const response = await this.fetchTtsGeneration(text, voiceId); | 130 | const response = await this.fetchTtsGeneration(text, voiceId); |
| 136 | return response; | 131 | return response; |
| @@ -198,7 +193,6 @@ class CosyVoiceProvider { | |||
| 198 | } | 193 | } |
| 199 | 194 | ||
| 200 | 195 | ||
| 201 | |||
| 202 | // Interface not used | 196 | // Interface not used |
| 203 | async fetchTtsFromHistory(history_item_id) { | 197 | async fetchTtsFromHistory(history_item_id) { |
| 204 | return Promise.resolve(history_item_id); | 198 | return Promise.resolve(history_item_id); |
| @@ -132,7 +132,7 @@ class ElevenLabsTtsProvider { | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | if (Object.hasOwn(settings, 'apiKey')) { | 134 | if (Object.hasOwn(settings, 'apiKey')) { |
| 135 | if (settings.apiKey && !secret_state[SECRET_KEYS.ELEVENLABS]){ | 135 | if (settings.apiKey && !secret_state[SECRET_KEYS.ELEVENLABS]) { |
| 136 | await writeSecret(SECRET_KEYS.ELEVENLABS, settings.apiKey); | 136 | await writeSecret(SECRET_KEYS.ELEVENLABS, settings.apiKey); |
| 137 | } | 137 | } |
| 138 | delete settings.apiKey; | 138 | delete settings.apiKey; |
| @@ -124,7 +124,6 @@ export class GoogleNativeTtsProvider { | |||
| 124 | console.info(`Google TTS: Loaded ${this.voices.length} voices`); | 124 | console.info(`Google TTS: Loaded ${this.voices.length} voices`); |
| 125 | 125 | ||
| 126 | return this.voices; | 126 | return this.voices; |
| 127 | |||
| 128 | } catch (error) { | 127 | } catch (error) { |
| 129 | console.error('Failed to fetch Google TTS voices:', error); | 128 | console.error('Failed to fetch Google TTS voices:', error); |
| 130 | throw error; | 129 | throw error; |
| @@ -151,7 +150,6 @@ export class GoogleNativeTtsProvider { | |||
| 151 | this.audioElement.src = url; | 150 | this.audioElement.src = url; |
| 152 | this.audioElement.play(); | 151 | this.audioElement.play(); |
| 153 | this.audioElement.onended = () => URL.revokeObjectURL(url); | 152 | this.audioElement.onended = () => URL.revokeObjectURL(url); |
| 154 | |||
| 155 | } catch (error) { | 153 | } catch (error) { |
| 156 | console.error('TTS Preview Error:', error); | 154 | console.error('TTS Preview Error:', error); |
| 157 | toastr.error(`Could not generate preview: ${error.message}`); | 155 | toastr.error(`Could not generate preview: ${error.message}`); |
| @@ -115,15 +115,11 @@ class GptSovitsV2Provider { | |||
| 115 | //#################// | 115 | //#################// |
| 116 | 116 | ||
| 117 | async getVoice(voiceName) { | 117 | async getVoice(voiceName) { |
| 118 | |||
| 119 | |||
| 120 | |||
| 121 | if (this.voices.length == 0) { | 118 | if (this.voices.length == 0) { |
| 122 | this.voices = await this.fetchTtsVoiceObjects(); | 119 | this.voices = await this.fetchTtsVoiceObjects(); |
| 123 | } | 120 | } |
| 124 | 121 | ||
| 125 | 122 | ||
| 126 | |||
| 127 | const match = this.voices.filter( | 123 | const match = this.voices.filter( |
| 128 | v => v.name == voiceName, | 124 | v => v.name == voiceName, |
| 129 | )[0]; | 125 | )[0]; |
| @@ -135,7 +131,6 @@ class GptSovitsV2Provider { | |||
| 135 | } | 131 | } |
| 136 | 132 | ||
| 137 | 133 | ||
| 138 | |||
| 139 | async generateTts(text, voiceId) { | 134 | async generateTts(text, voiceId) { |
| 140 | const response = await this.fetchTtsGeneration(text, voiceId); | 135 | const response = await this.fetchTtsGeneration(text, voiceId); |
| 141 | return response; | 136 | return response; |
| @@ -171,8 +166,6 @@ class GptSovitsV2Provider { | |||
| 171 | */ | 166 | */ |
| 172 | 167 | ||
| 173 | 168 | ||
| 174 | |||
| 175 | |||
| 176 | async fetchTtsGeneration(inputText, voiceId, lang = null, forceNoStreaming = false) { | 169 | async fetchTtsGeneration(inputText, voiceId, lang = null, forceNoStreaming = false) { |
| 177 | console.info(`Generating new TTS for voice_id ${voiceId}`); | 170 | console.info(`Generating new TTS for voice_id ${voiceId}`); |
| 178 | 171 | ||
| @@ -215,7 +208,6 @@ class GptSovitsV2Provider { | |||
| 215 | } | 208 | } |
| 216 | 209 | ||
| 217 | 210 | ||
| 218 | |||
| 219 | // Interface not used | 211 | // Interface not used |
| 220 | async fetchTtsFromHistory(history_item_id) { | 212 | async fetchTtsFromHistory(history_item_id) { |
| 221 | return Promise.resolve(history_item_id); | 213 | return Promise.resolve(history_item_id); |
| @@ -1,4 +1,3 @@ | |||
| 1 | |||
| 2 | import { saveTtsProviderSettings } from './index.js'; | 1 | import { saveTtsProviderSettings } from './index.js'; |
| 3 | 2 | ||
| 4 | export { GSVITtsProvider }; | 3 | export { GSVITtsProvider }; |
| @@ -60,11 +59,9 @@ class GSVITtsProvider { | |||
| 60 | const characterList = await response.json(); | 59 | const characterList = await response.json(); |
| 61 | this.characterList = characterList; | 60 | this.characterList = characterList; |
| 62 | this.voices = Object.keys(characterList); | 61 | this.voices = Object.keys(characterList); |
| 63 | |||
| 64 | } | 62 | } |
| 65 | 63 | ||
| 66 | 64 | ||
| 67 | |||
| 68 | get settingsHtml() { | 65 | get settingsHtml() { |
| 69 | let html = ` | 66 | let html = ` |
| 70 | <label for="gsvi_api_language">Text Language</label> | 67 | <label for="gsvi_api_language">Text Language</label> |
| @@ -142,11 +139,8 @@ class GSVITtsProvider { | |||
| 142 | $('#gsvi_batch_size_output').text(this.settings.batch_size); | 139 | $('#gsvi_batch_size_output').text(this.settings.batch_size); |
| 143 | 140 | ||
| 144 | 141 | ||
| 145 | |||
| 146 | |||
| 147 | // Persist settings changes | 142 | // Persist settings changes |
| 148 | saveTtsProviderSettings(); | 143 | saveTtsProviderSettings(); |
| 149 | |||
| 150 | } | 144 | } |
| 151 | 145 | ||
| 152 | async loadSettings(settings) { | 146 | async loadSettings(settings) { |
| @@ -197,7 +191,6 @@ class GSVITtsProvider { | |||
| 197 | } | 191 | } |
| 198 | 192 | ||
| 199 | 193 | ||
| 200 | |||
| 201 | // Perform a simple readiness check by trying to fetch voiceIds | 194 | // Perform a simple readiness check by trying to fetch voiceIds |
| 202 | async checkReady() { | 195 | async checkReady() { |
| 203 | await Promise.allSettled([this.fetchCharacterList()]); | 196 | await Promise.allSettled([this.fetchCharacterList()]); |
| @@ -256,12 +249,10 @@ class GSVITtsProvider { | |||
| 256 | 249 | ||
| 257 | 250 | ||
| 258 | return `${this.settings.provider_endpoint}/tts?${params.toString()}`; | 251 | return `${this.settings.provider_endpoint}/tts?${params.toString()}`; |
| 259 | |||
| 260 | } | 252 | } |
| 261 | 253 | ||
| 262 | // Interface not used by GSVI TTS | 254 | // Interface not used by GSVI TTS |
| 263 | async fetchTtsFromHistory(history_item_id) { | 255 | async fetchTtsFromHistory(history_item_id) { |
| 264 | return Promise.resolve(history_item_id); | 256 | return Promise.resolve(history_item_id); |
| 265 | } | 257 | } |
| 266 | |||
| 267 | } | 258 | } |
| @@ -611,7 +611,6 @@ async function processTtsQueue() { | |||
| 611 | 611 | ||
| 612 | // Pass the full voiceMapKey (e.g., "User ("Quotes")") as well with character name | 612 | // Pass the full voiceMapKey (e.g., "User ("Quotes")") as well with character name |
| 613 | await tts(segmentText, voiceId, char, voiceMapKey); | 613 | await tts(segmentText, voiceId, char, voiceMapKey); |
| 614 | |||
| 615 | } catch (error) { | 614 | } catch (error) { |
| 616 | toastr.error(error.toString()); | 615 | toastr.error(error.toString()); |
| 617 | console.error(error); | 616 | console.error(error); |
| @@ -707,7 +706,6 @@ async function processTtsQueue() { | |||
| 707 | 706 | ||
| 708 | // Clear current job so the segmented jobs can be processed | 707 | // Clear current job so the segmented jobs can be processed |
| 709 | currentTtsJob = null; | 708 | currentTtsJob = null; |
| 710 | |||
| 711 | } catch (error) { | 709 | } catch (error) { |
| 712 | toastr.error(error.toString()); | 710 | toastr.error(error.toString()); |
| 713 | console.error(error); | 711 | console.error(error); |
| @@ -1286,7 +1284,6 @@ export function getCharacters(unrestricted) { | |||
| 1286 | } | 1284 | } |
| 1287 | 1285 | ||
| 1288 | return characters; | 1286 | return characters; |
| 1289 | |||
| 1290 | } | 1287 | } |
| 1291 | 1288 | ||
| 1292 | export function sanitizeId(input) { | 1289 | export function sanitizeId(input) { |
| @@ -1314,7 +1311,6 @@ function parseVoiceMap(voiceMapString) { | |||
| 1314 | } | 1311 | } |
| 1315 | 1312 | ||
| 1316 | 1313 | ||
| 1317 | |||
| 1318 | /** | 1314 | /** |
| 1319 | * Apply voiceMap based on current voiceMapEntries | 1315 | * Apply voiceMap based on current voiceMapEntries |
| 1320 | */ | 1316 | */ |
| @@ -7,7 +7,7 @@ let ready = false; | |||
| 7 | let voices = []; | 7 | let voices = []; |
| 8 | 8 | ||
| 9 | // Handle messages from the main thread | 9 | // Handle messages from the main thread |
| 10 | self.onmessage = async function(e) { | 10 | self.onmessage = async function (e) { |
| 11 | const { action, data } = e.data; | 11 | const { action, data } = e.data; |
| 12 | 12 | ||
| 13 | switch (action) { | 13 | switch (action) { |
| @@ -837,7 +837,6 @@ class MiniMaxTtsProvider { | |||
| 837 | // Backend handles all the complex processing and returns audio data directly | 837 | // Backend handles all the complex processing and returns audio data directly |
| 838 | console.debug('MiniMax TTS: Audio response received from backend'); | 838 | console.debug('MiniMax TTS: Audio response received from backend'); |
| 839 | return response; | 839 | return response; |
| 840 | |||
| 841 | } catch (error) { | 840 | } catch (error) { |
| 842 | console.error('Error in MiniMax TTS generation:', error); | 841 | console.error('Error in MiniMax TTS generation:', error); |
| 843 | throw error; | 842 | throw error; |
| @@ -954,7 +953,6 @@ class MiniMaxTtsProvider { | |||
| 954 | this.audioElement.onended = null; | 953 | this.audioElement.onended = null; |
| 955 | this.audioElement.onerror = null; | 954 | this.audioElement.onerror = null; |
| 956 | }; | 955 | }; |
| 957 | |||
| 958 | } catch (error) { | 956 | } catch (error) { |
| 959 | console.error('MiniMax TTS Preview Error:', error); | 957 | console.error('MiniMax TTS Preview Error:', error); |
| 960 | toastr.error(`Could not generate preview: ${error.message}`); | 958 | toastr.error(`Could not generate preview: ${error.message}`); |
| @@ -146,7 +146,6 @@ class OpenAITtsProvider { | |||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | populateCharacterInstructions() { | 148 | populateCharacterInstructions() { |
| 149 | |||
| 150 | const currentCharacters = $('.tts_voicemap_block_char span').map((i, el) => $(el).text()).get(); | 149 | const currentCharacters = $('.tts_voicemap_block_char span').map((i, el) => $(el).text()).get(); |
| 151 | 150 | ||
| 152 | $('#openai-character-instructions').empty(); | 151 | $('#openai-character-instructions').empty(); |
| @@ -172,5 +172,4 @@ class SileroTtsProvider { | |||
| 172 | async fetchTtsFromHistory(history_item_id) { | 172 | async fetchTtsFromHistory(history_item_id) { |
| 173 | return Promise.resolve(history_item_id); | 173 | return Promise.resolve(history_item_id); |
| 174 | } | 174 | } |
| 175 | |||
| 176 | } | 175 | } |
| @@ -323,5 +323,4 @@ class XTTSTtsProvider { | |||
| 323 | async fetchTtsFromHistory(history_item_id) { | 323 | async fetchTtsFromHistory(history_item_id) { |
| 324 | return Promise.resolve(history_item_id); | 324 | return Promise.resolve(history_item_id); |
| 325 | } | 325 | } |
| 326 | |||
| 327 | } | 326 | } |
| @@ -1456,7 +1456,6 @@ async function onViewStatsClick() { | |||
| 1456 | messageElement.addClass('vectorized'); | 1456 | messageElement.addClass('vectorized'); |
| 1457 | } | 1457 | } |
| 1458 | } | 1458 | } |
| 1459 | |||
| 1460 | } | 1459 | } |
| 1461 | 1460 | ||
| 1462 | async function onVectorizeAllFilesClick() { | 1461 | async function onVectorizeAllFilesClick() { |
| @@ -13,7 +13,6 @@ export function SaveLocal(target, val) { | |||
| 13 | export function LoadLocal(target) { | 13 | export function LoadLocal(target) { |
| 14 | console.debug('LoadLocal -- ' + target); | 14 | console.debug('LoadLocal -- ' + target); |
| 15 | return localStorage.getItem(target); | 15 | return localStorage.getItem(target); |
| 16 | |||
| 17 | } | 16 | } |
| 18 | /** | 17 | /** |
| 19 | * @deprecated THIS FUNCTION IS OBSOLETE. DO NOT USE | 18 | * @deprecated THIS FUNCTION IS OBSOLETE. DO NOT USE |
| @@ -76,7 +76,6 @@ export const fuzzySearchCategories = Object.freeze({ | |||
| 76 | * data = filterHelper.applyFilters(data); | 76 | * data = filterHelper.applyFilters(data); |
| 77 | */ | 77 | */ |
| 78 | export class FilterHelper { | 78 | export class FilterHelper { |
| 79 | |||
| 80 | /** | 79 | /** |
| 81 | * Cache fuzzy search weighting scores for re-usability, sorting and stuff | 80 | * Cache fuzzy search weighting scores for re-usability, sorting and stuff |
| 82 | * | 81 | * |
| @@ -2477,7 +2477,6 @@ jQuery(() => { | |||
| 2477 | const value = $(this).prop('checked'); | 2477 | const value = $(this).prop('checked'); |
| 2478 | hideMutedSprites = value; | 2478 | hideMutedSprites = value; |
| 2479 | onHideMutedSpritesClick(value); | 2479 | onHideMutedSpritesClick(value); |
| 2480 | |||
| 2481 | }); | 2480 | }); |
| 2482 | $('#send_textarea').on('keyup', onSendTextareaInput); | 2481 | $('#send_textarea').on('keyup', onSendTextareaInput); |
| 2483 | $('#groupCurrentMemberPopoutButton').on('click', doCurMemberListPopout); | 2482 | $('#groupCurrentMemberPopoutButton').on('click', doCurMemberListPopout); |
| @@ -59,7 +59,8 @@ export function initInputMarkdown() { | |||
| 59 | let cursorShift = charsToAdd.length; | 59 | let cursorShift = charsToAdd.length; |
| 60 | let selectedTextandPossibleFormatting = textarea.value.substring(start - possiblePreviousFormattingMargin, end + possiblePreviousFormattingMargin).trim(); | 60 | let selectedTextandPossibleFormatting = textarea.value.substring(start - possiblePreviousFormattingMargin, end + possiblePreviousFormattingMargin).trim(); |
| 61 | 61 | ||
| 62 | if (isTextSelected) { //if text is selected | 62 | if (isTextSelected) { |
| 63 | //if text is selected | ||
| 63 | selectedText = textarea.value.substring(start, end); | 64 | selectedText = textarea.value.substring(start, end); |
| 64 | if (selectedTextandPossibleFormatting === charsToAdd + selectedText + charsToAdd) { | 65 | if (selectedTextandPossibleFormatting === charsToAdd + selectedText + charsToAdd) { |
| 65 | // If the selected text is already formatted, remove the formatting | 66 | // If the selected text is already formatted, remove the formatting |
| @@ -90,7 +91,8 @@ export function initInputMarkdown() { | |||
| 90 | textarea.focus(); | 91 | textarea.focus(); |
| 91 | document.execCommand('insertText', false, charsToAdd + selectedText + charsToAdd + possibleAddedSpace); | 92 | document.execCommand('insertText', false, charsToAdd + selectedText + charsToAdd + possibleAddedSpace); |
| 92 | } | 93 | } |
| 93 | } else {// No text is selected | 94 | } else { |
| 95 | // No text is selected | ||
| 94 | //check 1 character before and after the cursor for non-space characters | 96 | //check 1 character before and after the cursor for non-space characters |
| 95 | 97 | ||
| 96 | if (beforeCaret !== ' ' && afterCaret !== ' ' && afterCaret !== '' && beforeCaret !== '') { //look for caret in the middle of a word | 98 | if (beforeCaret !== ' ' && afterCaret !== ' ' && afterCaret !== '' && beforeCaret !== '') { //look for caret in the middle of a word |
| @@ -116,7 +118,6 @@ export function initInputMarkdown() { | |||
| 116 | } | 118 | } |
| 117 | 119 | ||
| 118 | if (charsToAdd + discoveredWord + charsToAdd === discoveredWordWithPossibleFormatting) { | 120 | if (charsToAdd + discoveredWord + charsToAdd === discoveredWordWithPossibleFormatting) { |
| 119 | |||
| 120 | // Replace the expanded selection with the original discovered word | 121 | // Replace the expanded selection with the original discovered word |
| 121 | textarea.focus(); | 122 | textarea.focus(); |
| 122 | document.execCommand('insertText', false, discoveredWord); | 123 | document.execCommand('insertText', false, discoveredWord); |
| @@ -126,8 +127,6 @@ export function initInputMarkdown() { | |||
| 126 | textarea.focus(); | 127 | textarea.focus(); |
| 127 | document.execCommand('insertText', false, charsToAdd + discoveredWord + charsToAdd); | 128 | document.execCommand('insertText', false, charsToAdd + discoveredWord + charsToAdd); |
| 128 | } | 129 | } |
| 129 | |||
| 130 | |||
| 131 | } else { //caret is not inside a word, so just add the formatting | 130 | } else { //caret is not inside a word, so just add the formatting |
| 132 | textarea.focus(); | 131 | textarea.focus(); |
| 133 | textarea.setSelectionRange(start, end); | 132 | textarea.setSelectionRange(start, end); |
| @@ -798,7 +798,6 @@ jQuery(() => { | |||
| 798 | $('#instruct_system_sequence').prop('readOnly', false); | 798 | $('#instruct_system_sequence').prop('readOnly', false); |
| 799 | $('#instruct_system_suffix').prop('readOnly', false); | 799 | $('#instruct_system_suffix').prop('readOnly', false); |
| 800 | } | 800 | } |
| 801 | |||
| 802 | }); | 801 | }); |
| 803 | 802 | ||
| 804 | $('#instruct_enabled').on('change', function () { | 803 | $('#instruct_enabled').on('change', function () { |
| @@ -2279,7 +2279,6 @@ function appendElectronHubOptions(model_list, groupModels = false) { | |||
| 2279 | appendOption(model); | 2279 | appendOption(model); |
| 2280 | }); | 2280 | }); |
| 2281 | } | 2281 | } |
| 2282 | |||
| 2283 | } | 2282 | } |
| 2284 | 2283 | ||
| 2285 | function electronHubSortBy(data, property = 'alphabetically') { | 2284 | function electronHubSortBy(data, property = 'alphabetically') { |
| @@ -3985,7 +3984,6 @@ function loadOpenAISettings(data, settings) { | |||
| 3985 | option.value = i; | 3984 | option.value = i; |
| 3986 | option.text = item; | 3985 | option.text = item; |
| 3987 | $('#settings_preset_openai').append(option); | 3986 | $('#settings_preset_openai').append(option); |
| 3988 | |||
| 3989 | }); | 3987 | }); |
| 3990 | openai_setting_names = settingNames; | 3988 | openai_setting_names = settingNames; |
| 3991 | 3989 | ||
| @@ -4896,7 +4894,6 @@ function getSiliconflowMaxContext(model, isUnlocked) { | |||
| 4896 | 4894 | ||
| 4897 | // Return context size if model found, otherwise default to 32k | 4895 | // Return context size if model found, otherwise default to 32k |
| 4898 | return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_32k; | 4896 | return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_32k; |
| 4899 | |||
| 4900 | } | 4897 | } |
| 4901 | 4898 | ||
| 4902 | /** | 4899 | /** |
| @@ -5041,7 +5038,6 @@ async function onModelChange() { | |||
| 5041 | console.log('Claude model changed to', value); | 5038 | console.log('Claude model changed to', value); |
| 5042 | oai_settings.claude_model = value; | 5039 | oai_settings.claude_model = value; |
| 5043 | $('#model_claude_select').val(oai_settings.claude_model); | 5040 | $('#model_claude_select').val(oai_settings.claude_model); |
| 5044 | |||
| 5045 | } | 5041 | } |
| 5046 | 5042 | ||
| 5047 | if ($(this).is('#model_openai_select')) { | 5043 | if ($(this).is('#model_openai_select')) { |
| @@ -1593,7 +1593,6 @@ export async function showCharConnections() { | |||
| 1593 | highlightPersonas: true, | 1593 | highlightPersonas: true, |
| 1594 | targetedChar: getCurrentConnectionObj(), | 1594 | targetedChar: getCurrentConnectionObj(), |
| 1595 | shiftClickHandler: (element, ev) => { | 1595 | shiftClickHandler: (element, ev) => { |
| 1596 | |||
| 1597 | const personaId = $(element).attr('data-pid'); | 1596 | const personaId = $(element).attr('data-pid'); |
| 1598 | 1597 | ||
| 1599 | /** @type {PersonaConnection[]} */ | 1598 | /** @type {PersonaConnection[]} */ |
| @@ -1845,7 +1844,6 @@ async function lockPersonaCallback(_args, value) { | |||
| 1845 | if (isFalseBoolean(value)) { | 1844 | if (isFalseBoolean(value)) { |
| 1846 | await setPersonaLockState(false, type); | 1845 | await setPersonaLockState(false, type); |
| 1847 | return 'false'; | 1846 | return 'false'; |
| 1848 | |||
| 1849 | } | 1847 | } |
| 1850 | 1848 | ||
| 1851 | return ''; | 1849 | return ''; |
| @@ -478,7 +478,6 @@ export class Popup { | |||
| 478 | break; | 478 | break; |
| 479 | } | 479 | } |
| 480 | } | 480 | } |
| 481 | |||
| 482 | }; | 481 | }; |
| 483 | this.dlg.addEventListener('keydown', keyListener.bind(this)); | 482 | this.dlg.addEventListener('keydown', keyListener.bind(this)); |
| 484 | } | 483 | } |
| @@ -536,7 +536,6 @@ function switchSwipeNumAllMessages() { | |||
| 536 | var originalSliderValues = []; | 536 | var originalSliderValues = []; |
| 537 | 537 | ||
| 538 | async function switchLabMode({ noReset = false } = {}) { | 538 | async function switchLabMode({ noReset = false } = {}) { |
| 539 | |||
| 540 | /* if (power_user.enableZenSliders && power_user.enableLabMode) { | 539 | /* if (power_user.enableZenSliders && power_user.enableLabMode) { |
| 541 | toastr.warning("Can't start Lab Mode while Zen Sliders are active") | 540 | toastr.warning("Can't start Lab Mode while Zen Sliders are active") |
| 542 | return | 541 | return |
| @@ -571,8 +570,6 @@ async function switchLabMode({ noReset = false } = {}) { | |||
| 571 | $('#amount_gen').attr('min', '1') | 570 | $('#amount_gen').attr('min', '1') |
| 572 | .attr('max', '99999') | 571 | .attr('max', '99999') |
| 573 | .attr('step', '1'); | 572 | .attr('step', '1'); |
| 574 | |||
| 575 | |||
| 576 | } else if (!noReset) { | 573 | } else if (!noReset) { |
| 577 | //re apply the original sliders values to each input | 574 | //re apply the original sliders values to each input |
| 578 | originalSliderValues.forEach(function (slider) { | 575 | originalSliderValues.forEach(function (slider) { |
| @@ -628,7 +625,6 @@ async function switchZenSliders() { | |||
| 628 | }); | 625 | }); |
| 629 | $('div[id$="_zenslider"]').remove(); | 626 | $('div[id$="_zenslider"]').remove(); |
| 630 | } | 627 | } |
| 631 | |||
| 632 | } | 628 | } |
| 633 | async function CreateZenSliders(elmnt) { | 629 | async function CreateZenSliders(elmnt) { |
| 634 | var originalSlider = elmnt; | 630 | var originalSlider = elmnt; |
| @@ -1178,7 +1174,6 @@ function applyShadowWidth() { | |||
| 1178 | document.documentElement.style.setProperty('--shadowWidth', String(power_user.shadow_width)); | 1174 | document.documentElement.style.setProperty('--shadowWidth', String(power_user.shadow_width)); |
| 1179 | $('#shadow_width_counter').val(power_user.shadow_width); | 1175 | $('#shadow_width_counter').val(power_user.shadow_width); |
| 1180 | $('#shadow_width').val(power_user.shadow_width); | 1176 | $('#shadow_width').val(power_user.shadow_width); |
| 1181 | |||
| 1182 | } | 1177 | } |
| 1183 | 1178 | ||
| 1184 | function applyFontScale(type) { | 1179 | function applyFontScale(type) { |
| @@ -2954,7 +2949,6 @@ function setAvgBG() { | |||
| 2954 | } */ | 2949 | } */ |
| 2955 | 2950 | ||
| 2956 | function getAverageRGB(imgEl) { | 2951 | function getAverageRGB(imgEl) { |
| 2957 | |||
| 2958 | var blockSize = 5, // only visit every 5 pixels | 2952 | var blockSize = 5, // only visit every 5 pixels |
| 2959 | defaultRGB = { r: 0, g: 0, b: 0 }, // for non-supporting envs | 2953 | defaultRGB = { r: 0, g: 0, b: 0 }, // for non-supporting envs |
| 2960 | canvas = document.createElement('canvas'), | 2954 | canvas = document.createElement('canvas'), |
| @@ -2994,7 +2988,6 @@ function setAvgBG() { | |||
| 2994 | rgb.b = ~~(rgb.b / count); | 2988 | rgb.b = ~~(rgb.b / count); |
| 2995 | 2989 | ||
| 2996 | return rgb; | 2990 | return rgb; |
| 2997 | |||
| 2998 | } | 2991 | } |
| 2999 | 2992 | ||
| 3000 | /** | 2993 | /** |
| @@ -4035,7 +4028,7 @@ jQuery(() => { | |||
| 4035 | return; | 4028 | return; |
| 4036 | } | 4029 | } |
| 4037 | 4030 | ||
| 4038 | eventSource.once(event_types.SETTINGS_UPDATED, function() { | 4031 | eventSource.once(event_types.SETTINGS_UPDATED, function () { |
| 4039 | toastr.warning( | 4032 | toastr.warning( |
| 4040 | t`Click here to reload.`, | 4033 | t`Click here to reload.`, |
| 4041 | t`Toggling the Experimental Macro Engine requires a reload.`, | 4034 | t`Toggling the Experimental Macro Engine requires a reload.`, |
| @@ -514,7 +514,6 @@ class PresetManager { | |||
| 514 | console.error('Preset could not be renamed', error); | 514 | console.error('Preset could not be renamed', error); |
| 515 | throw new Error('Preset could not be renamed'); | 515 | throw new Error('Preset could not be renamed'); |
| 516 | } | 516 | } |
| 517 | |||
| 518 | } | 517 | } |
| 519 | 518 | ||
| 520 | /** | 519 | /** |
| @@ -865,7 +865,6 @@ function selectReasoningTemplateCallback(args, name) { | |||
| 865 | UI.$select.val(foundName).trigger('change'); | 865 | UI.$select.val(foundName).trigger('change'); |
| 866 | !quiet && toastr.success(`Reasoning template "${foundName}" selected`); | 866 | !quiet && toastr.success(`Reasoning template "${foundName}" selected`); |
| 867 | return foundName; | 867 | return foundName; |
| 868 | |||
| 869 | } | 868 | } |
| 870 | 869 | ||
| 871 | function registerReasoningSlashCommands() { | 870 | function registerReasoningSlashCommands() { |
| @@ -203,7 +203,6 @@ function setSamplerListListeners() { | |||
| 203 | 203 | ||
| 204 | console.log(samplerName, relatedDOMElement.data(SELECT_SAMPLER.DATA), shouldDisplay); | 204 | console.log(samplerName, relatedDOMElement.data(SELECT_SAMPLER.DATA), shouldDisplay); |
| 205 | }); | 205 | }); |
| 206 | |||
| 207 | } | 206 | } |
| 208 | 207 | ||
| 209 | function isElementVisibleInDOM(element) { | 208 | function isElementVisibleInDOM(element) { |
| @@ -9,7 +9,7 @@ export const markdownUnderscoreExt = () => { | |||
| 9 | return [{ | 9 | return [{ |
| 10 | type: 'output', | 10 | type: 'output', |
| 11 | regex: new RegExp('(<code(?:\\s+[^>]*)?>[\\s\\S]*?<\\/code>|<style(?:\\s+[^>]*)?>[\\s\\S]*?<\\/style>)|\\b(?<!_)_(?!_)(.*?)(?<!_)_(?!_)\\b', 'gi'), | 11 | regex: new RegExp('(<code(?:\\s+[^>]*)?>[\\s\\S]*?<\\/code>|<style(?:\\s+[^>]*)?>[\\s\\S]*?<\\/style>)|\\b(?<!_)_(?!_)(.*?)(?<!_)_(?!_)\\b', 'gi'), |
| 12 | replace: function(match, tagContent, italicContent) { | 12 | replace: function (match, tagContent, italicContent) { |
| 13 | if (tagContent) { | 13 | if (tagContent) { |
| 14 | // If it's inside <code> or <style> tags, return unchanged | 14 | // If it's inside <code> or <style> tags, return unchanged |
| 15 | return match; | 15 | return match; |
| @@ -4916,7 +4916,6 @@ export async function sendNarratorMessage(args, text) { | |||
| 4916 | } | 4916 | } |
| 4917 | 4917 | ||
| 4918 | export async function promptQuietForLoudResponse(who, text) { | 4918 | export async function promptQuietForLoudResponse(who, text) { |
| 4919 | |||
| 4920 | let character_id = getContext().characterId; | 4919 | let character_id = getContext().characterId; |
| 4921 | if (who === 'sys') { | 4920 | if (who === 'sys') { |
| 4922 | text = 'System: ' + text; | 4921 | text = 'System: ' + text; |
| @@ -4955,7 +4954,6 @@ export async function promptQuietForLoudResponse(who, text) { | |||
| 4955 | addOneMessage(message); | 4954 | addOneMessage(message); |
| 4956 | await eventSource.emit(event_types.USER_MESSAGE_RENDERED, (chat.length - 1)); | 4955 | await eventSource.emit(event_types.USER_MESSAGE_RENDERED, (chat.length - 1)); |
| 4957 | await saveChatConditional(); | 4956 | await saveChatConditional(); |
| 4958 | |||
| 4959 | } | 4957 | } |
| 4960 | 4958 | ||
| 4961 | async function sendCommentMessage(args, text) { | 4959 | async function sendCommentMessage(args, text) { |
| @@ -26,7 +26,6 @@ import { SlashCommandScope } from './SlashCommandScope.js'; | |||
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | |||
| 30 | export class SlashCommand { | 29 | export class SlashCommand { |
| 31 | /** | 30 | /** |
| 32 | * Creates a SlashCommand from a properties object. | 31 | * Creates a SlashCommand from a properties object. |
| @@ -48,8 +47,6 @@ export class SlashCommand { | |||
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | 49 | ||
| 51 | |||
| 52 | |||
| 53 | /**@type {string}*/ name; | 50 | /**@type {string}*/ name; |
| 54 | /**@type {(namedArguments:NamedArguments, unnamedArguments:UnnamedArguments)=>string|SlashCommandClosure|Promise<string|SlashCommandClosure>}*/ callback; | 51 | /**@type {(namedArguments:NamedArguments, unnamedArguments:UnnamedArguments)=>string|SlashCommandClosure|Promise<string|SlashCommandClosure>}*/ callback; |
| 55 | /**@type {string}*/ helpString; | 52 | /**@type {string}*/ helpString; |
| @@ -86,7 +83,7 @@ export class SlashCommand { | |||
| 86 | name.classList.add('name'); | 83 | name.classList.add('name'); |
| 87 | name.classList.add('monospace'); | 84 | name.classList.add('monospace'); |
| 88 | name.textContent = '/'; | 85 | name.textContent = '/'; |
| 89 | key.split('').forEach(char=>{ | 86 | key.split('').forEach(char => { |
| 90 | const span = document.createElement('span'); { | 87 | const span = document.createElement('span'); { |
| 91 | span.textContent = char; | 88 | span.textContent = char; |
| 92 | name.append(span); | 89 | name.append(span); |
| @@ -229,7 +226,7 @@ export class SlashCommand { | |||
| 229 | const unnamedArguments = cmd.unnamedArgumentList ?? []; | 226 | const unnamedArguments = cmd.unnamedArgumentList ?? []; |
| 230 | const returnType = cmd.returns ?? 'void'; | 227 | const returnType = cmd.returns ?? 'void'; |
| 231 | const helpString = cmd.helpString ?? 'NO DETAILS'; | 228 | const helpString = cmd.helpString ?? 'NO DETAILS'; |
| 232 | const aliasList = [cmd.name, ...(cmd.aliases ?? [])].filter(it=>it != key); | 229 | const aliasList = [cmd.name, ...(cmd.aliases ?? [])].filter(it => it != key); |
| 233 | const specs = document.createElement('div'); { | 230 | const specs = document.createElement('div'); { |
| 234 | specs.classList.add('specs'); | 231 | specs.classList.add('specs'); |
| 235 | const head = document.createElement('div'); { | 232 | const head = document.createElement('div'); { |
| @@ -257,7 +254,7 @@ export class SlashCommand { | |||
| 257 | this.isExtension ? 'Extension' : 'Core', | 254 | this.isExtension ? 'Extension' : 'Core', |
| 258 | this.isThirdParty ? 'Third Party' : (this.isExtension ? 'Core' : null), | 255 | this.isThirdParty ? 'Third Party' : (this.isExtension ? 'Core' : null), |
| 259 | this.source, | 256 | this.source, |
| 260 | ].filter(it=>it).join('\n'); | 257 | ].filter(it => it).join('\n'); |
| 261 | head.append(src); | 258 | head.append(src); |
| 262 | } | 259 | } |
| 263 | if (this.rawQuotes) { | 260 | if (this.rawQuotes) { |
| @@ -5,7 +5,6 @@ import { SlashCommandExecutor } from './SlashCommandExecutor.js'; | |||
| 5 | import { SlashCommandScope } from './SlashCommandScope.js'; | 5 | import { SlashCommandScope } from './SlashCommandScope.js'; |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | |||
| 9 | /**@readonly*/ | 8 | /**@readonly*/ |
| 10 | /**@enum {string}*/ | 9 | /**@enum {string}*/ |
| 11 | export const ARGUMENT_TYPE = { | 10 | export const ARGUMENT_TYPE = { |
| @@ -68,7 +67,7 @@ export class SlashCommandArgument { | |||
| 68 | this.isRequired = isRequired ?? false; | 67 | this.isRequired = isRequired ?? false; |
| 69 | this.acceptsMultiple = acceptsMultiple ?? false; | 68 | this.acceptsMultiple = acceptsMultiple ?? false; |
| 70 | this.defaultValue = defaultValue; | 69 | this.defaultValue = defaultValue; |
| 71 | this.enumList = (enums ? Array.isArray(enums) ? enums : [enums] : []).map(it=>{ | 70 | this.enumList = (enums ? Array.isArray(enums) ? enums : [enums] : []).map(it => { |
| 72 | if (it instanceof SlashCommandEnumValue) return it; | 71 | if (it instanceof SlashCommandEnumValue) return it; |
| 73 | return new SlashCommandEnumValue(it); | 72 | return new SlashCommandEnumValue(it); |
| 74 | }); | 73 | }); |
| @@ -22,11 +22,11 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 22 | executor.start, | 22 | executor.start, |
| 23 | Object | 23 | Object |
| 24 | .keys(commands) | 24 | .keys(commands) |
| 25 | .map(key=>new SlashCommandCommandAutoCompleteOption(commands[key], key)) | 25 | .map(key => new SlashCommandCommandAutoCompleteOption(commands[key], key)) |
| 26 | , | 26 | , |
| 27 | false, | 27 | false, |
| 28 | ()=>`No matching slash commands for "/${this.name}"`, | 28 | () => `No matching slash commands for "/${this.name}"`, |
| 29 | ()=>'No slash commands found!', | 29 | () => 'No slash commands found!', |
| 30 | ); | 30 | ); |
| 31 | this.executor = executor; | 31 | this.executor = executor; |
| 32 | this.scope = scope; | 32 | this.scope = scope; |
| @@ -63,7 +63,7 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 63 | if (!Array.isArray(this.executor.command?.namedArgumentList)) { | 63 | if (!Array.isArray(this.executor.command?.namedArgumentList)) { |
| 64 | return null; | 64 | return null; |
| 65 | } | 65 | } |
| 66 | const notProvidedNamedArguments = this.executor.command.namedArgumentList.filter(arg=>!this.executor.namedArgumentList.find(it=>it.name == arg.name)); | 66 | const notProvidedNamedArguments = this.executor.command.namedArgumentList.filter(arg => !this.executor.namedArgumentList.find(it => it.name == arg.name)); |
| 67 | let name; | 67 | let name; |
| 68 | let value; | 68 | let value; |
| 69 | let start; | 69 | let start; |
| @@ -73,13 +73,13 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 73 | const namedArgsFollowedBySpace = text[this.executor.endNamedArgs] == ' '; | 73 | const namedArgsFollowedBySpace = text[this.executor.endNamedArgs] == ' '; |
| 74 | if (this.executor.startNamedArgs <= index && this.executor.endNamedArgs + (namedArgsFollowedBySpace ? 1 : 0) >= index) { | 74 | if (this.executor.startNamedArgs <= index && this.executor.endNamedArgs + (namedArgsFollowedBySpace ? 1 : 0) >= index) { |
| 75 | // cursor is somewhere within the named arguments (including final space) | 75 | // cursor is somewhere within the named arguments (including final space) |
| 76 | argAssign = this.executor.namedArgumentList.find(it=>it.start <= index && it.end >= index); | 76 | argAssign = this.executor.namedArgumentList.find(it => it.start <= index && it.end >= index); |
| 77 | if (argAssign) { | 77 | if (argAssign) { |
| 78 | const [argName, ...v] = text.slice(argAssign.start, index).split(getSplitRegex()); | 78 | const [argName, ...v] = text.slice(argAssign.start, index).split(getSplitRegex()); |
| 79 | name = argName; | 79 | name = argName; |
| 80 | value = v.join(''); | 80 | value = v.join(''); |
| 81 | start = argAssign.start; | 81 | start = argAssign.start; |
| 82 | cmdArg = this.executor.command.namedArgumentList.find(it=>[it.name, `${it.name}=`].includes(argAssign.name)); | 82 | cmdArg = this.executor.command.namedArgumentList.find(it => [it.name, `${it.name}=`].includes(argAssign.name)); |
| 83 | if (cmdArg) notProvidedNamedArguments.push(cmdArg); | 83 | if (cmdArg) notProvidedNamedArguments.push(cmdArg); |
| 84 | } else { | 84 | } else { |
| 85 | name = ''; | 85 | name = ''; |
| @@ -106,13 +106,13 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 106 | // if cursor is already behind "=" check for enums | 106 | // if cursor is already behind "=" check for enums |
| 107 | const enumList = cmdArg?.enumProvider?.(this.executor, this.scope) ?? cmdArg?.enumList; | 107 | const enumList = cmdArg?.enumProvider?.(this.executor, this.scope) ?? cmdArg?.enumList; |
| 108 | if (cmdArg && enumList?.length) { | 108 | if (cmdArg && enumList?.length) { |
| 109 | if (isSelect && enumList.find(it=>it.value == value) && argAssign && argAssign.end == index) { | 109 | if (isSelect && enumList.find(it => it.value == value) && argAssign && argAssign.end == index) { |
| 110 | return null; | 110 | return null; |
| 111 | } | 111 | } |
| 112 | const result = new AutoCompleteSecondaryNameResult( | 112 | const result = new AutoCompleteSecondaryNameResult( |
| 113 | value, | 113 | value, |
| 114 | start + name.length, | 114 | start + name.length, |
| 115 | enumList.map(it=>SlashCommandEnumAutoCompleteOption.from(this.executor.command, it)), | 115 | enumList.map(it => SlashCommandEnumAutoCompleteOption.from(this.executor.command, it)), |
| 116 | true, | 116 | true, |
| 117 | ); | 117 | ); |
| 118 | result.isRequired = true; | 118 | result.isRequired = true; |
| @@ -125,10 +125,10 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 125 | const result = new AutoCompleteSecondaryNameResult( | 125 | const result = new AutoCompleteSecondaryNameResult( |
| 126 | name, | 126 | name, |
| 127 | start, | 127 | start, |
| 128 | notProvidedNamedArguments.map(it=>new SlashCommandNamedArgumentAutoCompleteOption(it, this.executor.command)), | 128 | notProvidedNamedArguments.map(it => new SlashCommandNamedArgumentAutoCompleteOption(it, this.executor.command)), |
| 129 | false, | 129 | false, |
| 130 | ); | 130 | ); |
| 131 | result.isRequired = notProvidedNamedArguments.find(it=>it.isRequired) != null; | 131 | result.isRequired = notProvidedNamedArguments.find(it => it.isRequired) != null; |
| 132 | return result; | 132 | return result; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| @@ -147,7 +147,7 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 147 | let argAssign; | 147 | let argAssign; |
| 148 | if (this.executor.startUnnamedArgs <= index && this.executor.endUnnamedArgs + 1 >= index) { | 148 | if (this.executor.startUnnamedArgs <= index && this.executor.endUnnamedArgs + 1 >= index) { |
| 149 | // cursor is somwehere in the unnamed args | 149 | // cursor is somwehere in the unnamed args |
| 150 | const idx = this.executor.unnamedArgumentList.findIndex(it=>it.start <= index && it.end >= index); | 150 | const idx = this.executor.unnamedArgumentList.findIndex(it => it.start <= index && it.end >= index); |
| 151 | if (idx > -1) { | 151 | if (idx > -1) { |
| 152 | argAssign = this.executor.unnamedArgumentList[idx]; | 152 | argAssign = this.executor.unnamedArgumentList[idx]; |
| 153 | cmdArg = this.executor.command.unnamedArgumentList[idx]; | 153 | cmdArg = this.executor.command.unnamedArgumentList[idx]; |
| @@ -179,10 +179,10 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult { | |||
| 179 | const result = new AutoCompleteSecondaryNameResult( | 179 | const result = new AutoCompleteSecondaryNameResult( |
| 180 | value, | 180 | value, |
| 181 | start, | 181 | start, |
| 182 | enumList.map(it=>SlashCommandEnumAutoCompleteOption.from(this.executor.command, it)), | 182 | enumList.map(it => SlashCommandEnumAutoCompleteOption.from(this.executor.command, it)), |
| 183 | false, | 183 | false, |
| 184 | ); | 184 | ); |
| 185 | const isCompleteValue = enumList.find(it=>it.value == value); | 185 | const isCompleteValue = enumList.find(it => it.value == value); |
| 186 | const isSelectedValue = isSelect && isCompleteValue; | 186 | const isSelectedValue = isSelect && isCompleteValue; |
| 187 | result.isRequired = cmdArg.isRequired && !isSelectedValue; | 187 | result.isRequired = cmdArg.isRequired && !isSelectedValue; |
| 188 | result.forceMatch = cmdArg.forceEnum; | 188 | result.forceMatch = cmdArg.forceEnum; |
| @@ -25,7 +25,7 @@ export class SlashCommandBrowser { | |||
| 25 | inp.classList.add('text_pole'); | 25 | inp.classList.add('text_pole'); |
| 26 | inp.type = 'search'; | 26 | inp.type = 'search'; |
| 27 | inp.placeholder = 'Search slash commands - use quotes to search "literal" instead of fuzzy'; | 27 | inp.placeholder = 'Search slash commands - use quotes to search "literal" instead of fuzzy'; |
| 28 | inp.addEventListener('input', ()=>{ | 28 | inp.addEventListener('input', () => { |
| 29 | this.details?.remove(); | 29 | this.details?.remove(); |
| 30 | this.details = null; | 30 | this.details = null; |
| 31 | let query = inp.value.trim(); | 31 | let query = inp.value.trim(); |
| @@ -38,7 +38,7 @@ export class SlashCommandBrowser { | |||
| 38 | const match = queryRegex.exec(query); | 38 | const match = queryRegex.exec(query); |
| 39 | if (!match) break; | 39 | if (!match) break; |
| 40 | if (match[1] !== undefined) { | 40 | if (match[1] !== undefined) { |
| 41 | fuzzyList.push(new RegExp(`^(.*?)${match[1].split('').map(char=>`(${escapeRegex(char)})`).join('(.*?)')}(.*?)$`, 'i')); | 41 | fuzzyList.push(new RegExp(`^(.*?)${match[1].split('').map(char => `(${escapeRegex(char)})`).join('(.*?)')}(.*?)$`, 'i')); |
| 42 | } else if (match[2] !== undefined) { | 42 | } else if (match[2] !== undefined) { |
| 43 | quotedList.push(match[2]); | 43 | quotedList.push(match[2]); |
| 44 | } | 44 | } |
| @@ -47,17 +47,17 @@ export class SlashCommandBrowser { | |||
| 47 | for (const cmd of this.cmdList) { | 47 | for (const cmd of this.cmdList) { |
| 48 | const targets = [ | 48 | const targets = [ |
| 49 | cmd.name, | 49 | cmd.name, |
| 50 | ...cmd.namedArgumentList.map(it=>it.name), | 50 | ...cmd.namedArgumentList.map(it => it.name), |
| 51 | ...cmd.namedArgumentList.map(it=>it.description), | 51 | ...cmd.namedArgumentList.map(it => it.description), |
| 52 | ...cmd.namedArgumentList.map(it=>it.enumList.map(e=>e.value)).flat(), | 52 | ...cmd.namedArgumentList.map(it => it.enumList.map(e => e.value)).flat(), |
| 53 | ...cmd.namedArgumentList.map(it=>it.typeList).flat(), | 53 | ...cmd.namedArgumentList.map(it => it.typeList).flat(), |
| 54 | ...cmd.unnamedArgumentList.map(it=>it.description), | 54 | ...cmd.unnamedArgumentList.map(it => it.description), |
| 55 | ...cmd.unnamedArgumentList.map(it=>it.enumList.map(e=>e.value)).flat(), | 55 | ...cmd.unnamedArgumentList.map(it => it.enumList.map(e => e.value)).flat(), |
| 56 | ...cmd.unnamedArgumentList.map(it=>it.typeList).flat(), | 56 | ...cmd.unnamedArgumentList.map(it => it.typeList).flat(), |
| 57 | ...cmd.aliases, | 57 | ...cmd.aliases, |
| 58 | cmd.helpString, | 58 | cmd.helpString, |
| 59 | ]; | 59 | ]; |
| 60 | const find = ()=>targets.find(t=>(fuzzyList.find(f=>f.test(t)) ?? quotedList.find(q=>t.includes(q))) !== undefined) !== undefined; | 60 | const find = () => targets.find(t => (fuzzyList.find(f => f.test(t)) ?? quotedList.find(q => t.includes(q))) !== undefined) !== undefined; |
| 61 | if (fuzzyList.length + quotedList.length === 0 || find()) { | 61 | if (fuzzyList.length + quotedList.length === 0 || find()) { |
| 62 | this.itemMap[cmd.name].classList.remove('isFiltered'); | 62 | this.itemMap[cmd.name].classList.remove('isFiltered'); |
| 63 | } else { | 63 | } else { |
| @@ -85,7 +85,7 @@ export class SlashCommandBrowser { | |||
| 85 | const item = cmd.renderHelpItem(); | 85 | const item = cmd.renderHelpItem(); |
| 86 | this.itemMap[cmd.name] = item; | 86 | this.itemMap[cmd.name] = item; |
| 87 | let details; | 87 | let details; |
| 88 | item.addEventListener('click', ()=>{ | 88 | item.addEventListener('click', () => { |
| 89 | if (!details) { | 89 | if (!details) { |
| 90 | details = document.createElement('div'); { | 90 | details = document.createElement('div'); { |
| 91 | details.classList.add('autoComplete-detailsWrap'); | 91 | details.classList.add('autoComplete-detailsWrap'); |
| @@ -97,7 +97,7 @@ export class SlashCommandBrowser { | |||
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | if (this.details !== details) { | 99 | if (this.details !== details) { |
| 100 | Array.from(list.querySelectorAll('.selected')).forEach(it=>it.classList.remove('selected')); | 100 | Array.from(list.querySelectorAll('.selected')).forEach(it => it.classList.remove('selected')); |
| 101 | item.classList.add('selected'); | 101 | item.classList.add('selected'); |
| 102 | this.details?.remove(); | 102 | this.details?.remove(); |
| 103 | container.append(details); | 103 | container.append(details); |
| @@ -122,13 +122,13 @@ export class SlashCommandBrowser { | |||
| 122 | } | 122 | } |
| 123 | parent.append(this.dom); | 123 | parent.append(this.dom); |
| 124 | 124 | ||
| 125 | this.mo = new MutationObserver(muts=>{ | 125 | this.mo = new MutationObserver(muts => { |
| 126 | if (muts.find(mut=>Array.from(mut.removedNodes).find(it=>it === this.dom || it.contains(this.dom)))) { | 126 | if (muts.find(mut => Array.from(mut.removedNodes).find(it => it === this.dom || it.contains(this.dom)))) { |
| 127 | this.mo.disconnect(); | 127 | this.mo.disconnect(); |
| 128 | window.removeEventListener('keydown', boundHandler); | 128 | window.removeEventListener('keydown', boundHandler); |
| 129 | } | 129 | } |
| 130 | }); | 130 | }); |
| 131 | this.mo.observe(document.querySelector('#chat'), { childList:true, subtree:true }); | 131 | this.mo.observe(document.querySelector('#chat'), { childList: true, subtree: true }); |
| 132 | const boundHandler = this.handleKeyDown.bind(this); | 132 | const boundHandler = this.handleKeyDown.bind(this); |
| 133 | window.addEventListener('keydown', boundHandler); | 133 | window.addEventListener('keydown', boundHandler); |
| 134 | return this.dom; | 134 | return this.dom; |
| @@ -37,7 +37,7 @@ export class SlashCommandClosure { | |||
| 37 | 37 | ||
| 38 | /**@type {number}*/ | 38 | /**@type {number}*/ |
| 39 | get commandCount() { | 39 | get commandCount() { |
| 40 | return this.executorList.map(executor=>executor.commandCount).reduce((sum,cur)=>sum + cur, 0); | 40 | return this.executorList.map(executor => executor.commandCount).reduce((sum, cur) => sum + cur, 0); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | constructor(parent) { | 43 | constructor(parent) { |
| @@ -156,7 +156,7 @@ export class SlashCommandClosure { | |||
| 156 | let isList = false; | 156 | let isList = false; |
| 157 | let listValues = []; | 157 | let listValues = []; |
| 158 | scope = scope ?? this.scope; | 158 | scope = scope ?? this.scope; |
| 159 | const escapeMacro = (it, isAnchored = false)=>{ | 159 | const escapeMacro = (it, isAnchored = false) => { |
| 160 | const regexText = escapeRegex(it.key.replace(/\*/g, '~~~WILDCARD~~~')) | 160 | const regexText = escapeRegex(it.key.replace(/\*/g, '~~~WILDCARD~~~')) |
| 161 | .replaceAll('~~~WILDCARD~~~', '(?:(?:(?!(?:::|}})).)*)') | 161 | .replaceAll('~~~WILDCARD~~~', '(?:(?:(?!(?:::|}})).)*)') |
| 162 | ; | 162 | ; |
| @@ -165,7 +165,7 @@ export class SlashCommandClosure { | |||
| 165 | } | 165 | } |
| 166 | return regexText; | 166 | return regexText; |
| 167 | }; | 167 | }; |
| 168 | const macroList = scope.macroList.toSorted((a,b)=>{ | 168 | const macroList = scope.macroList.toSorted((a, b) => { |
| 169 | if (a.key.includes('*') && !b.key.includes('*')) return 1; | 169 | if (a.key.includes('*') && !b.key.includes('*')) return 1; |
| 170 | if (!a.key.includes('*') && b.key.includes('*')) return -1; | 170 | if (!a.key.includes('*') && b.key.includes('*')) return -1; |
| 171 | if (a.key.includes('*') && b.key.includes('*')) return b.key.indexOf('*') - a.key.indexOf('*'); | 171 | if (a.key.includes('*') && b.key.includes('*')) return b.key.indexOf('*') - a.key.indexOf('*'); |
| @@ -174,7 +174,7 @@ export class SlashCommandClosure { | |||
| 174 | if (power_user.experimental_macro_engine) { | 174 | if (power_user.experimental_macro_engine) { |
| 175 | return this.substituteWithMacroEngine(text, scope, macroList); | 175 | return this.substituteWithMacroEngine(text, scope, macroList); |
| 176 | } | 176 | } |
| 177 | const macros = macroList.map(it=>escapeMacro(it)).join('|'); | 177 | const macros = macroList.map(it => escapeMacro(it)).join('|'); |
| 178 | const re = new RegExp(`(?<pipe>{{pipe}})|(?:{{var::(?<var>[^\\s]+?)(?:::(?<varIndex>(?!}}).+))?}})|(?:{{(?<macro>${macros})}})`); | 178 | const re = new RegExp(`(?<pipe>{{pipe}})|(?:{{var::(?<var>[^\\s]+?)(?:::(?<varIndex>(?!}}).+))?}})|(?:{{(?<macro>${macros})}})`); |
| 179 | let done = ''; | 179 | let done = ''; |
| 180 | let remaining = text; | 180 | let remaining = text; |
| @@ -182,7 +182,7 @@ export class SlashCommandClosure { | |||
| 182 | const match = re.exec(remaining); | 182 | const match = re.exec(remaining); |
| 183 | const before = substituteParams(remaining.slice(0, match.index)); | 183 | const before = substituteParams(remaining.slice(0, match.index)); |
| 184 | const after = remaining.slice(match.index + match[0].length); | 184 | const after = remaining.slice(match.index + match[0].length); |
| 185 | const replacer = match.groups.pipe ? scope.pipe : match.groups.var ? scope.getVariable(match.groups.var, match.groups.index) : macroList.find(it=>it.key == match.groups.macro || new RegExp(escapeMacro(it, true)).test(match.groups.macro))?.value; | 185 | const replacer = match.groups.pipe ? scope.pipe : match.groups.var ? scope.getVariable(match.groups.var, match.groups.index) : macroList.find(it => it.key == match.groups.macro || new RegExp(escapeMacro(it, true)).test(match.groups.macro))?.value; |
| 186 | if (replacer instanceof SlashCommandClosure) { | 186 | if (replacer instanceof SlashCommandClosure) { |
| 187 | replacer.abortController = this.abortController; | 187 | replacer.abortController = this.abortController; |
| 188 | replacer.breakController = this.breakController; | 188 | replacer.breakController = this.breakController; |
| @@ -253,7 +253,7 @@ export class SlashCommandClosure { | |||
| 253 | return step.value; | 253 | return step.value; |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | async * executeDirect() { | 256 | async* executeDirect() { |
| 257 | this.debugController?.down(this); | 257 | this.debugController?.down(this); |
| 258 | // closure arguments | 258 | // closure arguments |
| 259 | for (const arg of this.argumentList) { | 259 | for (const arg of this.argumentList) { |
| @@ -325,10 +325,10 @@ export class SlashCommandClosure { | |||
| 325 | // breakpoint has to yield before arguments are resolved if one of the | 325 | // breakpoint has to yield before arguments are resolved if one of the |
| 326 | // arguments is an immediate closure, otherwise you cannot step into the | 326 | // arguments is an immediate closure, otherwise you cannot step into the |
| 327 | // immediate closure | 327 | // immediate closure |
| 328 | const hasImmediateClosureInNamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.namedArgumentList?.find(it=>it.value instanceof SlashCommandClosure && it.value.executeNow); | 328 | const hasImmediateClosureInNamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.namedArgumentList?.find(it => it.value instanceof SlashCommandClosure && it.value.executeNow); |
| 329 | const hasImmediateClosureInUnnamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.unnamedArgumentList?.find(it=>it.value instanceof SlashCommandClosure && it.value.executeNow); | 329 | const hasImmediateClosureInUnnamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.unnamedArgumentList?.find(it => it.value instanceof SlashCommandClosure && it.value.executeNow); |
| 330 | if (hasImmediateClosureInNamedArgs || hasImmediateClosureInUnnamedArgs) { | 330 | if (hasImmediateClosureInNamedArgs || hasImmediateClosureInUnnamedArgs) { |
| 331 | this.debugController.isStepping = yield { closure:this, executor:step.value }; | 331 | this.debugController.isStepping = yield { closure: this, executor: step.value }; |
| 332 | } else { | 332 | } else { |
| 333 | this.debugController.isStepping = true; | 333 | this.debugController.isStepping = true; |
| 334 | this.debugController.stepStack[this.debugController.stepStack.length - 1] = true; | 334 | this.debugController.stepStack[this.debugController.stepStack.length - 1] = true; |
| @@ -338,10 +338,10 @@ export class SlashCommandClosure { | |||
| 338 | this.debugController.isSteppingInto = false; | 338 | this.debugController.isSteppingInto = false; |
| 339 | // if stepping, have to yield before arguments are resolved if one of the arguments | 339 | // if stepping, have to yield before arguments are resolved if one of the arguments |
| 340 | // is an immediate closure, otherwise you cannot step into the immediate closure | 340 | // is an immediate closure, otherwise you cannot step into the immediate closure |
| 341 | const hasImmediateClosureInNamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.namedArgumentList?.find(it=>it.value instanceof SlashCommandClosure && it.value.executeNow); | 341 | const hasImmediateClosureInNamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.namedArgumentList?.find(it => it.value instanceof SlashCommandClosure && it.value.executeNow); |
| 342 | const hasImmediateClosureInUnnamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.unnamedArgumentList?.find(it=>it.value instanceof SlashCommandClosure && it.value.executeNow); | 342 | const hasImmediateClosureInUnnamedArgs = /**@type {SlashCommandExecutor}*/(step.value)?.unnamedArgumentList?.find(it => it.value instanceof SlashCommandClosure && it.value.executeNow); |
| 343 | if (hasImmediateClosureInNamedArgs || hasImmediateClosureInUnnamedArgs) { | 343 | if (hasImmediateClosureInNamedArgs || hasImmediateClosureInUnnamedArgs) { |
| 344 | this.debugController.isStepping = yield { closure:this, executor:step.value }; | 344 | this.debugController.isStepping = yield { closure: this, executor: step.value }; |
| 345 | } | 345 | } |
| 346 | } | 346 | } |
| 347 | // resolve args | 347 | // resolve args |
| @@ -354,7 +354,7 @@ export class SlashCommandClosure { | |||
| 354 | } | 354 | } |
| 355 | } else if (!step.done && this.debugController?.testStepping(this)) { | 355 | } else if (!step.done && this.debugController?.testStepping(this)) { |
| 356 | this.debugController.isSteppingInto = false; | 356 | this.debugController.isSteppingInto = false; |
| 357 | this.debugController.isStepping = yield { closure:this, executor:step.value }; | 357 | this.debugController.isStepping = yield { closure: this, executor: step.value }; |
| 358 | } | 358 | } |
| 359 | // execute executor | 359 | // execute executor |
| 360 | step = await stepper.next(); | 360 | step = await stepper.next(); |
| @@ -377,7 +377,7 @@ export class SlashCommandClosure { | |||
| 377 | * - after arguments are resolved | 377 | * - after arguments are resolved |
| 378 | * - after execution | 378 | * - after execution |
| 379 | */ | 379 | */ |
| 380 | async * executeStep() { | 380 | async* executeStep() { |
| 381 | let done = 0; | 381 | let done = 0; |
| 382 | let isFirst = true; | 382 | let isFirst = true; |
| 383 | for (const executor of this.executorList) { | 383 | for (const executor of this.executorList) { |
| @@ -429,7 +429,7 @@ export class SlashCommandClosure { | |||
| 429 | // then yield for "before exec" | 429 | // then yield for "before exec" |
| 430 | yield executor; | 430 | yield executor; |
| 431 | // followed by command execution | 431 | // followed by command execution |
| 432 | executor.onProgress = (subDone, subTotal)=>this.onProgress?.(done + subDone, this.commandCount); | 432 | executor.onProgress = (subDone, subTotal) => this.onProgress?.(done + subDone, this.commandCount); |
| 433 | const isStepping = this.debugController?.testStepping(this); | 433 | const isStepping = this.debugController?.testStepping(this); |
| 434 | if (this.debugController) { | 434 | if (this.debugController) { |
| 435 | this.debugController.isStepping = false || this.debugController.isSteppingInto; | 435 | this.debugController.isStepping = false || this.debugController.isSteppingInto; |
| @@ -586,7 +586,7 @@ export class SlashCommandClosure { | |||
| 586 | if (!executor.command.splitUnnamedArgument) { | 586 | if (!executor.command.splitUnnamedArgument) { |
| 587 | if (value.length == 1) { | 587 | if (value.length == 1) { |
| 588 | value = value[0]; | 588 | value = value[0]; |
| 589 | } else if (!value.find(it=>it instanceof SlashCommandClosure)) { | 589 | } else if (!value.find(it => it instanceof SlashCommandClosure)) { |
| 590 | value = value.join(''); | 590 | value = value.join(''); |
| 591 | } | 591 | } |
| 592 | } | 592 | } |
| @@ -598,7 +598,7 @@ export class SlashCommandClosure { | |||
| 598 | ?.replace(/\\\}/g, '}') | 598 | ?.replace(/\\\}/g, '}') |
| 599 | ; | 599 | ; |
| 600 | } else if (Array.isArray(value)) { | 600 | } else if (Array.isArray(value)) { |
| 601 | value = value.map(v=>{ | 601 | value = value.map(v => { |
| 602 | if (typeof v == 'string') { | 602 | if (typeof v == 'string') { |
| 603 | return v | 603 | return v |
| 604 | ?.replace(/\\\{/g, '{') | 604 | ?.replace(/\\\{/g, '{') |
| @@ -10,8 +10,6 @@ export class SlashCommandCommandAutoCompleteOption extends AutoCompleteOption { | |||
| 10 | } | 10 | } |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | |||
| 14 | |||
| 15 | /** | 13 | /** |
| 16 | * @param {SlashCommand} command | 14 | * @param {SlashCommand} command |
| 17 | * @param {string} name | 15 | * @param {string} name |
| @@ -155,7 +155,7 @@ export const commonEnumProviders = { | |||
| 155 | ...isAll || types.includes('scope') ? scope.allVariableNames.map(name => new SlashCommandEnumValue(name, null, enumTypes.variable, enumIcons.scopeVariable)) : [], | 155 | ...isAll || types.includes('scope') ? scope.allVariableNames.map(name => new SlashCommandEnumValue(name, null, enumTypes.variable, enumIcons.scopeVariable)) : [], |
| 156 | ...isAll || types.includes('local') ? Object.keys(chat_metadata.variables ?? []).map(name => new SlashCommandEnumValue(name, null, enumTypes.name, enumIcons.localVariable)) : [], | 156 | ...isAll || types.includes('local') ? Object.keys(chat_metadata.variables ?? []).map(name => new SlashCommandEnumValue(name, null, enumTypes.name, enumIcons.localVariable)) : [], |
| 157 | ...isAll || types.includes('global') ? Object.keys(extension_settings.variables.global ?? []).map(name => new SlashCommandEnumValue(name, null, enumTypes.macro, enumIcons.globalVariable)) : [], | 157 | ...isAll || types.includes('global') ? Object.keys(extension_settings.variables.global ?? []).map(name => new SlashCommandEnumValue(name, null, enumTypes.macro, enumIcons.globalVariable)) : [], |
| 158 | ].filter((item, idx, list)=>idx == list.findIndex(it=>it.value == item.value)); | 158 | ].filter((item, idx, list) => idx == list.findIndex(it => it.value == item.value)); |
| 159 | }, | 159 | }, |
| 160 | 160 | ||
| 161 | /** | 161 | /** |
| @@ -18,15 +18,11 @@ export class SlashCommandDebugController { | |||
| 18 | /** @type {(closure:SlashCommandClosure, executor:SlashCommandExecutor)=>Promise<boolean>} */ onBreakPoint; | 18 | /** @type {(closure:SlashCommandClosure, executor:SlashCommandExecutor)=>Promise<boolean>} */ onBreakPoint; |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | |||
| 22 | |||
| 23 | testStepping(closure) { | 21 | testStepping(closure) { |
| 24 | return this.stepStack[this.stack.indexOf(closure)]; | 22 | return this.stepStack[this.stack.indexOf(closure)]; |
| 25 | } | 23 | } |
| 26 | 24 | ||
| 27 | 25 | ||
| 28 | |||
| 29 | |||
| 30 | down(closure) { | 26 | down(closure) { |
| 31 | this.stack.push(closure); | 27 | this.stack.push(closure); |
| 32 | if (this.stepStack.length < this.stack.length) { | 28 | if (this.stepStack.length < this.stack.length) { |
| @@ -44,20 +40,19 @@ export class SlashCommandDebugController { | |||
| 44 | } | 40 | } |
| 45 | 41 | ||
| 46 | 42 | ||
| 47 | |||
| 48 | resume() { | 43 | resume() { |
| 49 | this.continueResolver?.(false); | 44 | this.continueResolver?.(false); |
| 50 | this.continuePromise = null; | 45 | this.continuePromise = null; |
| 51 | this.stepStack.forEach((_,idx)=>this.stepStack[idx] = false); | 46 | this.stepStack.forEach((_, idx) => this.stepStack[idx] = false); |
| 52 | } | 47 | } |
| 53 | step() { | 48 | step() { |
| 54 | this.stepStack.forEach((_,idx)=>this.stepStack[idx] = true); | 49 | this.stepStack.forEach((_, idx) => this.stepStack[idx] = true); |
| 55 | this.continueResolver?.(true); | 50 | this.continueResolver?.(true); |
| 56 | this.continuePromise = null; | 51 | this.continuePromise = null; |
| 57 | } | 52 | } |
| 58 | stepInto() { | 53 | stepInto() { |
| 59 | this.isSteppingInto = true; | 54 | this.isSteppingInto = true; |
| 60 | this.stepStack.forEach((_,idx)=>this.stepStack[idx] = true); | 55 | this.stepStack.forEach((_, idx) => this.stepStack[idx] = true); |
| 61 | this.continueResolver?.(true); | 56 | this.continueResolver?.(true); |
| 62 | this.continuePromise = null; | 57 | this.continuePromise = null; |
| 63 | } | 58 | } |
| @@ -69,7 +64,7 @@ export class SlashCommandDebugController { | |||
| 69 | } | 64 | } |
| 70 | 65 | ||
| 71 | async awaitContinue() { | 66 | async awaitContinue() { |
| 72 | this.continuePromise ??= new Promise(resolve=>{ | 67 | this.continuePromise ??= new Promise(resolve => { |
| 73 | this.continueResolver = resolve; | 68 | this.continueResolver = resolve; |
| 74 | }); | 69 | }); |
| 75 | this.isStepping = await this.continuePromise; | 70 | this.isStepping = await this.continuePromise; |
| @@ -9,7 +9,7 @@ export class SlashCommandEnumAutoCompleteOption extends AutoCompleteOption { | |||
| 9 | * @returns {SlashCommandEnumAutoCompleteOption} | 9 | * @returns {SlashCommandEnumAutoCompleteOption} |
| 10 | */ | 10 | */ |
| 11 | static from(cmd, enumValue) { | 11 | static from(cmd, enumValue) { |
| 12 | const mapped = this.valueToOptionMap.find(it=>enumValue instanceof it.value)?.option ?? this; | 12 | const mapped = this.valueToOptionMap.find(it => enumValue instanceof it.value)?.option ?? this; |
| 13 | return new mapped(cmd, enumValue); | 13 | return new mapped(cmd, enumValue); |
| 14 | } | 14 | } |
| 15 | /**@type {{value:(typeof SlashCommandEnumValue), option:(typeof SlashCommandEnumAutoCompleteOption)}[]} */ | 15 | /**@type {{value:(typeof SlashCommandEnumValue), option:(typeof SlashCommandEnumAutoCompleteOption)}[]} */ |
| @@ -18,7 +18,6 @@ export class SlashCommandEnumAutoCompleteOption extends AutoCompleteOption { | |||
| 18 | /**@type {SlashCommandEnumValue}*/ enumValue; | 18 | /**@type {SlashCommandEnumValue}*/ enumValue; |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | |||
| 22 | /** | 21 | /** |
| 23 | * @param {SlashCommand} cmd | 22 | * @param {SlashCommand} cmd |
| 24 | * @param {SlashCommandEnumValue} enumValue | 23 | * @param {SlashCommandEnumValue} enumValue |
| @@ -48,7 +48,6 @@ export class SlashCommandExecutionError extends Error { | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | 50 | ||
| 51 | |||
| 52 | constructor(cause, message, commandName, start, end, commandText, fullText) { | 51 | constructor(cause, message, commandName, start, end, commandText, fullText) { |
| 53 | super(message, { cause }); | 52 | super(message, { cause }); |
| 54 | this.commandName = commandName; | 53 | this.commandName = commandName; |
| @@ -17,10 +17,10 @@ export class SlashCommandExecutor { | |||
| 17 | get source() { return this.#source; } | 17 | get source() { return this.#source; } |
| 18 | set source(value) { | 18 | set source(value) { |
| 19 | this.#source = value; | 19 | this.#source = value; |
| 20 | for (const arg of this.namedArgumentList.filter(it=>it.value instanceof SlashCommandClosure)) { | 20 | for (const arg of this.namedArgumentList.filter(it => it.value instanceof SlashCommandClosure)) { |
| 21 | arg.value.source = value; | 21 | arg.value.source = value; |
| 22 | } | 22 | } |
| 23 | for (const arg of this.unnamedArgumentList.filter(it=>it.value instanceof SlashCommandClosure)) { | 23 | for (const arg of this.unnamedArgumentList.filter(it => it.value instanceof SlashCommandClosure)) { |
| 24 | arg.value.source = value; | 24 | arg.value.source = value; |
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| @@ -31,15 +31,15 @@ export class SlashCommandExecutor { | |||
| 31 | 31 | ||
| 32 | get commandCount() { | 32 | get commandCount() { |
| 33 | return 1 | 33 | return 1 |
| 34 | + this.namedArgumentList.filter(it=>it.value instanceof SlashCommandClosure).map(it=>/**@type {SlashCommandClosure}*/(it.value).commandCount).reduce((cur, sum)=>cur + sum, 0) | 34 | + this.namedArgumentList.filter(it => it.value instanceof SlashCommandClosure).map(it =>/**@type {SlashCommandClosure}*/(it.value).commandCount).reduce((cur, sum) => cur + sum, 0) |
| 35 | + this.unnamedArgumentList.filter(it=>it.value instanceof SlashCommandClosure).map(it=>/**@type {SlashCommandClosure}*/(it.value).commandCount).reduce((cur, sum)=>cur + sum, 0) | 35 | + this.unnamedArgumentList.filter(it => it.value instanceof SlashCommandClosure).map(it =>/**@type {SlashCommandClosure}*/(it.value).commandCount).reduce((cur, sum) => cur + sum, 0) |
| 36 | ; | 36 | ; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | set onProgress(value) { | 39 | set onProgress(value) { |
| 40 | const closures = /**@type {SlashCommandClosure[]}*/([ | 40 | const closures = /**@type {SlashCommandClosure[]}*/([ |
| 41 | ...this.namedArgumentList.filter(it=>it.value instanceof SlashCommandClosure).map(it=>it.value), | 41 | ...this.namedArgumentList.filter(it => it.value instanceof SlashCommandClosure).map(it => it.value), |
| 42 | ...this.unnamedArgumentList.filter(it=>it.value instanceof SlashCommandClosure).map(it=>it.value), | 42 | ...this.unnamedArgumentList.filter(it => it.value instanceof SlashCommandClosure).map(it => it.value), |
| 43 | ]); | 43 | ]); |
| 44 | for (const closure of closures) { | 44 | for (const closure of closures) { |
| 45 | closure.onProgress = value; | 45 | closure.onProgress = value; |
| @@ -65,7 +65,7 @@ export class SlashCommandParser { | |||
| 65 | static addCommandObject(command) { | 65 | static addCommandObject(command) { |
| 66 | const reserved = ['/', '#', ':', 'parser-flag', 'breakpoint']; | 66 | const reserved = ['/', '#', ':', 'parser-flag', 'breakpoint']; |
| 67 | for (const start of reserved) { | 67 | for (const start of reserved) { |
| 68 | if (command.name.toLowerCase().startsWith(start) || (command.aliases ?? []).find(a=>a.toLowerCase().startsWith(start))) { | 68 | if (command.name.toLowerCase().startsWith(start) || (command.aliases ?? []).find(a => a.toLowerCase().startsWith(start))) { |
| 69 | throw new Error(`Illegal Name. Slash command name cannot begin with "${start}".`); | 69 | throw new Error(`Illegal Name. Slash command name cannot begin with "${start}".`); |
| 70 | } | 70 | } |
| 71 | } | 71 | } |
| @@ -80,15 +80,15 @@ export class SlashCommandParser { | |||
| 80 | console.trace('WARN: Duplicate slash command registered!', [command.name, ...command.aliases]); | 80 | console.trace('WARN: Duplicate slash command registered!', [command.name, ...command.aliases]); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | const stack = new Error().stack.split('\n').map(it=>it.trim()); | 83 | const stack = new Error().stack.split('\n').map(it => it.trim()); |
| 84 | command.isExtension = stack.find(it=>it.includes('/scripts/extensions/')) != null; | 84 | command.isExtension = stack.find(it => it.includes('/scripts/extensions/')) != null; |
| 85 | command.isThirdParty = stack.find(it=>it.includes('/scripts/extensions/third-party/')) != null; | 85 | command.isThirdParty = stack.find(it => it.includes('/scripts/extensions/third-party/')) != null; |
| 86 | if (command.isThirdParty) { | 86 | if (command.isThirdParty) { |
| 87 | command.source = stack.find(it=>it.includes('/scripts/extensions/third-party/')).replace(/^.*?\/scripts\/extensions\/third-party\/([^/]+)\/.*$/, '$1'); | 87 | command.source = stack.find(it => it.includes('/scripts/extensions/third-party/')).replace(/^.*?\/scripts\/extensions\/third-party\/([^/]+)\/.*$/, '$1'); |
| 88 | } else if (command.isExtension) { | 88 | } else if (command.isExtension) { |
| 89 | command.source = stack.find(it=>it.includes('/scripts/extensions/')).replace(/^.*?\/scripts\/extensions\/([^/]+)\/.*$/, '$1'); | 89 | command.source = stack.find(it => it.includes('/scripts/extensions/')).replace(/^.*?\/scripts\/extensions\/([^/]+)\/.*$/, '$1'); |
| 90 | } else { | 90 | } else { |
| 91 | const idx = stack.findLastIndex(it=>it.includes('at SlashCommandParser.')) + 1; | 91 | const idx = stack.findLastIndex(it => it.includes('at SlashCommandParser.')) + 1; |
| 92 | command.source = stack[idx].replace(/^.*?\/((?:scripts\/)?(?:[^/]+)\.js).*$/, '$1'); | 92 | command.source = stack[idx].replace(/^.*?\/((?:scripts\/)?(?:[^/]+)\.js).*$/, '$1'); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| @@ -153,7 +153,7 @@ export class SlashCommandParser { | |||
| 153 | description: 'The parser flag to modify.', | 153 | description: 'The parser flag to modify.', |
| 154 | typeList: [ARGUMENT_TYPE.STRING], | 154 | typeList: [ARGUMENT_TYPE.STRING], |
| 155 | isRequired: true, | 155 | isRequired: true, |
| 156 | enumList: Object.keys(PARSER_FLAG).map(flag=>new SlashCommandEnumValue(flag, help[PARSER_FLAG[flag]])), | 156 | enumList: Object.keys(PARSER_FLAG).map(flag => new SlashCommandEnumValue(flag, help[PARSER_FLAG[flag]])), |
| 157 | }), | 157 | }), |
| 158 | SlashCommandArgument.fromProps({ | 158 | SlashCommandArgument.fromProps({ |
| 159 | description: 'The state of the parser flag to set.', | 159 | description: 'The state of the parser flag to set.', |
| @@ -439,7 +439,7 @@ export class SlashCommandParser { | |||
| 439 | PIPEBREAK, | 439 | PIPEBREAK, |
| 440 | PIPE, | 440 | PIPE, |
| 441 | ); | 441 | ); |
| 442 | hljs.registerLanguage('stscript', ()=>({ | 442 | hljs.registerLanguage('stscript', () => ({ |
| 443 | case_insensitive: false, | 443 | case_insensitive: false, |
| 444 | keywords: [], | 444 | keywords: [], |
| 445 | contains: [ | 445 | contains: [ |
| @@ -480,19 +480,19 @@ export class SlashCommandParser { | |||
| 480 | } | 480 | } |
| 481 | } | 481 | } |
| 482 | const executor = this.commandIndex | 482 | const executor = this.commandIndex |
| 483 | .filter(it=>it.start <= index && (it.end >= index || it.end == null)) | 483 | .filter(it => it.start <= index && (it.end >= index || it.end == null)) |
| 484 | .slice(-1)[0] | 484 | .slice(-1)[0] |
| 485 | ?? null | 485 | ?? null |
| 486 | ; | 486 | ; |
| 487 | 487 | ||
| 488 | if (executor) { | 488 | if (executor) { |
| 489 | const childClosure = this.closureIndex | 489 | const childClosure = this.closureIndex |
| 490 | .find(it=>it.start <= index && (it.end >= index || it.end == null) && it.start > executor.start) | 490 | .find(it => it.start <= index && (it.end >= index || it.end == null) && it.start > executor.start) |
| 491 | ?? null | 491 | ?? null |
| 492 | ; | 492 | ; |
| 493 | if (childClosure !== null) return null; | 493 | if (childClosure !== null) return null; |
| 494 | // Check if cursor is inside a macro | 494 | // Check if cursor is inside a macro |
| 495 | const macroEntry = this.macroIndex.findLast(it=>it.start <= index && it.end >= index); | 495 | const macroEntry = this.macroIndex.findLast(it => it.start <= index && it.end >= index); |
| 496 | if (macroEntry) { | 496 | if (macroEntry) { |
| 497 | // Build macro info object for shared function | 497 | // Build macro info object for shared function |
| 498 | const macroContent = text.slice(macroEntry.start + 2, macroEntry.end - (text.slice(macroEntry.end - 2, macroEntry.end) === '}}' ? 2 : 0)); | 498 | const macroContent = text.slice(macroEntry.start + 2, macroEntry.end - (text.slice(macroEntry.end - 2, macroEntry.end) === '}}' ? 2 : 0)); |
| @@ -522,16 +522,16 @@ export class SlashCommandParser { | |||
| 522 | if (executor.name == ':') { | 522 | if (executor.name == ':') { |
| 523 | const options = this.scopeIndex[this.commandIndex.indexOf(executor)] | 523 | const options = this.scopeIndex[this.commandIndex.indexOf(executor)] |
| 524 | ?.allVariableNames | 524 | ?.allVariableNames |
| 525 | ?.map(it=>new SlashCommandVariableAutoCompleteOption(it)) | 525 | ?.map(it => new SlashCommandVariableAutoCompleteOption(it)) |
| 526 | ?? [] | 526 | ?? [] |
| 527 | ; | 527 | ; |
| 528 | try { | 528 | try { |
| 529 | if ('quickReplyApi' in globalThis) { | 529 | if ('quickReplyApi' in globalThis) { |
| 530 | const qrApi = globalThis.quickReplyApi; | 530 | const qrApi = globalThis.quickReplyApi; |
| 531 | options.push(...qrApi.listSets() | 531 | options.push(...qrApi.listSets() |
| 532 | .map(set=>qrApi.listQuickReplies(set).map(qr=>`${set}.${qr}`)) | 532 | .map(set => qrApi.listQuickReplies(set).map(qr => `${set}.${qr}`)) |
| 533 | .flat() | 533 | .flat() |
| 534 | .map(qr=>new SlashCommandQuickReplyAutoCompleteOption(qr)), | 534 | .map(qr => new SlashCommandQuickReplyAutoCompleteOption(qr)), |
| 535 | ); | 535 | ); |
| 536 | } | 536 | } |
| 537 | } catch { /* empty */ } | 537 | } catch { /* empty */ } |
| @@ -540,8 +540,8 @@ export class SlashCommandParser { | |||
| 540 | executor.start, | 540 | executor.start, |
| 541 | options, | 541 | options, |
| 542 | true, | 542 | true, |
| 543 | ()=>`No matching variables in scope and no matching Quick Replies for "${result.name}"`, | 543 | () => `No matching variables in scope and no matching Quick Replies for "${result.name}"`, |
| 544 | ()=>'No variables in scope and no Quick Replies found.', | 544 | () => 'No variables in scope and no Quick Replies found.', |
| 545 | ); | 545 | ); |
| 546 | return result; | 546 | return result; |
| 547 | } | 547 | } |
| @@ -741,7 +741,7 @@ export class SlashCommandParser { | |||
| 741 | return this.testSymbol(':}'); | 741 | return this.testSymbol(':}'); |
| 742 | } | 742 | } |
| 743 | parseClosure(isRoot = false) { | 743 | parseClosure(isRoot = false) { |
| 744 | const closureIndexEntry = { start:this.index + 1, end:null }; | 744 | const closureIndexEntry = { start: this.index + 1, end: null }; |
| 745 | this.closureIndex.push(closureIndexEntry); | 745 | this.closureIndex.push(closureIndexEntry); |
| 746 | let injectPipe = true; | 746 | let injectPipe = true; |
| 747 | if (!isRoot) this.take(2); // discard opening {: | 747 | if (!isRoot) this.take(2); // discard opening {: |
| @@ -1023,14 +1023,14 @@ export class SlashCommandParser { | |||
| 1023 | cmd.unnamedArgumentList = this.parseUnnamedArgument(cmd.command?.unnamedArgumentList?.length && cmd?.command?.splitUnnamedArgument, cmd?.command?.splitUnnamedArgumentCount, rawQuotes); | 1023 | cmd.unnamedArgumentList = this.parseUnnamedArgument(cmd.command?.unnamedArgumentList?.length && cmd?.command?.splitUnnamedArgument, cmd?.command?.splitUnnamedArgumentCount, rawQuotes); |
| 1024 | cmd.endUnnamedArgs = this.index; | 1024 | cmd.endUnnamedArgs = this.index; |
| 1025 | if (cmd.name == 'let') { | 1025 | if (cmd.name == 'let') { |
| 1026 | const keyArg = cmd.namedArgumentList.find(it=>it.name == 'key'); | 1026 | const keyArg = cmd.namedArgumentList.find(it => it.name == 'key'); |
| 1027 | if (keyArg) { | 1027 | if (keyArg) { |
| 1028 | this.scope.variableNames.push(keyArg.value.toString()); | 1028 | this.scope.variableNames.push(keyArg.value.toString()); |
| 1029 | } else if (typeof cmd.unnamedArgumentList[0]?.value == 'string') { | 1029 | } else if (typeof cmd.unnamedArgumentList[0]?.value == 'string') { |
| 1030 | this.scope.variableNames.push(cmd.unnamedArgumentList[0].value); | 1030 | this.scope.variableNames.push(cmd.unnamedArgumentList[0].value); |
| 1031 | } | 1031 | } |
| 1032 | } else if (cmd.name == 'import') { | 1032 | } else if (cmd.name == 'import') { |
| 1033 | const value = /**@type {string[]}*/(cmd.unnamedArgumentList.map(it=>it.value)); | 1033 | const value = /**@type {string[]}*/(cmd.unnamedArgumentList.map(it => it.value)); |
| 1034 | for (let i = 0; i < value.length; i++) { | 1034 | for (let i = 0; i < value.length; i++) { |
| 1035 | const srcName = value[i]; | 1035 | const srcName = value[i]; |
| 1036 | let dstName = srcName; | 1036 | let dstName = srcName; |
| @@ -5,7 +5,7 @@ export class SlashCommandScope { | |||
| 5 | /** @type {string[]} */ variableNames = []; | 5 | /** @type {string[]} */ variableNames = []; |
| 6 | get allVariableNames() { | 6 | get allVariableNames() { |
| 7 | const names = [...this.variableNames, ...(this.parent?.allVariableNames ?? [])]; | 7 | const names = [...this.variableNames, ...(this.parent?.allVariableNames ?? [])]; |
| 8 | return names.filter((it,idx)=>idx == names.indexOf(it)); | 8 | return names.filter((it, idx) => idx == names.indexOf(it)); |
| 9 | } | 9 | } |
| 10 | // @ts-ignore | 10 | // @ts-ignore |
| 11 | /** @type {object.<string, string|SlashCommandClosure>} */ variables = {}; | 11 | /** @type {object.<string, string|SlashCommandClosure>} */ variables = {}; |
| @@ -13,7 +13,7 @@ export class SlashCommandScope { | |||
| 13 | /** @type {object.<string, string|SlashCommandClosure>} */ macros = {}; | 13 | /** @type {object.<string, string|SlashCommandClosure>} */ macros = {}; |
| 14 | /** @type {{key:string, value:string|SlashCommandClosure}[]} */ | 14 | /** @type {{key:string, value:string|SlashCommandClosure}[]} */ |
| 15 | get macroList() { | 15 | get macroList() { |
| 16 | return [...Object.keys(this.macros).map(key=>({ key, value:this.macros[key] })), ...(this.parent?.macroList ?? [])]; | 16 | return [...Object.keys(this.macros).map(key => ({ key, value: this.macros[key] })), ...(this.parent?.macroList ?? [])]; |
| 17 | } | 17 | } |
| 18 | /** @type {SlashCommandScope} */ parent; | 18 | /** @type {SlashCommandScope} */ parent; |
| 19 | /** @type {string} */ #pipe; | 19 | /** @type {string} */ #pipe; |
| @@ -40,7 +40,7 @@ export class SlashCommandScope { | |||
| 40 | 40 | ||
| 41 | 41 | ||
| 42 | setMacro(key, value, overwrite = true) { | 42 | setMacro(key, value, overwrite = true) { |
| 43 | if (overwrite || !this.macroList.find(it=>it.key == key)) { | 43 | if (overwrite || !this.macroList.find(it => it.key == key)) { |
| 44 | this.macros[key] = value; | 44 | this.macros[key] = value; |
| 45 | } | 45 | } |
| 46 | } | 46 | } |
| @@ -109,8 +109,6 @@ export class SlashCommandScope { | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | 111 | ||
| 112 | |||
| 113 | |||
| 114 | export class SlashCommandScopeVariableExistsError extends Error {} | 112 | export class SlashCommandScopeVariableExistsError extends Error {} |
| 115 | 113 | ||
| 116 | 114 | ||
| @@ -2091,7 +2091,6 @@ function onTagAsFolderClick() { | |||
| 2091 | // If folder display has changed, we have to redraw the character list, otherwise this folders state would not change | 2091 | // If folder display has changed, we have to redraw the character list, otherwise this folders state would not change |
| 2092 | printCharactersDebounced(); | 2092 | printCharactersDebounced(); |
| 2093 | saveSettingsDebounced(); | 2093 | saveSettingsDebounced(); |
| 2094 | |||
| 2095 | } | 2094 | } |
| 2096 | 2095 | ||
| 2097 | function updateDrawTagFolder(element, tag) { | 2096 | function updateDrawTagFolder(element, tag) { |
| @@ -802,7 +802,6 @@ async function getStatusTextgen() { | |||
| 802 | console.info('Status check aborted.', err.reason); | 802 | console.info('Status check aborted.', err.reason); |
| 803 | } else { | 803 | } else { |
| 804 | console.error('Error getting status', err); | 804 | console.error('Error getting status', err); |
| 805 | |||
| 806 | } | 805 | } |
| 807 | setOnlineStatus('no_connection'); | 806 | setOnlineStatus('no_connection'); |
| 808 | } | 807 | } |
| @@ -1126,7 +1125,7 @@ export function initTextGenSettings() { | |||
| 1126 | * @returns void | 1125 | * @returns void |
| 1127 | */ | 1126 | */ |
| 1128 | function showSamplerControls(apiType = null) { | 1127 | function showSamplerControls(apiType = null) { |
| 1129 | $('#textgenerationwebui_api-settings [data-tg-samplers], #textgenerationwebui_api [data-tg-samplers]').each(function(idx, elem) { | 1128 | $('#textgenerationwebui_api-settings [data-tg-samplers], #textgenerationwebui_api [data-tg-samplers]').each(function (idx, elem) { |
| 1130 | const typeSpecificControlled = $(elem).data('tg-type') !== undefined; | 1129 | const typeSpecificControlled = $(elem).data('tg-type') !== undefined; |
| 1131 | 1130 | ||
| 1132 | if (!typeSpecificControlled) $(this).show(); | 1131 | if (!typeSpecificControlled) $(this).show(); |
| @@ -1139,7 +1138,7 @@ function showSamplerControls(apiType = null) { | |||
| 1139 | 1138 | ||
| 1140 | if (!samplersActivatedManually?.length || !prioritizeManualSamplerSelect) return; | 1139 | if (!samplersActivatedManually?.length || !prioritizeManualSamplerSelect) return; |
| 1141 | 1140 | ||
| 1142 | $('#textgenerationwebui_api-settings [data-tg-samplers], #textgenerationwebui_api [data-tg-samplers]').each(function() { | 1141 | $('#textgenerationwebui_api-settings [data-tg-samplers], #textgenerationwebui_api [data-tg-samplers]').each(function () { |
| 1143 | const tgSamplers = $(this).attr('data-tg-samplers').split(',').map(x => x.trim()).filter(str => str !== ''); | 1142 | const tgSamplers = $(this).attr('data-tg-samplers').split(',').map(x => x.trim()).filter(str => str !== ''); |
| 1144 | 1143 | ||
| 1145 | for (const tgSampler of tgSamplers) { | 1144 | for (const tgSampler of tgSamplers) { |
| @@ -455,7 +455,6 @@ async function changeName(handle, name, callback) { | |||
| 455 | 455 | ||
| 456 | toastr.success('Name changed successfully', 'Name Changed'); | 456 | toastr.success('Name changed successfully', 'Name Changed'); |
| 457 | callback(); | 457 | callback(); |
| 458 | |||
| 459 | } catch (error) { | 458 | } catch (error) { |
| 460 | console.error('Error changing name:', error); | 459 | console.error('Error changing name:', error); |
| 461 | } | 460 | } |
| @@ -495,7 +494,6 @@ async function restoreSnapshot(name, callback) { | |||
| 495 | } catch (error) { | 494 | } catch (error) { |
| 496 | console.error('Error restoring snapshot:', error); | 495 | console.error('Error restoring snapshot:', error); |
| 497 | } | 496 | } |
| 498 | |||
| 499 | } | 497 | } |
| 500 | 498 | ||
| 501 | /** | 499 | /** |
| @@ -601,7 +599,6 @@ async function viewSettingsSnapshots() { | |||
| 601 | const content = await loadSnapshotContent(snapshot.name); | 599 | const content = await loadSnapshotContent(snapshot.name); |
| 602 | contentBlock.val(content); | 600 | contentBlock.val(content); |
| 603 | } | 601 | } |
| 604 | |||
| 605 | }); | 602 | }); |
| 606 | template.find('.snapshotList').append(snapshotBlock); | 603 | template.find('.snapshotList').append(snapshotBlock); |
| 607 | } | 604 | } |
| @@ -667,7 +664,6 @@ async function resetEverything(callback) { | |||
| 667 | } catch (error) { | 664 | } catch (error) { |
| 668 | console.error('Error resetting everything:', error); | 665 | console.error('Error resetting everything:', error); |
| 669 | } | 666 | } |
| 670 | |||
| 671 | } | 667 | } |
| 672 | 668 | ||
| 673 | async function openUserProfile() { | 669 | async function openUserProfile() { |
| @@ -2310,7 +2310,6 @@ export function highlightRegex(regexStr) { | |||
| 2310 | flags: new RegExp('(?<=\\/)([gimsuy]*)$', 'g'), // Match trailing flags | 2310 | flags: new RegExp('(?<=\\/)([gimsuy]*)$', 'g'), // Match trailing flags |
| 2311 | delimiters: new RegExp('^\\/|(?<![\\\\<])\\/', 'g'), // Match leading or trailing delimiters | 2311 | delimiters: new RegExp('^\\/|(?<![\\\\<])\\/', 'g'), // Match leading or trailing delimiters |
| 2312 | }; | 2312 | }; |
| 2313 | |||
| 2314 | } catch (error) { | 2313 | } catch (error) { |
| 2315 | return { | 2314 | return { |
| 2316 | brackets: new RegExp('(\\\\)?\\[.*?\\]', 'g'), // Non-escaped square brackets | 2315 | brackets: new RegExp('(\\\\)?\\[.*?\\]', 'g'), // Non-escaped square brackets |
| @@ -675,7 +675,6 @@ class WorldInfoTimedEffects { | |||
| 675 | console.log('[WI] Timed effect "delay" applied to entry', entry); | 675 | console.log('[WI] Timed effect "delay" applied to entry', entry); |
| 676 | } | 676 | } |
| 677 | } | 677 | } |
| 678 | |||
| 679 | } | 678 | } |
| 680 | 679 | ||
| 681 | /** | 680 | /** |
| @@ -4495,7 +4494,6 @@ function parseDecorators(content) { | |||
| 4495 | } | 4494 | } |
| 4496 | 4495 | ||
| 4497 | return [[], content]; | 4496 | return [[], content]; |
| 4498 | |||
| 4499 | } | 4497 | } |
| 4500 | 4498 | ||
| 4501 | /** | 4499 | /** |
| @@ -111,7 +111,6 @@ router.post('/get', async (request, response) => { | |||
| 111 | 111 | ||
| 112 | try { | 112 | try { |
| 113 | if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) { | 113 | if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) { |
| 114 | |||
| 115 | ensureFoldersExist(request.user.directories); | 114 | ensureFoldersExist(request.user.directories); |
| 116 | 115 | ||
| 117 | const folders = fs.readdirSync(folderPath, { withFileTypes: true }) | 116 | const folders = fs.readdirSync(folderPath, { withFileTypes: true }) |
| @@ -346,7 +345,6 @@ router.post('/character', async (request, response) => { | |||
| 346 | let output = []; | 345 | let output = []; |
| 347 | try { | 346 | try { |
| 348 | if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) { | 347 | if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) { |
| 349 | |||
| 350 | // Live2d assets | 348 | // Live2d assets |
| 351 | if (category == 'live2d') { | 349 | if (category == 'live2d') { |
| 352 | const folders = fs.readdirSync(folderPath, { withFileTypes: true }); | 350 | const folders = fs.readdirSync(folderPath, { withFileTypes: true }); |
| @@ -541,7 +541,6 @@ llamacpp.post('/props', async function (request, response) { | |||
| 541 | console.debug('LlamaCpp props response:', data); | 541 | console.debug('LlamaCpp props response:', data); |
| 542 | 542 | ||
| 543 | return response.send(data); | 543 | return response.send(data); |
| 544 | |||
| 545 | } catch (error) { | 544 | } catch (error) { |
| 546 | console.error(error); | 545 | console.error(error); |
| 547 | return response.sendStatus(500); | 546 | return response.sendStatus(500); |
| @@ -591,7 +590,6 @@ llamacpp.post('/slots', async function (request, response) { | |||
| 591 | console.debug('LlamaCpp slots response:', data); | 590 | console.debug('LlamaCpp slots response:', data); |
| 592 | 591 | ||
| 593 | return response.send(data); | 592 | return response.send(data); |
| 594 | |||
| 595 | } catch (error) { | 593 | } catch (error) { |
| 596 | console.error(error); | 594 | console.error(error); |
| 597 | return response.sendStatus(500); | 595 | return response.sendStatus(500); |
| @@ -11,7 +11,7 @@ router.post('/chat/get', async (request, response) => { | |||
| 11 | const backupModels = []; | 11 | const backupModels = []; |
| 12 | const backupFiles = await fsPromises | 12 | const backupFiles = await fsPromises |
| 13 | .readdir(request.user.directories.backups, { withFileTypes: true }) | 13 | .readdir(request.user.directories.backups, { withFileTypes: true }) |
| 14 | .then(d => d .filter(d => d.isFile() && path.extname(d.name) === '.jsonl' && d.name.startsWith(CHAT_BACKUPS_PREFIX)).map(d => d.name)); | 14 | .then(d => d.filter(d => d.isFile() && path.extname(d.name) === '.jsonl' && d.name.startsWith(CHAT_BACKUPS_PREFIX)).map(d => d.name)); |
| 15 | 15 | ||
| 16 | for (const name of backupFiles) { | 16 | for (const name of backupFiles) { |
| 17 | const filePath = path.join(request.user.directories.backups, name); | 17 | const filePath = path.join(request.user.directories.backups, name); |
| @@ -639,7 +639,6 @@ function charaFormatData(data, directories) { | |||
| 639 | if (file && file.entries) { | 639 | if (file && file.entries) { |
| 640 | _.set(char, 'data.character_book', convertWorldInfoToCharacterBook(data.world, file.entries)); | 640 | _.set(char, 'data.character_book', convertWorldInfoToCharacterBook(data.world, file.entries)); |
| 641 | } | 641 | } |
| 642 | |||
| 643 | } catch { | 642 | } catch { |
| 644 | console.warn(`Failed to read world info file: ${data.world}. Character book will not be available.`); | 643 | console.warn(`Failed to read world info file: ${data.world}. Character book will not be available.`); |
| 645 | } | 644 | } |
| @@ -921,7 +920,8 @@ async function importFromJson(uploadPath, { request }, preservedFileName) { | |||
| 921 | let charJSON = JSON.stringify(char); | 920 | let charJSON = JSON.stringify(char); |
| 922 | const result = await writeCharacterData(DEFAULT_AVATAR_PATH, charJSON, pngName, request); | 921 | const result = await writeCharacterData(DEFAULT_AVATAR_PATH, charJSON, pngName, request); |
| 923 | return result ? pngName : ''; | 922 | return result ? pngName : ''; |
| 924 | } else if (jsonData.char_name !== undefined) {//json Pygmalion notepad | 923 | } else if (jsonData.char_name !== undefined) { |
| 924 | //json Pygmalion notepad | ||
| 925 | console.info('Importing from gradio json'); | 925 | console.info('Importing from gradio json'); |
| 926 | jsonData.char_name = sanitize(jsonData.char_name); | 926 | jsonData.char_name = sanitize(jsonData.char_name); |
| 927 | if (jsonData.creator_notes) { | 927 | if (jsonData.creator_notes) { |
| @@ -367,7 +367,6 @@ router.post('/version', async (request, response) => { | |||
| 367 | const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath); | 367 | const { isUpToDate, remoteUrl } = await checkIfRepoIsUpToDate(extensionPath); |
| 368 | 368 | ||
| 369 | return response.send({ currentBranchName, currentCommitHash, isUpToDate, remoteUrl }); | 369 | return response.send({ currentBranchName, currentCommitHash, isUpToDate, remoteUrl }); |
| 370 | |||
| 371 | } catch (error) { | 370 | } catch (error) { |
| 372 | console.error('Getting extension version failed', error); | 371 | console.error('Getting extension version failed', error); |
| 373 | return response.status(500).send(`Server Error: ${error.message}`); | 372 | return response.status(500).send(`Server Error: ${error.message}`); |
| @@ -406,7 +405,6 @@ router.post('/delete', async (request, response) => { | |||
| 406 | console.info(`Extension has been deleted at ${extensionPath}`); | 405 | console.info(`Extension has been deleted at ${extensionPath}`); |
| 407 | 406 | ||
| 408 | return response.send(`Extension has been deleted at ${extensionPath}`); | 407 | return response.send(`Extension has been deleted at ${extensionPath}`); |
| 409 | |||
| 410 | } catch (error) { | 408 | } catch (error) { |
| 411 | console.error('Deleting custom content failed', error); | 409 | console.error('Deleting custom content failed', error); |
| 412 | return response.status(500).send(`Server Error: ${error.message}`); | 410 | return response.status(500).send(`Server Error: ${error.message}`); |
| @@ -51,7 +51,7 @@ export async function migrateGroupChatsMetadataFormat(userDirectories) { | |||
| 51 | if (!needsMigration) { | 51 | if (!needsMigration) { |
| 52 | continue; | 52 | continue; |
| 53 | } | 53 | } |
| 54 | if (!fs.existsSync(backupPath)){ | 54 | if (!fs.existsSync(backupPath)) { |
| 55 | await fsPromises.mkdir(backupPath, { recursive: true }); | 55 | await fsPromises.mkdir(backupPath, { recursive: true }); |
| 56 | } | 56 | } |
| 57 | await fsPromises.copyFile(groupFilePath, path.join(backupPath, groupFile.name)); | 57 | await fsPromises.copyFile(groupFilePath, path.join(backupPath, groupFile.name)); |
| @@ -256,7 +256,6 @@ router.post('/caption-image', async (request, response) => { | |||
| 256 | console.info(status); | 256 | console.info(status); |
| 257 | 257 | ||
| 258 | if (status.state === HordeAsyncRequestStates.done) { | 258 | if (status.state === HordeAsyncRequestStates.done) { |
| 259 | |||
| 260 | if (status.forms === undefined) { | 259 | if (status.forms === undefined) { |
| 261 | console.error('Image interrogation request failed: no forms found.'); | 260 | console.error('Image interrogation request failed: no forms found.'); |
| 262 | return response.sendStatus(500); | 261 | return response.sendStatus(500); |
| @@ -278,7 +277,6 @@ router.post('/caption-image', async (request, response) => { | |||
| 278 | return response.sendStatus(503); | 277 | return response.sendStatus(503); |
| 279 | } | 278 | } |
| 280 | } | 279 | } |
| 281 | |||
| 282 | } catch (error) { | 280 | } catch (error) { |
| 283 | console.error(error); | 281 | console.error(error); |
| 284 | response.sendStatus(500); | 282 | response.sendStatus(500); |
| @@ -442,7 +442,6 @@ router.post('/', async function (request, response) { | |||
| 442 | } | 442 | } |
| 443 | 443 | ||
| 444 | return response.status(400).json({ error: 'Invalid request format.' }); | 444 | return response.status(400).json({ error: 'Invalid request format.' }); |
| 445 | |||
| 446 | } catch (error) { | 445 | } catch (error) { |
| 447 | console.error('[ImageMetadata] API error:', error); | 446 | console.error('[ImageMetadata] API error:', error); |
| 448 | return response.status(500).json({ error: 'Internal server error.' }); | 447 | return response.status(500).json({ error: 'Internal server error.' }); |
| @@ -189,7 +189,6 @@ router.post('/generate-voice', async (request, response) => { | |||
| 189 | response.setHeader('Content-Length', audioBytes.length); | 189 | response.setHeader('Content-Length', audioBytes.length); |
| 190 | 190 | ||
| 191 | return response.send(Buffer.from(audioBytes)); | 191 | return response.send(Buffer.from(audioBytes)); |
| 192 | |||
| 193 | } catch (conversionError) { | 192 | } catch (conversionError) { |
| 194 | console.error('MiniMax TTS: Audio conversion error:', conversionError); | 193 | console.error('MiniMax TTS: Audio conversion error:', conversionError); |
| 195 | return response.status(500).json({ error: `Audio data conversion failed: ${conversionError.message}` }); | 194 | return response.status(500).json({ error: `Audio data conversion failed: ${conversionError.message}` }); |
| @@ -222,7 +221,6 @@ router.post('/generate-voice', async (request, response) => { | |||
| 222 | console.error('MiniMax TTS: No valid audio data in response:', responseData); | 221 | console.error('MiniMax TTS: No valid audio data in response:', responseData); |
| 223 | return response.status(500).json({ error: `API Error: ${errorMessage}` }); | 222 | return response.status(500).json({ error: `API Error: ${errorMessage}` }); |
| 224 | } | 223 | } |
| 225 | |||
| 226 | } catch (error) { | 224 | } catch (error) { |
| 227 | console.error('MiniMax TTS generation failed:', error); | 225 | console.error('MiniMax TTS generation failed:', error); |
| 228 | return response.status(500).json({ error: 'Internal server error' }); | 226 | return response.status(500).json({ error: 'Internal server error' }); |
| @@ -158,7 +158,6 @@ router.post('/samplers', async (request, response) => { | |||
| 158 | const data = await result.json(); | 158 | const data = await result.json(); |
| 159 | const names = data.map(x => x.name); | 159 | const names = data.map(x => x.name); |
| 160 | return response.send(names); | 160 | return response.send(names); |
| 161 | |||
| 162 | } catch (error) { | 161 | } catch (error) { |
| 163 | console.error(error); | 162 | console.error(error); |
| 164 | return response.sendStatus(500); | 163 | return response.sendStatus(500); |
| @@ -301,7 +301,6 @@ publicRouter.get('/', async function (request, response) { | |||
| 301 | 301 | ||
| 302 | // Send a 404 so the frontend can display a placeholder | 302 | // Send a 404 so the frontend can display a placeholder |
| 303 | return response.sendStatus(404); | 303 | return response.sendStatus(404); |
| 304 | |||
| 305 | } catch (error) { | 304 | } catch (error) { |
| 306 | console.error('Failed getting thumbnail', error); | 305 | console.error('Failed getting thumbnail', error); |
| 307 | return response.sendStatus(500); | 306 | return response.sendStatus(500); |
| @@ -118,7 +118,6 @@ export function postProcessPrompt(messages, type, names) { | |||
| 118 | * @copyright Prompt Conversion script taken from RisuAI by kwaroran (GPLv3). | 118 | * @copyright Prompt Conversion script taken from RisuAI by kwaroran (GPLv3). |
| 119 | */ | 119 | */ |
| 120 | export function convertClaudePrompt(messages, addAssistantPostfix, addAssistantPrefill, withSysPromptSupport, useSystemPrompt, addSysHumanMsg, excludePrefixes) { | 120 | export function convertClaudePrompt(messages, addAssistantPostfix, addAssistantPrefill, withSysPromptSupport, useSystemPrompt, addSysHumanMsg, excludePrefixes) { |
| 121 | |||
| 122 | //Prepare messages for claude. | 121 | //Prepare messages for claude. |
| 123 | //When 'Exclude Human/Assistant prefixes' checked, setting messages role to the 'system'(last message is exception). | 122 | //When 'Exclude Human/Assistant prefixes' checked, setting messages role to the 'system'(last message is exception). |
| 124 | if (messages.length > 0) { | 123 | if (messages.length > 0) { |
| @@ -1278,7 +1277,7 @@ export function calculateGoogleBudgetTokens(maxTokens, reasoningEffort, model) { | |||
| 1278 | return getGemini3ProBudget(); | 1277 | return getGemini3ProBudget(); |
| 1279 | } | 1278 | } |
| 1280 | 1279 | ||
| 1281 | if (/gemini-3-flash/.test(model) ) { | 1280 | if (/gemini-3-flash/.test(model)) { |
| 1282 | return getGemini3FlashBudget(); | 1281 | return getGemini3FlashBudget(); |
| 1283 | } | 1282 | } |
| 1284 | 1283 | ||
| @@ -1012,7 +1012,6 @@ export async function canResolve(name, useIPv6 = true, useIPv4 = true) { | |||
| 1012 | } | 1012 | } |
| 1013 | 1013 | ||
| 1014 | return v6Resolved || v4Resolved; | 1014 | return v6Resolved || v4Resolved; |
| 1015 | |||
| 1016 | } catch (error) { | 1015 | } catch (error) { |
| 1017 | return false; | 1016 | return false; |
| 1018 | } | 1017 | } |