From 117d99eb4ac36ef5c57aa21f6b4e4b76b867a533 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 10 Oct 2025 10:03:58 +0530 Subject: [PATCH 1/7] feat: add optional support of delete message for me --- examples/ExpoMessaging/app/index.tsx | 10 ++++++++-- .../ExpoMessaging/components/ChatWrapper.tsx | 2 +- package/src/components/Channel/Channel.tsx | 3 +++ .../Channel/hooks/useCreateMessagesContext.ts | 2 ++ package/src/components/Message/Message.tsx | 6 ++++++ .../Message/hooks/useMessageActionHandlers.ts | 20 ++++++++++++++++++- .../Message/hooks/useMessageActions.tsx | 20 +++++++++++++++++++ .../messagesContext/MessagesContext.tsx | 2 ++ package/src/i18n/en.json | 1 + package/src/i18n/es.json | 1 + package/src/i18n/fr.json | 1 + package/src/i18n/he.json | 1 + package/src/i18n/hi.json | 1 + package/src/i18n/it.json | 1 + package/src/i18n/ja.json | 1 + package/src/i18n/ko.json | 1 + package/src/i18n/nl.json | 1 + package/src/i18n/pt-br.json | 1 + package/src/i18n/ru.json | 1 + package/src/i18n/tr.json | 1 + package/src/store/SqliteClient.ts | 2 +- package/src/store/apis/softDeleteMessage.ts | 12 +++++------ .../src/store/mappers/mapMessageToStorable.ts | 2 ++ .../src/store/mappers/mapStorableToMessage.ts | 2 ++ package/src/store/schema.ts | 2 ++ 25 files changed, 86 insertions(+), 11 deletions(-) diff --git a/examples/ExpoMessaging/app/index.tsx b/examples/ExpoMessaging/app/index.tsx index 14742ae6ea..e484cccbfa 100644 --- a/examples/ExpoMessaging/app/index.tsx +++ b/examples/ExpoMessaging/app/index.tsx @@ -1,5 +1,5 @@ import { Alert, Image, Pressable, StyleSheet, View } from 'react-native'; -import { ChannelList } from 'stream-chat-expo'; +import { ChannelList, SqliteClient } from 'stream-chat-expo'; import { useCallback, useContext, useMemo } from 'react'; import { Stack, useRouter } from 'expo-router'; import { ChannelSort } from 'stream-chat'; @@ -19,7 +19,13 @@ const LogoutButton = () => { const onLogoutHandler = useCallback(() => { Alert.alert('Logout', 'Are you sure you want to logout?', [ { text: 'Cancel', style: 'cancel' }, - { text: 'Logout', onPress: logOut }, + { + text: 'Logout', + onPress: () => { + SqliteClient.resetDB(); + logOut(); + }, + }, ]); }, [logOut]); diff --git a/examples/ExpoMessaging/components/ChatWrapper.tsx b/examples/ExpoMessaging/components/ChatWrapper.tsx index 4054f9edc6..d0bf6eff10 100644 --- a/examples/ExpoMessaging/components/ChatWrapper.tsx +++ b/examples/ExpoMessaging/components/ChatWrapper.tsx @@ -46,7 +46,7 @@ export const ChatWrapper = ({ children }: PropsWithChildren<{}>) => { return ( - + {children} diff --git a/package/src/components/Channel/Channel.tsx b/package/src/components/Channel/Channel.tsx index 523e2d7297..8844c777a2 100644 --- a/package/src/components/Channel/Channel.tsx +++ b/package/src/components/Channel/Channel.tsx @@ -321,6 +321,7 @@ export type ChannelPropsWithContext = Pick & | 'giphyVersion' | 'handleBan' | 'handleCopy' + | 'handleDeleteForMe' | 'handleDelete' | 'handleEdit' | 'handleFlag' @@ -579,6 +580,7 @@ const ChannelWithContext = (props: PropsWithChildren) = handleAttachButtonPress, handleBan, handleCopy, + handleDeleteForMe, handleDelete, handleEdit, handleFlag, @@ -1837,6 +1839,7 @@ const ChannelWithContext = (props: PropsWithChildren) = handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, diff --git a/package/src/components/Channel/hooks/useCreateMessagesContext.ts b/package/src/components/Channel/hooks/useCreateMessagesContext.ts index 71f3e02795..3ac1e7236d 100644 --- a/package/src/components/Channel/hooks/useCreateMessagesContext.ts +++ b/package/src/components/Channel/hooks/useCreateMessagesContext.ts @@ -33,6 +33,7 @@ export const useCreateMessagesContext = ({ handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -150,6 +151,7 @@ export const useCreateMessagesContext = ({ handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, diff --git a/package/src/components/Message/Message.tsx b/package/src/components/Message/Message.tsx index 1f10124150..bc9df95e0e 100644 --- a/package/src/components/Message/Message.tsx +++ b/package/src/components/Message/Message.tsx @@ -155,6 +155,7 @@ export type MessagePropsWithContext = Pick< | 'handleBan' | 'handleCopy' | 'handleDelete' + | 'handleDeleteForMe' | 'handleEdit' | 'handleFlag' | 'handleMarkUnread' @@ -228,6 +229,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { groupStyles = ['bottom'], handleBan, handleCopy, + handleDeleteForMe, handleDelete, handleEdit, handleFlag, @@ -508,12 +510,14 @@ const MessageWithContext = (props: MessagePropsWithContext) => { setEditingState, setQuotedMessage, supportedReactions, + updateMessage, }); const { banUser, copyMessage, deleteMessage, + deleteForMeMessage, editMessage, flagMessage, handleReaction, @@ -534,6 +538,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -565,6 +570,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { : messageActionsProp({ banUser, copyMessage, + deleteForMe: deleteForMeMessage, deleteMessage, dismissOverlay, editMessage, diff --git a/package/src/components/Message/hooks/useMessageActionHandlers.ts b/package/src/components/Message/hooks/useMessageActionHandlers.ts index 3f835dca3c..d458402449 100644 --- a/package/src/components/Message/hooks/useMessageActionHandlers.ts +++ b/package/src/components/Message/hooks/useMessageActionHandlers.ts @@ -19,9 +19,15 @@ export const useMessageActionHandlers = ({ sendReaction, setEditingState, setQuotedMessage, + updateMessage, }: Pick< MessagesContextValue, - 'sendReaction' | 'deleteMessage' | 'deleteReaction' | 'retrySendMessage' | 'supportedReactions' + | 'sendReaction' + | 'deleteMessage' + | 'updateMessage' + | 'deleteReaction' + | 'retrySendMessage' + | 'supportedReactions' > & Pick & Pick & @@ -66,6 +72,17 @@ export const useMessageActionHandlers = ({ ); }; + const handleDeleteForMeMessage = async () => { + try { + const { message: deletedMessage } = await client.deleteMessage(message.id, { + deleteForMe: true, + }); + updateMessage(deletedMessage); + } catch (error) { + console.log('Error deleting message for me:', error); + } + }; + const handleToggleMuteUser = async () => { if (!message.user?.id) { return; @@ -182,6 +199,7 @@ export const useMessageActionHandlers = ({ return { handleCopyMessage, + handleDeleteForMeMessage, handleDeleteMessage, handleEditMessage, handleFlagMessage, diff --git a/package/src/components/Message/hooks/useMessageActions.tsx b/package/src/components/Message/hooks/useMessageActions.tsx index 7f45b451ec..49fdf38051 100644 --- a/package/src/components/Message/hooks/useMessageActions.tsx +++ b/package/src/components/Message/hooks/useMessageActions.tsx @@ -38,6 +38,7 @@ export type MessageActionsHookProps = Pick< | 'sendReaction' | 'handleBan' | 'handleCopy' + | 'handleDeleteForMe' | 'handleDelete' | 'handleEdit' | 'handleFlag' @@ -72,6 +73,7 @@ export const useMessageActions = ({ enforceUniqueReaction, handleBan, handleCopy, + handleDeleteForMe, handleDelete, handleEdit, handleFlag, @@ -92,6 +94,7 @@ export const useMessageActions = ({ supportedReactions, t, setQuotedMessage, + updateMessage, }: MessageActionsHookProps) => { const { theme: { @@ -100,6 +103,7 @@ export const useMessageActions = ({ } = useTheme(); const { handleCopyMessage, + handleDeleteForMeMessage, handleDeleteMessage, handleEditMessage, handleFlagMessage, @@ -122,6 +126,7 @@ export const useMessageActions = ({ setEditingState, setQuotedMessage, supportedReactions, + updateMessage, }); const error = message.type === 'error' || message.status === MessageStatusTypes.FAILED; @@ -182,6 +187,20 @@ export const useMessageActions = ({ titleStyle: { color: accent_red }, }; + const deleteForMeMessage: MessageActionType = { + action: () => { + dismissOverlay(); + if (handleDeleteForMe) { + handleDeleteForMe(message); + } + handleDeleteForMeMessage(); + }, + actionType: 'deleteForMe', + icon: , + title: t('Delete for me'), + titleStyle: { color: accent_red }, + }; + const editMessage: MessageActionType = { action: () => { dismissOverlay(); @@ -319,6 +338,7 @@ export const useMessageActions = ({ return { banUser, copyMessage, + deleteForMeMessage, deleteMessage, editMessage, flagMessage, diff --git a/package/src/contexts/messagesContext/MessagesContext.tsx b/package/src/contexts/messagesContext/MessagesContext.tsx index f919028760..5f08dca2ed 100644 --- a/package/src/contexts/messagesContext/MessagesContext.tsx +++ b/package/src/contexts/messagesContext/MessagesContext.tsx @@ -404,6 +404,8 @@ export type MessagesContextValue = Pick Promise; /** Handler to access when a copy message action is invoked */ handleCopy?: (message: LocalMessage) => Promise; + /** Handler to access when a delete for me message action is invoked */ + handleDeleteForMe?: (message: LocalMessage) => Promise; /** Handler to access when a delete message action is invoked */ handleDelete?: (message: LocalMessage) => Promise; /** Handler to access when an edit message action is invoked */ diff --git a/package/src/i18n/en.json b/package/src/i18n/en.json index 3e9465eda0..9837a87b65 100644 --- a/package/src/i18n/en.json +++ b/package/src/i18n/en.json @@ -23,6 +23,7 @@ "Create Poll": "Create Poll", "Delete": "Delete", "Delete Message": "Delete Message", + "Delete for me": "Delete for me", "Device camera is used to take photos or videos.": "Device camera is used to take photos or videos.", "Device gallery permissions is used to take photos or videos.": "Device gallery permissions is used to take photos or videos.", "Do you want to send a copy of this message to a moderator for further investigation?": "Do you want to send a copy of this message to a moderator for further investigation?", diff --git a/package/src/i18n/es.json b/package/src/i18n/es.json index 74657b6a1b..4daf4147d7 100644 --- a/package/src/i18n/es.json +++ b/package/src/i18n/es.json @@ -23,6 +23,7 @@ "Create Poll": "Crear encuesta", "Delete": "Eliminar", "Delete Message": "Eliminar mensaje", + "Delete for me": "Eliminar para mí", "Device camera is used to take photos or videos.": "La cámara del dispositivo se utiliza para tomar fotografías o vídeos.", "Device gallery permissions is used to take photos or videos.": "Los permisos de la galería del dispositivo se utilizan para tomar fotos o videos.", "Do you want to send a copy of this message to a moderator for further investigation?": "¿Deseas enviar una copia de este mensaje a un moderador para una investigación adicional?", diff --git a/package/src/i18n/fr.json b/package/src/i18n/fr.json index 7ac6cfe1ea..3227ab9290 100644 --- a/package/src/i18n/fr.json +++ b/package/src/i18n/fr.json @@ -23,6 +23,7 @@ "Create Poll": "Créer un sondage", "Delete": "Supprimer", "Delete Message": "Supprimer un message", + "Delete for me": "Supprimer pour moi", "Device camera is used to take photos or videos.": "L'appareil photo de l'appareil est utilisé pour prendre des photos ou des vidéos.", "Device gallery permissions is used to take photos or videos.": "Les autorisations de la galerie de l'appareil sont utilisées pour prendre des photos ou des vidéos.", "Do you want to send a copy of this message to a moderator for further investigation?": "Voulez-vous envoyer une copie de ce message à un modérateur pour une enquête plus approfondie?", diff --git a/package/src/i18n/he.json b/package/src/i18n/he.json index 2e913471ee..376f6294eb 100644 --- a/package/src/i18n/he.json +++ b/package/src/i18n/he.json @@ -23,6 +23,7 @@ "Create Poll": "צור סקר", "Delete": "מחק", "Delete Message": "מחק/י הודעה", + "Delete for me": "מחק עבורי", "Device camera is used to take photos or videos.": "מצלמת המכשיר משמשת לצילום תמונות או סרטונים.", "Device gallery permissions is used to take photos or videos.": "הרשאות גלריית המכשיר משמשות לצילום תמונות או סרטונים.", "Do you want to send a copy of this message to a moderator for further investigation?": "האם את/ה רוצה לשלוח עותק של הודעה זו למנחה להמשך חקירה?", diff --git a/package/src/i18n/hi.json b/package/src/i18n/hi.json index 5f2b5bcb4a..2ea6b2a80d 100644 --- a/package/src/i18n/hi.json +++ b/package/src/i18n/hi.json @@ -23,6 +23,7 @@ "Create Poll": "सर्वेक्षण बनाएं", "Delete": "हटाएं", "Delete Message": "मैसेज को डिलीट करे", + "Delete for me": "मुझे हटाएं", "Device camera is used to take photos or videos.": "डिवाइस कैमरे का उपयोग फ़ोटो या वीडियो लेने के लिए किया जाता है।", "Device gallery permissions is used to take photos or videos.": "डिवाइस गैलरी की अनुमतियों का उपयोग फोटो या वीडियो लेने के लिए किया जाता है।", "Do you want to send a copy of this message to a moderator for further investigation?": "क्या आप इस संदेश की एक प्रति आगे की जाँच के लिए किसी मॉडरेटर को भेजना चाहते हैं?", diff --git a/package/src/i18n/it.json b/package/src/i18n/it.json index 728d8a44d5..e89c76d4ba 100644 --- a/package/src/i18n/it.json +++ b/package/src/i18n/it.json @@ -23,6 +23,7 @@ "Create Poll": "Crea sondaggio", "Delete": "Elimina", "Delete Message": "Cancella il Messaggio", + "Delete for me": "Elimina per me", "Device camera is used to take photos or videos.": "La fotocamera del dispositivo viene utilizzata per scattare foto o video.", "Device gallery permissions is used to take photos or videos.": "Le autorizzazioni della galleria del dispositivo vengono utilizzate per scattare foto o video.", "Do you want to send a copy of this message to a moderator for further investigation?": "Vuoi inviare una copia di questo messaggio a un moderatore per ulteriori indagini?", diff --git a/package/src/i18n/ja.json b/package/src/i18n/ja.json index 099a53591d..4394088f31 100644 --- a/package/src/i18n/ja.json +++ b/package/src/i18n/ja.json @@ -23,6 +23,7 @@ "Create Poll": "アンケートを作成", "Delete": "消去", "Delete Message": "メッセージを削除", + "Delete for me": "自分で削除", "Device camera is used to take photos or videos.": "デバイスのカメラは写真やビデオの撮影に使用されます。", "Device gallery permissions is used to take photos or videos.": "デバイスギャラリーの権限は写真やビデオを撮るために使用されます。", "Do you want to send a copy of this message to a moderator for further investigation?": "このメッセージのコピーをモデレーターに送信して、さらに調査しますか?", diff --git a/package/src/i18n/ko.json b/package/src/i18n/ko.json index c297cbd67b..a9d61ef72a 100644 --- a/package/src/i18n/ko.json +++ b/package/src/i18n/ko.json @@ -23,6 +23,7 @@ "Create Poll": "투표 생성", "Delete": "삭제", "Delete Message": "메시지 삭제", + "Delete for me": "나 삭제", "Device camera is used to take photos or videos.": "기기 카메라는 사진이나 동영상을 촬영하는 데 사용됩니다.", "Device gallery permissions is used to take photos or videos.": "장치 갤러리 권한은 사진 또는 비디오를 촬영하는 데 사용됩니다.", "Do you want to send a copy of this message to a moderator for further investigation?": "이 메시지의 복사본을 운영자에게 보내 추가 조사를합니까?", diff --git a/package/src/i18n/nl.json b/package/src/i18n/nl.json index 0c68500e11..eada070bd6 100644 --- a/package/src/i18n/nl.json +++ b/package/src/i18n/nl.json @@ -23,6 +23,7 @@ "Create Poll": "Peiling aanmaken", "Delete": "Verwijderen", "Delete Message": "Verwijder bericht", + "Delete for me": "Verwijder voor mij", "Device camera is used to take photos or videos.": "De camera van het apparaat wordt gebruikt om foto's of video's te maken.", "Device gallery permissions is used to take photos or videos.": "Apparaatgallerijmachtigingen worden gebruikt om foto’s of video’s te maken.", "Do you want to send a copy of this message to a moderator for further investigation?": "Wil je een kopie van dit bericht naar een moderator sturen voor verder onderzoek?", diff --git a/package/src/i18n/pt-br.json b/package/src/i18n/pt-br.json index d8e975f378..4fb3d21991 100644 --- a/package/src/i18n/pt-br.json +++ b/package/src/i18n/pt-br.json @@ -23,6 +23,7 @@ "Create Poll": "Criar enquete", "Delete": "Excluir", "Delete Message": "Excluir Mensagem", + "Delete for me": "Excluir para mim", "Device camera is used to take photos or videos.": "A câmera do dispositivo é usada para tirar fotos ou vídeos.", "Device gallery permissions is used to take photos or videos.": "As permissões da galeria do dispositivo são usadas para tirar fotos ou vídeos.", "Do you want to send a copy of this message to a moderator for further investigation?": "Deseja enviar uma cópia desta mensagem para um moderador para investigação adicional?", diff --git a/package/src/i18n/ru.json b/package/src/i18n/ru.json index ea29cf9806..5f4a81f7e5 100644 --- a/package/src/i18n/ru.json +++ b/package/src/i18n/ru.json @@ -24,6 +24,7 @@ "Create Poll": "Создать опрос", "Delete": "удалять", "Delete Message": "Удалить сообщение", + "Delete for me": "Удалить для себя", "Device camera is used to take photos or videos.": "Камера устройства используется для съемки фотографий или видео.", "Device gallery permissions is used to take photos or videos.": "Разрешения галереи устройства используются для съемки фото или видео.", "Do you want to send a copy of this message to a moderator for further investigation?": "Вы хотите отправить копию этого сообщения модератору для дальнейшего изучения?", diff --git a/package/src/i18n/tr.json b/package/src/i18n/tr.json index 3305b84b6a..6f2b955938 100644 --- a/package/src/i18n/tr.json +++ b/package/src/i18n/tr.json @@ -23,6 +23,7 @@ "Create Poll": "Anket oluştur", "Delete": "Sil", "Delete Message": "Mesajı Sil", + "Delete for me": "Benim için sil", "Device camera is used to take photos or videos.": "Cihaz kamerası fotoğraf veya video çekmek için kullanılır.", "Device gallery permissions is used to take photos or videos.": "Cihaz galerisi izinleri fotoğraf veya video çekmek için kullanılır.", "Do you want to send a copy of this message to a moderator for further investigation?": "Detaylı inceleme için bu mesajın kopyasını moderatöre göndermek istiyor musunuz?", diff --git a/package/src/store/SqliteClient.ts b/package/src/store/SqliteClient.ts index 74380960c6..103eaa25e0 100644 --- a/package/src/store/SqliteClient.ts +++ b/package/src/store/SqliteClient.ts @@ -28,7 +28,7 @@ import type { PreparedBatchQueries, PreparedQueries, Scalar, Table } from './typ * This way usage @op-engineering/op-sqlite package is scoped to a single class/file. */ export class SqliteClient { - static dbVersion = 13; + static dbVersion = 14; static dbName = DB_NAME; static dbLocation = DB_LOCATION; diff --git a/package/src/store/apis/softDeleteMessage.ts b/package/src/store/apis/softDeleteMessage.ts index e88964f358..ce9c99a104 100644 --- a/package/src/store/apis/softDeleteMessage.ts +++ b/package/src/store/apis/softDeleteMessage.ts @@ -1,25 +1,25 @@ -import { MessageLabel } from 'stream-chat'; +import { DBDeleteMessageType, MessageLabel } from 'stream-chat'; import { createUpdateQuery } from '../sqlite-utils/createUpdateQuery'; import { SqliteClient } from '../SqliteClient'; export const softDeleteMessage = async ({ + deleteForMe = false, execute = true, id, -}: { - id: string; - execute?: boolean; -}) => { +}: DBDeleteMessageType) => { const query = createUpdateQuery( 'messages', { - deletedAt: new Date().toISOString(), + deletedAt: deleteForMe ? undefined : new Date().toISOString(), + deletedForMe: deleteForMe, type: 'deleted' as MessageLabel, }, { id }, ); SqliteClient.logger?.('info', 'softDeleteMessage', { + deleteForMe, execute, id, }); diff --git a/package/src/store/mappers/mapMessageToStorable.ts b/package/src/store/mappers/mapMessageToStorable.ts index f307355af2..ac166d7c98 100644 --- a/package/src/store/mappers/mapMessageToStorable.ts +++ b/package/src/store/mappers/mapMessageToStorable.ts @@ -12,6 +12,7 @@ export const mapMessageToStorable = ( cid, created_at, deleted_at, + deleted_for_me, id, // eslint-disable-next-line @typescript-eslint/no-unused-vars latest_reactions, @@ -37,6 +38,7 @@ export const mapMessageToStorable = ( cid: cid || '', createdAt: mapDateTimeToStorable(created_at), deletedAt: mapDateTimeToStorable(deleted_at), + deletedForMe: deleted_for_me, extraData: JSON.stringify(extraData), id, messageTextUpdatedAt: mapDateTimeToStorable(message_text_updated_at), diff --git a/package/src/store/mappers/mapStorableToMessage.ts b/package/src/store/mappers/mapStorableToMessage.ts index 30ca649ee5..e4b6459466 100644 --- a/package/src/store/mappers/mapStorableToMessage.ts +++ b/package/src/store/mappers/mapStorableToMessage.ts @@ -24,6 +24,7 @@ export const mapStorableToMessage = ({ const { createdAt, deletedAt, + deletedForMe, extraData, messageTextUpdatedAt, poll_id, @@ -42,6 +43,7 @@ export const mapStorableToMessage = ({ attachments: messageRow.attachments ? JSON.parse(messageRow.attachments) : [], created_at: createdAt, deleted_at: deletedAt, + deleted_for_me: deletedForMe, latest_reactions: latestReactions, message_text_updated_at: messageTextUpdatedAt, own_reactions: ownReactions, diff --git a/package/src/store/schema.ts b/package/src/store/schema.ts index 50ec7ee2aa..21de2afed4 100644 --- a/package/src/store/schema.ts +++ b/package/src/store/schema.ts @@ -170,6 +170,7 @@ export const tables: Tables = { cid: 'TEXT NOT NULL', createdAt: 'TEXT', deletedAt: 'TEXT', + deletedForMe: 'BOOLEAN DEFAULT FALSE', extraData: 'TEXT', id: 'TEXT', messageTextUpdatedAt: 'TEXT', @@ -408,6 +409,7 @@ export type Schema = { cid: string; createdAt: string; deletedAt: string; + deletedForMe?: boolean; extraData: string; id: string; messageTextUpdatedAt: string; From 75b42817a9f7f2b59636c2f4647a86be202a3aa2 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 10 Oct 2025 10:04:21 +0530 Subject: [PATCH 2/7] feat: add optional support of delete message for me --- package/src/components/Message/utils/messageActions.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package/src/components/Message/utils/messageActions.ts b/package/src/components/Message/utils/messageActions.ts index 8d019238b9..575f6d21da 100644 --- a/package/src/components/Message/utils/messageActions.ts +++ b/package/src/components/Message/utils/messageActions.ts @@ -25,6 +25,8 @@ export type MessageActionsParams = { showMessageReactions: boolean; threadReply: MessageActionType; unpinMessage: MessageActionType; + // Optional Actions + deleteForMe?: MessageActionType; } & Pick; export type MessageActionsProp = (param: MessageActionsParams) => MessageActionType[]; From b1d412b9b50dcec6fe4f26b002824e1f9c897975 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 10 Oct 2025 10:09:52 +0530 Subject: [PATCH 3/7] fix: update stream-chat package --- package/package.json | 2 +- package/yarn.lock | 30 ++++++++++-------------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/package/package.json b/package/package.json index 99ba8839f6..350cf0c05c 100644 --- a/package/package.json +++ b/package/package.json @@ -79,7 +79,7 @@ "path": "0.12.7", "react-native-markdown-package": "1.8.2", "react-native-url-polyfill": "^2.0.0", - "stream-chat": "^9.17.0", + "stream-chat": "^9.22.0", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { diff --git a/package/yarn.lock b/package/yarn.lock index b2258ec83a..392dd67647 100644 --- a/package/yarn.lock +++ b/package/yarn.lock @@ -2956,13 +2956,13 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -axios@^1.6.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.1.tgz#7c118d2146e9ebac512b7d1128771cdd738d11e3" - integrity sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g== +axios@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7" + integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw== dependencies: follow-redirects "^1.15.6" - form-data "^4.0.0" + form-data "^4.0.4" proxy-from-env "^1.1.0" b4a@^1.6.4: @@ -4651,16 +4651,6 @@ foreground-child@^3.1.0: cross-spawn "^7.0.6" signal-exit "^4.0.1" -form-data@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" - integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - es-set-tostringtag "^2.1.0" - mime-types "^2.1.12" - form-data@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" @@ -8354,14 +8344,14 @@ statuses@~1.5.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== -stream-chat@^9.17.0: - version "9.17.0" - resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.17.0.tgz#540cf1ea03b08a394d6140696aae8528e9ba9ce2" - integrity sha512-ys6K73wIVWs5+qsfPJ9wumEUtgbMXYVbH1dhmAZ1oYtQ01dY/avsvt25PYDakVjKeyrnT+y8T/xEzfeF/WDJsg== +stream-chat@^9.22.0: + version "9.22.0" + resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.22.0.tgz#9b4c47974b0bf135fba7bf6122f406f78470f49b" + integrity sha512-7OZVxV+H0Ye8/HCqXlbQCwxgCy/JFA4fMJ7OvmGw1/yoUg/fgzQr827QqPhzPG3arSNV6f0+VT6Dnju8bCvUpQ== dependencies: "@types/jsonwebtoken" "^9.0.8" "@types/ws" "^8.5.14" - axios "^1.6.0" + axios "^1.12.2" base64-js "^1.5.1" form-data "^4.0.4" isomorphic-ws "^5.0.0" From 089577befe8f9512500da4cab837307d2f21148d Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Tue, 14 Oct 2025 11:39:40 +0530 Subject: [PATCH 4/7] fix: add action to sample app only --- .../SampleApp/src/utils/messageActions.tsx | 27 ++++++++++++++++++- package/src/components/Channel/Channel.tsx | 3 --- .../Channel/hooks/useCreateMessagesContext.ts | 2 -- package/src/components/Message/Message.tsx | 6 +---- .../Message/hooks/useMessageActionHandlers.ts | 13 --------- .../Message/hooks/useMessageActions.tsx | 18 ------------- .../Message/utils/messageActions.ts | 6 ++--- .../messagesContext/MessagesContext.tsx | 2 -- 8 files changed, 30 insertions(+), 47 deletions(-) diff --git a/examples/SampleApp/src/utils/messageActions.tsx b/examples/SampleApp/src/utils/messageActions.tsx index e462763e22..3adda3fc04 100644 --- a/examples/SampleApp/src/utils/messageActions.tsx +++ b/examples/SampleApp/src/utils/messageActions.tsx @@ -2,6 +2,7 @@ import { Alert } from 'react-native'; import { StreamChat } from 'stream-chat'; import { Colors, + Delete, messageActions, MessageActionsParams, Time, @@ -20,7 +21,7 @@ export function channelMessageActions({ t: TranslationContextValue['t']; colors?: typeof Colors; }) { - const { dismissOverlay } = params; + const { dismissOverlay, updateMessage } = params; const actions = messageActions(params); // We cannot use the useMessageReminder hook here because it is a hook. @@ -88,6 +89,30 @@ export function channelMessageActions({ title: reminder ? 'Remove Reminder' : 'Remind Me', icon: , }); + actions.push({ + action: async () => { + Alert.alert('Delete for me', 'Are you sure you want to delete this message for me?', [ + { + text: 'Cancel', + style: 'cancel', + }, + { + text: 'Delete', + onPress: async () => { + const { message: deletedMessage } = await chatClient.deleteMessage(params.message.id, { + deleteForMe: true, + }); + updateMessage(deletedMessage); + dismissOverlay(); + }, + style: 'destructive', + }, + ]); + }, + actionType: 'deleteForMe', + icon: , + title: t('Delete for me'), + }); return actions; } diff --git a/package/src/components/Channel/Channel.tsx b/package/src/components/Channel/Channel.tsx index 8844c777a2..523e2d7297 100644 --- a/package/src/components/Channel/Channel.tsx +++ b/package/src/components/Channel/Channel.tsx @@ -321,7 +321,6 @@ export type ChannelPropsWithContext = Pick & | 'giphyVersion' | 'handleBan' | 'handleCopy' - | 'handleDeleteForMe' | 'handleDelete' | 'handleEdit' | 'handleFlag' @@ -580,7 +579,6 @@ const ChannelWithContext = (props: PropsWithChildren) = handleAttachButtonPress, handleBan, handleCopy, - handleDeleteForMe, handleDelete, handleEdit, handleFlag, @@ -1839,7 +1837,6 @@ const ChannelWithContext = (props: PropsWithChildren) = handleBan, handleCopy, handleDelete, - handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, diff --git a/package/src/components/Channel/hooks/useCreateMessagesContext.ts b/package/src/components/Channel/hooks/useCreateMessagesContext.ts index 3ac1e7236d..71f3e02795 100644 --- a/package/src/components/Channel/hooks/useCreateMessagesContext.ts +++ b/package/src/components/Channel/hooks/useCreateMessagesContext.ts @@ -33,7 +33,6 @@ export const useCreateMessagesContext = ({ handleBan, handleCopy, handleDelete, - handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -151,7 +150,6 @@ export const useCreateMessagesContext = ({ handleBan, handleCopy, handleDelete, - handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, diff --git a/package/src/components/Message/Message.tsx b/package/src/components/Message/Message.tsx index bc9df95e0e..15e6d945de 100644 --- a/package/src/components/Message/Message.tsx +++ b/package/src/components/Message/Message.tsx @@ -155,7 +155,6 @@ export type MessagePropsWithContext = Pick< | 'handleBan' | 'handleCopy' | 'handleDelete' - | 'handleDeleteForMe' | 'handleEdit' | 'handleFlag' | 'handleMarkUnread' @@ -229,7 +228,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => { groupStyles = ['bottom'], handleBan, handleCopy, - handleDeleteForMe, handleDelete, handleEdit, handleFlag, @@ -517,7 +515,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => { banUser, copyMessage, deleteMessage, - deleteForMeMessage, editMessage, flagMessage, handleReaction, @@ -538,7 +535,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => { handleBan, handleCopy, handleDelete, - handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -570,7 +566,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => { : messageActionsProp({ banUser, copyMessage, - deleteForMe: deleteForMeMessage, deleteMessage, dismissOverlay, editMessage, @@ -588,6 +583,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { showMessageReactions, threadReply, unpinMessage, + updateMessage, }); const actionHandlers: MessageActionHandlers = { diff --git a/package/src/components/Message/hooks/useMessageActionHandlers.ts b/package/src/components/Message/hooks/useMessageActionHandlers.ts index d458402449..b54772974e 100644 --- a/package/src/components/Message/hooks/useMessageActionHandlers.ts +++ b/package/src/components/Message/hooks/useMessageActionHandlers.ts @@ -19,7 +19,6 @@ export const useMessageActionHandlers = ({ sendReaction, setEditingState, setQuotedMessage, - updateMessage, }: Pick< MessagesContextValue, | 'sendReaction' @@ -72,17 +71,6 @@ export const useMessageActionHandlers = ({ ); }; - const handleDeleteForMeMessage = async () => { - try { - const { message: deletedMessage } = await client.deleteMessage(message.id, { - deleteForMe: true, - }); - updateMessage(deletedMessage); - } catch (error) { - console.log('Error deleting message for me:', error); - } - }; - const handleToggleMuteUser = async () => { if (!message.user?.id) { return; @@ -199,7 +187,6 @@ export const useMessageActionHandlers = ({ return { handleCopyMessage, - handleDeleteForMeMessage, handleDeleteMessage, handleEditMessage, handleFlagMessage, diff --git a/package/src/components/Message/hooks/useMessageActions.tsx b/package/src/components/Message/hooks/useMessageActions.tsx index 49fdf38051..3af7c48717 100644 --- a/package/src/components/Message/hooks/useMessageActions.tsx +++ b/package/src/components/Message/hooks/useMessageActions.tsx @@ -38,7 +38,6 @@ export type MessageActionsHookProps = Pick< | 'sendReaction' | 'handleBan' | 'handleCopy' - | 'handleDeleteForMe' | 'handleDelete' | 'handleEdit' | 'handleFlag' @@ -73,7 +72,6 @@ export const useMessageActions = ({ enforceUniqueReaction, handleBan, handleCopy, - handleDeleteForMe, handleDelete, handleEdit, handleFlag, @@ -103,7 +101,6 @@ export const useMessageActions = ({ } = useTheme(); const { handleCopyMessage, - handleDeleteForMeMessage, handleDeleteMessage, handleEditMessage, handleFlagMessage, @@ -187,20 +184,6 @@ export const useMessageActions = ({ titleStyle: { color: accent_red }, }; - const deleteForMeMessage: MessageActionType = { - action: () => { - dismissOverlay(); - if (handleDeleteForMe) { - handleDeleteForMe(message); - } - handleDeleteForMeMessage(); - }, - actionType: 'deleteForMe', - icon: , - title: t('Delete for me'), - titleStyle: { color: accent_red }, - }; - const editMessage: MessageActionType = { action: () => { dismissOverlay(); @@ -338,7 +321,6 @@ export const useMessageActions = ({ return { banUser, copyMessage, - deleteForMeMessage, deleteMessage, editMessage, flagMessage, diff --git a/package/src/components/Message/utils/messageActions.ts b/package/src/components/Message/utils/messageActions.ts index 575f6d21da..1817e06d94 100644 --- a/package/src/components/Message/utils/messageActions.ts +++ b/package/src/components/Message/utils/messageActions.ts @@ -1,4 +1,5 @@ import type { MessageContextValue } from '../../../contexts/messageContext/MessageContext'; +import type { MessagesContextValue } from '../../../contexts/messagesContext/MessagesContext'; import type { OwnCapabilitiesContextValue } from '../../../contexts/ownCapabilitiesContext/OwnCapabilitiesContext'; import { isClipboardAvailable } from '../../../native'; @@ -25,9 +26,8 @@ export type MessageActionsParams = { showMessageReactions: boolean; threadReply: MessageActionType; unpinMessage: MessageActionType; - // Optional Actions - deleteForMe?: MessageActionType; -} & Pick; +} & Pick & + Pick; export type MessageActionsProp = (param: MessageActionsParams) => MessageActionType[]; diff --git a/package/src/contexts/messagesContext/MessagesContext.tsx b/package/src/contexts/messagesContext/MessagesContext.tsx index 5f08dca2ed..f919028760 100644 --- a/package/src/contexts/messagesContext/MessagesContext.tsx +++ b/package/src/contexts/messagesContext/MessagesContext.tsx @@ -404,8 +404,6 @@ export type MessagesContextValue = Pick Promise; /** Handler to access when a copy message action is invoked */ handleCopy?: (message: LocalMessage) => Promise; - /** Handler to access when a delete for me message action is invoked */ - handleDeleteForMe?: (message: LocalMessage) => Promise; /** Handler to access when a delete message action is invoked */ handleDelete?: (message: LocalMessage) => Promise; /** Handler to access when an edit message action is invoked */ From cfc81abc7f7dc741efd20b599e4917feb70671f5 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Tue, 14 Oct 2025 11:42:18 +0530 Subject: [PATCH 5/7] fix: add action to sample app only --- package/src/components/Message/Message.tsx | 1 - .../components/Message/hooks/useMessageActionHandlers.ts | 7 +------ package/src/components/Message/hooks/useMessageActions.tsx | 2 -- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/package/src/components/Message/Message.tsx b/package/src/components/Message/Message.tsx index 15e6d945de..0aa40f685e 100644 --- a/package/src/components/Message/Message.tsx +++ b/package/src/components/Message/Message.tsx @@ -508,7 +508,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => { setEditingState, setQuotedMessage, supportedReactions, - updateMessage, }); const { diff --git a/package/src/components/Message/hooks/useMessageActionHandlers.ts b/package/src/components/Message/hooks/useMessageActionHandlers.ts index b54772974e..3f835dca3c 100644 --- a/package/src/components/Message/hooks/useMessageActionHandlers.ts +++ b/package/src/components/Message/hooks/useMessageActionHandlers.ts @@ -21,12 +21,7 @@ export const useMessageActionHandlers = ({ setQuotedMessage, }: Pick< MessagesContextValue, - | 'sendReaction' - | 'deleteMessage' - | 'updateMessage' - | 'deleteReaction' - | 'retrySendMessage' - | 'supportedReactions' + 'sendReaction' | 'deleteMessage' | 'deleteReaction' | 'retrySendMessage' | 'supportedReactions' > & Pick & Pick & diff --git a/package/src/components/Message/hooks/useMessageActions.tsx b/package/src/components/Message/hooks/useMessageActions.tsx index 3af7c48717..7f45b451ec 100644 --- a/package/src/components/Message/hooks/useMessageActions.tsx +++ b/package/src/components/Message/hooks/useMessageActions.tsx @@ -92,7 +92,6 @@ export const useMessageActions = ({ supportedReactions, t, setQuotedMessage, - updateMessage, }: MessageActionsHookProps) => { const { theme: { @@ -123,7 +122,6 @@ export const useMessageActions = ({ setEditingState, setQuotedMessage, supportedReactions, - updateMessage, }); const error = message.type === 'error' || message.status === MessageStatusTypes.FAILED; From 06c630a0432f1b8b819592d89bb6db70bb16f75c Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Tue, 14 Oct 2025 16:49:52 +0530 Subject: [PATCH 6/7] fix: how delete for me action is handled on the SDK --- examples/SampleApp/src/utils/messageActions.tsx | 7 ++----- package/src/components/Channel/Channel.tsx | 16 ++++++++++++++-- .../Channel/hooks/useCreateMessagesContext.ts | 2 ++ package/src/components/Message/Message.tsx | 8 ++++++++ .../Message/hooks/useMessageActionHandlers.ts | 9 +++++++++ .../Message/hooks/useMessageActions.tsx | 17 +++++++++++++++++ .../components/Message/utils/messageActions.ts | 2 ++ .../messagesContext/MessagesContext.tsx | 9 ++++++++- 8 files changed, 62 insertions(+), 8 deletions(-) diff --git a/examples/SampleApp/src/utils/messageActions.tsx b/examples/SampleApp/src/utils/messageActions.tsx index 3adda3fc04..7dafc4ff79 100644 --- a/examples/SampleApp/src/utils/messageActions.tsx +++ b/examples/SampleApp/src/utils/messageActions.tsx @@ -21,7 +21,7 @@ export function channelMessageActions({ t: TranslationContextValue['t']; colors?: typeof Colors; }) { - const { dismissOverlay, updateMessage } = params; + const { dismissOverlay, deleteForMeMessage } = params; const actions = messageActions(params); // We cannot use the useMessageReminder hook here because it is a hook. @@ -99,10 +99,7 @@ export function channelMessageActions({ { text: 'Delete', onPress: async () => { - const { message: deletedMessage } = await chatClient.deleteMessage(params.message.id, { - deleteForMe: true, - }); - updateMessage(deletedMessage); + await deleteForMeMessage?.action(); dismissOverlay(); }, style: 'destructive', diff --git a/package/src/components/Channel/Channel.tsx b/package/src/components/Channel/Channel.tsx index 523e2d7297..29ac2ca4b2 100644 --- a/package/src/components/Channel/Channel.tsx +++ b/package/src/components/Channel/Channel.tsx @@ -9,6 +9,7 @@ import { Channel as ChannelClass, ChannelState, Channel as ChannelType, + DeleteMessageOptions, EventHandler, LocalMessage, localMessageToNewMessagePayload, @@ -322,6 +323,7 @@ export type ChannelPropsWithContext = Pick & | 'handleBan' | 'handleCopy' | 'handleDelete' + | 'handleDeleteForMe' | 'handleEdit' | 'handleFlag' | 'handleMarkUnread' @@ -580,6 +582,7 @@ const ChannelWithContext = (props: PropsWithChildren) = handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -1509,7 +1512,15 @@ const ChannelWithContext = (props: PropsWithChildren) = }); const deleteMessage: MessagesContextValue['deleteMessage'] = useStableCallback( - async (message, hardDelete = false) => { + async (message, optionsOrHardDelete = false) => { + let options: DeleteMessageOptions = {}; + if (typeof optionsOrHardDelete === 'boolean') { + options = optionsOrHardDelete ? { hardDelete: true } : {}; + } else if (optionsOrHardDelete?.deleteForMe) { + options = { deleteForMe: true }; + } else if (optionsOrHardDelete?.hardDelete) { + options = { hardDelete: true }; + } if (!channel.id) { throw new Error('Channel has not been initialized yet'); } @@ -1528,7 +1539,7 @@ const ChannelWithContext = (props: PropsWithChildren) = threadInstance?.upsertReplyLocally({ message: updatedMessage }); - const data = await client.deleteMessage(message.id, hardDelete); + const data = await client.deleteMessage(message.id, options); if (data?.message) { updateMessage({ ...data.message }); @@ -1837,6 +1848,7 @@ const ChannelWithContext = (props: PropsWithChildren) = handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, diff --git a/package/src/components/Channel/hooks/useCreateMessagesContext.ts b/package/src/components/Channel/hooks/useCreateMessagesContext.ts index 71f3e02795..3ac1e7236d 100644 --- a/package/src/components/Channel/hooks/useCreateMessagesContext.ts +++ b/package/src/components/Channel/hooks/useCreateMessagesContext.ts @@ -33,6 +33,7 @@ export const useCreateMessagesContext = ({ handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -150,6 +151,7 @@ export const useCreateMessagesContext = ({ handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, diff --git a/package/src/components/Message/Message.tsx b/package/src/components/Message/Message.tsx index 0aa40f685e..6a677616ae 100644 --- a/package/src/components/Message/Message.tsx +++ b/package/src/components/Message/Message.tsx @@ -121,6 +121,7 @@ export type MessagePressableHandlerPayload = PressableHandlerPayload & { export type MessageActionHandlers = { copyMessage: () => void; deleteMessage: () => void; + deleteForMeMessage: () => void; editMessage: () => void; flagMessage: () => void; markUnread: () => Promise; @@ -155,6 +156,7 @@ export type MessagePropsWithContext = Pick< | 'handleBan' | 'handleCopy' | 'handleDelete' + | 'handleDeleteForMe' | 'handleEdit' | 'handleFlag' | 'handleMarkUnread' @@ -229,6 +231,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -487,6 +490,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { const { handleCopyMessage, handleDeleteMessage, + handleDeleteForMeMessage, handleEditMessage, handleFlagMessage, handleMarkUnreadMessage, @@ -514,6 +518,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { banUser, copyMessage, deleteMessage, + deleteForMeMessage, editMessage, flagMessage, handleReaction, @@ -534,6 +539,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -565,6 +571,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { : messageActionsProp({ banUser, copyMessage, + deleteForMeMessage, deleteMessage, dismissOverlay, editMessage, @@ -587,6 +594,7 @@ const MessageWithContext = (props: MessagePropsWithContext) => { const actionHandlers: MessageActionHandlers = { copyMessage: handleCopyMessage, + deleteForMeMessage: handleDeleteForMeMessage, deleteMessage: handleDeleteMessage, editMessage: handleEditMessage, flagMessage: handleFlagMessage, diff --git a/package/src/components/Message/hooks/useMessageActionHandlers.ts b/package/src/components/Message/hooks/useMessageActionHandlers.ts index 3f835dca3c..872cd5e6eb 100644 --- a/package/src/components/Message/hooks/useMessageActionHandlers.ts +++ b/package/src/components/Message/hooks/useMessageActionHandlers.ts @@ -66,6 +66,14 @@ export const useMessageActionHandlers = ({ ); }; + const handleDeleteForMeMessage = async () => { + if (!message.id) { + return; + } + + await deleteMessage(message, { deleteForMe: true }); + }; + const handleToggleMuteUser = async () => { if (!message.user?.id) { return; @@ -182,6 +190,7 @@ export const useMessageActionHandlers = ({ return { handleCopyMessage, + handleDeleteForMeMessage, handleDeleteMessage, handleEditMessage, handleFlagMessage, diff --git a/package/src/components/Message/hooks/useMessageActions.tsx b/package/src/components/Message/hooks/useMessageActions.tsx index 7f45b451ec..9f307f56fd 100644 --- a/package/src/components/Message/hooks/useMessageActions.tsx +++ b/package/src/components/Message/hooks/useMessageActions.tsx @@ -39,6 +39,7 @@ export type MessageActionsHookProps = Pick< | 'handleBan' | 'handleCopy' | 'handleDelete' + | 'handleDeleteForMe' | 'handleEdit' | 'handleFlag' | 'handleQuotedReply' @@ -73,6 +74,7 @@ export const useMessageActions = ({ handleBan, handleCopy, handleDelete, + handleDeleteForMe, handleEdit, handleFlag, handleMarkUnread, @@ -101,6 +103,7 @@ export const useMessageActions = ({ const { handleCopyMessage, handleDeleteMessage, + handleDeleteForMeMessage, handleEditMessage, handleFlagMessage, handleMarkUnreadMessage, @@ -182,6 +185,19 @@ export const useMessageActions = ({ titleStyle: { color: accent_red }, }; + const deleteForMeMessage: MessageActionType = { + action: () => { + dismissOverlay(); + if (handleDeleteForMe) { + handleDeleteForMe(message); + } + handleDeleteForMeMessage(); + }, + actionType: 'deleteForMeMessage', + icon: , + title: t('Delete for me'), + }; + const editMessage: MessageActionType = { action: () => { dismissOverlay(); @@ -319,6 +335,7 @@ export const useMessageActions = ({ return { banUser, copyMessage, + deleteForMeMessage, deleteMessage, editMessage, flagMessage, diff --git a/package/src/components/Message/utils/messageActions.ts b/package/src/components/Message/utils/messageActions.ts index 1817e06d94..d7973cc2db 100644 --- a/package/src/components/Message/utils/messageActions.ts +++ b/package/src/components/Message/utils/messageActions.ts @@ -26,6 +26,8 @@ export type MessageActionsParams = { showMessageReactions: boolean; threadReply: MessageActionType; unpinMessage: MessageActionType; + // Optional Actions + deleteForMeMessage?: MessageActionType; } & Pick & Pick; diff --git a/package/src/contexts/messagesContext/MessagesContext.tsx b/package/src/contexts/messagesContext/MessagesContext.tsx index f919028760..3e5441292c 100644 --- a/package/src/contexts/messagesContext/MessagesContext.tsx +++ b/package/src/contexts/messagesContext/MessagesContext.tsx @@ -7,6 +7,7 @@ import type { Channel, ChannelState, CommandSuggestion, + DeleteMessageOptions, LocalMessage, MessageResponse, } from 'stream-chat'; @@ -114,7 +115,11 @@ export type MessagesContextValue = Pick; - deleteMessage: (message: LocalMessage, hardDelete?: boolean) => Promise; + // FIXME: Remove the signature with optionsOrHardDelete boolean with the next major release + deleteMessage: ( + message: LocalMessage, + optionsOrHardDelete?: boolean | DeleteMessageOptions, + ) => Promise; deleteReaction: (type: string, messageId: string) => Promise; /** Should keyboard be dismissed when messaged is touched */ @@ -404,6 +409,8 @@ export type MessagesContextValue = Pick Promise; /** Handler to access when a copy message action is invoked */ handleCopy?: (message: LocalMessage) => Promise; + /** Handler to access when a delete for me message action is invoked */ + handleDeleteForMe?: (message: LocalMessage) => Promise; /** Handler to access when a delete message action is invoked */ handleDelete?: (message: LocalMessage) => Promise; /** Handler to access when an edit message action is invoked */ From e66469310fac5eac77917564424141ccac31f244 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Wed, 15 Oct 2025 14:51:14 +0530 Subject: [PATCH 7/7] chore: update stream-chat version --- examples/ExpoMessaging/yarn.lock | 17 ++++++++++++++++- examples/SampleApp/yarn.lock | 19 ++++++++++++++----- examples/TypeScriptMessaging/yarn.lock | 19 ++++++++++++++----- package/package.json | 2 +- package/yarn.lock | 8 ++++---- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/examples/ExpoMessaging/yarn.lock b/examples/ExpoMessaging/yarn.lock index e9c8f552bd..96f43cad27 100644 --- a/examples/ExpoMessaging/yarn.lock +++ b/examples/ExpoMessaging/yarn.lock @@ -6063,7 +6063,22 @@ stream-chat-react-native-core@8.1.0: version "0.0.0" uid "" -stream-chat@^9.17.0, stream-chat@^9.9.0: +stream-chat@^9.23.0: + version "9.23.0" + resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.23.0.tgz#e7e5cf729861597e7198907c1cab22a57d68a2fc" + integrity sha512-UW112HYsLnYb4RMIXBtAouNQCCe0weVzNivjezsw+JKK1b/TX0JLBi+wK25mBUEO+coOGKfXiye6IB3gao8ipw== + dependencies: + "@types/jsonwebtoken" "^9.0.8" + "@types/ws" "^8.5.14" + axios "^1.12.2" + base64-js "^1.5.1" + form-data "^4.0.4" + isomorphic-ws "^5.0.0" + jsonwebtoken "^9.0.2" + linkifyjs "^4.3.2" + ws "^8.18.1" + +stream-chat@^9.9.0: version "9.20.3" resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.20.3.tgz#5f47d6f46d146202c743282f5fb7350f4a640922" integrity sha512-206Lea0ZAVWbfYZkIwLG5m+++ELD3f8EAEL/YzbMDL++E2vU2WhQ2d1HNb1ROXURZUF0Sy845htTw1rwnahomw== diff --git a/examples/SampleApp/yarn.lock b/examples/SampleApp/yarn.lock index ff8c1c7832..f2a8f2a2f3 100644 --- a/examples/SampleApp/yarn.lock +++ b/examples/SampleApp/yarn.lock @@ -3474,6 +3474,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axios@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7" + integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + axios@^1.6.0: version "1.7.9" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" @@ -8179,14 +8188,14 @@ stream-chat-react-native-core@8.1.0: version "0.0.0" uid "" -stream-chat@^9.17.0: - version "9.17.0" - resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.17.0.tgz#540cf1ea03b08a394d6140696aae8528e9ba9ce2" - integrity sha512-ys6K73wIVWs5+qsfPJ9wumEUtgbMXYVbH1dhmAZ1oYtQ01dY/avsvt25PYDakVjKeyrnT+y8T/xEzfeF/WDJsg== +stream-chat@^9.23.0: + version "9.23.0" + resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.23.0.tgz#e7e5cf729861597e7198907c1cab22a57d68a2fc" + integrity sha512-UW112HYsLnYb4RMIXBtAouNQCCe0weVzNivjezsw+JKK1b/TX0JLBi+wK25mBUEO+coOGKfXiye6IB3gao8ipw== dependencies: "@types/jsonwebtoken" "^9.0.8" "@types/ws" "^8.5.14" - axios "^1.6.0" + axios "^1.12.2" base64-js "^1.5.1" form-data "^4.0.4" isomorphic-ws "^5.0.0" diff --git a/examples/TypeScriptMessaging/yarn.lock b/examples/TypeScriptMessaging/yarn.lock index 46cd8ec3b9..e5cb3eef85 100644 --- a/examples/TypeScriptMessaging/yarn.lock +++ b/examples/TypeScriptMessaging/yarn.lock @@ -2734,6 +2734,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axios@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.12.2.tgz#6c307390136cf7a2278d09cec63b136dfc6e6da7" + integrity sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + axios@^1.6.0: version "1.7.9" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" @@ -7319,14 +7328,14 @@ stream-chat-react-native-core@8.1.0: version "0.0.0" uid "" -stream-chat@^9.17.0: - version "9.17.0" - resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.17.0.tgz#540cf1ea03b08a394d6140696aae8528e9ba9ce2" - integrity sha512-ys6K73wIVWs5+qsfPJ9wumEUtgbMXYVbH1dhmAZ1oYtQ01dY/avsvt25PYDakVjKeyrnT+y8T/xEzfeF/WDJsg== +stream-chat@^9.23.0: + version "9.23.0" + resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.23.0.tgz#e7e5cf729861597e7198907c1cab22a57d68a2fc" + integrity sha512-UW112HYsLnYb4RMIXBtAouNQCCe0weVzNivjezsw+JKK1b/TX0JLBi+wK25mBUEO+coOGKfXiye6IB3gao8ipw== dependencies: "@types/jsonwebtoken" "^9.0.8" "@types/ws" "^8.5.14" - axios "^1.6.0" + axios "^1.12.2" base64-js "^1.5.1" form-data "^4.0.4" isomorphic-ws "^5.0.0" diff --git a/package/package.json b/package/package.json index 350cf0c05c..5037c56ff2 100644 --- a/package/package.json +++ b/package/package.json @@ -79,7 +79,7 @@ "path": "0.12.7", "react-native-markdown-package": "1.8.2", "react-native-url-polyfill": "^2.0.0", - "stream-chat": "^9.22.0", + "stream-chat": "^9.23.0", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { diff --git a/package/yarn.lock b/package/yarn.lock index 392dd67647..855c6b8a95 100644 --- a/package/yarn.lock +++ b/package/yarn.lock @@ -8344,10 +8344,10 @@ statuses@~1.5.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== -stream-chat@^9.22.0: - version "9.22.0" - resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.22.0.tgz#9b4c47974b0bf135fba7bf6122f406f78470f49b" - integrity sha512-7OZVxV+H0Ye8/HCqXlbQCwxgCy/JFA4fMJ7OvmGw1/yoUg/fgzQr827QqPhzPG3arSNV6f0+VT6Dnju8bCvUpQ== +stream-chat@^9.23.0: + version "9.23.0" + resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.23.0.tgz#e7e5cf729861597e7198907c1cab22a57d68a2fc" + integrity sha512-UW112HYsLnYb4RMIXBtAouNQCCe0weVzNivjezsw+JKK1b/TX0JLBi+wK25mBUEO+coOGKfXiye6IB3gao8ipw== dependencies: "@types/jsonwebtoken" "^9.0.8" "@types/ws" "^8.5.14"