Merge pull request #2036 from Wolfsblvt/group-chat-desc-join-template

Group chat-specific join prefix/suffix for char fields
This commit is contained in:
Cohee 2024-04-08 15:22:24 +03:00 committed by GitHub
commit db9ade20d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 94 additions and 9 deletions

View File

@ -58,6 +58,11 @@
cursor: unset; cursor: unset;
} }
#rm_group_buttons textarea {
margin: 0px;
min-width: 200px;
}
#rm_group_members, #rm_group_members,
#rm_group_add_members { #rm_group_add_members {
margin-top: 0.25rem; margin-top: 0.25rem;

View File

@ -4360,24 +4360,44 @@
</div> </div>
<div name="GroupStragegyAndOrder" id="rm_group_buttons" class="flex-container paddingLeftRight5 flex2"> <div name="GroupStragegyAndOrder" id="rm_group_buttons" class="flex-container paddingLeftRight5 flex2">
<div class="flex1 flexGap5"> <div class="flex1 flexGap5">
<div class="flex-container flexnowrap width100p whitespacenowrap"> <label for="rm_group_activation_strategy" class="flexnowrap width100p whitespacenowrap">
<span data-i18n="Group reply strategy">Group reply strategy</span> <span data-i18n="Group reply strategy">Group reply strategy</span>
</div> </label>
<select id="rm_group_activation_strategy"> <select id="rm_group_activation_strategy">
<option value="0" data-i18n="Natural order">Natural order</option> <option value="0" data-i18n="Natural order">Natural order</option>
<option value="1" data-i18n="List order">List order</option> <option value="1" data-i18n="List order">List order</option>
</select> </select>
</div> </div>
<div class="flex1 flexGap5"> <div class="flex1 flexGap5">
<div class="flex-container flexnowrap width100p whitespacenowrap"> <label for="rm_group_generation_mode" class="flexnowrap width100p whitespacenowrap">
<span data-i18n="Group generation handling mode">Group generation handling mode</span> <span data-i18n="Group generation handling mode">Group generation handling mode</span>
</div> </label>
<select id="rm_group_generation_mode"> <select id="rm_group_generation_mode">
<option value="0" data-i18n="Swap character cards">Swap character cards</option> <option value="0" data-i18n="Swap character cards">Swap character cards</option>
<option value="1" data-i18n="Join character cards (exclude muted)">Join character cards (exclude muted)</option> <option value="1" data-i18n="Join character cards (exclude muted)">Join character cards (exclude muted)</option>
<option value="2" data-i18n="Join character cards (include muted)">Join character cards (include muted)</option> <option value="2" data-i18n="Join character cards (include muted)">Join character cards (include muted)</option>
</select> </select>
</div> </div>
<div class="flex1 flexGap5" title="Inserted before each part of the joined fields.">
<label for="rm_group_generation_mode_join_prefix" class="flexnowrap width100p whitespacenowrap">
<span data-i18n="Join Prefix">Join Prefix</span>
<div class="fa-solid fa-circle-info opacity50p"
data-i18n="[title]When 'Join character cards' is selected, all respective fields of the characters are being joined together.&#13;This means that in the story string for example all character descriptions will be joined to one big text.&#13;If you want those fields to be separated, you can define a prefix or suffix here.&#13;&#13;This value supports normal macros and will also replace {{char}} with the relevant char's name and &lt;FIELDNAME&gt; with the name of the part (e.g.: description, personality, scenario, etc.)"
title="When 'Join character cards' is selected, all respective fields of the characters are being joined together.&#13;This means that in the story string for example all character descriptions will be joined to one big text.&#13;If you want those fields to be separated, you can define a prefix or suffix here.&#13;&#13;This value supports normal macros and will also replace {{char}} with the relevant char's name and &lt;FIELDNAME&gt; with the name of the part (e.g.: description, personality, scenario, etc.)">
</div>
</label>
<textarea id="rm_group_generation_mode_join_prefix" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="&mdash;" rows="1"></textarea>
</div>
<div class="flex1 flexGap5" title="Inserted after each part of the joined fields.">
<label for="rm_group_generation_mode_join_suffix" class="flexnowrap width100p whitespacenowrap">
<span data-i18n="Join Suffix">Join Suffix</span>
<div class="fa-solid fa-circle-info opacity50p"
data-i18n="[title]When 'Join character cards' is selected, all respective fields of the characters are being joined together.&#13;This means that in the story string for example all character descriptions will be joined to one big text.&#13;If you want those fields to be separated, you can define a prefix or suffix here.&#13;&#13;This value supports normal macros and will also replace {{char}} with the relevant char's name and &lt;FIELDNAME&gt; with the name of the part (e.g.: description, personality, scenario, etc.)"
title="When 'Join character cards' is selected, all respective fields of the characters are being joined together.&#13;This means that in the story string for example all character descriptions will be joined to one big text.&#13;If you want those fields to be separated, you can define a prefix or suffix here.&#13;&#13;This value supports normal macros and will also replace {{char}} with the relevant char's name and &lt;FIELDNAME&gt; with the name of the part (e.g.: description, personality, scenario, etc.)">
</div>
</label>
<textarea id="rm_group_generation_mode_join_suffix" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="&mdash;" rows="1"></textarea>
</div>
</div> </div>
<div id="GroupFavDelOkBack" class="flex-container flexGap5 spaceEvenly flex1"> <div id="GroupFavDelOkBack" class="flex-container flexGap5 spaceEvenly flex1">
<div id="rm_button_back_from_group" class="heightFitContent margin0 menu_button fa-solid fa-left-long"></div> <div id="rm_button_back_from_group" class="heightFitContent margin0 menu_button fa-solid fa-left-long"></div>

View File

@ -9,9 +9,11 @@ import {
saveBase64AsFile, saveBase64AsFile,
PAGINATION_TEMPLATE, PAGINATION_TEMPLATE,
getBase64Async, getBase64Async,
resetScrollHeight,
initScrollHeight,
} from './utils.js'; } from './utils.js';
import { RA_CountCharTokens, humanizedDateTime, dragElement, favsToHotswap, getMessageTimeStamp } from './RossAscends-mods.js'; import { RA_CountCharTokens, humanizedDateTime, dragElement, favsToHotswap, getMessageTimeStamp } from './RossAscends-mods.js';
import { loadMovingUIState, sortEntitiesList } from './power-user.js'; import { power_user, loadMovingUIState, sortEntitiesList } from './power-user.js';
import { import {
chat, chat,
@ -351,6 +353,30 @@ export function getGroupCharacterCards(groupId, characterId) {
return null; return null;
} }
/** Runs the macro engine on a text, with custom <FIELDNAME> replace @param {string} value @param {string} characterName @param {string} fieldName @returns {string} */
function customBaseChatReplace(value, fieldName, characterName) {
// We should do the custom field name replacement first, and then run it through the normal macro engine with provided names
value = value.replace(/<FIELDNAME>/gi, fieldName);
return baseChatReplace(value.trim(), name1, characterName);
}
/** Prepares text with prefix/suffix for a character field @param {string} value @param {string} characterName @param {string} fieldName @returns {string} */
function replaceAndPrepareForJoin(value, characterName, fieldName) {
value = value.trim();
if (!value) {
return '';
}
// Prepare and replace prefixes
const prefix = customBaseChatReplace(group.generation_mode_join_prefix, fieldName, characterName);
const suffix = customBaseChatReplace(group.generation_mode_join_suffix, fieldName, characterName);
const separator = power_user.instruct.wrap ? '\n' : '';
// Also run the macro replacement on the actual content
value = customBaseChatReplace(value, fieldName, characterName);
return `${prefix ? prefix + separator : ''}${value}${suffix ? separator + suffix : ''}`;
}
const scenarioOverride = chat_metadata['scenario']; const scenarioOverride = chat_metadata['scenario'];
let descriptions = []; let descriptions = [];
@ -372,10 +398,10 @@ export function getGroupCharacterCards(groupId, characterId) {
continue; continue;
} }
descriptions.push(baseChatReplace(character.description.trim(), name1, character.name)); descriptions.push(replaceAndPrepareForJoin(character.description, character.name, 'Description'));
personalities.push(baseChatReplace(character.personality.trim(), name1, character.name)); personalities.push(replaceAndPrepareForJoin(character.personality, character.name, 'Personality'));
scenarios.push(baseChatReplace(character.scenario.trim(), name1, character.name)); scenarios.push(replaceAndPrepareForJoin(character.scenario, character.name, 'Scenario'));
mesExamplesArray.push(baseChatReplace(character.mes_example.trim(), name1, character.name)); mesExamplesArray.push(replaceAndPrepareForJoin(character.mes_example, character.name, 'Example Messages'));
} }
const description = descriptions.filter(x => x.length).join('\n'); const description = descriptions.filter(x => x.length).join('\n');
@ -1093,6 +1119,8 @@ async function onGroupGenerationModeInput(e) {
let _thisGroup = groups.find((x) => x.id == openGroupId); let _thisGroup = groups.find((x) => x.id == openGroupId);
_thisGroup.generation_mode = Number(e.target.value); _thisGroup.generation_mode = Number(e.target.value);
await editGroup(openGroupId, false, false); await editGroup(openGroupId, false, false);
toggleHiddenControls(_thisGroup);
} }
} }
@ -1105,6 +1133,15 @@ async function onGroupAutoModeDelayInput(e) {
} }
} }
async function onGroupGenerationModeTemplateInput(e) {
if (openGroupId) {
let _thisGroup = groups.find((x) => x.id == openGroupId);
const prop = $(e.target).attr('setting');
_thisGroup[prop] = String(e.target.value);
await editGroup(openGroupId, false, false);
}
}
async function onGroupNameInput() { async function onGroupNameInput() {
if (openGroupId) { if (openGroupId) {
let _thisGroup = groups.find((x) => x.id == openGroupId); let _thisGroup = groups.find((x) => x.id == openGroupId);
@ -1270,6 +1307,14 @@ async function onHideMutedSpritesClick(value) {
} }
} }
function toggleHiddenControls(group, generationMode = null) {
const isJoin = [group_generation_mode.APPEND, group_generation_mode.APPEND_DISABLED].includes(generationMode ?? group?.generation_mode);
$('#rm_group_generation_mode_join_prefix').parent().toggle(isJoin);
$('#rm_group_generation_mode_join_suffix').parent().toggle(isJoin);
initScrollHeight($('#rm_group_generation_mode_join_prefix'));
initScrollHeight($('#rm_group_generation_mode_join_suffix'));
}
function select_group_chats(groupId, skipAnimation) { function select_group_chats(groupId, skipAnimation) {
openGroupId = groupId; openGroupId = groupId;
newGroupMembers = []; newGroupMembers = [];
@ -1305,6 +1350,10 @@ function select_group_chats(groupId, skipAnimation) {
$('#rm_group_hidemutedsprites').prop('checked', group && group.hideMutedSprites); $('#rm_group_hidemutedsprites').prop('checked', group && group.hideMutedSprites);
$('#rm_group_automode_delay').val(group?.auto_mode_delay ?? DEFAULT_AUTO_MODE_DELAY); $('#rm_group_automode_delay').val(group?.auto_mode_delay ?? DEFAULT_AUTO_MODE_DELAY);
$('#rm_group_generation_mode_join_prefix').val(group?.generation_mode_join_prefix ?? '').attr('setting', 'generation_mode_join_prefix');
$('#rm_group_generation_mode_join_suffix').val(group?.generation_mode_join_suffix ?? '').attr('setting', 'generation_mode_join_suffix');
toggleHiddenControls(group, generationMode);
// bottom buttons // bottom buttons
if (openGroupId) { if (openGroupId) {
$('#rm_group_submit').hide(); $('#rm_group_submit').hide();
@ -1338,6 +1387,11 @@ function select_group_chats(groupId, skipAnimation) {
$('#rm_group_automode_label').hide(); $('#rm_group_automode_label').hide();
} }
// Toggle textbox sizes, as input events have not fired here
$('#rm_group_chats_block .autoSetHeight').each(element => {
resetScrollHeight(element);
});
eventSource.emit('groupSelected', { detail: { id: openGroupId, group: group } }); eventSource.emit('groupSelected', { detail: { id: openGroupId, group: group } });
} }
@ -1796,6 +1850,10 @@ function doCurMemberListPopout() {
} }
jQuery(() => { jQuery(() => {
$(document).on('input', '#rm_group_chats_block .autoSetHeight', function () {
resetScrollHeight($(this));
});
$(document).on('click', '.group_select', function () { $(document).on('click', '.group_select', function () {
const groupId = $(this).attr('chid') || $(this).attr('grid') || $(this).data('id'); const groupId = $(this).attr('chid') || $(this).attr('grid') || $(this).data('id');
openGroupById(groupId); openGroupById(groupId);
@ -1823,6 +1881,8 @@ jQuery(() => {
$('#rm_group_activation_strategy').on('change', onGroupActivationStrategyInput); $('#rm_group_activation_strategy').on('change', onGroupActivationStrategyInput);
$('#rm_group_generation_mode').on('change', onGroupGenerationModeInput); $('#rm_group_generation_mode').on('change', onGroupGenerationModeInput);
$('#rm_group_automode_delay').on('input', onGroupAutoModeDelayInput); $('#rm_group_automode_delay').on('input', onGroupAutoModeDelayInput);
$('#rm_group_generation_mode_join_prefix').on('input', onGroupGenerationModeTemplateInput);
$('#rm_group_generation_mode_join_suffix').on('input', onGroupGenerationModeTemplateInput);
$('#group_avatar_button').on('input', uploadGroupAvatar); $('#group_avatar_button').on('input', uploadGroupAvatar);
$('#rm_group_restore_avatar').on('click', restoreGroupAvatar); $('#rm_group_restore_avatar').on('click', restoreGroupAvatar);
$(document).on('click', '.group_member .right_menu_button', onGroupActionClick); $(document).on('click', '.group_member .right_menu_button', onGroupActionClick);