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/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/src/utils/messageActions.tsx b/examples/SampleApp/src/utils/messageActions.tsx index e462763e22..7dafc4ff79 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, deleteForMeMessage } = params; const actions = messageActions(params); // We cannot use the useMessageReminder hook here because it is a hook. @@ -88,6 +89,27 @@ 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 () => { + await deleteForMeMessage?.action(); + dismissOverlay(); + }, + style: 'destructive', + }, + ]); + }, + actionType: 'deleteForMe', + icon: , + title: t('Delete for me'), + }); return actions; } 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 99ba8839f6..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.17.0", + "stream-chat": "^9.23.0", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { 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 1f10124150..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, @@ -582,10 +589,12 @@ const MessageWithContext = (props: MessagePropsWithContext) => { showMessageReactions, threadReply, unpinMessage, + updateMessage, }); 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 8d019238b9..d7973cc2db 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,7 +26,10 @@ export type MessageActionsParams = { showMessageReactions: boolean; threadReply: MessageActionType; unpinMessage: MessageActionType; -} & Pick; + // Optional Actions + deleteForMeMessage?: MessageActionType; +} & 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 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 */ 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; diff --git a/package/yarn.lock b/package/yarn.lock index b2258ec83a..855c6b8a95 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.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"