Merge pull request #3955 from SillyTavern/pin-styles Add style pin feature for greeting messages
Signed| @@ -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> |
| @@ -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'; |
| 101 | 102 | ||
| 102 | import { | 103 | import { |
| @@ -1920,6 +1921,7 @@ export async function showMoreMessages(messagesToLoad = null) { | |||
| 1920 | $('#chat').scrollTop(newHeight - prevHeight); | 1921 | $('#chat').scrollTop(newHeight - prevHeight); |
| 1921 | } | 1922 | } |
| 1922 | 1923 | ||
| 1924 | applyStylePins(); | ||
| 1923 | await eventSource.emit(event_types.MORE_MESSAGES_LOADED); | 1925 | await eventSource.emit(event_types.MORE_MESSAGES_LOADED); |
| 1924 | } | 1926 | } |
| 1925 | 1927 | ||
| @@ -1957,6 +1959,7 @@ export async function printMessages() { | |||
| 1957 | hideSwipeButtons(); | 1959 | hideSwipeButtons(); |
| 1958 | showSwipeButtons(); | 1960 | showSwipeButtons(); |
| 1959 | scrollChatToBottom(); | 1961 | scrollChatToBottom(); |
| 1962 | applyStylePins(); | ||
| 1960 | 1963 | ||
| 1961 | function incrementAndCheck() { | 1964 | function incrementAndCheck() { |
| 1962 | imagesLoaded++; | 1965 | imagesLoaded++; |
| @@ -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'; |
| 29 | import { isMobile, initMovingUI, favsToHotswap } from './RossAscends-mods.js'; | 30 | import { isMobile, initMovingUI, favsToHotswap } from './RossAscends-mods.js'; |
| 30 | import { | 31 | import { |
| @@ -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 | }; |
| 322 | 324 | ||
| 323 | let themes = []; | 325 | let themes = []; |
| @@ -1390,6 +1392,50 @@ function applyPowerUserSettings() { | |||
| 1390 | switchSwipeNumAllMessages(); | 1392 | switchSwipeNumAllMessages(); |
| 1391 | } | 1393 | } |
| 1392 | 1394 | ||
| 1395 | export 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 | |||
| 1393 | function getExampleMessagesBehavior() { | 1439 | function 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); | ||
| 1603 | 1650 | ||
| 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 | }); |
| 3878 | 3925 | ||
| 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 | }); |
| @@ -1205,6 +1205,17 @@ body .panelControlBar { | |||
| 1205 | background-color: rgb(102, 0, 0); | 1205 | background-color: rgb(102, 0, 0); |
| 1206 | } | 1206 | } |
| 1207 | 1207 | ||
| 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: ''; |