parent
36cf68a9f4
commit
99ee1b887a
|
@ -10,10 +10,12 @@ import {
|
|||
getRequestHeaders,
|
||||
this_chid
|
||||
} from "../script.js";
|
||||
|
||||
import {favsToHotswap} from "./RossAscends-mods.js";
|
||||
import {convertCharacterToPersona} from "./personas.js";
|
||||
import {createTagInput, getTagKeyForCharacter, tag_map} from "./tags.js";
|
||||
|
||||
// Utility object for popup messages.
|
||||
const popupMessage = {
|
||||
deleteChat(characterCount) {
|
||||
return `<h3>Delete ${characterCount} characters?</h3>
|
||||
|
@ -25,29 +27,29 @@ const popupMessage = {
|
|||
},
|
||||
}
|
||||
|
||||
const toggleFavoriteHighlight = (characterId) => {
|
||||
const element = document.getElementById(`CharID${characterId}`);
|
||||
element.classList.toggle('is_fav');
|
||||
}
|
||||
|
||||
class CharacterGroupOverlayState {
|
||||
static browse = 0;
|
||||
static select = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static object representing the actions of the
|
||||
* character context menu override.
|
||||
*/
|
||||
class CharacterContextMenu {
|
||||
/**
|
||||
* Tag one or more characters,
|
||||
* opens a popup.
|
||||
*
|
||||
* @param selectedCharacters
|
||||
*/
|
||||
static tag = (selectedCharacters) => {
|
||||
BulkTagPopupHandler.show(selectedCharacters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate a character
|
||||
* Duplicate one or more characters
|
||||
*
|
||||
* @param characterId
|
||||
* @returns {Promise<Response>}
|
||||
*/
|
||||
static duplicate = async (characterId) => {
|
||||
const character = CharacterContextMenu.getCharacter(characterId);
|
||||
const character = CharacterContextMenu.#getCharacter(characterId);
|
||||
|
||||
return fetch('/dupecharacter', {
|
||||
method: 'POST',
|
||||
|
@ -58,13 +60,15 @@ class CharacterContextMenu {
|
|||
|
||||
/**
|
||||
* Favorite a character
|
||||
* and toggle its ui element.
|
||||
* and highlight it.
|
||||
*
|
||||
* @param characterId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static favorite = async (characterId) => {
|
||||
const character = CharacterContextMenu.getCharacter(characterId);
|
||||
const character = CharacterContextMenu.#getCharacter(characterId);
|
||||
|
||||
// Only set fav for V2 spec
|
||||
const data = {
|
||||
name: character.name,
|
||||
avatar: character.avatar,
|
||||
|
@ -80,22 +84,34 @@ class CharacterContextMenu {
|
|||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify(data),
|
||||
}).then((response) => {
|
||||
if (response.ok) toggleFavoriteHighlight(characterId)
|
||||
else response.json().then(json => toastr.error('Character not saved. Error: ' + json.message + '. Field: ' + json.error));
|
||||
if (response.ok) {
|
||||
const element = document.getElementById(`CharID${characterId}`);
|
||||
element.classList.toggle('is_fav');
|
||||
} else {
|
||||
response.json().then(json => toastr.error('Character not saved. Error: ' + json.message + '. Field: ' + json.error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given characters to personas.
|
||||
* Shows popup for each.
|
||||
* Convert one or more characters to persona,
|
||||
* may open a popup for one or more characters.
|
||||
*
|
||||
* @param characterId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static persona = async (characterId) => await convertCharacterToPersona(characterId);
|
||||
|
||||
/**
|
||||
* Delete one or more characters,
|
||||
* opens a popup.
|
||||
*
|
||||
* @param characterId
|
||||
* @param deleteChats
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
static delete = async (characterId, deleteChats = false) => {
|
||||
const character = CharacterContextMenu.getCharacter(characterId);
|
||||
const character = CharacterContextMenu.#getCharacter(characterId);
|
||||
|
||||
return fetch('/deletecharacter', {
|
||||
method: 'POST',
|
||||
|
@ -123,12 +139,19 @@ class CharacterContextMenu {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
eventSource.emit('characterDeleted', { id: this_chid, character: characters[this_chid] });
|
||||
});
|
||||
}
|
||||
|
||||
static getCharacter = (characterId) => characters[characterId] ?? null;
|
||||
static #getCharacter = (characterId) => characters[characterId] ?? null;
|
||||
|
||||
/**
|
||||
* Show the context menu at the given position
|
||||
*
|
||||
* @param positionX
|
||||
* @param positionY
|
||||
*/
|
||||
static show = (positionX, positionY) => {
|
||||
let contextMenu = document.getElementById(BulkEditOverlay.contextMenuId);
|
||||
contextMenu.style.left = `${positionX}px`;
|
||||
|
@ -137,8 +160,16 @@ class CharacterContextMenu {
|
|||
document.getElementById(BulkEditOverlay.contextMenuId).classList.remove('hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the context menu
|
||||
*/
|
||||
static hide = () => document.getElementById(BulkEditOverlay.contextMenuId).classList.add('hidden');
|
||||
|
||||
/**
|
||||
* Sets up the context menu for the given overlay
|
||||
*
|
||||
* @param characterGroupOverlay
|
||||
*/
|
||||
constructor(characterGroupOverlay) {
|
||||
const contextMenuItems = [
|
||||
{id: 'character_context_menu_favorite', callback: characterGroupOverlay.handleContextMenuFavorite},
|
||||
|
@ -153,7 +184,7 @@ class CharacterContextMenu {
|
|||
}
|
||||
|
||||
/**
|
||||
* Appends/Removes the bulk tag popup
|
||||
* Represents a tag control not bound to a single character
|
||||
*/
|
||||
class BulkTagPopupHandler {
|
||||
static #getHtml = (characterIds) => {
|
||||
|
@ -180,6 +211,11 @@ class BulkTagPopupHandler {
|
|||
`
|
||||
};
|
||||
|
||||
/**
|
||||
* Append and show the tag control
|
||||
*
|
||||
* @param characters - The characters assigned to this control
|
||||
*/
|
||||
static show(characters) {
|
||||
document.body.insertAdjacentHTML('beforeend', this.#getHtml(characters));
|
||||
createTagInput('#bulkTagInput', '#bulkTagList');
|
||||
|
@ -187,6 +223,9 @@ class BulkTagPopupHandler {
|
|||
document.querySelector('#bulk_tag_popup_reset').addEventListener('click', this.resetTags.bind(this, characters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide and remove the tag control
|
||||
*/
|
||||
static hide() {
|
||||
let popupElement = document.querySelector('#bulk_tag_shadow_popup');
|
||||
if (popupElement) {
|
||||
|
@ -194,6 +233,11 @@ class BulkTagPopupHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the tag map for the given characters
|
||||
*
|
||||
* @param characterIds
|
||||
*/
|
||||
static resetTags(characterIds) {
|
||||
characterIds.forEach((characterId) => {
|
||||
const key = getTagKeyForCharacter(characterId);
|
||||
|
@ -202,6 +246,20 @@ class BulkTagPopupHandler {
|
|||
}
|
||||
}
|
||||
|
||||
class CharacterGroupOverlayState {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
static browse = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
*/
|
||||
static select = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement a SingletonPattern, allowing access to the group overlay instance
|
||||
* from everywhere via (new CharacterGroupOverlay())
|
||||
|
@ -273,7 +331,14 @@ class BulkEditOverlay {
|
|||
bulkEditOverlayInstance = Object.freeze(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the overlay to browse mode
|
||||
*/
|
||||
browseState = () => this.state = CharacterGroupOverlayState.browse;
|
||||
|
||||
/**
|
||||
* Set the overlay to select mode
|
||||
*/
|
||||
selectState = () => this.state = CharacterGroupOverlayState.select;
|
||||
|
||||
/**
|
||||
|
@ -294,6 +359,32 @@ class BulkEditOverlay {
|
|||
grid.addEventListener('click', this.handleCancelClick);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle state changes
|
||||
*
|
||||
*
|
||||
*/
|
||||
handleStateChange = () => {
|
||||
switch (this.state) {
|
||||
case CharacterGroupOverlayState.browse:
|
||||
this.container.classList.remove(BulkEditOverlay.selectModeClass);
|
||||
this.#enableClickEventsForCharacters();
|
||||
this.clearSelectedCharacters();
|
||||
this.disableContextMenu();
|
||||
this.#disableBulkEditButtonHighlight();
|
||||
CharacterContextMenu.hide();
|
||||
break;
|
||||
case CharacterGroupOverlayState.select:
|
||||
this.container.classList.add(BulkEditOverlay.selectModeClass);
|
||||
this.#disableClickEventsForCharacters();
|
||||
this.enableContextMenu();
|
||||
this.#enableBulkEditButtonHighlight();
|
||||
break;
|
||||
}
|
||||
|
||||
this.stateChangeCallbacks.forEach(callback => callback(this.state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Block the browsers native context menu and
|
||||
* set a click event to hide the custom context menu.
|
||||
|
@ -331,27 +422,6 @@ class BulkEditOverlay {
|
|||
this.state = CharacterGroupOverlayState.browse;
|
||||
}
|
||||
|
||||
handleStateChange = () => {
|
||||
switch (this.state) {
|
||||
case CharacterGroupOverlayState.browse:
|
||||
this.container.classList.remove(BulkEditOverlay.selectModeClass);
|
||||
this.#enableClickEventsForCharacters();
|
||||
this.clearSelectedCharacters();
|
||||
this.disableContextMenu();
|
||||
this.#disableBulkEditButtonHighlight();
|
||||
CharacterContextMenu.hide();
|
||||
break;
|
||||
case CharacterGroupOverlayState.select:
|
||||
this.container.classList.add(BulkEditOverlay.selectModeClass);
|
||||
this.#disableClickEventsForCharacters();
|
||||
this.enableContextMenu();
|
||||
this.#enableBulkEditButtonHighlight();
|
||||
break;
|
||||
}
|
||||
|
||||
this.stateChangeCallbacks.forEach(callback => callback(this.state));
|
||||
}
|
||||
|
||||
#enableClickEventsForCharacters = () => [...this.container.getElementsByClassName(BulkEditOverlay.characterClass)]
|
||||
.forEach(element => element.removeEventListener('click', this.toggleCharacterSelected));
|
||||
|
||||
|
|
Loading…
Reference in New Issue