From 485d07b91f2bfc2e00e7de5dcbda55aa462e163f Mon Sep 17 00:00:00 2001 From: awaae001 <3271436144@qq.com> Date: Tue, 22 Apr 2025 23:51:40 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat(slash-commands):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=20/goto-floor=20=E5=91=BD=E4=BB=A4=E5=B9=B6=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E9=AB=98=E4=BA=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 /goto-floor 命令,允许用户滚动到指定的消息索引 - 实现消息高亮功能,滚动到指定消息后进行突出显示 - 添加相关的 CSS 样式,确保高亮效果在不同浏览器中兼容 --- public/scripts/slash-commands.js | 121 +++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index e97e4955d..04ed35a13 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2130,6 +2130,127 @@ export function initDefaultSlashCommands() { `, })); + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ + name: 'goto-floor', + aliases: ['floor', 'jump', 'scrollto'], + callback: async (_, index) => { + const floorIndex = Number(index); + + // Validate input + if (isNaN(floorIndex) || floorIndex < 0 || (typeof chat !== 'undefined' && floorIndex >= chat.length)) { + const maxIndex = (typeof chat !== 'undefined' ? chat.length - 1 : 'unknown'); + toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); + console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`); + return ''; + } + + const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); + + if (messageElement) { + const headerElement = messageElement.querySelector('.mes_header') || + messageElement.querySelector('.mes_meta') || + messageElement.querySelector('.mes_name_area') || + messageElement.querySelector('.mes_name'); + + const elementToScroll = headerElement || messageElement; // Prefer header, fallback to whole message + const blockPosition = headerElement ? 'center' : 'start'; // Center header, else start of message + + elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); + console.log(`INFO: Scrolled ${headerElement ? 'header of' : ''} message ${floorIndex} into view (block: ${blockPosition}).`); + + // --- Highlight with smooth animation --- + messageElement.classList.add('highlight-scroll'); + setTimeout(() => { + // Add a class to fade out, then remove the highlight class after fade + messageElement.classList.add('highlight-scroll-fadeout'); + // Wait for fadeout transition to complete before removing the base class + // Match this duration to the transition duration in CSS + setTimeout(() => { + messageElement.classList.remove('highlight-scroll', 'highlight-scroll-fadeout'); + }, 500); // Matches the 0.5s transition duration + }, 1500); // Start fade out after 1.5 seconds + + } else { + toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]). It might not be rendered yet. Try scrolling up or use /chat-render all.`); + console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor.`); + const chatContainer = document.getElementById('chat'); + if (chatContainer) { + chatContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + } + return ''; + }, + unnamedArgumentList: [ + SlashCommandArgument.fromProps({ + description: 'The message index (0-based) to scroll to.', + typeList: [ARGUMENT_TYPE.NUMBER], + isRequired: true, + enumProvider: commonEnumProviders.messages(), + }), + ], + helpString: ` +
+ Scrolls the chat view to the specified message index. Uses the [mesid] attribute for locating the message element. Index starts at 0. + It attempts to center the character's name/header area within the message block. Highlights the message using the theme's 'matchedText' color with a smooth animation. +
+
+ Example:
/goto-floor 10
Scrolls to the 11th message (mesid=10). +
+
+ Note: Due to virtual scrolling, very old messages might need loading first. +
+ `, + })); + + // --- Improved CSS for highlight --- + const styleId = 'goto-floor-highlight-style'; + if (!document.getElementById(styleId)) { + const style = document.createElement('style'); + style.id = styleId; + style.textContent = ` + /* Base state for elements that *can* be highlighted */ + /* Ensures transition applies smoothly in both directions */ + .mes, .mes_block { + transition: background-color 0.5s ease-in-out, box-shadow 0.5s ease-in-out; + /* Add position relative if not already present, needed for potential pseudo-elements */ + position: relative; + } + + /* --- Highlighting Style --- */ + .mes.highlight-scroll, + .mes_block.highlight-scroll { + /* Use theme color for shadow, fallback to gold */ + box-shadow: 0 0 10px var(--ac-style-color-matchedText, #FFD700) !important; + z-index: 5; /* Ensure highlight is visually prominent */ + } + + /* Modern browsers: Use color-mix for transparent background */ + @supports (background-color: color-mix(in srgb, white 50%, black)) { + .mes.highlight-scroll, + .mes_block.highlight-scroll { + /* Mix theme color with transparent for background */ + background-color: color-mix(in srgb, var(--ac-style-color-matchedText, #FFD700) 35%, transparent) !important; + } + } + + /* Fallback for older browsers: Use a fixed semi-transparent background */ + @supports not (background-color: color-mix(in srgb, white 50%, black)) { + .mes.highlight-scroll, + .mes_block.highlight-scroll { + background-color: rgba(255, 215, 0, 0.35) !important; /* Fallback semi-transparent gold */ + } + } + + /* --- Fade-out Control --- */ + /* When fading out, explicitly transition back to transparent/none */ + .mes.highlight-scroll-fadeout, + .mes_block.highlight-scroll-fadeout { + background-color: transparent !important; + box-shadow: none !important; + } + `; + document.head.appendChild(style); + } registerVariableCommands(); } From 6d0318eb36c864938c2abde8c3a51b391d9cfd76 Mon Sep 17 00:00:00 2001 From: awaae001 <3271436144@qq.com> Date: Wed, 23 Apr 2025 00:05:35 +0800 Subject: [PATCH 2/7] =?UTF-8?q?refactor(slash-commands):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/goto-floor=20=E5=91=BD=E4=BB=A4=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=A0=BC=E5=BC=8F=E5=92=8C=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修正 EDLint 标记错误 --- public/scripts/slash-commands.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 04ed35a13..f16ce9e7b 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2135,29 +2135,29 @@ export function initDefaultSlashCommands() { aliases: ['floor', 'jump', 'scrollto'], callback: async (_, index) => { const floorIndex = Number(index); - + // Validate input if (isNaN(floorIndex) || floorIndex < 0 || (typeof chat !== 'undefined' && floorIndex >= chat.length)) { - const maxIndex = (typeof chat !== 'undefined' ? chat.length - 1 : 'unknown'); + const maxIndex = (typeof chat !== 'undefined' ? chat.length - 1 : 'unknown'); toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`); return ''; } - + const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); - + if (messageElement) { const headerElement = messageElement.querySelector('.mes_header') || messageElement.querySelector('.mes_meta') || messageElement.querySelector('.mes_name_area') || messageElement.querySelector('.mes_name'); - + const elementToScroll = headerElement || messageElement; // Prefer header, fallback to whole message const blockPosition = headerElement ? 'center' : 'start'; // Center header, else start of message - + elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); console.log(`INFO: Scrolled ${headerElement ? 'header of' : ''} message ${floorIndex} into view (block: ${blockPosition}).`); - + // --- Highlight with smooth animation --- messageElement.classList.add('highlight-scroll'); setTimeout(() => { @@ -2169,7 +2169,7 @@ export function initDefaultSlashCommands() { messageElement.classList.remove('highlight-scroll', 'highlight-scroll-fadeout'); }, 500); // Matches the 0.5s transition duration }, 1500); // Start fade out after 1.5 seconds - + } else { toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]). It might not be rendered yet. Try scrolling up or use /chat-render all.`); console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor.`); @@ -2201,7 +2201,7 @@ export function initDefaultSlashCommands() { `, })); - + // --- Improved CSS for highlight --- const styleId = 'goto-floor-highlight-style'; if (!document.getElementById(styleId)) { From ceeaeea1237edfff3455a329a00171455a82ac31 Mon Sep 17 00:00:00 2001 From: awaae001 <3271436144@qq.com> Date: Wed, 23 Apr 2025 00:45:05 +0800 Subject: [PATCH 3/7] =?UTF-8?q?feat(slash-commands):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20/goto-floor=20=E5=91=BD=E4=BB=A4=E5=B9=B6=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=89=80=E6=9C=89=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在执行 /goto-floor 命令前加载所有消息,确保目标元素存在 - 添加加载消息的步骤,解决因懒加载导致的元素找不到问题 --- public/scripts/slash-commands.js | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index f16ce9e7b..1647cd55f 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2134,8 +2134,15 @@ export function initDefaultSlashCommands() { name: 'goto-floor', aliases: ['floor', 'jump', 'scrollto'], callback: async (_, index) => { + // --- Load all messages first to ensure the target element exists --- + console.log(`INFO: Loading all messages before attempting to goto-floor ${index}.`); + await showMoreMessages(Number.MAX_SAFE_INTEGER); + console.log(`INFO: All messages loaded (or loading initiated).`); + // --- End of loading step --- + + const floorIndex = Number(index); - + // Validate input if (isNaN(floorIndex) || floorIndex < 0 || (typeof chat !== 'undefined' && floorIndex >= chat.length)) { const maxIndex = (typeof chat !== 'undefined' ? chat.length - 1 : 'unknown'); @@ -2143,21 +2150,25 @@ export function initDefaultSlashCommands() { console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`); return ''; } - + + // Give the rendering a moment to potentially catch up after showMoreMessages + // This might be necessary depending on how showMoreMessages works internally + await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed + const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); - + if (messageElement) { const headerElement = messageElement.querySelector('.mes_header') || messageElement.querySelector('.mes_meta') || messageElement.querySelector('.mes_name_area') || messageElement.querySelector('.mes_name'); - + const elementToScroll = headerElement || messageElement; // Prefer header, fallback to whole message const blockPosition = headerElement ? 'center' : 'start'; // Center header, else start of message - + elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); console.log(`INFO: Scrolled ${headerElement ? 'header of' : ''} message ${floorIndex} into view (block: ${blockPosition}).`); - + // --- Highlight with smooth animation --- messageElement.classList.add('highlight-scroll'); setTimeout(() => { @@ -2169,10 +2180,12 @@ export function initDefaultSlashCommands() { messageElement.classList.remove('highlight-scroll', 'highlight-scroll-fadeout'); }, 500); // Matches the 0.5s transition duration }, 1500); // Start fade out after 1.5 seconds - + } else { - toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]). It might not be rendered yet. Try scrolling up or use /chat-render all.`); - console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor.`); + // This case is less likely now after showMoreMessages, but still possible + // if the element hasn't been added to the DOM yet for some reason after loading. + toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]) even after attempting to load all messages. It might not be rendered yet. Try scrolling up or use /chat-render all again if issues persist.`); + console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor, even after attempting to load all messages.`); const chatContainer = document.getElementById('chat'); if (chatContainer) { chatContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); @@ -2192,16 +2205,14 @@ export function initDefaultSlashCommands() {
Scrolls the chat view to the specified message index. Uses the [mesid] attribute for locating the message element. Index starts at 0. It attempts to center the character's name/header area within the message block. Highlights the message using the theme's 'matchedText' color with a smooth animation. + Automatically attempts to load all messages before scrolling to improve success rate, addressing issues with lazy loading.
Example:
/goto-floor 10
Scrolls to the 11th message (mesid=10).
-
- Note: Due to virtual scrolling, very old messages might need loading first. -
`, })); - + // --- Improved CSS for highlight --- const styleId = 'goto-floor-highlight-style'; if (!document.getElementById(styleId)) { From ee11f021ebfae786dc1be56b9ef02a77c9f05642 Mon Sep 17 00:00:00 2001 From: awaae001 <3271436144@qq.com> Date: Wed, 23 Apr 2025 01:04:52 +0800 Subject: [PATCH 4/7] =?UTF-8?q?refactor(slash-commands):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20/goto-floor=20=E5=91=BD=E4=BB=A4=E5=B9=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=AB=98=E4=BA=AE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重新组织消息加载和滚动逻辑,提高命令成功率 - 添加消息元素高亮功能,使用 flashHighlight 或临时 CSS 类 --- public/scripts/slash-commands.js | 137 +++++++++++-------------------- 1 file changed, 49 insertions(+), 88 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 1647cd55f..53f3ba364 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -1,4 +1,5 @@ import { Fuse, DOMPurify } from '../lib.js'; +import { flashHighlight } from './utils.js'; import { Generate, @@ -2134,64 +2135,67 @@ export function initDefaultSlashCommands() { name: 'goto-floor', aliases: ['floor', 'jump', 'scrollto'], callback: async (_, index) => { - // --- Load all messages first to ensure the target element exists --- - console.log(`INFO: Loading all messages before attempting to goto-floor ${index}.`); - await showMoreMessages(Number.MAX_SAFE_INTEGER); - console.log(`INFO: All messages loaded (or loading initiated).`); - // --- End of loading step --- - - const floorIndex = Number(index); - // Validate input - if (isNaN(floorIndex) || floorIndex < 0 || (typeof chat !== 'undefined' && floorIndex >= chat.length)) { - const maxIndex = (typeof chat !== 'undefined' ? chat.length - 1 : 'unknown'); + const chatLength = typeof chat !== 'undefined' ? chat.length : -1; // Use -1 if chat is undefined to avoid errors + if (isNaN(floorIndex) || floorIndex < 0 || (chatLength !== -1 && floorIndex >= chatLength)) { + const maxIndex = (chatLength !== -1 ? chatLength - 1 : 'unknown'); toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`); return ''; } - // Give the rendering a moment to potentially catch up after showMoreMessages - // This might be necessary depending on how showMoreMessages works internally - await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed + // --- Load all messages first to ensure the target element exists --- + console.log(`INFO: Attempting to load all messages before attempting to goto-floor ${index}.`); + try { + // Assuming showMoreMessages is available globally or within scope + await showMoreMessages(Number.MAX_SAFE_INTEGER); + console.log(`INFO: All messages loaded (or loading initiated).`); + // Give the rendering a moment to potentially catch up after showMoreMessages + await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed + } catch (error) { + console.error('Error loading messages:', error); + toastr.error('An error occurred while trying to load messages.'); + return ''; // Exit if loading fails + } + // --- End of loading step --- const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); if (messageElement) { - const headerElement = messageElement.querySelector('.mes_header') || - messageElement.querySelector('.mes_meta') || - messageElement.querySelector('.mes_name_area') || - messageElement.querySelector('.mes_name'); - - const elementToScroll = headerElement || messageElement; // Prefer header, fallback to whole message - const blockPosition = headerElement ? 'center' : 'start'; // Center header, else start of message + // --- Corrected: Use the actual class from the template --- + const headerElement = messageElement.querySelector('.ch_name'); + const elementToScroll = headerElement || messageElement; // Fallback to the entire message div + const blockPosition = headerElement ? 'center' : 'start'; elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); - console.log(`INFO: Scrolled ${headerElement ? 'header of' : ''} message ${floorIndex} into view (block: ${blockPosition}).`); - // --- Highlight with smooth animation --- - messageElement.classList.add('highlight-scroll'); - setTimeout(() => { - // Add a class to fade out, then remove the highlight class after fade - messageElement.classList.add('highlight-scroll-fadeout'); - // Wait for fadeout transition to complete before removing the base class - // Match this duration to the transition duration in CSS - setTimeout(() => { - messageElement.classList.remove('highlight-scroll', 'highlight-scroll-fadeout'); - }, 500); // Matches the 0.5s transition duration - }, 1500); // Start fade out after 1.5 seconds + // Highlight the message element + if (messageElement instanceof HTMLElement) { + if (typeof $ !== 'undefined') { // Check if jQuery is available + flashHighlight($(messageElement), 1500); + } else { + console.warn('jQuery not available, cannot use flashHighlight.'); + // Optional: Add a temporary CSS class highlight if jQuery/flashHighlight is missing + messageElement.style.transition = 'background-color 0.5s ease'; + messageElement.style.backgroundColor = 'yellow'; // Or some highlight color + setTimeout(() => { + messageElement.style.backgroundColor = ''; // Remove highlight + }, 1500); // Match flash duration + } + + } else { + console.warn('Message element is not an HTMLElement, cannot flash highlight.'); + } + } else { - // This case is less likely now after showMoreMessages, but still possible - // if the element hasn't been added to the DOM yet for some reason after loading. - toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]) even after attempting to load all messages. It might not be rendered yet. Try scrolling up or use /chat-render all again if issues persist.`); + // Only warn if element is not found *after* attempting to load all messages + toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]) even after attempting to load all messages. It might not be rendered yet or the index is invalid.`); console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor, even after attempting to load all messages.`); - const chatContainer = document.getElementById('chat'); - if (chatContainer) { - chatContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } + // Do NOT scroll the chat container in this case } - return ''; + return ''; // Return empty string as expected by some slash command parsers }, unnamedArgumentList: [ SlashCommandArgument.fromProps({ @@ -2204,8 +2208,9 @@ export function initDefaultSlashCommands() { helpString: `
Scrolls the chat view to the specified message index. Uses the [mesid] attribute for locating the message element. Index starts at 0. - It attempts to center the character's name/header area within the message block. Highlights the message using the theme's 'matchedText' color with a smooth animation. + It attempts to center the character's name/header area within the message block by targeting the .ch_name element. Highlights the message using a flash animation. Automatically attempts to load all messages before scrolling to improve success rate, addressing issues with lazy loading. + A warning is displayed if the message element cannot be located even after attempting to load all messages.
Example:
/goto-floor 10
Scrolls to the 11th message (mesid=10). @@ -2213,55 +2218,11 @@ export function initDefaultSlashCommands() { `, })); - // --- Improved CSS for highlight --- const styleId = 'goto-floor-highlight-style'; - if (!document.getElementById(styleId)) { - const style = document.createElement('style'); - style.id = styleId; - style.textContent = ` - /* Base state for elements that *can* be highlighted */ - /* Ensures transition applies smoothly in both directions */ - .mes, .mes_block { - transition: background-color 0.5s ease-in-out, box-shadow 0.5s ease-in-out; - /* Add position relative if not already present, needed for potential pseudo-elements */ - position: relative; - } - - /* --- Highlighting Style --- */ - .mes.highlight-scroll, - .mes_block.highlight-scroll { - /* Use theme color for shadow, fallback to gold */ - box-shadow: 0 0 10px var(--ac-style-color-matchedText, #FFD700) !important; - z-index: 5; /* Ensure highlight is visually prominent */ - } - - /* Modern browsers: Use color-mix for transparent background */ - @supports (background-color: color-mix(in srgb, white 50%, black)) { - .mes.highlight-scroll, - .mes_block.highlight-scroll { - /* Mix theme color with transparent for background */ - background-color: color-mix(in srgb, var(--ac-style-color-matchedText, #FFD700) 35%, transparent) !important; - } - } - - /* Fallback for older browsers: Use a fixed semi-transparent background */ - @supports not (background-color: color-mix(in srgb, white 50%, black)) { - .mes.highlight-scroll, - .mes_block.highlight-scroll { - background-color: rgba(255, 215, 0, 0.35) !important; /* Fallback semi-transparent gold */ - } - } - - /* --- Fade-out Control --- */ - /* When fading out, explicitly transition back to transparent/none */ - .mes.highlight-scroll-fadeout, - .mes_block.highlight-scroll-fadeout { - background-color: transparent !important; - box-shadow: none !important; - } - `; - document.head.appendChild(style); + if (document.getElementById(styleId)) { + document.getElementById(styleId).remove(); } + registerVariableCommands(); } From 59ebf2e5b8a23080bec1ed05d152ad1c61a323ec Mon Sep 17 00:00:00 2001 From: awaae001 <3271436144@qq.com> Date: Wed, 23 Apr 2025 01:12:57 +0800 Subject: [PATCH 5/7] =?UTF-8?q?refactor(slash-commands):=20=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8D=20goto-floor=20=E5=91=BD=E4=BB=A4=E4=B8=BA?= =?UTF-8?q?=20chat-jump?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将命令名称从 'goto-floor' 修改为 'chat-jump',以更好地反映其功能 --- public/scripts/slash-commands.js | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 53f3ba364..1ba7a3a5f 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2132,25 +2132,25 @@ export function initDefaultSlashCommands() { })); SlashCommandParser.addCommandObject(SlashCommand.fromProps({ - name: 'goto-floor', + name: 'chat-jump', aliases: ['floor', 'jump', 'scrollto'], callback: async (_, index) => { const floorIndex = Number(index); - + const chatLength = typeof chat !== 'undefined' ? chat.length : -1; // Use -1 if chat is undefined to avoid errors if (isNaN(floorIndex) || floorIndex < 0 || (chatLength !== -1 && floorIndex >= chatLength)) { const maxIndex = (chatLength !== -1 ? chatLength - 1 : 'unknown'); toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); - console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`); + console.warn(`WARN: Invalid message index provided for /chat-jump: ${index}. Max index: ${maxIndex}`); return ''; } - + // --- Load all messages first to ensure the target element exists --- - console.log(`INFO: Attempting to load all messages before attempting to goto-floor ${index}.`); + console.log(`INFO: Attempting to load all messages before attempting to chat-jump ${index}.`); try { // Assuming showMoreMessages is available globally or within scope await showMoreMessages(Number.MAX_SAFE_INTEGER); - console.log(`INFO: All messages loaded (or loading initiated).`); + console.log('INFO: All messages loaded (or loading initiated).'); // Give the rendering a moment to potentially catch up after showMoreMessages await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed } catch (error) { @@ -2159,40 +2159,40 @@ export function initDefaultSlashCommands() { return ''; // Exit if loading fails } // --- End of loading step --- - + const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); - + if (messageElement) { // --- Corrected: Use the actual class from the template --- const headerElement = messageElement.querySelector('.ch_name'); const elementToScroll = headerElement || messageElement; // Fallback to the entire message div const blockPosition = headerElement ? 'center' : 'start'; - + elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); - + // Highlight the message element if (messageElement instanceof HTMLElement) { if (typeof $ !== 'undefined') { // Check if jQuery is available - flashHighlight($(messageElement), 1500); + flashHighlight($(messageElement), 1500); } else { console.warn('jQuery not available, cannot use flashHighlight.'); // Optional: Add a temporary CSS class highlight if jQuery/flashHighlight is missing - messageElement.style.transition = 'background-color 0.5s ease'; - messageElement.style.backgroundColor = 'yellow'; // Or some highlight color - setTimeout(() => { - messageElement.style.backgroundColor = ''; // Remove highlight - }, 1500); // Match flash duration + messageElement.style.transition = 'background-color 0.5s ease'; + messageElement.style.backgroundColor = 'yellow'; // Or some highlight color + setTimeout(() => { + messageElement.style.backgroundColor = ''; // Remove highlight + }, 1500); // Match flash duration } - + } else { console.warn('Message element is not an HTMLElement, cannot flash highlight.'); } - - + + } else { // Only warn if element is not found *after* attempting to load all messages toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]) even after attempting to load all messages. It might not be rendered yet or the index is invalid.`); - console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor, even after attempting to load all messages.`); + console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /chat-jump, even after attempting to load all messages.`); // Do NOT scroll the chat container in this case } return ''; // Return empty string as expected by some slash command parsers @@ -2213,12 +2213,12 @@ export function initDefaultSlashCommands() { A warning is displayed if the message element cannot be located even after attempting to load all messages.
- Example:
/goto-floor 10
Scrolls to the 11th message (mesid=10). + Example:
/chat-jump 10
Scrolls to the 11th message (mesid=10).
`, })); - - const styleId = 'goto-floor-highlight-style'; + + const styleId = 'chat-jump-highlight-style'; if (document.getElementById(styleId)) { document.getElementById(styleId).remove(); } From b39b7998ce5cfed8e5945d0bd29e3851eb9a205a Mon Sep 17 00:00:00 2001 From: awaae001 <3271436144@qq.com> Date: Wed, 23 Apr 2025 01:34:29 +0800 Subject: [PATCH 6/7] =?UTF-8?q?refactor(slash-commands):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=B6=88=E6=81=AF=E5=AE=9A=E4=BD=8D=E5=92=8C=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/scripts/slash-commands.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 1ba7a3a5f..6ac0e445c 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -2161,14 +2161,22 @@ export function initDefaultSlashCommands() { // --- End of loading step --- const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); + const chatContainer = document.getElementById('chat'); - if (messageElement) { - // --- Corrected: Use the actual class from the template --- + if (messageElement && chatContainer) { const headerElement = messageElement.querySelector('.ch_name'); const elementToScroll = headerElement || messageElement; // Fallback to the entire message div - const blockPosition = headerElement ? 'center' : 'start'; - elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); + // Calculate position relative to chat container + const elementRect = elementToScroll.getBoundingClientRect(); + const containerRect = chatContainer.getBoundingClientRect(); + const scrollPosition = elementRect.top - containerRect.top + chatContainer.scrollTop; + + const viewportOffset = chatContainer.clientHeight * 0.1; // 25% from top + chatContainer.scrollTo({ + top: scrollPosition - viewportOffset, + behavior: 'smooth', + }); // Highlight the message element if (messageElement instanceof HTMLElement) { @@ -2183,12 +2191,9 @@ export function initDefaultSlashCommands() { messageElement.style.backgroundColor = ''; // Remove highlight }, 1500); // Match flash duration } - } else { console.warn('Message element is not an HTMLElement, cannot flash highlight.'); } - - } else { // Only warn if element is not found *after* attempting to load all messages toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]) even after attempting to load all messages. It might not be rendered yet or the index is invalid.`); From 870abe077675f30e3546a9c4eaa6a4b68b1c234e Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:36:01 +0300 Subject: [PATCH 7/7] Code clean-up --- public/scripts/slash-commands.js | 85 +++++++++----------------------- 1 file changed, 24 insertions(+), 61 deletions(-) diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 6ac0e445c..ae1523039 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -22,6 +22,7 @@ import { extractMessageBias, generateQuietPrompt, generateRaw, + getFirstDisplayedMessageId, getThumbnailUrl, is_send_press, main_api, @@ -2133,74 +2134,44 @@ export function initDefaultSlashCommands() { SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'chat-jump', - aliases: ['floor', 'jump', 'scrollto'], + aliases: ['chat-scrollto', 'floor-teleport'], callback: async (_, index) => { - const floorIndex = Number(index); + const messageIndex = Number(index); - const chatLength = typeof chat !== 'undefined' ? chat.length : -1; // Use -1 if chat is undefined to avoid errors - if (isNaN(floorIndex) || floorIndex < 0 || (chatLength !== -1 && floorIndex >= chatLength)) { - const maxIndex = (chatLength !== -1 ? chatLength - 1 : 'unknown'); - toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); - console.warn(`WARN: Invalid message index provided for /chat-jump: ${index}. Max index: ${maxIndex}`); + if (isNaN(messageIndex) || messageIndex < 0 || messageIndex >= chat.length) { + toastr.warning(t`Invalid message index: ${index}. Please enter a number between 0 and ${chat.length}.`); + console.warn(`WARN: Invalid message index provided for /chat-jump: ${index}. Max index: ${chat.length}`); return ''; } - // --- Load all messages first to ensure the target element exists --- - console.log(`INFO: Attempting to load all messages before attempting to chat-jump ${index}.`); - try { - // Assuming showMoreMessages is available globally or within scope - await showMoreMessages(Number.MAX_SAFE_INTEGER); - console.log('INFO: All messages loaded (or loading initiated).'); - // Give the rendering a moment to potentially catch up after showMoreMessages - await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed - } catch (error) { - console.error('Error loading messages:', error); - toastr.error('An error occurred while trying to load messages.'); - return ''; // Exit if loading fails + // Load more messages if needed + const firstDisplayedMessageId = getFirstDisplayedMessageId(); + if (isFinite(firstDisplayedMessageId) && messageIndex < firstDisplayedMessageId) { + const needToLoadCount = firstDisplayedMessageId - messageIndex; + await showMoreMessages(needToLoadCount); + await delay(1); } - // --- End of loading step --- - const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); const chatContainer = document.getElementById('chat'); + const messageElement = document.querySelector(`#chat .mes[mesid="${messageIndex}"]`); - if (messageElement && chatContainer) { - const headerElement = messageElement.querySelector('.ch_name'); - const elementToScroll = headerElement || messageElement; // Fallback to the entire message div - - // Calculate position relative to chat container - const elementRect = elementToScroll.getBoundingClientRect(); + if (messageElement instanceof HTMLElement && chatContainer instanceof HTMLElement) { + const elementRect = messageElement.getBoundingClientRect(); const containerRect = chatContainer.getBoundingClientRect(); - const scrollPosition = elementRect.top - containerRect.top + chatContainer.scrollTop; - const viewportOffset = chatContainer.clientHeight * 0.1; // 25% from top + const scrollPosition = elementRect.top - containerRect.top + chatContainer.scrollTop; chatContainer.scrollTo({ - top: scrollPosition - viewportOffset, + top: scrollPosition, behavior: 'smooth', }); - // Highlight the message element - if (messageElement instanceof HTMLElement) { - if (typeof $ !== 'undefined') { // Check if jQuery is available - flashHighlight($(messageElement), 1500); - } else { - console.warn('jQuery not available, cannot use flashHighlight.'); - // Optional: Add a temporary CSS class highlight if jQuery/flashHighlight is missing - messageElement.style.transition = 'background-color 0.5s ease'; - messageElement.style.backgroundColor = 'yellow'; // Or some highlight color - setTimeout(() => { - messageElement.style.backgroundColor = ''; // Remove highlight - }, 1500); // Match flash duration - } - } else { - console.warn('Message element is not an HTMLElement, cannot flash highlight.'); - } + flashHighlight($(messageElement), 2000); } else { - // Only warn if element is not found *after* attempting to load all messages - toastr.warning(`Could not find element for message ${floorIndex} (using [mesid="${floorIndex}"]) even after attempting to load all messages. It might not be rendered yet or the index is invalid.`); - console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /chat-jump, even after attempting to load all messages.`); - // Do NOT scroll the chat container in this case + toastr.warning(t`Could not find element for message ${messageIndex}. It might not be rendered yet or the index is invalid.`); + console.warn(`WARN: Element not found for message index ${messageIndex} in /chat-jump.`); } - return ''; // Return empty string as expected by some slash command parsers + + return ''; }, unnamedArgumentList: [ SlashCommandArgument.fromProps({ @@ -2212,22 +2183,14 @@ export function initDefaultSlashCommands() { ], helpString: `
- Scrolls the chat view to the specified message index. Uses the [mesid] attribute for locating the message element. Index starts at 0. - It attempts to center the character's name/header area within the message block by targeting the .ch_name element. Highlights the message using a flash animation. - Automatically attempts to load all messages before scrolling to improve success rate, addressing issues with lazy loading. - A warning is displayed if the message element cannot be located even after attempting to load all messages. + Scrolls the chat view to the specified message index. Index starts at 0.
- Example:
/chat-jump 10
Scrolls to the 11th message (mesid=10). + Example:
/chat-jump 10
Scrolls to the 11th message (id=10).
`, })); - const styleId = 'chat-jump-highlight-style'; - if (document.getElementById(styleId)) { - document.getElementById(styleId).remove(); - } - registerVariableCommands(); }