Add scroll behavior options for media appending
| @@ -183,7 +183,7 @@ import { | |||
| 183 | trimSpaces, | 183 | trimSpaces, |
| 184 | clamp, | 184 | clamp, |
| 185 | } from './scripts/utils.js'; | 185 | } from './scripts/utils.js'; |
| 186 | import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids, MEDIA_DISPLAY, MEDIA_TYPE, SWIPE_DIRECTION } from './scripts/constants.js'; | 186 | import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL, inject_ids, MEDIA_DISPLAY, MEDIA_TYPE, SCROLL_BEHAVIOR, SWIPE_DIRECTION } from './scripts/constants.js'; |
| 187 | 187 | ||
| 188 | import { cancelDebouncedMetadataSave, doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js'; | 188 | import { cancelDebouncedMetadataSave, doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js'; |
| 189 | import { COMMENT_NAME_DEFAULT, CONNECT_API_MAP, executeSlashCommandsOnChatInput, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, stopScriptExecution, UNIQUE_APIS } from './scripts/slash-commands.js'; | 189 | import { COMMENT_NAME_DEFAULT, CONNECT_API_MAP, executeSlashCommandsOnChatInput, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, stopScriptExecution, UNIQUE_APIS } from './scripts/slash-commands.js'; |
| @@ -2071,9 +2071,9 @@ export function getMediaIndex(mes) { | |||
| 2071 | * Appends image or file to the message element. | 2071 | * Appends image or file to the message element. |
| 2072 | * @param {ChatMessage} mes Message object | 2072 | * @param {ChatMessage} mes Message object |
| 2073 | * @param {JQuery<HTMLElement>} messageElement Message element | 2073 | * @param {JQuery<HTMLElement>} messageElement Message element |
| 2074 | * @param {boolean} [adjustScroll=true] Whether to adjust the scroll position after appending the media | 2074 | * @param {string} [scrollBehavior] Scroll behavior when adjusting scroll position |
| 2075 | */ | 2075 | */ |
| 2076 | export function appendMediaToMessage(mes, messageElement, adjustScroll = true) { | 2076 | export function appendMediaToMessage(mes, messageElement, scrollBehavior = SCROLL_BEHAVIOR.ADJUST) { |
| 2077 | ensureMessageMediaIsArray(mes); | 2077 | ensureMessageMediaIsArray(mes); |
| 2078 | 2078 | ||
| 2079 | const hasMedia = Array.isArray(mes?.extra?.media) && mes.extra.media.length > 0; | 2079 | const hasMedia = Array.isArray(mes?.extra?.media) && mes.extra.media.length > 0; |
| @@ -2084,13 +2084,16 @@ export function appendMediaToMessage(mes, messageElement, adjustScroll = true) { | |||
| 2084 | const mediaBlocks = []; | 2084 | const mediaBlocks = []; |
| 2085 | const mediaPromises = []; | 2085 | const mediaPromises = []; |
| 2086 | 2086 | ||
| 2087 | const chatHeight = adjustScroll && (hasMedia || hasFiles) ? chatElement.prop('scrollHeight') : 0; | 2087 | const chatHeight = (hasMedia || hasFiles) ? chatElement.prop('scrollHeight') : 0; |
| 2088 | const scrollPosition = chatElement.scrollTop(); | 2088 | const scrollPosition = (hasMedia || hasFiles) ? chatElement.scrollTop() : 0; |
| 2089 | const doAdjustScroll = () => { | 2089 | const doAdjustScroll = () => { |
| 2090 | if (!hasMedia && !hasFiles) { | 2090 | if (!hasMedia && !hasFiles) { |
| 2091 | return; | 2091 | return; |
| 2092 | } | 2092 | } |
| 2093 | if (!adjustScroll) { | 2093 | if (scrollBehavior === SCROLL_BEHAVIOR.NONE) { |
| 2094 | return; | ||
| 2095 | } | ||
| 2096 | if (scrollBehavior === SCROLL_BEHAVIOR.KEEP) { | ||
| 2094 | chatElement.scrollTop(scrollPosition); | 2097 | chatElement.scrollTop(scrollPosition); |
| 2095 | return; | 2098 | return; |
| 2096 | } | 2099 | } |
| @@ -2397,7 +2400,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2397 | swipeMessage.find('.mes_text').html(messageText).attr('title', title); | 2400 | swipeMessage.find('.mes_text').html(messageText).attr('title', title); |
| 2398 | swipeMessage.find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`); | 2401 | swipeMessage.find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`); |
| 2399 | updateReasoningUI(swipeMessage); | 2402 | updateReasoningUI(swipeMessage); |
| 2400 | appendMediaToMessage(mes, swipeMessage); | 2403 | appendMediaToMessage(mes, swipeMessage, scroll ? SCROLL_BEHAVIOR.ADJUST : SCROLL_BEHAVIOR.NONE); |
| 2401 | if (power_user.timestamp_model_icon && params.extra?.api) { | 2404 | if (power_user.timestamp_model_icon && params.extra?.api) { |
| 2402 | insertSVGIcon(swipeMessage, params.extra); | 2405 | insertSVGIcon(swipeMessage, params.extra); |
| 2403 | } | 2406 | } |
| @@ -2412,7 +2415,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2412 | } else { | 2415 | } else { |
| 2413 | const messageId = forceId ?? chat.length - 1; | 2416 | const messageId = forceId ?? chat.length - 1; |
| 2414 | chatElement.find(`[mesid="${messageId}"] .mes_text`).append(messageText); | 2417 | chatElement.find(`[mesid="${messageId}"] .mes_text`).append(messageText); |
| 2415 | appendMediaToMessage(mes, newMessage); | 2418 | appendMediaToMessage(mes, newMessage, scroll ? SCROLL_BEHAVIOR.ADJUST : SCROLL_BEHAVIOR.NONE); |
| 2416 | showSwipes && hideSwipeButtons(); | 2419 | showSwipes && hideSwipeButtons(); |
| 2417 | } | 2420 | } |
| 2418 | 2421 | ||
| @@ -57,7 +57,7 @@ import { renderTemplateAsync } from './templates.js'; | |||
| 57 | import { t } from './i18n.js'; | 57 | import { t } from './i18n.js'; |
| 58 | import { humanizedDateTime } from './RossAscends-mods.js'; | 58 | import { humanizedDateTime } from './RossAscends-mods.js'; |
| 59 | import { accountStorage } from './util/AccountStorage.js'; | 59 | import { accountStorage } from './util/AccountStorage.js'; |
| 60 | import { MEDIA_DISPLAY, MEDIA_TYPE, SWIPE_DIRECTION } from './constants.js'; | 60 | import { MEDIA_DISPLAY, MEDIA_TYPE, SCROLL_BEHAVIOR, SWIPE_DIRECTION } from './constants.js'; |
| 61 | 61 | ||
| 62 | /** | 62 | /** |
| 63 | * @typedef {Object} FileAttachment | 63 | * @typedef {Object} FileAttachment |
| @@ -418,7 +418,7 @@ async function deleteMessageFile(messageBlock, messageId, fileIndex) { | |||
| 418 | await saveChatConditional(); | 418 | await saveChatConditional(); |
| 419 | await deleteFileFromServer(url); | 419 | await deleteFileFromServer(url); |
| 420 | 420 | ||
| 421 | appendMediaToMessage(message, messageBlock, false); | 421 | appendMediaToMessage(message, messageBlock, SCROLL_BEHAVIOR.KEEP); |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | /** | 424 | /** |
| @@ -489,7 +489,7 @@ function embedMessageFile(messageId, messageBlock) { | |||
| 489 | 489 | ||
| 490 | await populateFileAttachment(message, 'embed_file_input'); | 490 | await populateFileAttachment(message, 'embed_file_input'); |
| 491 | await eventSource.emit(event_types.MESSAGE_FILE_EMBEDDED, messageId); | 491 | await eventSource.emit(event_types.MESSAGE_FILE_EMBEDDED, messageId); |
| 492 | appendMediaToMessage(message, messageBlock, false); | 492 | appendMediaToMessage(message, messageBlock, SCROLL_BEHAVIOR.KEEP); |
| 493 | await saveChatConditional(); | 493 | await saveChatConditional(); |
| 494 | } | 494 | } |
| 495 | } | 495 | } |
| @@ -1022,7 +1022,7 @@ async function deleteMessageMedia(messageId, mediaIndex, messageBlock) { | |||
| 1022 | } | 1022 | } |
| 1023 | 1023 | ||
| 1024 | await saveChatConditional(); | 1024 | await saveChatConditional(); |
| 1025 | appendMediaToMessage(message, messageBlock, false); | 1025 | appendMediaToMessage(message, messageBlock, SCROLL_BEHAVIOR.KEEP); |
| 1026 | } | 1026 | } |
| 1027 | 1027 | ||
| 1028 | /** | 1028 | /** |
| @@ -1051,7 +1051,7 @@ async function switchMessageMediaDisplay(messageId, messageBlock, targetDisplay) | |||
| 1051 | 1051 | ||
| 1052 | message.extra.media_display = targetDisplay; | 1052 | message.extra.media_display = targetDisplay; |
| 1053 | await saveChatConditional(); | 1053 | await saveChatConditional(); |
| 1054 | appendMediaToMessage(message, messageBlock, false); | 1054 | appendMediaToMessage(message, messageBlock, SCROLL_BEHAVIOR.KEEP); |
| 1055 | } | 1055 | } |
| 1056 | 1056 | ||
| 1057 | /** | 1057 | /** |
| @@ -94,6 +94,17 @@ export const MEDIA_TYPE = { | |||
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | /** | 96 | /** |
| 97 | * Scroll behavior options when appending media to messages. | ||
| 98 | * @enum {string} | ||
| 99 | * @readonly | ||
| 100 | */ | ||
| 101 | export const SCROLL_BEHAVIOR = { | ||
| 102 | NONE: 'none', | ||
| 103 | KEEP: 'keep', | ||
| 104 | ADJUST: 'adjust', | ||
| 105 | }; | ||
| 106 | |||
| 107 | /** | ||
| 97 | * @type {{readonly LEFT: 'left', readonly RIGHT: 'right'}} | 108 | * @type {{readonly LEFT: 'left', readonly RIGHT: 'right'}} |
| 98 | */ | 109 | */ |
| 99 | export const SWIPE_DIRECTION = { | 110 | export const SWIPE_DIRECTION = { |
| @@ -10,7 +10,7 @@ import { SlashCommand } from '../../slash-commands/SlashCommand.js'; | |||
| 10 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; | 10 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; |
| 11 | import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; | 11 | import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 12 | import { callGenericPopup, Popup, POPUP_TYPE } from '../../popup.js'; | 12 | import { callGenericPopup, Popup, POPUP_TYPE } from '../../popup.js'; |
| 13 | import { MEDIA_DISPLAY, MEDIA_TYPE } from '../../constants.js'; | 13 | import { MEDIA_DISPLAY, MEDIA_TYPE, SCROLL_BEHAVIOR } from '../../constants.js'; |
| 14 | export { MODULE_NAME }; | 14 | export { MODULE_NAME }; |
| 15 | 15 | ||
| 16 | const MODULE_NAME = 'caption'; | 16 | const MODULE_NAME = 'caption'; |
| @@ -692,7 +692,7 @@ jQuery(async function () { | |||
| 692 | const imageIndex = Number(imageBlock.attr('data-index')); | 692 | const imageIndex = Number(imageBlock.attr('data-index')); |
| 693 | const data = getContext().chat[messageId]; | 693 | const data = getContext().chat[messageId]; |
| 694 | await captionExistingMessage(data, imageIndex); | 694 | await captionExistingMessage(data, imageIndex); |
| 695 | appendMediaToMessage(data, messageBlock, false); | 695 | appendMediaToMessage(data, messageBlock, SCROLL_BEHAVIOR.KEEP); |
| 696 | await saveChatConditional(); | 696 | await saveChatConditional(); |
| 697 | } catch (e) { | 697 | } catch (e) { |
| 698 | console.error('Message image recaption failed', e); | 698 | console.error('Message image recaption failed', e); |
| @@ -52,7 +52,7 @@ import { | |||
| 52 | SlashCommandArgument, | 52 | SlashCommandArgument, |
| 53 | SlashCommandNamedArgument, | 53 | SlashCommandNamedArgument, |
| 54 | } from '../../slash-commands/SlashCommandArgument.js'; | 54 | } from '../../slash-commands/SlashCommandArgument.js'; |
| 55 | import { debounce_timeout, MEDIA_DISPLAY, MEDIA_TYPE, VIDEO_EXTENSIONS } from '../../constants.js'; | 55 | import { debounce_timeout, MEDIA_DISPLAY, MEDIA_TYPE, SCROLL_BEHAVIOR, VIDEO_EXTENSIONS } from '../../constants.js'; |
| 56 | import { SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js'; | 56 | import { SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js'; |
| 57 | import { callGenericPopup, Popup, POPUP_TYPE } from '../../popup.js'; | 57 | import { callGenericPopup, Popup, POPUP_TYPE } from '../../popup.js'; |
| 58 | import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; | 58 | import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; |
| @@ -4290,7 +4290,7 @@ async function sdMessageButton(e) { | |||
| 4290 | message.extra.media.push(newMediaAttachment); | 4290 | message.extra.media.push(newMediaAttachment); |
| 4291 | message.extra.media_index = message.extra.media.length - 1; | 4291 | message.extra.media_index = message.extra.media.length - 1; |
| 4292 | 4292 | ||
| 4293 | appendMediaToMessage(message, messageElement, false); | 4293 | appendMediaToMessage(message, messageElement, SCROLL_BEHAVIOR.KEEP); |
| 4294 | 4294 | ||
| 4295 | await context.saveChat(); | 4295 | await context.saveChat(); |
| 4296 | } | 4296 | } |