diff --git a/public/scripts/char-data.js b/public/scripts/char-data.js index 378c19ca3..ee87958ce 100644 --- a/public/scripts/char-data.js +++ b/public/scripts/char-data.js @@ -112,5 +112,6 @@ * @property {string} chat - name of the current chat file chat * @property {string} avatar - file name of the avatar image (acts as a unique identifier) * @property {string} json_data - the full raw JSON data of the character + * @property {number} queueOrder - Characters position in the char queue. #1 is currently generating. */ export default 0;// now this file is a module diff --git a/public/scripts/group-chats.js b/public/scripts/group-chats.js index a9eaddd82..5047c9dc4 100644 --- a/public/scripts/group-chats.js +++ b/public/scripts/group-chats.js @@ -70,6 +70,7 @@ import { animation_duration, depth_prompt_role_default, shouldAutoContinue, + this_chid, } from '../script.js'; import { printTagList, createTagMapFromList, applyTagsOnCharacterSelect, tag_map, applyTagsOnGroupSelect } from './tags.js'; import { FILTER_TYPES, FilterHelper } from './filters.js'; @@ -785,7 +786,8 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { sendSystemMessage(system_message_types.EMPTY, '', { isSmallSys: true }); return Promise.resolve(); } - + + const showChatQueue = (!(typingIndicator.length === 0 && !isStreamingEnabled()) && openGroupId); try { throwIfAborted(); hideSwipeButtons(); @@ -857,7 +859,11 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { await saveChatConditional(); $('#send_textarea').val('')[0].dispatchEvent(new Event('input', { bubbles:true })); } - + if (showChatQueue){ + for (let i = 0; i < activatedMembers.length; ++i){ + characters[activatedMembers[i]].queueOrder = (i+1); + } + } // now the real generation begins: cycle through every activated character for (const chId of activatedMembers) { throwIfAborted(); @@ -865,6 +871,9 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { const generateType = type == 'swipe' || type == 'impersonate' || type == 'quiet' || type == 'continue' ? type : 'group_chat'; setCharacterId(chId); setCharacterName(characters[chId].name); + if (showChatQueue){ + printGroupMembers(); + } await eventSource.emit(event_types.GROUP_MEMBER_DRAFTED, chId); if (type !== 'swipe' && type !== 'impersonate' && !isStreamingEnabled()) { @@ -885,6 +894,10 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { messageChunk = textResult?.messageChunk; } } + if (showChatQueue){ + activatedMembers.filter(chidx => characters[chidx].queueOrder > 0) + .forEach(chindex => characters[chindex].queueOrder -= 1); + } } } finally { typingIndicator.hide(); @@ -892,6 +905,14 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) { is_group_generating = false; setSendButtonState(false); setCharacterId(undefined); + + if (showChatQueue){ + group.members.forEach(avatar => { + let character = characters.find(x => x.avatar === avatar || x.name === avatar); + character.queueOrder = undefined; + }); + printGroupMembers(); + } setCharacterName(''); activateSendButtons(); showSwipeButtons(); @@ -1309,11 +1330,13 @@ function getGroupCharacterBlock(character) { const isFav = character.fav || character.fav == 'true'; template.data('id', character.avatar); template.find('.avatar img').attr({ 'src': avatar, 'title': character.avatar }); - template.find('.ch_name').text(character.name); - template.attr('chid', characters.indexOf(character)); + template.find('.ch_name').text(character.name + (character.queueOrder > 0?' (#' + character.queueOrder + ')':'')); template.attr('chid', characters.indexOf(character)); template.find('.ch_fav').val(isFav); template.toggleClass('is_fav', isFav); + template.toggleClass('is_active', character.queueOrder === 1); + template.toggleClass('is_queued', character.queueOrder > 1); template.toggleClass('disabled', isGroupMemberDisabled(character.avatar)); + template.toggleClass('is_active', character.avatar === (this_chid && characters[this_chid] && characters[this_chid].avatar)); // Display inline tags const tagsElement = template.find('.tags'); diff --git a/public/style.css b/public/style.css index 7f1aa081a..0a9a1eaf8 100644 --- a/public/style.css +++ b/public/style.css @@ -2922,6 +2922,14 @@ input[type=search]:focus::-webkit-search-cancel-button { position: relative; } +.group_member.is_queued { + border: 2px solid var(--golden); +} + +.group_member.is_active { + border: 2px solid var(--active); +} + .character_select.is_fav .avatar, .group_select.is_fav .avatar, .group_member.is_fav .avatar,