Add style pin feature for greeting messages

ca29de47047477ea46323944f8305610c9d7bc07

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

4 files changed, +72 -1Ignore whitespace
public/index.html+4 -0
@@ -4778,6 +4778,10 @@
47784778 <input id="show_group_chat_queue" type="checkbox" />
47794779 <small data-i18n="Show group chat queue">Show group chat queue</small>
47804780 </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>
47814785 <div class="inline-drawer wide100p flexFlowColumn">
47824786 <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">
47834787 <b><span data-i18n="Auto-swipe">Auto-swipe</span></b>
public/script.js+3 -0
@@ -97,6 +97,7 @@ import {
9797 forceCharacterEditorTokenize,
9898 applyPowerUserSettings,
9999 generatedTextFiltered,
100+ applyStylePins,
100101} from './scripts/power-user.js';
101102
102103import {
@@ -1920,6 +1921,7 @@ export async function showMoreMessages(messagesToLoad = null) {
19201921 $('#chat').scrollTop(newHeight - prevHeight);
19211922 }
19221923
1924+ applyStylePins();
19231925 await eventSource.emit(event_types.MORE_MESSAGES_LOADED);
19241926}
19251927
@@ -1957,6 +1959,7 @@ export async function printMessages() {
19571959 hideSwipeButtons();
19581960 showSwipeButtons();
19591961 scrollChatToBottom();
1962+ applyStylePins();
19601963
19611964 function incrementAndCheck() {
19621965 imagesLoaded++;
public/scripts/power-user.js+54 -1
@@ -25,6 +25,7 @@ import {
2525 setActiveCharacter,
2626 entitiesFilter,
2727 doNewChat,
28+ messageFormatting,
2829} from '../script.js';
2930import { isMobile, initMovingUI, favsToHotswap } from './RossAscends-mods.js';
3031import {
@@ -318,6 +319,7 @@ let power_user = {
318319 forbid_external_media: true,
319320 external_media_allowed_overrides: [],
320321 external_media_forbidden_overrides: [],
322+ pin_styles: true,
321323};
322324
323325let themes = [];
@@ -1390,6 +1392,50 @@ function applyPowerUserSettings() {
13901392 switchSwipeNumAllMessages();
13911393}
13921394
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+
13931439function getExampleMessagesBehavior() {
13941440 if (power_user.strip_examples) {
13951441 return 'strip';
@@ -1600,6 +1646,7 @@ async function loadPowerUserSettings(settings, data) {
16001646 $('#auto-connect-checkbox').prop('checked', power_user.auto_connect);
16011647 $('#auto-load-chat-checkbox').prop('checked', power_user.auto_load_chat);
16021648 $('#forbid_external_media').prop('checked', power_user.forbid_external_media);
1649+ $('#pin_styles').prop('checked', power_user.pin_styles);
16031650
16041651 for (const theme of themes) {
16051652 const option = document.createElement('option');
@@ -3876,6 +3923,12 @@ $(document).ready(() => {
38763923 reloadCurrentChat();
38773924 });
38783925
3926+ $('#pin_styles').on('input', function () {
3927+ power_user.pin_styles = !!$(this).prop('checked');
3928+ saveSettingsDebounced();
3929+ applyStylePins();
3930+ });
3931+
38793932 $('#ui_preset_import_button').on('click', function () {
38803933 $('#ui_preset_import_file').trigger('click');
38813934 });
@@ -4227,7 +4280,7 @@ $(document).ready(() => {
42274280 enumList: commonEnumProviders.boolean('trueFalse')(),
42284281 }),
42294282 ],
42304283 unnamedArgumentList: [
42314284 SlashCommandArgument.fromProps({
42324285 description: 'value',
42334286 typeList: [ARGUMENT_TYPE.STRING],
public/style.css+11 -0
@@ -1205,6 +1205,17 @@ body .panelControlBar {
12051205 background-color: rgb(102, 0, 0);
12061206}
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+
12081219.mes q:before,
12091220.mes q:after {
12101221 content: '';