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: ` +
[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.
+ /goto-floor 10
Scrolls to the 11th message (mesid=10).
+