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() {
14671467 await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
14681468}
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+ */
1476+export 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+
14701532export async function reloadCurrentChat() {
14711533 preserveNeutralChat();
14721534 await clearChat();
@@ -10531,48 +10593,11 @@ jQuery(async function () {
1053110593
1053210594 $(document).on('click', '.mes_edit_delete', async function (event, customData) {
1053310595 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) {
1055510596 const message = chat[this_edit_mes_id];
1055610597 const swipe_idselectedSwipe = 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);
1057610601 });
1057710602
1057810603 $(document).on('click', '.mes_edit_done', async function () {
public/scripts/st-context.js+2 -0
@@ -55,6 +55,7 @@ import {
5555 generateRaw,
5656 showSwipeButtons,
5757 hideSwipeButtons,
58+ deleteMessage,
5859} from '../script.js';
5960import {
6061 extension_settings,
@@ -119,6 +120,7 @@ export function getContext() {
119120 eventTypes: event_types,
120121 addOneMessage,
121122 deleteLastMessage,
123+ deleteMessage,
122124 generate: Generate,
123125 sendStreamingRequest,
124126 sendGenerationRequest,