1- import React , { RefObject , useCallback , useEffect , useRef , useState } from 'react' ;
1+ import React , { RefObject , useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
22import { Image , ImageStyle , Keyboard , StyleSheet , ViewStyle } from 'react-native' ;
33
44import { Gesture , GestureDetector } from 'react-native-gesture-handler' ;
@@ -132,9 +132,6 @@ export const ImageGallery = <
132132 numberOfImageGalleryGridColumns,
133133 overlayOpacity,
134134 } = props ;
135- const [ imageGalleryAttachments , setImageGalleryAttachments ] = useState <
136- Photo < StreamChatGenerics > [ ]
137- > ( [ ] ) ;
138135 const { resizableCDNHosts } = useChatConfigContext ( ) ;
139136 const {
140137 theme : {
@@ -198,13 +195,6 @@ export const ImageGallery = <
198195 */
199196 const [ currentImageHeight , setCurrentImageHeight ] = useState < number > ( fullWindowHeight ) ;
200197
201- /**
202- * JS and UI index values, the JS follows the UI but is needed
203- * for rendering the virtualized image list
204- */
205- const [ selectedIndex , setSelectedIndex ] = useState ( 0 ) ;
206- const index = useSharedValue ( 0 ) ;
207-
208198 /**
209199 * Header visible value for animating in out
210200 */
@@ -224,57 +214,86 @@ export const ImageGallery = <
224214 * photo attachments
225215 */
226216
227- const photos = messages . reduce ( ( acc : Photo < StreamChatGenerics > [ ] , cur ) => {
228- const attachmentImages =
229- cur . attachments
230- ?. filter (
231- ( attachment ) =>
232- ( attachment . type === FileTypes . Giphy &&
233- ( attachment . giphy ?. [ giphyVersion ] ?. url ||
234- attachment . thumb_url ||
235- attachment . image_url ) ) ||
236- ( attachment . type === FileTypes . Image &&
237- ! attachment . title_link &&
238- ! attachment . og_scrape_url &&
239- getUrlOfImageAttachment ( attachment ) ) ||
240- ( isVideoPlayerAvailable ( ) && attachment . type === FileTypes . Video ) ,
241- )
242- . reverse ( ) || [ ] ;
243-
244- const attachmentPhotos = attachmentImages . map ( ( a ) => {
245- const imageUrl = getUrlOfImageAttachment ( a ) as string ;
246- const giphyURL = a . giphy ?. [ giphyVersion ] ?. url || a . thumb_url || a . image_url ;
247- const isInitiallyPaused = ! autoPlayVideo ;
248-
249- return {
250- channelId : cur . cid ,
251- created_at : cur . created_at ,
252- duration : 0 ,
253- id : `photoId-${ cur . id } -${ imageUrl } ` ,
254- messageId : cur . id ,
255- mime_type : a . type === 'giphy' ? getGiphyMimeType ( giphyURL ?? '' ) : a . mime_type ,
256- original_height : a . original_height ,
257- original_width : a . original_width ,
258- paused : isInitiallyPaused ,
259- progress : 0 ,
260- thumb_url : a . thumb_url ,
261- type : a . type ,
262- uri :
263- a . type === 'giphy'
264- ? giphyURL
265- : getResizedImageUrl ( {
266- height : fullWindowHeight ,
267- resizableCDNHosts,
268- url : imageUrl ,
269- width : fullWindowWidth ,
270- } ) ,
271- user : cur . user ,
272- user_id : cur . user_id ,
273- } ;
274- } ) ;
217+ const photos = useMemo (
218+ ( ) =>
219+ messages . reduce ( ( acc : Photo < StreamChatGenerics > [ ] , cur ) => {
220+ const attachmentImages =
221+ cur . attachments
222+ ?. filter (
223+ ( attachment ) =>
224+ ( attachment . type === FileTypes . Giphy &&
225+ ( attachment . giphy ?. [ giphyVersion ] ?. url ||
226+ attachment . thumb_url ||
227+ attachment . image_url ) ) ||
228+ ( attachment . type === FileTypes . Image &&
229+ ! attachment . title_link &&
230+ ! attachment . og_scrape_url &&
231+ getUrlOfImageAttachment ( attachment ) ) ||
232+ ( isVideoPlayerAvailable ( ) && attachment . type === FileTypes . Video ) ,
233+ )
234+ . reverse ( ) || [ ] ;
235+
236+ const attachmentPhotos = attachmentImages . map ( ( a ) => {
237+ const imageUrl = getUrlOfImageAttachment ( a ) as string ;
238+ const giphyURL = a . giphy ?. [ giphyVersion ] ?. url || a . thumb_url || a . image_url ;
239+ const isInitiallyPaused = ! autoPlayVideo ;
240+
241+ return {
242+ channelId : cur . cid ,
243+ created_at : cur . created_at ,
244+ duration : 0 ,
245+ id : `photoId-${ cur . id } -${ imageUrl } ` ,
246+ messageId : cur . id ,
247+ mime_type : a . type === 'giphy' ? getGiphyMimeType ( giphyURL ?? '' ) : a . mime_type ,
248+ original_height : a . original_height ,
249+ original_width : a . original_width ,
250+ paused : isInitiallyPaused ,
251+ progress : 0 ,
252+ thumb_url : a . thumb_url ,
253+ type : a . type ,
254+ uri :
255+ a . type === 'giphy'
256+ ? giphyURL
257+ : getResizedImageUrl ( {
258+ height : fullWindowHeight ,
259+ resizableCDNHosts,
260+ url : imageUrl ,
261+ width : fullWindowWidth ,
262+ } ) ,
263+ user : cur . user ,
264+ user_id : cur . user_id ,
265+ } ;
266+ } ) ;
275267
276- return [ ...attachmentPhotos , ...acc ] as Photo < StreamChatGenerics > [ ] ;
277- } , [ ] ) ;
268+ return [ ...attachmentPhotos , ...acc ] as Photo < StreamChatGenerics > [ ] ;
269+ } , [ ] ) ,
270+ [ autoPlayVideo , fullWindowHeight , fullWindowWidth , giphyVersion , messages , resizableCDNHosts ] ,
271+ ) ;
272+
273+ /**
274+ * The URL for the images may differ because of dimensions passed as
275+ * part of the query.
276+ */
277+ const stripQueryFromUrl = ( url : string ) => url . split ( '?' ) [ 0 ] ;
278+
279+ const photoSelectedIndex = useMemo ( ( ) => {
280+ const idx = photos . findIndex (
281+ ( photo ) =>
282+ photo . messageId === selectedMessage ?. messageId &&
283+ stripQueryFromUrl ( photo . uri ) === stripQueryFromUrl ( selectedMessage ?. url || '' ) ,
284+ ) ;
285+
286+ return idx === - 1 ? 0 : idx ;
287+ } , [ photos , selectedMessage ] ) ;
288+
289+ /**
290+ * JS and UI index values, the JS follows the UI but is needed
291+ * for rendering the virtualized image list
292+ */
293+ const [ selectedIndex , setSelectedIndex ] = useState ( photoSelectedIndex ) ;
294+ const index = useSharedValue ( photoSelectedIndex ) ;
295+
296+ const [ imageGalleryAttachments , setImageGalleryAttachments ] = useState < Photo < StreamChatGenerics > [ ] > ( photos ) ;
278297
279298 /**
280299 * Photos length needs to be kept as a const here so if the length
@@ -284,17 +303,6 @@ export const ImageGallery = <
284303 */
285304 const photoLength = photos . length ;
286305
287- useEffect ( ( ) => {
288- setImageGalleryAttachments ( photos ) ;
289- // eslint-disable-next-line react-hooks/exhaustive-deps
290- } , [ ] ) ;
291-
292- /**
293- * The URL for the images may differ because of dimensions passed as
294- * part of the query.
295- */
296- const stripQueryFromUrl = ( url : string ) => url . split ( '?' ) [ 0 ] ;
297-
298306 /**
299307 * Set selected photo when changed via pressing in the message list
300308 */
@@ -316,8 +324,7 @@ export const ImageGallery = <
316324 ) ;
317325
318326 runOnUI ( updatePosition ) ( newIndex ) ;
319- // eslint-disable-next-line react-hooks/exhaustive-deps
320- } , [ selectedMessage , photoLength ] ) ;
327+ } , [ selectedMessage , photos , index , translationX , fullWindowWidth ] ) ;
321328
322329 /**
323330 * Image heights are not provided and therefore need to be calculated.
@@ -328,22 +335,24 @@ export const ImageGallery = <
328335 const uriForCurrentImage = imageGalleryAttachments [ selectedIndex ] ?. uri ;
329336
330337 useEffect ( ( ) => {
331- setCurrentImageHeight ( fullWindowHeight ) ;
338+ let currentImageHeight = fullWindowHeight ;
332339 const photo = imageGalleryAttachments [ index . value ] ;
333340 const height = photo ?. original_height ;
334341 const width = photo ?. original_width ;
335342
336343 if ( height && width ) {
337344 const imageHeight = Math . floor ( height * ( fullWindowWidth / width ) ) ;
338- setCurrentImageHeight ( imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ) ;
345+ currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ;
339346 } else if ( photo ?. uri ) {
340347 if ( photo . type === FileTypes . Image ) {
341348 Image . getSize ( photo . uri , ( width , height ) => {
342349 const imageHeight = Math . floor ( height * ( fullWindowWidth / width ) ) ;
343- setCurrentImageHeight ( imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ) ;
350+ currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ;
344351 } ) ;
345352 }
346353 }
354+
355+ setCurrentImageHeight ( currentImageHeight ) ;
347356 // eslint-disable-next-line react-hooks/exhaustive-deps
348357 } , [ uriForCurrentImage ] ) ;
349358
0 commit comments