| 2130 | `, | 2130 | `, |
| 2131 | })); | 2131 | })); |
| 2132 | | 2132 | |
| | 2133 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ |
| | 2134 | name: 'goto-floor', |
| | 2135 | aliases: ['floor', 'jump', 'scrollto'], |
| | 2136 | callback: async (_, index) => { |
| | 2137 | const floorIndex = Number(index); |
| | 2138 | |
| | 2139 | // Validate input |
| | 2140 | if (isNaN(floorIndex) || floorIndex < 0 || (typeof chat !== 'undefined' && floorIndex >= chat.length)) { |
| | 2141 | const maxIndex = (typeof chat !== 'undefined' ? chat.length - 1 : 'unknown'); |
| | 2142 | toastr.warning(`Invalid message index: ${index}. Please enter a number between 0 and ${maxIndex}.`); |
| | 2143 | console.warn(`WARN: Invalid message index provided for /goto-floor: ${index}. Max index: ${maxIndex}`); |
| | 2144 | return ''; |
| | 2145 | } |
| | 2146 | |
| | 2147 | const messageElement = document.querySelector(`[mesid="${floorIndex}"]`); |
| | 2148 | |
| | 2149 | if (messageElement) { |
| | 2150 | const headerElement = messageElement.querySelector('.mes_header') || |
| | 2151 | messageElement.querySelector('.mes_meta') || |
| | 2152 | messageElement.querySelector('.mes_name_area') || |
| | 2153 | messageElement.querySelector('.mes_name'); |
| | 2154 | |
| | 2155 | const elementToScroll = headerElement || messageElement; // Prefer header, fallback to whole message |
| | 2156 | const blockPosition = headerElement ? 'center' : 'start'; // Center header, else start of message |
| | 2157 | |
| | 2158 | elementToScroll.scrollIntoView({ behavior: 'smooth', block: blockPosition }); |
| | 2159 | console.log(`INFO: Scrolled ${headerElement ? 'header of' : ''} message ${floorIndex} into view (block: ${blockPosition}).`); |
| | 2160 | |
| | 2161 | // --- Highlight with smooth animation --- |
| | 2162 | messageElement.classList.add('highlight-scroll'); |
| | 2163 | setTimeout(() => { |
| | 2164 | // Add a class to fade out, then remove the highlight class after fade |
| | 2165 | messageElement.classList.add('highlight-scroll-fadeout'); |
| | 2166 | // Wait for fadeout transition to complete before removing the base class |
| | 2167 | // Match this duration to the transition duration in CSS |
| | 2168 | setTimeout(() => { |
| | 2169 | messageElement.classList.remove('highlight-scroll', 'highlight-scroll-fadeout'); |
| | 2170 | }, 500); // Matches the 0.5s transition duration |
| | 2171 | }, 1500); // Start fade out after 1.5 seconds |
| | 2172 | |
| | 2173 | } else { |
| | 2174 | 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.`); |
| | 2175 | console.warn(`WARN: Element not found for message index ${floorIndex} using querySelector [mesid="${floorIndex}"] in /goto-floor.`); |
| | 2176 | const chatContainer = document.getElementById('chat'); |
| | 2177 | if (chatContainer) { |
| | 2178 | chatContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); |
| | 2179 | } |
| | 2180 | } |
| | 2181 | return ''; |
| | 2182 | }, |
| | 2183 | unnamedArgumentList: [ |
| | 2184 | SlashCommandArgument.fromProps({ |
| | 2185 | description: 'The message index (0-based) to scroll to.', |
| | 2186 | typeList: [ARGUMENT_TYPE.NUMBER], |
| | 2187 | isRequired: true, |
| | 2188 | enumProvider: commonEnumProviders.messages(), |
| | 2189 | }), |
| | 2190 | ], |
| | 2191 | helpString: ` |
| | 2192 | <div> |
| | 2193 | Scrolls the chat view to the specified message index. Uses the <code>[mesid]</code> attribute for locating the message element. Index starts at 0. |
| | 2194 | 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. |
| | 2195 | </div> |
| | 2196 | <div> |
| | 2197 | <strong>Example:</strong> <pre><code>/goto-floor 10</code></pre> Scrolls to the 11th message (mesid=10). |
| | 2198 | </div> |
| | 2199 | <div> |
| | 2200 | Note: Due to virtual scrolling, very old messages might need loading first. |
| | 2201 | </div> |
| | 2202 | `, |
| | 2203 | })); |
| | 2204 | |
| | 2205 | // --- Improved CSS for highlight --- |
| | 2206 | const styleId = 'goto-floor-highlight-style'; |
| | 2207 | if (!document.getElementById(styleId)) { |
| | 2208 | const style = document.createElement('style'); |
| | 2209 | style.id = styleId; |
| | 2210 | style.textContent = ` |
| | 2211 | /* Base state for elements that *can* be highlighted */ |
| | 2212 | /* Ensures transition applies smoothly in both directions */ |
| | 2213 | .mes, .mes_block { |
| | 2214 | transition: background-color 0.5s ease-in-out, box-shadow 0.5s ease-in-out; |
| | 2215 | /* Add position relative if not already present, needed for potential pseudo-elements */ |
| | 2216 | position: relative; |
| | 2217 | } |
| | 2218 | |
| | 2219 | /* --- Highlighting Style --- */ |
| | 2220 | .mes.highlight-scroll, |
| | 2221 | .mes_block.highlight-scroll { |
| | 2222 | /* Use theme color for shadow, fallback to gold */ |
| | 2223 | box-shadow: 0 0 10px var(--ac-style-color-matchedText, #FFD700) !important; |
| | 2224 | z-index: 5; /* Ensure highlight is visually prominent */ |
| | 2225 | } |
| | 2226 | |
| | 2227 | /* Modern browsers: Use color-mix for transparent background */ |
| | 2228 | @supports (background-color: color-mix(in srgb, white 50%, black)) { |
| | 2229 | .mes.highlight-scroll, |
| | 2230 | .mes_block.highlight-scroll { |
| | 2231 | /* Mix theme color with transparent for background */ |
| | 2232 | background-color: color-mix(in srgb, var(--ac-style-color-matchedText, #FFD700) 35%, transparent) !important; |
| | 2233 | } |
| | 2234 | } |
| | 2235 | |
| | 2236 | /* Fallback for older browsers: Use a fixed semi-transparent background */ |
| | 2237 | @supports not (background-color: color-mix(in srgb, white 50%, black)) { |
| | 2238 | .mes.highlight-scroll, |
| | 2239 | .mes_block.highlight-scroll { |
| | 2240 | background-color: rgba(255, 215, 0, 0.35) !important; /* Fallback semi-transparent gold */ |
| | 2241 | } |
| | 2242 | } |
| | 2243 | |
| | 2244 | /* --- Fade-out Control --- */ |
| | 2245 | /* When fading out, explicitly transition back to transparent/none */ |
| | 2246 | .mes.highlight-scroll-fadeout, |
| | 2247 | .mes_block.highlight-scroll-fadeout { |
| | 2248 | background-color: transparent !important; |
| | 2249 | box-shadow: none !important; |
| | 2250 | } |
| | 2251 | `; |
| | 2252 | document.head.appendChild(style); |
| | 2253 | } |
| 2133 | registerVariableCommands(); | 2254 | registerVariableCommands(); |
| 2134 | } | 2255 | } |
| 2135 | | 2256 | |