mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-09 08:38:53 +01:00
Merge pull request #1337 from artisticMink/hotfix/bulk-edit-enhanced
Fixes for bulk editing overlay
This commit is contained in:
commit
bc2b3e9c4e
@ -1,7 +1,3 @@
|
||||
#rm_print_characters_block .character_select,
|
||||
#rm_print_characters_block .group_select{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#rm_print_characters_block.group_overlay_mode_select .character_select {
|
||||
transition: background-color 0.4s ease;
|
||||
@ -9,6 +5,15 @@
|
||||
background-color: rgba(170, 170, 170, 0.15);
|
||||
}
|
||||
|
||||
#rm_print_characters_block.group_overlay_mode_select .group_select {
|
||||
cursor: auto;
|
||||
filter: saturate(0.3);
|
||||
}
|
||||
|
||||
#rm_print_characters_block.group_overlay_mode_select .group_select:hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
#rm_print_characters_block.group_overlay_mode_select .character_select input.bulk_select_checkbox {
|
||||
display: none !important;
|
||||
}
|
||||
@ -26,7 +31,7 @@
|
||||
#character_context_menu {
|
||||
position: absolute;
|
||||
padding: 3px;
|
||||
z-index: 10000;
|
||||
z-index: 9998;
|
||||
background-color: var(--black90a);
|
||||
border: 1px solid var(--black90a);
|
||||
border-radius: 10px;
|
||||
|
@ -93,11 +93,11 @@
|
||||
<div id="bg1"></div>
|
||||
<div id="character_context_menu" class="hidden">
|
||||
<ul>
|
||||
<li><button id="character_context_menu_favorite">Favorite</button></li>
|
||||
<li><button id="character_context_menu_tag">Tag</button></li>
|
||||
<li><button id="character_context_menu_duplicate">Duplicate</button></li>
|
||||
<li><button id="character_context_menu_persona">Persona</button></li>
|
||||
<li><button id="character_context_menu_delete">Delete</button></li>
|
||||
<li><button id="character_context_menu_favorite" data-i18n="Favorite">Favorite</button></li>
|
||||
<li><button id="character_context_menu_tag" data-i18n="Tag">Tag</button></li>
|
||||
<li><button id="character_context_menu_duplicate" data-i18n="Duplicate">Duplicate</button></li>
|
||||
<li><button id="character_context_menu_persona" data-i18n="Persona">Persona</button></li>
|
||||
<li><button id="character_context_menu_delete" data-i18n="Delete">Delete</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- top bar central settings buttons -->
|
||||
|
@ -159,6 +159,15 @@ class CharacterContextMenu {
|
||||
contextMenu.style.top = `${positionY}px`;
|
||||
|
||||
document.getElementById(BulkEditOverlay.contextMenuId).classList.remove('hidden');
|
||||
|
||||
// Adjust position if context menu is outside of viewport
|
||||
const boundingRect = contextMenu.getBoundingClientRect();
|
||||
if (boundingRect.right > window.innerWidth) {
|
||||
contextMenu.style.left = `${positionX - (boundingRect.right - window.innerWidth)}px`;
|
||||
}
|
||||
if (boundingRect.bottom > window.innerHeight) {
|
||||
contextMenu.style.top = `${positionY - (boundingRect.bottom - window.innerHeight)}px`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,6 +286,7 @@ class BulkEditOverlay {
|
||||
static containerId = 'rm_print_characters_block';
|
||||
static contextMenuId = 'character_context_menu';
|
||||
static characterClass = 'character_select';
|
||||
static groupClass = 'group_select';
|
||||
static selectModeClass = 'group_overlay_mode_select';
|
||||
static selectedClass = 'character_selected';
|
||||
static legacySelectedClass = 'bulk_select_checkbox';
|
||||
@ -288,6 +298,20 @@ class BulkEditOverlay {
|
||||
#stateChangeCallbacks = [];
|
||||
#selectedCharacters = [];
|
||||
|
||||
/**
|
||||
* Locks other pointer actions when the context menu is open
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
#contextMenuOpen = false;
|
||||
|
||||
/**
|
||||
* Whether the next character select should be skipped
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
#cancelNextToggle = false;
|
||||
|
||||
/**
|
||||
* @type HTMLElement
|
||||
*/
|
||||
@ -332,7 +356,6 @@ class BulkEditOverlay {
|
||||
return bulkEditOverlayInstance
|
||||
|
||||
this.container = document.getElementById(BulkEditOverlay.containerId);
|
||||
this.container.addEventListener('click', this.handleCancelClick);
|
||||
|
||||
eventSource.on(event_types.CHARACTER_GROUP_OVERLAY_STATE_CHANGE_AFTER, this.handleStateChange);
|
||||
bulkEditOverlayInstance = Object.freeze(this);
|
||||
@ -364,8 +387,9 @@ class BulkEditOverlay {
|
||||
elements.forEach(element => element.addEventListener('dragend', this.handleLongPressEnd));
|
||||
elements.forEach(element => element.addEventListener('touchmove', this.handleLongPressEnd));
|
||||
|
||||
const grid = document.getElementById(BulkEditOverlay.containerId);
|
||||
grid.addEventListener('click', this.handleCancelClick);
|
||||
// Cohee: It only triggers when clicking on a margin between the elements?
|
||||
// Feel free to fix or remove this, I'm not sure how to.
|
||||
//this.container.addEventListener('click', this.handleCancelClick);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -377,7 +401,9 @@ class BulkEditOverlay {
|
||||
switch (this.state) {
|
||||
case BulkEditOverlayState.browse:
|
||||
this.container.classList.remove(BulkEditOverlay.selectModeClass);
|
||||
this.#contextMenuOpen = false;
|
||||
this.#enableClickEventsForCharacters();
|
||||
this.#enableClickEventsForGroups();
|
||||
this.clearSelectedCharacters();
|
||||
this.disableContextMenu();
|
||||
this.#disableBulkEditButtonHighlight();
|
||||
@ -386,6 +412,7 @@ class BulkEditOverlay {
|
||||
case BulkEditOverlayState.select:
|
||||
this.container.classList.add(BulkEditOverlay.selectModeClass);
|
||||
this.#disableClickEventsForCharacters();
|
||||
this.#disableClickEventsForGroups();
|
||||
this.enableContextMenu();
|
||||
this.#enableBulkEditButtonHighlight();
|
||||
break;
|
||||
@ -399,7 +426,7 @@ class BulkEditOverlay {
|
||||
* set a click event to hide the custom context menu.
|
||||
*/
|
||||
enableContextMenu = () => {
|
||||
document.getElementById('rm_print_characters_block').addEventListener('contextmenu', this.handleContextMenuShow);
|
||||
this.container.addEventListener('contextmenu', this.handleContextMenuShow);
|
||||
document.addEventListener('click', this.handleContextMenuHide);
|
||||
}
|
||||
|
||||
@ -408,7 +435,7 @@ class BulkEditOverlay {
|
||||
* menu to be opened.
|
||||
*/
|
||||
disableContextMenu = () => {
|
||||
document.getElementById('rm_print_characters_block').removeEventListener('contextmenu', this.handleContextMenuShow);
|
||||
this.container.removeEventListener('contextmenu', this.handleContextMenuShow);
|
||||
document.removeEventListener('click', this.handleContextMenuHide);
|
||||
}
|
||||
|
||||
@ -420,26 +447,52 @@ class BulkEditOverlay {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens menu on long-press.
|
||||
*
|
||||
* @param event - Pointer event
|
||||
*/
|
||||
handleHold = (event) => {
|
||||
if (0 !== event.button && event.type !== 'touchstart') return;
|
||||
if (this.#contextMenuOpen) {
|
||||
this.#contextMenuOpen = false;
|
||||
this.#cancelNextToggle = true;
|
||||
CharacterContextMenu.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
let cancel = false;
|
||||
|
||||
const cancelHold = (event) => cancel = true;
|
||||
this.container.addEventListener('mouseup', cancelHold);
|
||||
this.container.addEventListener('touchend', cancelHold);
|
||||
|
||||
this.isLongPress = true;
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.isLongPress) {
|
||||
if (this.state === BulkEditOverlayState.browse)
|
||||
this.selectState();
|
||||
else if (this.state === BulkEditOverlayState.select)
|
||||
CharacterContextMenu.show(...this.#getContextMenuPosition(event));
|
||||
}
|
||||
}, BulkEditOverlay.longPressDelay);
|
||||
if (this.isLongPress && !cancel) {
|
||||
if (this.state === BulkEditOverlayState.browse) {
|
||||
this.selectState();
|
||||
} else if (this.state === BulkEditOverlayState.select) {
|
||||
this.#contextMenuOpen = true;
|
||||
CharacterContextMenu.show(...this.#getContextMenuPosition(event));
|
||||
}
|
||||
}
|
||||
|
||||
this.container.removeEventListener('mouseup', cancelHold);
|
||||
this.container.removeEventListener('touchend', cancelHold);
|
||||
},
|
||||
BulkEditOverlay.longPressDelay);
|
||||
}
|
||||
|
||||
handleLongPressEnd = () => {
|
||||
handleLongPressEnd = (event) => {
|
||||
this.isLongPress = false;
|
||||
if (this.#contextMenuOpen) event.stopPropagation();
|
||||
}
|
||||
|
||||
handleCancelClick = () => {
|
||||
this.state = BulkEditOverlayState.browse;
|
||||
if (false === this.#contextMenuOpen) this.state = BulkEditOverlayState.browse;
|
||||
this.#contextMenuOpen = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -453,6 +506,17 @@ class BulkEditOverlay {
|
||||
event.clientY || event.touches[0].clientY,
|
||||
];
|
||||
|
||||
#stopEventPropagation = (event) => {
|
||||
if (this.#contextMenuOpen) {
|
||||
this.handleContextMenuHide(event);
|
||||
}
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
#enableClickEventsForGroups = () => this.#getDisabledElements().forEach((element) => element.removeEventListener('click', this.#stopEventPropagation));
|
||||
|
||||
#disableClickEventsForGroups = () => this.#getDisabledElements().forEach((element) => element.addEventListener('click', this.#stopEventPropagation));
|
||||
|
||||
#enableClickEventsForCharacters = () => this.#getEnabledElements().forEach(element => element.removeEventListener('click', this.toggleCharacterSelected));
|
||||
|
||||
#disableClickEventsForCharacters = () => this.#getEnabledElements().forEach(element => element.addEventListener('click', this.toggleCharacterSelected));
|
||||
@ -463,6 +527,8 @@ class BulkEditOverlay {
|
||||
|
||||
#getEnabledElements = () => [...this.container.getElementsByClassName(BulkEditOverlay.characterClass)];
|
||||
|
||||
#getDisabledElements = () =>[...this.container.getElementsByClassName(BulkEditOverlay.groupClass)];
|
||||
|
||||
toggleCharacterSelected = event => {
|
||||
event.stopPropagation();
|
||||
|
||||
@ -473,25 +539,28 @@ class BulkEditOverlay {
|
||||
|
||||
const legacyBulkEditCheckbox = character.querySelector('.' + BulkEditOverlay.legacySelectedClass);
|
||||
|
||||
if (alreadySelected) {
|
||||
character.classList.remove(BulkEditOverlay.selectedClass);
|
||||
if (legacyBulkEditCheckbox) legacyBulkEditCheckbox.checked = false;
|
||||
this.dismissCharacter(characterId);
|
||||
} else {
|
||||
character.classList.add(BulkEditOverlay.selectedClass)
|
||||
if (legacyBulkEditCheckbox) legacyBulkEditCheckbox.checked = true;
|
||||
this.selectCharacter(characterId);
|
||||
}
|
||||
// Only toggle when context menu is closed and wasn't just closed.
|
||||
if (!this.#contextMenuOpen && !this.#cancelNextToggle)
|
||||
if (alreadySelected) {
|
||||
character.classList.remove(BulkEditOverlay.selectedClass);
|
||||
if (legacyBulkEditCheckbox) legacyBulkEditCheckbox.checked = false;
|
||||
this.dismissCharacter(characterId);
|
||||
} else {
|
||||
character.classList.add(BulkEditOverlay.selectedClass)
|
||||
if (legacyBulkEditCheckbox) legacyBulkEditCheckbox.checked = true;
|
||||
this.selectCharacter(characterId);
|
||||
}
|
||||
|
||||
this.#cancelNextToggle = false;
|
||||
}
|
||||
|
||||
handleContextMenuShow = (event) => {
|
||||
event.preventDefault();
|
||||
document.getElementById(BulkEditOverlay.containerId).style.pointerEvents = 'none';
|
||||
CharacterContextMenu.show(...this.#getContextMenuPosition(event));
|
||||
this.#contextMenuOpen = true;
|
||||
}
|
||||
|
||||
handleContextMenuHide = (event) => {
|
||||
document.getElementById(BulkEditOverlay.containerId).style.pointerEvents = '';
|
||||
let contextMenu = document.getElementById(BulkEditOverlay.contextMenuId);
|
||||
if (false === contextMenu.contains(event.target)) {
|
||||
CharacterContextMenu.hide();
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
import { FILTER_TYPES, FilterHelper } from "./filters.js";
|
||||
|
||||
import { groupCandidatesFilter, selected_group } from "./group-chats.js";
|
||||
import { uuidv4 } from "./utils.js";
|
||||
import { onlyUnique, uuidv4 } from "./utils.js";
|
||||
|
||||
export {
|
||||
tags,
|
||||
@ -153,6 +153,7 @@ function addTagToMap(tagId, characterId = null) {
|
||||
}
|
||||
else {
|
||||
tag_map[key].push(tagId);
|
||||
tag_map[key] = tag_map[key].filter(onlyUnique);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user