diff --git a/public/index.html b/public/index.html index cd0c71cf6..5c244c660 100644 --- a/public/index.html +++ b/public/index.html @@ -102,12 +102,12 @@ @@ -5111,4 +5111,4 @@ - \ No newline at end of file + diff --git a/public/script.js b/public/script.js index 969bfca99..28b48771a 100644 --- a/public/script.js +++ b/public/script.js @@ -185,6 +185,7 @@ import { applyLocale } from "./scripts/i18n.js"; import { getTokenCount, getTokenizerModel, initTokenizers, saveTokenCache } from "./scripts/tokenizers.js"; import { initPersonas, selectCurrentPersona, setPersonaDescription } from "./scripts/personas.js"; import { getBackgrounds, initBackgrounds } from "./scripts/backgrounds.js"; +import {CharacterContextMenu, CharacterGroupOverlay} from "./scripts/CharacterGroupOverlay.js"; //exporting functions and vars for mods export { @@ -314,8 +315,8 @@ eventSource.on(event_types.CHAT_CHANGED, displayOverrideWarnings); eventSource.on(event_types.MESSAGE_RECEIVED, processExtensionHelpers); eventSource.on(event_types.MESSAGE_SENT, processExtensionHelpers); -import {CharacterGroupOverlay} from "./scripts/CharacterGroupOverlay.js"; const characterGroupOverlay = new CharacterGroupOverlay(); +const characterContextMenu = new CharacterContextMenu(characterGroupOverlay); eventSource.on(event_types.CHARACTER_PAGE_LOADED, characterGroupOverlay.onPageLoad); hljs.addPlugin({ "before:highlightElement": ({ el }) => { el.textContent = el.innerText } }); @@ -989,7 +990,7 @@ export function getEntitiesList({ doFilter } = {}) { return entities; } -async function getOneCharacter(avatarUrl) { +export async function getOneCharacter(avatarUrl) { const response = await fetch("/getonecharacter", { method: "POST", headers: getRequestHeaders(), diff --git a/public/scripts/CharacterGroupOverlay.js b/public/scripts/CharacterGroupOverlay.js index 918bf88b6..183760c9d 100644 --- a/public/scripts/CharacterGroupOverlay.js +++ b/public/scripts/CharacterGroupOverlay.js @@ -1,6 +1,7 @@ "use strict"; -import {event_types, eventSource} from "../script.js"; +import {characters, event_types, eventSource, getOneCharacter} from "../script.js"; +import {favsToHotswap} from "./RossAscends-mods.js"; /** * Implement a SingletonPattern, allowing access to the group overlay instance @@ -15,9 +16,60 @@ class CharacterGroupOverlayState { static select = 1; } +class CharacterContextMenu { + static toggleFavorite = (characterId) => { + const character = CharacterContextMenu.getCharacter(characterId); + const data = { + name: character.name, + avatar: character.avatar, + data: { + extensions: { + fav: !character.data.extensions.fav + } + } + }; + + jQuery.ajax({ + type: "POST", + url: '/v2/editcharacterattribute', + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + cache: false, + processData: false, + success: () => + getOneCharacter(character.avatar) + .then(() => + favsToHotswap() + .then(() => eventSource.emit(event_types.CHARACTER_EDITED, { detail: { id: character.id, character: characters[character.id] } }) + )), + error: response => toastr.error('Character not saved. Error: ' + response.responseJSON?.message), + }); + } + + static getCharacter = (characterId) => characters[characterId] ?? null; + + static show = (positionX, positionY) => { + let contextMenu = document.getElementById(CharacterGroupOverlay.contextMenuId); + contextMenu.style.left = `${positionX}px`; + contextMenu.style.top = `${positionY}px`; + + document.getElementById(CharacterGroupOverlay.contextMenuId).classList.remove('hidden'); + } + + static hide = () => document.getElementById(CharacterGroupOverlay.contextMenuId).classList.add('hidden'); + + constructor(characterGroupOverlay) { + const contextMenuItems = [ + {id: 'character_context_menu_favorite', callback: characterGroupOverlay.handleContextMenuFavorite} + ]; + + contextMenuItems.forEach(contextMenuItem => document.getElementById(contextMenuItem.id).addEventListener('click', contextMenuItem.callback)) + } +} + class CharacterGroupOverlay { static containerId = 'rm_print_characters_block'; - static contextMenuClass = 'character_context_menu'; + static contextMenuId = 'character_context_menu'; static characterClass = 'character_select'; static selectModeClass = 'group_overlay_mode_select'; static selectedClass = 'character_selected'; @@ -124,7 +176,7 @@ class CharacterGroupOverlay { document.removeEventListener('click', this.handleContextMenuHide); } - handleHold = (event) => { + handleHold = () => { this.isLongPress = true; setTimeout(() => { if (this.isLongPress) { @@ -149,6 +201,7 @@ class CharacterGroupOverlay { .forEach(element => element.removeEventListener('click', this.toggleCharacterSelected)); this.clearSelectedCharacters(); this.disableContextMenu(); + CharacterContextMenu.hide(); break; case CharacterGroupOverlayState.select: this.container.classList.add(CharacterGroupOverlay.selectModeClass); @@ -181,17 +234,14 @@ class CharacterGroupOverlay { handleContextMenuShow = (event) => { event.preventDefault(); document.getElementById(CharacterGroupOverlay.containerId).style.pointerEvents = 'none'; - let contextMenu = document.getElementById(CharacterGroupOverlay.contextMenuClass); - contextMenu.style.top = `${event.clientY}px`; - contextMenu.style.left = `${event.clientX}px`; - contextMenu.classList.remove('hidden'); + CharacterContextMenu.show(event.clientX, event.clientY); } handleContextMenuHide = (event) => { document.getElementById(CharacterGroupOverlay.containerId).style.pointerEvents = ''; - let contextMenu = document.getElementById(CharacterGroupOverlay.contextMenuClass); + let contextMenu = document.getElementById(CharacterGroupOverlay.contextMenuId); if (false === contextMenu.contains(event.target)) { - contextMenu.classList.add('hidden'); + CharacterContextMenu.hide(); } }