Add create deck functionality to context menu
This commit is contained in:
parent
efdd280646
commit
015c83aec1
|
@ -102,7 +102,7 @@
|
|||
<div id="character_context_menu" class="hidden">
|
||||
<ul>
|
||||
<li><button id="character_context_menu_favorite">Favorite</button></li>
|
||||
<li><button id="character_context_menu_collection">Collection</button></li>
|
||||
<li><button id="character_context_menu_deck">Deck</button></li>
|
||||
<li><button id="character_context_menu_persona">To Persona</button></li>
|
||||
<li><button id="character_context_menu_duplicate">Duplicate</button></li>
|
||||
<li><button id="character_context_menu_delete">Delete</button></li>
|
||||
|
|
|
@ -954,6 +954,9 @@ async function printCharacters(fullRefresh = false) {
|
|||
callback: function (data) {
|
||||
$("#rm_print_characters_block").empty();
|
||||
for (const i of data) {
|
||||
if (i.type === 'deck') {
|
||||
$("#rm_print_characters_block").append(getCharacterBlock(i.item));
|
||||
}
|
||||
if (i.type === 'character') {
|
||||
$("#rm_print_characters_block").append(getCharacterBlock(i.item, i.id));
|
||||
}
|
||||
|
@ -979,6 +982,7 @@ async function printCharacters(fullRefresh = false) {
|
|||
|
||||
export function getEntitiesList({ doFilter } = {}) {
|
||||
let entities = [];
|
||||
entities.push(...(settings.characterDecks?.decks ?? []).map((item) => ({ item, id: item.id, type: 'deck' })));
|
||||
entities.push(...characters.map((item, index) => ({ item, id: index, type: 'character' })));
|
||||
entities.push(...groups.map((item) => ({ item, id: item.id, type: 'group' })));
|
||||
|
||||
|
@ -5170,6 +5174,7 @@ async function saveSettings(type) {
|
|||
horde_settings: horde_settings,
|
||||
power_user: power_user,
|
||||
extension_settings: extension_settings,
|
||||
characterDecks: settings.characterDecks,
|
||||
tags: tags,
|
||||
tag_map: tag_map,
|
||||
nai_settings: nai_settings,
|
||||
|
|
|
@ -2,14 +2,18 @@
|
|||
|
||||
import {
|
||||
callPopup,
|
||||
characters, deleteCharacter,
|
||||
characters,
|
||||
deleteCharacter,
|
||||
event_types,
|
||||
eventSource,
|
||||
getCharacters,
|
||||
getRequestHeaders, handleDeleteCharacter, this_chid
|
||||
getRequestHeaders,
|
||||
saveSettings,
|
||||
settings
|
||||
} from "../script.js";
|
||||
import {favsToHotswap} from "./RossAscends-mods.js";
|
||||
import {convertCharacterToPersona} from "./personas.js";
|
||||
import {uuidv4} from "./utils.js";
|
||||
|
||||
const popupMessage = {
|
||||
deleteChat(characterCount) {
|
||||
|
@ -20,9 +24,10 @@ const popupMessage = {
|
|||
<span>Also delete the chat files</span>
|
||||
</label><br></b>`;
|
||||
},
|
||||
exportCharacters(characterCount) {
|
||||
return `<h3>Export ${characterCount} characters?</h3>`;
|
||||
}
|
||||
newDeck() {
|
||||
return `<br/><p>Create a new character deck with the selected characters.</p>
|
||||
<h3>Set a name:</h3><br/>`;
|
||||
},
|
||||
}
|
||||
|
||||
const toggleFavoriteHighlight = (characterId) => {
|
||||
|
@ -30,6 +35,64 @@ const toggleFavoriteHighlight = (characterId) => {
|
|||
element.classList.toggle('is_fav');
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a visual grouping of characters
|
||||
*/
|
||||
class CharacterDeck {
|
||||
id = '';
|
||||
name = '';
|
||||
|
||||
/** @type {int[]} */
|
||||
characters = [];
|
||||
|
||||
constructor(id, name, characters = []) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.characters = characters;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
addCharacter = (characterId) => {
|
||||
this.characters.push(characterId);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static fromObject(obj) {
|
||||
return new CharacterDeck(obj.id, obj.name, obj.characters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the characterCollections setting
|
||||
*/
|
||||
class CharacterDeckCollection {
|
||||
/** @type {CharacterDeck[]} */
|
||||
decks = [];
|
||||
|
||||
constructor(decks = []) {
|
||||
if (false === Array.isArray(decks) || decks.some(deck => !(deck instanceof CharacterDeck))) {
|
||||
throw new Error('All groups must be instances of CharacterGroup');
|
||||
}
|
||||
this.decks = decks;
|
||||
}
|
||||
|
||||
addDeck = (deck) => {
|
||||
if (!(deck instanceof CharacterDeck)) {
|
||||
throw new Error('Group must be an instance of CharacterGroup');
|
||||
}
|
||||
this.decks.push(deck);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static fromObject(object) {
|
||||
const decks = object.decks.map(deck => CharacterDeck.fromObject(deck));
|
||||
return new CharacterDeckCollection(decks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement a SingletonPattern, allowing access to the group overlay instance
|
||||
* from everywhere via (new CharacterGroupOverlay())
|
||||
|
@ -44,6 +107,7 @@ class CharacterGroupOverlayState {
|
|||
}
|
||||
|
||||
class CharacterContextMenu {
|
||||
|
||||
/**
|
||||
* Duplicate a character
|
||||
*
|
||||
|
@ -91,6 +155,20 @@ class CharacterContextMenu {
|
|||
|
||||
static persona = async (characterId) => convertCharacterToPersona(characterId);
|
||||
|
||||
static deck = (name = 'New Deck', characterIds = []) => {
|
||||
let characterDeckCollection = null;
|
||||
if (settings.characterDecks && Array.isArray(settings.characterDecks.decks)) {
|
||||
characterDeckCollection = CharacterDeckCollection.fromObject(settings.characterDecks);
|
||||
} else {
|
||||
characterDeckCollection = new CharacterDeckCollection();
|
||||
}
|
||||
|
||||
const id = uuidv4();
|
||||
characterDeckCollection.addDeck(new CharacterDeck(id, name, characterIds));
|
||||
|
||||
settings.characterDecks = JSON.parse(JSON.stringify(characterDeckCollection))
|
||||
}
|
||||
|
||||
static delete = async (characterId, deleteChats = false) => {
|
||||
const character = CharacterContextMenu.getCharacter(characterId);
|
||||
|
||||
|
@ -120,7 +198,7 @@ class CharacterContextMenu {
|
|||
}
|
||||
})
|
||||
}
|
||||
eventSource.emit('characterDeleted', { id: this_chid, character: characters[this_chid] });
|
||||
eventSource.emit('characterDeleted', { id: characterId, character: character });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -141,7 +219,8 @@ class CharacterContextMenu {
|
|||
{id: 'character_context_menu_favorite', callback: characterGroupOverlay.handleContextMenuFavorite},
|
||||
{id: 'character_context_menu_duplicate', callback: characterGroupOverlay.handleContextMenuDuplicate},
|
||||
{id: 'character_context_menu_delete', callback: characterGroupOverlay.handleContextMenuDelete},
|
||||
{id: 'character_context_menu_persona', callback: characterGroupOverlay.handleContextMenuPersona}
|
||||
{id: 'character_context_menu_persona', callback: characterGroupOverlay.handleContextMenuPersona},
|
||||
{id: 'character_context_menu_deck', callback: characterGroupOverlay.handleContextMenuCreateDeck}
|
||||
];
|
||||
|
||||
contextMenuItems.forEach(contextMenuItem => document.getElementById(contextMenuItem.id).addEventListener('click', contextMenuItem.callback))
|
||||
|
@ -213,11 +292,11 @@ class CharacterGroupOverlay {
|
|||
* Set up a Sortable grid for the loaded page
|
||||
*/
|
||||
onPageLoad = () => {
|
||||
const elements = [...document.getElementsByClassName(CharacterGroupOverlay.characterClass)];
|
||||
this.browseState();
|
||||
|
||||
const elements = [...document.getElementsByClassName(CharacterGroupOverlay.characterClass)];
|
||||
elements.forEach(element => element.addEventListener('touchstart', this.handleHold));
|
||||
elements.forEach(element => element.addEventListener('mousedown', this.handleHold));
|
||||
|
||||
elements.forEach(element => element.addEventListener('touchend', this.handleLongPressEnd));
|
||||
elements.forEach(element => element.addEventListener('mouseup', this.handleLongPressEnd));
|
||||
elements.forEach(element => element.addEventListener('dragend', this.handleLongPressEnd));
|
||||
|
@ -326,9 +405,8 @@ class CharacterGroupOverlay {
|
|||
.then(() => getCharacters())
|
||||
.then(() => this.browseState())
|
||||
|
||||
handleContextMenuPersona = () => { Promise.all(this.selectedCharacters.map(async characterId => CharacterContextMenu.persona(characterId)))
|
||||
handleContextMenuPersona = () => Promise.all(this.selectedCharacters.map(async characterId => CharacterContextMenu.persona(characterId)))
|
||||
.then(() => this.browseState());
|
||||
}
|
||||
|
||||
handleContextMenuDelete = () => {
|
||||
callPopup(
|
||||
|
@ -340,6 +418,15 @@ class CharacterGroupOverlay {
|
|||
);
|
||||
}
|
||||
|
||||
handleContextMenuCreateDeck = () => {
|
||||
callPopup(popupMessage.newDeck, 'input').then(
|
||||
(resolve) => {
|
||||
CharacterContextMenu.deck(resolve, this.selectedCharacters);
|
||||
saveSettings().then(async () => await getCharacters());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
addStateChangeCallback = callback => this.stateChangeCallbacks.push(callback);
|
||||
|
||||
selectCharacter = characterId => this.selectedCharacters.push(String(characterId));
|
||||
|
|
Loading…
Reference in New Issue