Added deleteMessage method (#4666) * Added deleteMessage * Simpler swipeDeletion param * Added to context * Fix review comments * Only offer swipe deletion if count of swipes > 1 * Improve array check * Fix generation broken after message deleted * Use named constant for confirmation result * Save chat immediately --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

dcab740b99eaa0358c9f9dce4ff2409b7f2d8e4e

bmen25124 <bmen25124@gmail.com>

Signed
2 files changed, +68 -41Showing whitespace changes
public/script.js+66 -41
@@ -1467,6 +1467,68 @@ export async function deleteLastMessage() {
1467 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);1467 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
1468}1468}
14691469
1470/**
1471 * Deletes a message from the chat by its ID, optionally asking for confirmation.
1472 * @param {number} id The ID of the message to delete.
1473 * @param {number} [swipeDeletionIndex] Deletes the swipe with that index.
1474 * @param {boolean} [askConfirmation=false] Whether to ask for confirmation before deleting.
1475 */
1476export async function deleteMessage(id, swipeDeletionIndex = undefined, askConfirmation = false) {
1477 if (swipeDeletionIndex !== undefined) {
1478 if (swipeDeletionIndex < 0) {
1479 throw new Error('Swipe index cannot be negative');
1480 }
1481 if (!Array.isArray(chat[id].swipes)) {
1482 throw new Error('Message has no swipes to delete');
1483 }
1484 if (chat[id].swipes.length <= swipeDeletionIndex) {
1485 throw new Error('Swipe index out of bounds');
1486 }
1487 }
1488
1489 const messageElement = chatElement.find(`.mes[mesid="${id}"]`);
1490 if (messageElement.length === 0) {
1491 return;
1492 }
1493
1494 const canDeleteSwipe = swipeDeletionIndex !== undefined;
1495 let deleteOnlySwipe = canDeleteSwipe;
1496 if (askConfirmation) {
1497 const result = await callGenericPopup(t`Are you sure you want to delete this message?`, POPUP_TYPE.CONFIRM, null, {
1498 okButton: canDeleteSwipe ? t`Delete Swipe` : t`Delete Message`,
1499 cancelButton: 'Cancel',
1500 customButtons: canDeleteSwipe ? [t`Delete Message`] : null,
1501 });
1502 if (!result) {
1503 return;
1504 }
1505 deleteOnlySwipe = canDeleteSwipe && result === POPUP_RESULT.AFFIRMATIVE; // Default button, not the custom one
1506 }
1507
1508 if (deleteOnlySwipe) {
1509 await deleteSwipe(swipeDeletionIndex, id);
1510 return;
1511 }
1512
1513 chat.splice(id, 1);
1514 messageElement.remove();
1515
1516 chat_metadata['tainted'] = true;
1517
1518 const startFromZero = id === 0;
1519 updateViewMessageIds(startFromZero);
1520 await saveChatConditional();
1521
1522 if (this_edit_mes_id === id) {
1523 this_edit_mes_id = undefined;
1524 }
1525
1526 hideSwipeButtons();
1527 showSwipeButtons();
1528
1529 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
1530}
1531
1470export async function reloadCurrentChat() {1532export async function reloadCurrentChat() {
1471 preserveNeutralChat();1533 preserveNeutralChat();
1472 await clearChat();1534 await clearChat();
@@ -10531,48 +10593,11 @@ jQuery(async function () {
1053110593
10532 $(document).on('click', '.mes_edit_delete', async function (event, customData) {10594 $(document).on('click', '.mes_edit_delete', async function (event, customData) {
10533 const fromSlashCommand = customData?.fromSlashCommand || false;10595 const fromSlashCommand = customData?.fromSlashCommand || false;
10534 const canDeleteSwipe = (Array.isArray(chat[this_edit_mes_id].swipes) && chat[this_edit_mes_id].swipes.length > 1 && !chat[this_edit_mes_id].is_user && Number(this_edit_mes_id) === chat.length - 1);
10535
10536 let deleteOnlySwipe = false;
10537 if (power_user.confirm_message_delete && fromSlashCommand !== true) {
10538 const result = await callGenericPopup(t`Are you sure you want to delete this message?`, POPUP_TYPE.CONFIRM, null, {
10539 okButton: canDeleteSwipe ? t`Delete Swipe` : t`Delete Message`,
10540 cancelButton: 'Cancel',
10541 customButtons: canDeleteSwipe ? [t`Delete Message`] : null,
10542 });
10543 if (!result) {
10544 return;
10545 }
10546 deleteOnlySwipe = canDeleteSwipe && result === 1; // Default button, not the custom one
10547 }
10548
10549 const messageElement = $(this).closest('.mes');
10550 if (!messageElement) {
10551 return;
10552 }
10553
10554 if (deleteOnlySwipe) {
10555 const message = chat[this_edit_mes_id];10596 const message = chat[this_edit_mes_id];
10556 const swipe_id = message.swipe_id;10597 const selectedSwipe = message['swipe_id'] ?? undefined;
10557 await deleteSwipe(swipe_id, Number(this_edit_mes_id));10598 const swipesArray = Array.isArray(message['swipes']) ? message['swipes'] : [];
10558 return;10599 const canDeleteSwipe = !message.is_user && swipesArray.length > 1 && this_edit_mes_id === chat.length - 1 && selectedSwipe !== undefined;
10559 }10600 await deleteMessage(Number(this_edit_mes_id), canDeleteSwipe ? selectedSwipe : undefined, power_user.confirm_message_delete && fromSlashCommand !== true);
10560
10561 chat.splice(this_edit_mes_id, 1);
10562 messageElement.remove();
10563
10564 let startFromZero = Number(this_edit_mes_id) === 0;
10565
10566 this_edit_mes_id = undefined;
10567 chat_metadata['tainted'] = true;
10568
10569 updateViewMessageIds(startFromZero);
10570 saveChatDebounced();
10571
10572 hideSwipeButtons();
10573 showSwipeButtons();
10574
10575 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
10576 });10601 });
1057710602
10578 $(document).on('click', '.mes_edit_done', async function () {10603 $(document).on('click', '.mes_edit_done', async function () {
public/scripts/st-context.js+2 -0
@@ -55,6 +55,7 @@ import {
55 generateRaw,55 generateRaw,
56 showSwipeButtons,56 showSwipeButtons,
57 hideSwipeButtons,57 hideSwipeButtons,
58 deleteMessage,
58} from '../script.js';59} from '../script.js';
59import {60import {
60 extension_settings,61 extension_settings,
@@ -119,6 +120,7 @@ export function getContext() {
119 eventTypes: event_types,120 eventTypes: event_types,
120 addOneMessage,121 addOneMessage,
121 deleteLastMessage,122 deleteLastMessage,
123 deleteMessage,
122 generate: Generate,124 generate: Generate,
123 sendStreamingRequest,125 sendStreamingRequest,
124 sendGenerationRequest,126 sendGenerationRequest,