Merge pull request #3898 from awaae001/staging feat(slash-commands): Add /goto-floor command and implement message highlighting

fe4f0c2ea63a7ceedc314d02e8610b8e1948e6e5

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
1 files changed, +61 -0Showing whitespace changes
public/scripts/slash-commands.js+61 -0
@@ -1,4 +1,5 @@
11import { Fuse, DOMPurify } from '../lib.js';
2+import { flashHighlight } from './utils.js';
23
34import {
45 Generate,
@@ -21,6 +22,7 @@ import {
2122 extractMessageBias,
2223 generateQuietPrompt,
2324 generateRaw,
25+ getFirstDisplayedMessageId,
2426 getThumbnailUrl,
2527 is_send_press,
2628 main_api,
@@ -2130,6 +2132,65 @@ export function initDefaultSlashCommands() {
21302132 `,
21312133 }));
21322134
2135+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
2136+ name: 'chat-jump',
2137+ aliases: ['chat-scrollto', 'floor-teleport'],
2138+ callback: async (_, index) => {
2139+ const messageIndex = Number(index);
2140+
2141+ if (isNaN(messageIndex) || messageIndex < 0 || messageIndex >= chat.length) {
2142+ toastr.warning(t`Invalid message index: ${index}. Please enter a number between 0 and ${chat.length}.`);
2143+ console.warn(`WARN: Invalid message index provided for /chat-jump: ${index}. Max index: ${chat.length}`);
2144+ return '';
2145+ }
2146+
2147+ // Load more messages if needed
2148+ const firstDisplayedMessageId = getFirstDisplayedMessageId();
2149+ if (isFinite(firstDisplayedMessageId) && messageIndex < firstDisplayedMessageId) {
2150+ const needToLoadCount = firstDisplayedMessageId - messageIndex;
2151+ await showMoreMessages(needToLoadCount);
2152+ await delay(1);
2153+ }
2154+
2155+ const chatContainer = document.getElementById('chat');
2156+ const messageElement = document.querySelector(`#chat .mes[mesid="${messageIndex}"]`);
2157+
2158+ if (messageElement instanceof HTMLElement && chatContainer instanceof HTMLElement) {
2159+ const elementRect = messageElement.getBoundingClientRect();
2160+ const containerRect = chatContainer.getBoundingClientRect();
2161+
2162+ const scrollPosition = elementRect.top - containerRect.top + chatContainer.scrollTop;
2163+ chatContainer.scrollTo({
2164+ top: scrollPosition,
2165+ behavior: 'smooth',
2166+ });
2167+
2168+ flashHighlight($(messageElement), 2000);
2169+ } else {
2170+ toastr.warning(t`Could not find element for message ${messageIndex}. 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.`);
2172+ }
2173+
2174+ return '';
2175+ },
2176+ unnamedArgumentList: [
2177+ SlashCommandArgument.fromProps({
2178+ description: 'The message index (0-based) to scroll to.',
2179+ typeList: [ARGUMENT_TYPE.NUMBER],
2180+ isRequired: true,
2181+ enumProvider: commonEnumProviders.messages(),
2182+ }),
2183+ ],
2184+ helpString: `
2185+ <div>
2186+ Scrolls the chat view to the specified message index. Index starts at 0.
2187+ </div>
2188+ <div>
2189+ <strong>Example:</strong> <pre><code>/chat-jump 10</code></pre> Scrolls to the 11th message (id=10).
2190+ </div>
2191+ `,
2192+ }));
2193+
21332194 registerVariableCommands();
21342195}
21352196