diff --git a/public/scripts/reasoning.js b/public/scripts/reasoning.js index 52503d90d..8f7d504b8 100644 --- a/public/scripts/reasoning.js +++ b/public/scripts/reasoning.js @@ -13,7 +13,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from ' import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js'; import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; -import { copyText, escapeRegex, isFalseBoolean } from './utils.js'; +import { copyText, escapeRegex, isFalseBoolean, setDatasetProperty } from './utils.js'; /** * Gets a message from a jQuery element. @@ -323,8 +323,8 @@ export class ReasoningHandler { this.messageDom.classList.toggle('reasoning', this.state !== ReasoningState.None); // Update states to the relevant DOM elements - this.messageDom.dataset.reasoningState = this.state !== ReasoningState.None ? this.state : null; - this.messageReasoningDetailsDom.dataset.state = this.state; + setDatasetProperty(this.messageDom, 'reasoningState', this.state !== ReasoningState.None ? this.state : null); + setDatasetProperty(this.messageReasoningDetailsDom, 'state', this.state); // Update the reasoning message const reasoning = power_user.trim_spaces ? this.reasoning.trim() : this.reasoning; @@ -391,8 +391,8 @@ export class ReasoningHandler { data = null; } - this.messageReasoningDetailsDom.dataset.duration = data; - element.dataset.duration = data; + setDatasetProperty(this.messageReasoningDetailsDom, 'duration', data); + setDatasetProperty(element, 'duration', data); } } @@ -698,10 +698,9 @@ function setReasoningEventHandlers() { const textarea = messageBlock.find('.reasoning_edit_textarea'); textarea.remove(); - // Make sure we remove the fake placeholder from the reasoning string - const text = messageBlock.find('.mes_reasoning').text(); - if (text === PromptReasoning.REASONING_UI_PLACEHOLDER) { - messageBlock.find('.mes_reasoning').text(''); + // If we cancel, we might have to remove the reasong class again if this is an unsaved empty reasoning + if (!messageBlock.attr('data--reasoning-state')) { + messageBlock.removeClass('reasoning'); } messageBlock.find('.mes_reasoning_edit_cancel:visible').trigger('click'); @@ -718,9 +717,10 @@ function setReasoningEventHandlers() { return; } - // To be able to edit, we need to "fake" content being there inside the reasoning string - messageBlock.find('.mes_reasoning').text(PromptReasoning.REASONING_UI_PLACEHOLDER); + messageBlock.addClass('reasoning'); + // Open the reasoning area so we can actually edit it + messageBlock.find('.mes_reasoning_details').attr('open', ''); messageBlock.find('.mes_reasoning_edit').trigger('click'); await saveChatConditional(); }); diff --git a/public/scripts/utils.js b/public/scripts/utils.js index f49fe7b64..b385a760a 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -2059,6 +2059,23 @@ export function toggleDrawer(drawer, expand = true) { } } +/** + * Sets or removes a dataset property on an HTMLElement + * + * Utility function to make it easier to reset dataset properties on null, without them being "null" as value. + * + * @param {HTMLElement} element - The element to modify + * @param {string} name - The name of the dataset property + * @param {string|null} value - The value to set - If null, the dataset property will be removed + */ +export function setDatasetProperty(element, name, value) { + if (value === null) { + delete element.dataset[name]; + } else { + element.dataset[name] = value; + } +} + export async function fetchFaFile(name) { const style = document.createElement('style'); style.innerHTML = await (await fetch(`/css/${name}`)).text(); diff --git a/public/style.css b/public/style.css index 1a1c44ec1..f5754e5b5 100644 --- a/public/style.css +++ b/public/style.css @@ -410,17 +410,17 @@ input[type='checkbox']:focus-visible { } .mes_bias:empty, -.mes_reasoning:empty, -.mes_reasoning_details:has(.mes_reasoning:empty), +.mes:not(.reasoning) .mes_reasoning_details, .mes_reasoning_details:not([open]) .mes_reasoning_actions, .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning, .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning_header, -.mes_reasoning_details:not(:has(.reasoning_edit_textarea)) .mes_reasoning_actions .edit_button, .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning_actions .mes_button:not(.edit_button), +.mes_reasoning_details:not(:has(.reasoning_edit_textarea)) .mes_reasoning_actions .edit_button, .mes_block:has(.edit_textarea):has(.reasoning_edit_textarea) .mes_reasoning_actions, -.mes.reasoning:not([data-reasoning-state="none"]) .mes_edit_add_reasoning, -.mes[data-reasoning-state="none"] .mes_reasoning_arrow, -.mes[data-reasoning-state="none"] .mes_reasoning_actions { +.mes.reasoning .mes_edit_add_reasoning, +.mes[data-reasoning-state="hidden"] .mes_reasoning_arrow, +.mes[data-reasoning-state="hidden"] .mes_reasoning, +.mes[data-reasoning-state="hidden"] .mes_reasoning_copy { display: none; }