| 2133 | | 2134 | |
| 2134 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | 2135 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| 2135 | name: 'chat-jump', | 2136 | name: 'chat-jump', |
| 2136 | aliases: ['floor', 'jump', 'scrollto'], | 2137 | aliases: ['chat-scrollto', 'floor-teleport'], |
| 2137 | callback: async (_, index) => { | 2138 | callback: async (_, index) => { |
| 2138 | const floorIndex = Number(index); | 2139 | const messageIndex = Number(index); |
| 2139 | | 2140 | |
| 2140 | const chatLength = typeof chat !== 'undefined' ? chat.length : -1; // Use -1 if chat is undefined to avoid errors | 2141 | if (isNaN(messageIndex) || messageIndex < 0 || messageIndex >= chat.length) { |
| 2141 | if (isNaN(floorIndex) || floorIndex < 0 || (chatLength !== -1 && floorIndex >= chatLength)) { | 2142 | toastr.warning(t`Invalid message index: ${index}. Please enter a number between 0 and ${chat.length}.`); |
| 2142 | const maxIndex = (chatLength !== -1 ? chatLength - 1 : 'unknown'); | 2143 | console.warn(`WARN: Invalid message index provided for /chat-jump: ${index}. Max index: ${chat.length}`); |
| 2143 | toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); | | |
| 2144 | console.warn(`WARN: Invalid message index provided for /chat-jump: ${index}. Max index: ${maxIndex}`); | | |
| 2145 | return ''; | 2144 | return ''; |
| 2146 | } | 2145 | } |
| 2147 | | 2146 | |
| 2148 | // --- Load all messages first to ensure the target element exists --- | 2147 | // Load more messages if needed |
| 2149 | console.log(`INFO: Attempting to load all messages before attempting to chat-jump ${index}.`); | 2148 | const firstDisplayedMessageId = getFirstDisplayedMessageId(); |
| 2150 | try { | 2149 | if (isFinite(firstDisplayedMessageId) && messageIndex < firstDisplayedMessageId) { |
| 2151 | // Assuming showMoreMessages is available globally or within scope | 2150 | const needToLoadCount = firstDisplayedMessageId - messageIndex; |
| 2152 | await showMoreMessages(Number.MAX_SAFE_INTEGER); | 2151 | await showMoreMessages(needToLoadCount); |
| 2153 | console.log('INFO: All messages loaded (or loading initiated).'); | 2152 | await delay(1); |
| 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 | } | 2153 | } |
| 2161 | // --- End of loading step --- | | |
| 2162 | | 2154 | |
| 2163 | const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); | | |
| 2164 | const chatContainer = document.getElementById('chat'); | 2155 | const chatContainer = document.getElementById('chat'); |
| | 2156 | const messageElement = document.querySelector(`#chat .mes[mesid="${messageIndex}"]`); |
| 2165 | | 2157 | |
| 2166 | if (messageElement && chatContainer) { | 2158 | if (messageElement instanceof HTMLElement && chatContainer instanceof HTMLElement) { |
| 2167 | const headerElement = messageElement.querySelector('.ch_name'); | 2159 | const elementRect = messageElement.getBoundingClientRect(); |
| 2168 | const elementToScroll = headerElement || messageElement; // Fallback to the entire message div | | |
| 2169 | | | |
| 2170 | // Calculate position relative to chat container | | |
| 2171 | const elementRect = elementToScroll.getBoundingClientRect(); | | |
| 2172 | const containerRect = chatContainer.getBoundingClientRect(); | 2160 | const containerRect = chatContainer.getBoundingClientRect(); |
| 2173 | const scrollPosition = elementRect.top - containerRect.top + chatContainer.scrollTop; | | |
| 2174 | | 2161 | |
| 2175 | const viewportOffset = chatContainer.clientHeight * 0.1; // 25% from top | 2162 | const scrollPosition = elementRect.top - containerRect.top + chatContainer.scrollTop; |
| 2176 | chatContainer.scrollTo({ | 2163 | chatContainer.scrollTo({ |
| 2177 | top: scrollPosition - viewportOffset, | 2164 | top: scrollPosition, |
| 2178 | behavior: 'smooth', | 2165 | behavior: 'smooth', |
| 2179 | }); | 2166 | }); |
| 2180 | | 2167 | |
| 2181 | // Highlight the message element | 2168 | flashHighlight($(messageElement), 2000); |
| 2182 | if (messageElement instanceof HTMLElement) { | | |
| 2183 | if (typeof $ !== 'undefined') { // Check if jQuery is available | | |
| 2184 | flashHighlight($(messageElement), 1500); | | |
| 2185 | } else { | | |
| 2186 | console.warn('jQuery not available, cannot use flashHighlight.'); | | |
| 2187 | // Optional: Add a temporary CSS class highlight if jQuery/flashHighlight is missing | | |
| 2188 | messageElement.style.transition = 'background-color 0.5s ease'; | | |
| 2189 | messageElement.style.backgroundColor = 'yellow'; // Or some highlight color | | |
| 2190 | setTimeout(() => { | | |
| 2191 | messageElement.style.backgroundColor = ''; // Remove highlight | | |
| 2192 | }, 1500); // Match flash duration | | |
| 2193 | } | | |
| 2194 | } else { | | |
| 2195 | console.warn('Message element is not an HTMLElement, cannot flash highlight.'); | | |
| 2196 | } | | |
| 2197 | } else { | 2169 | } else { |
| 2198 | // Only warn if element is not found *after* attempting to load all messages | 2170 | toastr.warning(t`Could not find element for message ${messageIndex}. It might not be rendered yet or the index is invalid.`); |
| 2199 | 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.`); | 2171 | console.warn(`WARN: Element not found for message index ${messageIndex} in /chat-jump.`); |
| 2200 | console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /chat-jump, even after attempting to load all messages.`); | | |
| 2201 | // Do NOT scroll the chat container in this case | | |
| 2202 | } | 2172 | } |
| 2203 | return ''; // Return empty string as expected by some slash command parsers | 2173 | |
| | 2174 | return ''; |
| 2204 | }, | 2175 | }, |
| 2205 | unnamedArgumentList: [ | 2176 | unnamedArgumentList: [ |
| 2206 | SlashCommandArgument.fromProps({ | 2177 | SlashCommandArgument.fromProps({ |