diff --git a/package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx b/package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx index 7e274e4273..92e9e67bee 100644 --- a/package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx +++ b/package/src/components/AttachmentPicker/components/AttachmentMediaPicker/AttachmentPickerItem.tsx @@ -228,7 +228,8 @@ const useStyles = () => { margin: 1, alignItems: 'center', justifyContent: 'center', - backgroundColor: semantics.backgroundCoreSurfaceSubtle, + backgroundColor: semantics.backgroundCoreSurfaceCard, + gap: primitives.spacingXs, }, iosLimitedIcon: { color: semantics.textTertiary, diff --git a/package/src/components/Message/hooks/useMessageActions.tsx b/package/src/components/Message/hooks/useMessageActions.tsx index f2b383e1fa..a1451d4b65 100644 --- a/package/src/components/Message/hooks/useMessageActions.tsx +++ b/package/src/components/Message/hooks/useMessageActions.tsx @@ -1,4 +1,5 @@ import React, { useMemo } from 'react'; +import { Alert } from 'react-native'; import { LocalMessage } from 'stream-chat'; @@ -244,18 +245,41 @@ export const useMessageActions = ({ onOpenThread(); }); + const isMuted = useUserMuteActive(message.user); + const isBlocked = new Set(client.blockedUsers.getLatestValue().userIds).has( + message.user?.id ?? '', + ); + const onBlockUser = useStableCallback(() => { if (handleBlockUser) { handleBlockUser(message.user); } - handleToggleBlockUser(message.user); - }); + if (isBlocked) { + handleToggleBlockUser(message.user); + return; + } - const isMuted = useUserMuteActive(message.user); - const isBlocked = new Set(client.blockedUsers.getLatestValue().userIds).has( - message.user?.id ?? '', - ); + const name = message.user?.name || message.user?.id || ''; + + Alert.alert( + t('Block {{ name }}', { name }), + t("They won't be able to message or call you. You can unblock them later."), + [ + { + style: 'cancel', + text: t('Cancel'), + }, + { + onPress: () => { + handleToggleBlockUser(message.user); + }, + style: 'destructive', + text: t('Block'), + }, + ], + ); + }); return useMemo(() => { const handleReaction = diff --git a/package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx b/package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx index 229dcff90d..f3bb3d4c57 100644 --- a/package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx +++ b/package/src/hooks/actions/__tests__/useChannelActionItems.test.tsx @@ -105,7 +105,7 @@ describe('useChannelActionItems', () => { expect(result.current.map((item) => item.action)).toEqual([ channelActions.muteChannel, channelActions.pin, - channelActions.leave, + expect.any(Function), expect.any(Function), ]); expect(result.current.map((item) => item.id)).toEqual([ @@ -268,7 +268,7 @@ describe('getChannelActionItems', () => { expect(actionItems.map((item) => item.action)).toEqual([ channelActions.muteChannel, channelActions.pin, - channelActions.leave, + expect.any(Function), expect.any(Function), ]); expect(actionItems.map((item) => item.id)).toEqual(['mute', 'pin', 'leave', 'deleteChannel']); @@ -308,7 +308,7 @@ describe('getChannelActionItems', () => { channelActions.pin, channelActions.unmuteUser, channelActions.unblockUser, - channelActions.leave, + expect.any(Function), expect.any(Function), ]); expect(actionItems.map((item) => item.label)).toEqual([ @@ -383,7 +383,7 @@ describe('getChannelActionItems', () => { expect(actionItems[0].placement).toBe('swipe'); const leaveItem = actionItems.find((item) => item.id === 'leave'); - expect(leaveItem?.action).toBe(channelActions.leave); + expect(leaveItem?.action).toEqual(expect.any(Function)); expect(leaveItem?.label).toBe('Leave Group'); expect(leaveItem?.placement).toBe('sheet'); }); diff --git a/package/src/hooks/actions/__tests__/useChannelMemberActionItems.test.tsx b/package/src/hooks/actions/__tests__/useChannelMemberActionItems.test.tsx index edf5ec747a..aac6326a68 100644 --- a/package/src/hooks/actions/__tests__/useChannelMemberActionItems.test.tsx +++ b/package/src/hooks/actions/__tests__/useChannelMemberActionItems.test.tsx @@ -76,7 +76,7 @@ describe('useChannelMemberActionItems', () => { expect(result.current.map((item) => item.id)).toEqual(['muteUser', 'block']); expect(result.current.map((item) => item.action)).toEqual([ userActions.muteUser, - userActions.blockUser, + expect.any(Function), ]); expect(result.current.map((item) => item.type)).toEqual(['standard', 'destructive']); expect(result.current.map((item) => item.label)).toEqual(['Mute User', 'Block User']); @@ -259,7 +259,7 @@ describe('buildDefaultChannelMemberActionItems', () => { }); expect(items.map((item) => item.id)).toEqual(['muteUser', 'block']); - expect(items.map((item) => item.action)).toEqual([actions.muteUser, actions.blockUser]); + expect(items.map((item) => item.action)).toEqual([actions.muteUser, expect.any(Function)]); expect(items.map((item) => item.label)).toEqual(['Mute User', 'Block User']); expect(items.map((item) => item.type)).toEqual(['standard', 'destructive']); }); @@ -335,7 +335,7 @@ describe('buildDefaultChannelMemberActionItems', () => { }); expect(items.find((item) => item.id === 'muteUser')?.action).toBe(actions.unmuteUser); - expect(items.find((item) => item.id === 'block')?.action).toBe(actions.blockUser); + expect(items.find((item) => item.id === 'block')?.action).toEqual(expect.any(Function)); }); it('default getChannelMemberActionItems returns defaultItems unchanged', () => { diff --git a/package/src/hooks/actions/useChannelActionItems.tsx b/package/src/hooks/actions/useChannelActionItems.tsx index ec69e617fb..4f3a868eb0 100644 --- a/package/src/hooks/actions/useChannelActionItems.tsx +++ b/package/src/hooks/actions/useChannelActionItems.tsx @@ -179,8 +179,31 @@ export const buildDefaultChannelActionItems: BuildDefaultChannelActionItems = ( type: 'standard', }); + const blockUserWithConfirmation = (...args: Parameters) => { + const otherUser = getOtherUserInDirectChannel(channel)?.user; + const name = otherUser?.name || otherUser?.id || ''; + + Alert.alert( + t('Block {{ name }}', { name }), + t("They won't be able to message or call you. You can unblock them later."), + [ + { + style: 'cancel', + text: t('Cancel'), + }, + { + onPress: async () => { + await blockUser(...args); + }, + style: 'destructive', + text: t('Block'), + }, + ], + ); + }; + actionItems.push({ - action: isBlocked ? unblockUser : blockUser, + action: isBlocked ? unblockUser : blockUserWithConfirmation, Icon: (props) => , id: 'block', label: isBlocked ? t('Unblock User') : t('Block User'), @@ -189,8 +212,39 @@ export const buildDefaultChannelActionItems: BuildDefaultChannelActionItems = ( }); } + const leaveWithConfirmation = (...args: Parameters) => { + const channelName = channel.data?.name; + let name: string; + if (channelName) { + name = channelName; + } else if (isDirectChat) { + const otherUser = getOtherUserInDirectChannel(channel)?.user; + name = otherUser?.name || otherUser?.id || ''; + } else { + name = t('group'); + } + + Alert.alert( + isDirectChat ? t('Leave Chat') : t('Leave Group'), + t("You'll stop receiving messages from {{ name }}. You can rejoin anytime.", { name }), + [ + { + style: 'cancel', + text: t('Cancel'), + }, + { + onPress: async () => { + await leave(...args); + }, + style: 'destructive', + text: t('Leave'), + }, + ], + ); + }; + actionItems.push({ - action: leave, + action: leaveWithConfirmation, Icon: (props) => , id: 'leave', label: isDirectChat ? t('Leave Chat') : t('Leave Group'), diff --git a/package/src/hooks/actions/useChannelMemberActionItems.tsx b/package/src/hooks/actions/useChannelMemberActionItems.tsx index 27d35bcedf..25c056c550 100644 --- a/package/src/hooks/actions/useChannelMemberActionItems.tsx +++ b/package/src/hooks/actions/useChannelMemberActionItems.tsx @@ -83,7 +83,29 @@ export const buildDefaultChannelMemberActionItems: BuildDefaultChannelMemberActi type: 'standard', }, { - action: isBlocked ? unblockUser : blockUser, + action: isBlocked + ? unblockUser + : (...args: Parameters) => { + const name = member.user?.name || member.user?.id || ''; + + Alert.alert( + t('Block {{ name }}', { name }), + t("They won't be able to message or call you. You can unblock them later."), + [ + { + style: 'cancel', + text: t('Cancel'), + }, + { + onPress: async () => { + await blockUser(...args); + }, + style: 'destructive', + text: t('Block'), + }, + ], + ); + }, Icon: (props) => , id: 'block', label: isBlocked ? t('Unblock User') : t('Block User'), diff --git a/package/src/i18n/ar.json b/package/src/i18n/ar.json index aee82a8d02..0986f13809 100644 --- a/package/src/i18n/ar.json +++ b/package/src/i18n/ar.json @@ -457,5 +457,11 @@ "Pin Chat": "تثبيت الدردشة", "Pin Group": "تثبيت المجموعة", "Unpin Chat": "إلغاء تثبيت الدردشة", - "Unpin Group": "إلغاء تثبيت المجموعة" + "Unpin Group": "إلغاء تثبيت المجموعة", + "Block": "حظر", + "Block {{ name }}": "حظر {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "لن يتمكن/تتمكن من مراسلتك أو الاتصال بك. يمكنك إلغاء الحظر لاحقًا.", + "Leave": "مغادرة", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "ستتوقف عن تلقي الرسائل من {{ name }}. يمكنك الانضمام مجددًا في أي وقت.", + "group": "المجموعة" } diff --git a/package/src/i18n/en.json b/package/src/i18n/en.json index d9f62353f1..ba6beb1c9e 100644 --- a/package/src/i18n/en.json +++ b/package/src/i18n/en.json @@ -242,6 +242,12 @@ "No conversations yet": "No conversations yet", "Are you sure you want to delete this group? This can't be undone.": "Are you sure you want to delete this group? This can't be undone.", "Are you sure you want to delete this chat? This can't be undone.": "Are you sure you want to delete this chat? This can't be undone.", + "Block": "Block", + "Block {{ name }}": "Block {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "They won't be able to message or call you. You can unblock them later.", + "Leave": "Leave", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "You'll stop receiving messages from {{ name }}. You can rejoin anytime.", + "group": "this group", "Delete chat": "Delete chat", "Delete group": "Delete group", "Archive Chat": "Archive Chat", diff --git a/package/src/i18n/es.json b/package/src/i18n/es.json index 1f2a75a753..cd76ae5a3d 100644 --- a/package/src/i18n/es.json +++ b/package/src/i18n/es.json @@ -457,5 +457,11 @@ "Pin Chat": "Fijar chat", "Pin Group": "Fijar grupo", "Unpin Chat": "Desfijar chat", - "Unpin Group": "Desfijar grupo" + "Unpin Group": "Desfijar grupo", + "Block": "Bloquear", + "Block {{ name }}": "Bloquear a {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "No podrá enviarte mensajes ni llamarte. Puedes desbloquearlo más tarde.", + "Leave": "Salir", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "Dejarás de recibir mensajes de {{ name }}. Puedes volver a unirte cuando quieras.", + "group": "el grupo" } diff --git a/package/src/i18n/fr.json b/package/src/i18n/fr.json index 1b52d874f3..535e948bc3 100644 --- a/package/src/i18n/fr.json +++ b/package/src/i18n/fr.json @@ -457,5 +457,11 @@ "Pin Chat": "Épingler la discussion", "Pin Group": "Épingler le groupe", "Unpin Chat": "Détacher la discussion", - "Unpin Group": "Détacher le groupe" + "Unpin Group": "Détacher le groupe", + "Block": "Bloquer", + "Block {{ name }}": "Bloquer {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "Cette personne ne pourra plus vous envoyer de messages ni vous appeler. Vous pourrez la débloquer plus tard.", + "Leave": "Quitter", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "Vous ne recevrez plus de messages de {{ name }}. Vous pouvez rejoindre à tout moment.", + "group": "ce groupe" } diff --git a/package/src/i18n/he.json b/package/src/i18n/he.json index 417a18aca5..b9d6cc8615 100644 --- a/package/src/i18n/he.json +++ b/package/src/i18n/he.json @@ -457,5 +457,11 @@ "Pin Chat": "הצמד/י צ'אט", "Pin Group": "הצמד/י קבוצה", "Unpin Chat": "בטל/י הצמדת צ'אט", - "Unpin Group": "בטל/י הצמדת קבוצה" + "Unpin Group": "בטל/י הצמדת קבוצה", + "Block": "חסום/חסמי", + "Block {{ name }}": "חסימת {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "הוא/היא לא יוכל/תוכל לשלוח לך הודעות או להתקשר אליך. ניתן לבטל את החסימה מאוחר יותר.", + "Leave": "צא/י", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "תפסיק/תפסיקי לקבל הודעות מ-{{ name }}. ניתן להצטרף בחזרה בכל עת.", + "group": "הקבוצה" } diff --git a/package/src/i18n/hi.json b/package/src/i18n/hi.json index 3e89355001..18dd3f6150 100644 --- a/package/src/i18n/hi.json +++ b/package/src/i18n/hi.json @@ -457,5 +457,11 @@ "Pin Chat": "चैट पिन करें", "Pin Group": "ग्रुप पिन करें", "Unpin Chat": "चैट अनपिन करें", - "Unpin Group": "ग्रुप अनपिन करें" + "Unpin Group": "ग्रुप अनपिन करें", + "Block": "ब्लॉक करें", + "Block {{ name }}": "{{ name }} को ब्लॉक करें", + "They won't be able to message or call you. You can unblock them later.": "वे आपको संदेश या कॉल नहीं कर पाएंगे। आप उन्हें बाद में अनब्लॉक कर सकते हैं।", + "Leave": "छोड़ें", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "आपको {{ name }} से संदेश मिलना बंद हो जाएंगे। आप कभी भी दोबारा जुड़ सकते हैं।", + "group": "ग्रुप" } diff --git a/package/src/i18n/it.json b/package/src/i18n/it.json index 836e5ed082..1d36d90e7d 100644 --- a/package/src/i18n/it.json +++ b/package/src/i18n/it.json @@ -457,5 +457,11 @@ "Pin Chat": "Fissa chat", "Pin Group": "Fissa gruppo", "Unpin Chat": "Sfissa chat", - "Unpin Group": "Sfissa gruppo" + "Unpin Group": "Sfissa gruppo", + "Block": "Blocca", + "Block {{ name }}": "Blocca {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "Non potrà inviarti messaggi né chiamarti. Potrai sbloccarlo in seguito.", + "Leave": "Esci", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "Non riceverai più messaggi da {{ name }}. Puoi rientrare in qualsiasi momento.", + "group": "il gruppo" } diff --git a/package/src/i18n/ja.json b/package/src/i18n/ja.json index 0eaf022c44..a922096586 100644 --- a/package/src/i18n/ja.json +++ b/package/src/i18n/ja.json @@ -457,5 +457,11 @@ "Pin Chat": "チャットをピン留め", "Pin Group": "グループをピン留め", "Unpin Chat": "チャットのピン留めを解除", - "Unpin Group": "グループのピン留めを解除" + "Unpin Group": "グループのピン留めを解除", + "Block": "ブロック", + "Block {{ name }}": "{{ name }} をブロック", + "They won't be able to message or call you. You can unblock them later.": "メッセージや通話ができなくなります。あとでブロックを解除することもできます。", + "Leave": "退出", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "{{ name }} からのメッセージが届かなくなります。いつでも再参加できます。", + "group": "グループ" } diff --git a/package/src/i18n/ko.json b/package/src/i18n/ko.json index 69a3ac277f..9d37ff60c3 100644 --- a/package/src/i18n/ko.json +++ b/package/src/i18n/ko.json @@ -457,5 +457,11 @@ "Pin Chat": "채팅 고정", "Pin Group": "그룹 고정", "Unpin Chat": "채팅 고정 해제", - "Unpin Group": "그룹 고정 해제" + "Unpin Group": "그룹 고정 해제", + "Block": "차단", + "Block {{ name }}": "{{ name }} 차단", + "They won't be able to message or call you. You can unblock them later.": "메시지를 보내거나 전화를 걸 수 없게 됩니다. 나중에 차단을 해제할 수 있습니다.", + "Leave": "나가기", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "{{ name }}에서 더 이상 메시지를 받지 않게 됩니다. 언제든지 다시 참여할 수 있습니다.", + "group": "그룹" } diff --git a/package/src/i18n/nl.json b/package/src/i18n/nl.json index 0a25467b5d..06233b7411 100644 --- a/package/src/i18n/nl.json +++ b/package/src/i18n/nl.json @@ -457,5 +457,11 @@ "Pin Chat": "Chat vastmaken", "Pin Group": "Groep vastmaken", "Unpin Chat": "Chat losmaken", - "Unpin Group": "Groep losmaken" + "Unpin Group": "Groep losmaken", + "Block": "Blokkeren", + "Block {{ name }}": "{{ name }} blokkeren", + "They won't be able to message or call you. You can unblock them later.": "Deze persoon kan je geen berichten sturen of bellen. Je kunt de blokkering later opheffen.", + "Leave": "Verlaten", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "Je ontvangt geen berichten meer van {{ name }}. Je kunt op elk moment opnieuw deelnemen.", + "group": "de groep" } diff --git a/package/src/i18n/pt-br.json b/package/src/i18n/pt-br.json index cb231cff17..7b1e221e41 100644 --- a/package/src/i18n/pt-br.json +++ b/package/src/i18n/pt-br.json @@ -457,5 +457,11 @@ "Pin Chat": "Fixar conversa", "Pin Group": "Fixar grupo", "Unpin Chat": "Desafixar conversa", - "Unpin Group": "Desafixar grupo" + "Unpin Group": "Desafixar grupo", + "Block": "Bloquear", + "Block {{ name }}": "Bloquear {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "Essa pessoa não poderá enviar mensagens ou ligar para você. Você pode desbloqueá-la mais tarde.", + "Leave": "Sair", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "Você deixará de receber mensagens de {{ name }}. Pode entrar novamente a qualquer momento.", + "group": "o grupo" } diff --git a/package/src/i18n/ru.json b/package/src/i18n/ru.json index c00518ad09..dc52963fb2 100644 --- a/package/src/i18n/ru.json +++ b/package/src/i18n/ru.json @@ -457,5 +457,11 @@ "Pin Chat": "Закрепить чат", "Pin Group": "Закрепить группу", "Unpin Chat": "Открепить чат", - "Unpin Group": "Открепить группу" + "Unpin Group": "Открепить группу", + "Block": "Заблокировать", + "Block {{ name }}": "Заблокировать {{ name }}", + "They won't be able to message or call you. You can unblock them later.": "Он не сможет писать вам и звонить. Вы сможете снять блокировку позже.", + "Leave": "Покинуть", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "Вы перестанете получать сообщения от {{ name }}. Вы можете присоединиться снова в любое время.", + "group": "группы" } diff --git a/package/src/i18n/tr.json b/package/src/i18n/tr.json index 09c88e25ae..f467b1f249 100644 --- a/package/src/i18n/tr.json +++ b/package/src/i18n/tr.json @@ -457,5 +457,11 @@ "Pin Chat": "Sohbeti sabitle", "Pin Group": "Grubu sabitle", "Unpin Chat": "Sohbetin sabitlemesini kaldır", - "Unpin Group": "Grubun sabitlemesini kaldır" + "Unpin Group": "Grubun sabitlemesini kaldır", + "Block": "Engelle", + "Block {{ name }}": "{{ name }} kullanıcısını engelle", + "They won't be able to message or call you. You can unblock them later.": "Size mesaj gönderemez veya sizi arayamaz. Engeli daha sonra kaldırabilirsiniz.", + "Leave": "Ayrıl", + "You'll stop receiving messages from {{ name }}. You can rejoin anytime.": "{{ name }} kanalından mesaj almayı bırakacaksınız. İstediğiniz zaman tekrar katılabilirsiniz.", + "group": "grup" }