@@ -4,6 +4,7 @@ import { Animated, Image, StyleSheet, Text, TouchableOpacity, View } from 'react
4
4
import type { NotificationCardProps } from '../types' ;
5
5
import { CommonUtils , useSiren } from '../utils' ;
6
6
import { eventTypes , events } from '../utils/constants' ;
7
+ import { useSirenContext } from './sirenProvider' ;
7
8
import CloseIcon from './closeIcon' ;
8
9
import TimerIcon from './timerIcon' ;
9
10
@@ -47,28 +48,39 @@ const Card = (props: NotificationCardProps): ReactElement => {
47
48
disableAutoMarkAsRead,
48
49
hideDelete = false ,
49
50
onAvatarClick,
50
- deleteIcon = null
51
+ deleteIcon = null ,
52
+ hideMediaThumbnail = false ,
53
+ onMediaThumbnailClick
51
54
} = cardProps ;
52
55
const { markAsReadById } = useSiren ( ) ;
56
+ const { id : providerId } = useSirenContext ( ) ;
53
57
54
58
const opacity = useRef ( new Animated . Value ( 1 ) ) . current ;
55
59
56
60
const emptyState = ( ) => {
57
61
return darkMode ? require ( '../assets/emptyDark.png' ) : require ( '../assets/emptyLight.png' ) ;
58
62
} ;
59
63
64
+ const failedState = ( ) => {
65
+ return darkMode
66
+ ? require ( '../assets/failedImageDark.png' )
67
+ : require ( '../assets/failedImageLight.png' ) ;
68
+ } ;
69
+
70
+ const avatarUrl = notification ?. message ?. avatar ?. imageUrl || '' ;
71
+ const thumbnailUrl = notification ?. message ?. thumbnailUrl || '' ;
72
+
60
73
const [ imageSource , setImageSource ] = useState (
61
- notification ?. message ?. avatar ?. imageUrl ?. length > 0
62
- ? { uri : notification . message ?. avatar ?. imageUrl }
63
- : emptyState ( )
74
+ avatarUrl ?. length > 0 ? { uri : avatarUrl } : emptyState ( )
75
+ ) ;
76
+
77
+ const [ mediaSource , setMediaSource ] = useState (
78
+ thumbnailUrl ?. length > 0 ? { uri : thumbnailUrl } : emptyState ( )
64
79
) ;
65
80
66
81
useEffect ( ( ) => {
67
- setImageSource (
68
- notification ?. message ?. avatar ?. imageUrl ?. length > 0
69
- ? { uri : notification . message ?. avatar ?. imageUrl }
70
- : emptyState ( )
71
- ) ;
82
+ setImageSource ( avatarUrl ?. length > 0 ? { uri : avatarUrl } : emptyState ( ) ) ;
83
+ setMediaSource ( thumbnailUrl ?. length > 0 ? { uri : thumbnailUrl } : failedState ( ) ) ;
72
84
} , [ notification , darkMode ] ) ;
73
85
74
86
const cardClick = ( ) : void => {
@@ -80,10 +92,18 @@ const Card = (props: NotificationCardProps): ReactElement => {
80
92
setImageSource ( emptyState ( ) ) ;
81
93
} ;
82
94
95
+ const onErrorMedia = ( ) : void => {
96
+ setMediaSource ( failedState ( ) ) ;
97
+ } ;
98
+
83
99
const avatarClick = ( ) => {
84
100
if ( onAvatarClick ) onAvatarClick ( notification ) ;
85
101
} ;
86
102
103
+ const mediaClick = ( ) => {
104
+ if ( onMediaThumbnailClick ) onMediaThumbnailClick ( notification ) ;
105
+ } ;
106
+
87
107
const renderAvatar = useMemo ( ( ) : JSX . Element => {
88
108
return (
89
109
< View style = { style . cardIconContainer } >
@@ -104,6 +124,18 @@ const Card = (props: NotificationCardProps): ReactElement => {
104
124
) ;
105
125
} , [ styles , darkMode , imageSource , onAvatarClick ] ) ;
106
126
127
+ const renderMediaThumbnail = useMemo ( ( ) : JSX . Element => {
128
+ return (
129
+ < TouchableOpacity
130
+ style = { [ style . mediaContainer , styles . mediaContainer ] }
131
+ disabled = { Boolean ( ! onMediaThumbnailClick ) }
132
+ onPress = { mediaClick }
133
+ >
134
+ < Image source = { mediaSource } resizeMode = 'cover' style = { style . icon } onError = { onErrorMedia } />
135
+ </ TouchableOpacity >
136
+ ) ;
137
+ } , [ darkMode , mediaSource , onMediaThumbnailClick ] ) ;
138
+
107
139
const onDeleteItem = async ( ) : Promise < void > => {
108
140
const isSuccess = await onDelete ( notification . id , false ) ;
109
141
@@ -115,7 +147,7 @@ const Card = (props: NotificationCardProps): ReactElement => {
115
147
} ) . start ( ( ) => {
116
148
const payload = { id : notification . id , action : eventTypes . DELETE_ITEM } ;
117
149
118
- PubSub . publish ( events . NOTIFICATION_LIST_EVENT , JSON . stringify ( payload ) ) ;
150
+ PubSub . publish ( ` ${ events . NOTIFICATION_LIST_EVENT } ${ providerId } ` , JSON . stringify ( payload ) ) ;
119
151
} ) ;
120
152
} ;
121
153
@@ -141,19 +173,28 @@ const Card = (props: NotificationCardProps): ReactElement => {
141
173
< Text numberOfLines = { 2 } style = { [ styles . cardTitle , style . cardTitle ] } >
142
174
{ notification . message ?. header }
143
175
</ Text >
144
- { ! hideDelete &&
145
- ( deleteIcon || (
146
- < CloseIcon onDelete = { onDeleteItem } notification = { notification } styles = { styles } />
147
- ) ) }
176
+ { ! hideDelete && (
177
+ < CloseIcon
178
+ onDelete = { onDeleteItem }
179
+ customIcon = { deleteIcon }
180
+ notification = { notification }
181
+ styles = { styles }
182
+ />
183
+ ) }
148
184
</ View >
149
185
{ Boolean ( notification . message ?. subHeader ) && (
150
186
< Text numberOfLines = { 2 } style = { [ style . cardSubTitle , styles . cardSubTitle ] } >
151
187
{ notification . message ?. subHeader }
152
188
</ Text >
153
189
) }
154
- < Text numberOfLines = { 2 } style = { [ style . cardDescription , styles . cardDescription ] } >
155
- { notification . message ?. body }
156
- </ Text >
190
+ { Boolean ( notification . message ?. body ) && (
191
+ < Text numberOfLines = { 2 } style = { [ style . cardDescription , styles . cardDescription ] } >
192
+ { notification . message ?. body }
193
+ </ Text >
194
+ ) }
195
+ { ! hideMediaThumbnail &&
196
+ Boolean ( notification . message ?. thumbnailUrl ) &&
197
+ renderMediaThumbnail }
157
198
< View style = { style . dateContainer } >
158
199
< TimerIcon styles = { styles } />
159
200
< Text style = { [ style . dateStyle , styles . dateStyle ] } >
@@ -228,6 +269,14 @@ const style = StyleSheet.create({
228
269
} ,
229
270
transparent : {
230
271
backgroundColor : 'transparent'
272
+ } ,
273
+ mediaContainer : {
274
+ width : '100%' ,
275
+ height : 130 ,
276
+ borderRadius : 6 ,
277
+ marginBottom : 10 ,
278
+ overflow : 'hidden' ,
279
+ backgroundColor : '#D3D3D3'
231
280
}
232
281
} ) ;
233
282
0 commit comments