refactor(slash-commands): 优化 /goto-floor 命令并添加高亮功能 - 重新组织消息加载和滚动逻辑,提高命令成功率 - 添加消息元素高亮功能,使用 flashHighlight 或临时 CSS 类

ee11f021ebfae786dc1be56b9ef02a77c9f05642

awaae001 <3271436144@qq.com>

1 files changed, +49 -88Ignore whitespace
public/scripts/slash-commands.js+49 -88
@@ -1,4 +1,5 @@
11import { Fuse, DOMPurify } from '../lib.js';
2+import { flashHighlight } from './utils.js';
23
34import {
45 Generate,
@@ -2134,64 +2135,67 @@ export function initDefaultSlashCommands() {
21342135 name: 'goto-floor',
21352136 aliases: ['floor', 'jump', 'scrollto'],
21362137 callback: async (_, index) => {
2137- // --- Load all messages first to ensure the target element exists ---
2138- console.log(`INFO: Loading all messages before attempting to goto-floor ${index}.`);
2139- await showMoreMessages(Number.MAX_SAFE_INTEGER);
2140- console.log(`INFO: All messages loaded (or loading initiated).`);
2141- // --- End of loading step ---
2142-
2143-
21442138 const floorIndex = Number(index);
21452139
2146- // Validate input
2140+ const chatLength = typeof chat !== 'undefined' ? chat.length : -1; // Use -1 if chat is undefined to avoid errors
21472141 if (isNaN(floorIndex) || floorIndex < 0 || (typeof chatchatLength !== 'undefined'-1 && floorIndex >= chat.lengthchatLength)) {
21482142 const maxIndex = (typeof chatchatLength !== 'undefined'-1 ? chat.lengthchatLength - 1 : 'unknown');
21492143 toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`);
21502144 console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`);
21512145 return '';
21522146 }
21532147
21542148 // Give--- theLoad renderingall amessages momentfirst to potentiallyensure catchthe uptarget afterelement showMoreMessagesexists ---
2155- // This might be necessary depending on how showMoreMessages works internally
2149+ console.log(`INFO: Attempting to load all messages before attempting to goto-floor ${index}.`);
2156- await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed
2150+ try {
2151+ // Assuming showMoreMessages is available globally or within scope
2152+ await showMoreMessages(Number.MAX_SAFE_INTEGER);
2153+ console.log(`INFO: All messages loaded (or loading initiated).`);
2154+ // Give the rendering a moment to potentially catch up after showMoreMessages
2155+ await new Promise(resolve => setTimeout(resolve, 100)); // Adjust delay if needed
2156+ } catch (error) {
2157+ console.error('Error loading messages:', error);
2158+ toastr.error('An error occurred while trying to load messages.');
2159+ return ''; // Exit if loading fails
2160+ }
2161+ // --- End of loading step ---
21572162
21582163 const messageElement = document.querySelector(`[mesid="${floorIndex}"]`);
21592164
21602165 if (messageElement) {
2161- const headerElement = messageElement.querySelector('.mes_header') ||
2166+ // --- Corrected: Use the actual class from the template ---
21622167 const headerElement = messageElement.querySelector('.mes_metach_name') ||;
2163- messageElement.querySelector('.mes_name_area') ||
2168+ const elementToScroll = headerElement || messageElement; // Fallback to the entire message div
2164- messageElement.querySelector('.mes_name');
2169+ const blockPosition = headerElement ? 'center' : 'start';
2165-
2166- const elementToScroll = headerElement || messageElement; // Prefer header, fallback to whole message
2167- const blockPosition = headerElement ? 'center' : 'start'; // Center header, else start of message
21682170
21692171 elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition });
2170- console.log(`INFO: Scrolled ${headerElement ? 'header of' : ''} message ${floorIndex} into view (block: ${blockPosition}).`);
21712172
21722173 // --- Highlight with smooththe animationmessage ---element
2173- messageElement.classList.add('highlight-scroll');
2174+ if (messageElement instanceof HTMLElement) {
2174- setTimeout(() => {
2175+ if (typeof $ !== 'undefined') { // Check if jQuery is available
2175- // Add a class to fade out, then remove the highlight class after fade
2176+ flashHighlight($(messageElement), 1500);
2176- messageElement.classList.add('highlight-scroll-fadeout');
2177+ } else {
2177- // Wait for fadeout transition to complete before removing the base class
2178+ console.warn('jQuery not available, cannot use flashHighlight.');
2178- // Match this duration to the transition duration in CSS
2179+ // Optional: Add a temporary CSS class highlight if jQuery/flashHighlight is missing
2179- setTimeout(() => {
2180+ messageElement.style.transition = 'background-color 0.5s ease';
2180- messageElement.classList.remove('highlight-scroll', 'highlight-scroll-fadeout');
2181+ messageElement.style.backgroundColor = 'yellow'; // Or some highlight color
2181- }, 500); // Matches the 0.5s transition duration
2182+ setTimeout(() => {
2182- }, 1500); // Start fade out after 1.5 seconds
2183+ messageElement.style.backgroundColor = ''; // Remove highlight
2184+ }, 1500); // Match flash duration
2185+ }
2186+
2187+ } else {
2188+ console.warn('Message element is not an HTMLElement, cannot flash highlight.');
2189+ }
2190+
21832191
21842192 } else {
2185- // This case is less likely now after showMoreMessages, but still possible
2193+ // Only warn if element is not found *after* attempting to load all messages
2186- // if the element hasn't been added to the DOM yet for some reason after loading.
2194+ 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.`);
2187- 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.`);
21882195 console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor, even after attempting to load all messages.`);
2189- const chatContainer = document.getElementById('chat');
2196+ // Do NOT scroll the chat container in this case
2190- if (chatContainer) {
2191- chatContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
2192- }
21932197 }
2194- return '';
2198+ return ''; // Return empty string as expected by some slash command parsers
21952199 },
21962200 unnamedArgumentList: [
21972201 SlashCommandArgument.fromProps({
@@ -2204,8 +2208,9 @@ export function initDefaultSlashCommands() {
22042208 helpString: `
22052209 <div>
22062210 Scrolls the chat view to the specified message index. Uses the <code>[mesid]</code> attribute for locating the message element. Index starts at 0.
22072211 It attempts to center the character's name/header area within the message block. Highlightsby thetargeting messagethe using<code>.ch_name</code> theelement. theme'sHighlights 'matchedText'the colormessage withusing a smoothflash animation.
22082212 Automatically attempts to load all messages before scrolling to improve success rate, addressing issues with lazy loading.
2213+ A warning is displayed if the message element cannot be located even after attempting to load all messages.
22092214 </div>
22102215 <div>
22112216 <strong>Example:</strong> <pre><code>/goto-floor 10</code></pre> Scrolls to the 11th message (mesid=10).
@@ -2213,55 +2218,11 @@ export function initDefaultSlashCommands() {
22132218 `,
22142219 }));
22152220
2216- // --- Improved CSS for highlight ---
22172221 const styleId = 'goto-floor-highlight-style';
22182222 if (!document.getElementById(styleId)) {
2219- const style = document.createElement('style');
2223+ document.getElementById(styleId).remove();
2220- style.id = styleId;
2221- style.textContent = `
2222- /* Base state for elements that *can* be highlighted */
2223- /* Ensures transition applies smoothly in both directions */
2224- .mes, .mes_block {
2225- transition: background-color 0.5s ease-in-out, box-shadow 0.5s ease-in-out;
2226- /* Add position relative if not already present, needed for potential pseudo-elements */
2227- position: relative;
2228- }
2229-
2230- /* --- Highlighting Style --- */
2231- .mes.highlight-scroll,
2232- .mes_block.highlight-scroll {
2233- /* Use theme color for shadow, fallback to gold */
2234- box-shadow: 0 0 10px var(--ac-style-color-matchedText, #FFD700) !important;
2235- z-index: 5; /* Ensure highlight is visually prominent */
2236- }
2237-
2238- /* Modern browsers: Use color-mix for transparent background */
2239- @supports (background-color: color-mix(in srgb, white 50%, black)) {
2240- .mes.highlight-scroll,
2241- .mes_block.highlight-scroll {
2242- /* Mix theme color with transparent for background */
2243- background-color: color-mix(in srgb, var(--ac-style-color-matchedText, #FFD700) 35%, transparent) !important;
2244- }
2245- }
2246-
2247- /* Fallback for older browsers: Use a fixed semi-transparent background */
2248- @supports not (background-color: color-mix(in srgb, white 50%, black)) {
2249- .mes.highlight-scroll,
2250- .mes_block.highlight-scroll {
2251- background-color: rgba(255, 215, 0, 0.35) !important; /* Fallback semi-transparent gold */
2252- }
2253- }
2254-
2255- /* --- Fade-out Control --- */
2256- /* When fading out, explicitly transition back to transparent/none */
2257- .mes.highlight-scroll-fadeout,
2258- .mes_block.highlight-scroll-fadeout {
2259- background-color: transparent !important;
2260- box-shadow: none !important;
2261- }
2262- `;
2263- document.head.appendChild(style);
22642224 }
2225+
22652226 registerVariableCommands();
22662227}
22672228