Merge pull request #3955 from SillyTavern/pin-styles Add style pin feature for greeting messages

c6267002261555737eceff3b6b40c9d6c476bf20

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

Signed
4 files changed, +71 -0Showing whitespace changes
public/index.html+4 -0
@@ -4778,6 +4778,10 @@
4778 <input id="show_group_chat_queue" type="checkbox" />4778 <input id="show_group_chat_queue" type="checkbox" />
4779 <small data-i18n="Show group chat queue">Show group chat queue</small>4779 <small data-i18n="Show group chat queue">Show group chat queue</small>
4780 </label>4780 </label>
4781 <label class="checkbox_label" for="pin_styles" title="Always render style tags from greetings, even if the message is unloaded due to lazy loading." data-i18n="[title]Always render style tags from greetings, even if the message is unloaded due to lazy loading.">
4782 <input id="pin_styles" type="checkbox" />
4783 <small data-i18n="Pin greeting message styles">Pin greeting message styles</small>
4784 </label>
4781 <div class="inline-drawer wide100p flexFlowColumn">4785 <div class="inline-drawer wide100p flexFlowColumn">
4782 <div class="inline-drawer-toggle inline-drawer-header userSettingsInnerExpandable" title="Automatically reject and re-generate AI message based on configurable criteria." data-i18n="[title]Automatically reject and re-generate AI message based on configurable criteria">4786 <div class="inline-drawer-toggle inline-drawer-header userSettingsInnerExpandable" title="Automatically reject and re-generate AI message based on configurable criteria." data-i18n="[title]Automatically reject and re-generate AI message based on configurable criteria">
4783 <b><span data-i18n="Auto-swipe">Auto-swipe</span></b>4787 <b><span data-i18n="Auto-swipe">Auto-swipe</span></b>
public/script.js+3 -0
@@ -97,6 +97,7 @@ import {
97 forceCharacterEditorTokenize,97 forceCharacterEditorTokenize,
98 applyPowerUserSettings,98 applyPowerUserSettings,
99 generatedTextFiltered,99 generatedTextFiltered,
100 applyStylePins,
100} from './scripts/power-user.js';101} from './scripts/power-user.js';
101102
102import {103import {
@@ -1920,6 +1921,7 @@ export async function showMoreMessages(messagesToLoad = null) {
1920 $('#chat').scrollTop(newHeight - prevHeight);1921 $('#chat').scrollTop(newHeight - prevHeight);
1921 }1922 }
19221923
1924 applyStylePins();
1923 await eventSource.emit(event_types.MORE_MESSAGES_LOADED);1925 await eventSource.emit(event_types.MORE_MESSAGES_LOADED);
1924}1926}
19251927
@@ -1957,6 +1959,7 @@ export async function printMessages() {
1957 hideSwipeButtons();1959 hideSwipeButtons();
1958 showSwipeButtons();1960 showSwipeButtons();
1959 scrollChatToBottom();1961 scrollChatToBottom();
1962 applyStylePins();
19601963
1961 function incrementAndCheck() {1964 function incrementAndCheck() {
1962 imagesLoaded++;1965 imagesLoaded++;
public/scripts/power-user.js+53 -0
@@ -25,6 +25,7 @@ import {
25 setActiveCharacter,25 setActiveCharacter,
26 entitiesFilter,26 entitiesFilter,
27 doNewChat,27 doNewChat,
28 messageFormatting,
28} from '../script.js';29} from '../script.js';
29import { isMobile, initMovingUI, favsToHotswap } from './RossAscends-mods.js';30import { isMobile, initMovingUI, favsToHotswap } from './RossAscends-mods.js';
30import {31import {
@@ -318,6 +319,7 @@ let power_user = {
318 forbid_external_media: true,319 forbid_external_media: true,
319 external_media_allowed_overrides: [],320 external_media_allowed_overrides: [],
320 external_media_forbidden_overrides: [],321 external_media_forbidden_overrides: [],
322 pin_styles: true,
321};323};
322324
323let themes = [];325let themes = [];
@@ -1390,6 +1392,50 @@ function applyPowerUserSettings() {
1390 switchSwipeNumAllMessages();1392 switchSwipeNumAllMessages();
1391}1393}
13921394
1395export function applyStylePins() {
1396 try {
1397 const existingPins = document.querySelector('#chat > .style-pins');
1398 if (existingPins) {
1399 existingPins.remove();
1400 }
1401
1402 if (!power_user.pin_styles) {
1403 return;
1404 }
1405
1406 const firstDisplayed = getFirstDisplayedMessageId();
1407 if (firstDisplayed === 0 || !isFinite(firstDisplayed)) {
1408 return;
1409 }
1410
1411 const chatElement = document.getElementById('chat');
1412 if (!chatElement) {
1413 return;
1414 }
1415
1416 const firstMessage = chat[0];
1417 if (!firstMessage) {
1418 return;
1419 }
1420
1421 const formattedMessage = messageFormatting(firstMessage.mes, firstMessage.name, firstMessage.is_system, firstMessage.is_user, 0, {}, false);
1422 const htmlElement = document.createElement('div');
1423 htmlElement.innerHTML = formattedMessage;
1424
1425 const styleTags = htmlElement.querySelectorAll('style');
1426 if (styleTags.length === 0) {
1427 return;
1428 }
1429
1430 const pinsElement = document.createElement('div');
1431 pinsElement.classList.add('style-pins');
1432 pinsElement.append(...Array.from(styleTags));
1433 chatElement.prepend(pinsElement);
1434 } catch (error) {
1435 console.error('Error applying style pins:', error);
1436 }
1437}
1438
1393function getExampleMessagesBehavior() {1439function getExampleMessagesBehavior() {
1394 if (power_user.strip_examples) {1440 if (power_user.strip_examples) {
1395 return 'strip';1441 return 'strip';
@@ -1600,6 +1646,7 @@ async function loadPowerUserSettings(settings, data) {
1600 $('#auto-connect-checkbox').prop('checked', power_user.auto_connect);1646 $('#auto-connect-checkbox').prop('checked', power_user.auto_connect);
1601 $('#auto-load-chat-checkbox').prop('checked', power_user.auto_load_chat);1647 $('#auto-load-chat-checkbox').prop('checked', power_user.auto_load_chat);
1602 $('#forbid_external_media').prop('checked', power_user.forbid_external_media);1648 $('#forbid_external_media').prop('checked', power_user.forbid_external_media);
1649 $('#pin_styles').prop('checked', power_user.pin_styles);
16031650
1604 for (const theme of themes) {1651 for (const theme of themes) {
1605 const option = document.createElement('option');1652 const option = document.createElement('option');
@@ -3876,6 +3923,12 @@ $(document).ready(() => {
3876 reloadCurrentChat();3923 reloadCurrentChat();
3877 });3924 });
38783925
3926 $('#pin_styles').on('input', function () {
3927 power_user.pin_styles = !!$(this).prop('checked');
3928 saveSettingsDebounced();
3929 applyStylePins();
3930 });
3931
3879 $('#ui_preset_import_button').on('click', function () {3932 $('#ui_preset_import_button').on('click', function () {
3880 $('#ui_preset_import_file').trigger('click');3933 $('#ui_preset_import_file').trigger('click');
3881 });3934 });
public/style.css+11 -0
@@ -1205,6 +1205,17 @@ body .panelControlBar {
1205 background-color: rgb(102, 0, 0);1205 background-color: rgb(102, 0, 0);
1206}1206}
12071207
1208#chat .style-pins {
1209 visibility: hidden;
1210 position: fixed;
1211 left: -9999px;
1212 top: -9999px;
1213 width: 0;
1214 height: 0;
1215 opacity: 0;
1216 pointer-events: none;
1217}
1218
1208.mes q:before,1219.mes q:before,
1209.mes q:after {1220.mes q:after {
1210 content: '';1221 content: '';