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>
Signed| @@ -1467,6 +1467,68 @@ export async function deleteLastMessage() { | ||
| 1467 | 1467 | await eventSource.emit(event_types.MESSAGE_DELETED, chat.length); |
| 1468 | 1468 | } |
| 1469 | 1469 | |
| 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 | + | |
| 1470 | 1532 | export async function reloadCurrentChat() { |
| 1471 | 1533 | preserveNeutralChat(); |
| 1472 | 1534 | await clearChat(); |
| @@ -10531,48 +10593,11 @@ jQuery(async function () { | ||
| 10531 | 10593 | |
| 10532 | 10594 | $(document).on('click', '.mes_edit_delete', async function (event, customData) { |
| 10533 | 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); | |
| 10596 | + const message = chat[this_edit_mes_id]; | |
| 10535 | - | |
| 10597 | + const selectedSwipe = message['swipe_id'] ?? undefined; | |
| 10536 | - let deleteOnlySwipe = false; | |
| 10598 | + const swipesArray = Array.isArray(message['swipes']) ? message['swipes'] : []; | |
| 10537 | - if (power_user.confirm_message_delete && fromSlashCommand !== true) { | |
| 10599 | + const canDeleteSwipe = !message.is_user && swipesArray.length > 1 && this_edit_mes_id === chat.length - 1 && selectedSwipe !== undefined; | |
| 10538 | - const result = await callGenericPopup(t`Are you sure you want to delete this message?`, POPUP_TYPE.CONFIRM, null, { | |
| 10600 | + await deleteMessage(Number(this_edit_mes_id), canDeleteSwipe ? selectedSwipe : undefined, power_user.confirm_message_delete && fromSlashCommand !== true); | |
| 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]; | |
| 10556 | - const swipe_id = message.swipe_id; | |
| 10557 | - await deleteSwipe(swipe_id, Number(this_edit_mes_id)); | |
| 10558 | - return; | |
| 10559 | - } | |
| 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 | }); |
| 10577 | 10602 | |
| 10578 | 10603 | $(document).on('click', '.mes_edit_done', async function () { |
| @@ -55,6 +55,7 @@ import { | ||
| 55 | 55 | generateRaw, |
| 56 | 56 | showSwipeButtons, |
| 57 | 57 | hideSwipeButtons, |
| 58 | + deleteMessage, | |
| 58 | 59 | } from '../script.js'; |
| 59 | 60 | import { |
| 60 | 61 | extension_settings, |
| @@ -119,6 +120,7 @@ export function getContext() { | ||
| 119 | 120 | eventTypes: event_types, |
| 120 | 121 | addOneMessage, |
| 121 | 122 | deleteLastMessage, |
| 123 | + deleteMessage, | |
| 122 | 124 | generate: Generate, |
| 123 | 125 | sendStreamingRequest, |
| 124 | 126 | sendGenerationRequest, |