@@ -9,11 +9,15 @@ import { useComponentsContext } from '../../../contexts/componentsContext/Compon
99import { useOwnCapabilitiesContext } from '../../../contexts/ownCapabilitiesContext/OwnCapabilitiesContext' ;
1010import { useTheme } from '../../../contexts/themeContext/ThemeContext' ;
1111import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext' ;
12+ import { getNotificationErrorOptions } from '../../../hooks/useChannelActions' ;
1213import { useStableCallback } from '../../../hooks/useStableCallback' ;
1314import { Checkmark } from '../../../icons/checkmark-1' ;
1415import { UserAdd } from '../../../icons/user-add' ;
1516import { NewClose } from '../../../icons/xmark' ;
1617import { primitives } from '../../../theme' ;
18+ import { useNotificationApi } from '../../Notifications/hooks' ;
19+ import { NotificationList } from '../../Notifications/NotificationList' ;
20+ import { NotificationTargetProvider } from '../../Notifications/NotificationTargetContext' ;
1721import { Button } from '../../ui/Button/Button' ;
1822import { BottomSheetModal } from '../../UIComponents/BottomSheetModal' ;
1923import { useChannelDetailsMembersPreview } from '../hooks/useChannelDetailsMembersPreview' ;
@@ -22,8 +26,12 @@ export const ChannelDetailsMemberSection = () => {
2226 const { channel, onAddMembersPress, onViewAllMembersPress } = useChannelDetailsContext ( ) ;
2327 const { client } = useChatContext ( ) ;
2428 const { t } = useTranslationContext ( ) ;
29+ const { addNotification } = useNotificationApi ( ) ;
2530 const { updateChannelMembers } = useOwnCapabilitiesContext ( ) ;
2631 const { height : windowHeight } = useWindowDimensions ( ) ;
32+ const addMembersNotificationHostId = channel ?. cid
33+ ? `channel-add-members:${ channel . cid } `
34+ : undefined ;
2735 const {
2836 theme : {
2937 channelDetailsScreen : {
@@ -72,12 +80,26 @@ export const ChannelDetailsMemberSection = () => {
7280 const handleAddMembersConfirm = useStableCallback ( async ( ) => {
7381 if ( ! addMembersSelection . length || addingMembers ) return ;
7482 setAddingMembers ( true ) ;
83+ const addedCount = addMembersSelection . length ;
7584 try {
7685 await channel . addMembers ( addMembersSelection . map ( ( u ) => u . id ) ) ;
86+ addNotification ( {
87+ message : t ( '{{count}} members added' , { count : addedCount } ) ,
88+ options : { severity : 'success' , type : 'api:channel:add-members:success' } ,
89+ origin : { context : { channel } , emitter : 'ChannelDetailsMemberSection' } ,
90+ } ) ;
7791 setAddMembersVisible ( false ) ;
7892 setAddMembersSelection ( [ ] ) ;
79- } catch ( err ) {
80- console . warn ( '[ChannelDetailsMemberSection] failed to add members' , err ) ;
93+ } catch ( error ) {
94+ addNotification ( {
95+ message : t ( 'Failed to add members' ) ,
96+ options : {
97+ ...getNotificationErrorOptions ( error ) ,
98+ severity : 'error' ,
99+ type : 'api:channel:add-members:failed' ,
100+ } ,
101+ origin : { context : { channel } , emitter : 'ChannelDetailsMemberSection' } ,
102+ } ) ;
81103 } finally {
82104 setAddingMembers ( false ) ;
83105 }
@@ -205,59 +227,66 @@ export const ChannelDetailsMemberSection = () => {
205227 onClose = { handleAddMembersClose }
206228 visible = { isAddMembersVisible }
207229 >
208- < View style = { [ styles . modalHeader , modalHeaderOverride ] } >
209- < View style = { styles . modalHeaderSide } >
210- < Button
211- accessibilityLabelKey = 'a11y/Close'
212- iconOnly
213- LeadingIcon = { NewClose }
214- onPress = { handleAddMembersClose }
215- size = 'md'
216- type = 'outline'
217- variant = 'secondary'
218- />
219- </ View >
220- < View style = { styles . modalHeaderCenter } >
221- < Text
222- accessibilityRole = 'header'
223- numberOfLines = { 1 }
224- style = { [
225- styles . modalHeaderTitle ,
226- { color : semantics . textPrimary } ,
227- modalHeaderTitleOverride ,
228- ] }
229- >
230- { t ( 'Add Members' ) }
231- </ Text >
232- </ View >
233- < View style = { [ styles . modalHeaderSide , styles . modalHeaderSideRight ] } >
234- < Pressable
235- accessibilityLabel = { t ( 'a11y/Confirm add members' ) }
236- accessibilityRole = 'button'
237- accessibilityState = { { disabled : ! confirmEnabled } }
238- disabled = { ! confirmEnabled }
239- onPress = { handleAddMembersConfirm }
240- style = { [
241- styles . confirmButton ,
242- confirmEnabled
243- ? { backgroundColor : semantics . accentPrimary }
244- : {
245- borderColor : semantics . borderCoreDefault ,
246- borderWidth : 1 ,
247- } ,
248- confirmButtonOverride ,
249- ] }
250- testID = 'channel-details-add-members-confirm-button'
251- >
252- < Checkmark
253- height = { 20 }
254- pathFill = { confirmEnabled ? semantics . textOnInverse : semantics . textSecondary }
255- width = { 20 }
256- />
257- </ Pressable >
258- </ View >
259- </ View >
260- < ChannelAddMembers onSelectionChange = { handleAddMembersSelectionChange } />
230+ { addMembersNotificationHostId ? (
231+ < NotificationTargetProvider hostId = { addMembersNotificationHostId } panel = 'channel-details' >
232+ < View style = { styles . modalBody } >
233+ < View style = { [ styles . modalHeader , modalHeaderOverride ] } >
234+ < View style = { styles . modalHeaderSide } >
235+ < Button
236+ accessibilityLabelKey = 'a11y/Close'
237+ iconOnly
238+ LeadingIcon = { NewClose }
239+ onPress = { handleAddMembersClose }
240+ size = 'md'
241+ type = 'outline'
242+ variant = 'secondary'
243+ />
244+ </ View >
245+ < View style = { styles . modalHeaderCenter } >
246+ < Text
247+ accessibilityRole = 'header'
248+ numberOfLines = { 1 }
249+ style = { [
250+ styles . modalHeaderTitle ,
251+ { color : semantics . textPrimary } ,
252+ modalHeaderTitleOverride ,
253+ ] }
254+ >
255+ { t ( 'Add Members' ) }
256+ </ Text >
257+ </ View >
258+ < View style = { [ styles . modalHeaderSide , styles . modalHeaderSideRight ] } >
259+ < Pressable
260+ accessibilityLabel = { t ( 'a11y/Confirm add members' ) }
261+ accessibilityRole = 'button'
262+ accessibilityState = { { disabled : ! confirmEnabled } }
263+ disabled = { ! confirmEnabled }
264+ onPress = { handleAddMembersConfirm }
265+ style = { [
266+ styles . confirmButton ,
267+ confirmEnabled
268+ ? { backgroundColor : semantics . accentPrimary }
269+ : {
270+ borderColor : semantics . borderCoreDefault ,
271+ borderWidth : 1 ,
272+ } ,
273+ confirmButtonOverride ,
274+ ] }
275+ testID = 'channel-details-add-members-confirm-button'
276+ >
277+ < Checkmark
278+ height = { 20 }
279+ pathFill = { confirmEnabled ? semantics . textOnInverse : semantics . textSecondary }
280+ width = { 20 }
281+ />
282+ </ Pressable >
283+ </ View >
284+ </ View >
285+ < ChannelAddMembers onSelectionChange = { handleAddMembersSelectionChange } />
286+ < NotificationList />
287+ </ View >
288+ </ NotificationTargetProvider >
289+ ) : null }
261290 </ BottomSheetModal >
262291 </ View >
263292 ) ;
@@ -296,6 +325,9 @@ const useStyles = () => {
296325 list : {
297326 paddingBottom : primitives . spacingSm ,
298327 } ,
328+ modalBody : {
329+ flex : 1 ,
330+ } ,
299331 modalHeader : {
300332 alignItems : 'center' ,
301333 flexDirection : 'row' ,
0 commit comments