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' ;
@@ -125,7 +125,6 @@ export const ImageGallery = (props: Props) => {
125125 numberOfImageGalleryGridColumns,
126126 overlayOpacity,
127127 } = props ;
128- const [ imageGalleryAttachments , setImageGalleryAttachments ] = useState < Photo [ ] > ( [ ] ) ;
129128 const { resizableCDNHosts } = useChatConfigContext ( ) ;
130129 const {
131130 theme : {
@@ -188,13 +187,6 @@ export const ImageGallery = (props: Props) => {
188187 */
189188 const [ currentImageHeight , setCurrentImageHeight ] = useState < number > ( fullWindowHeight ) ;
190189
191- /**
192- * JS and UI index values, the JS follows the UI but is needed
193- * for rendering the virtualized image list
194- */
195- const [ selectedIndex , setSelectedIndex ] = useState ( 0 ) ;
196- const index = useSharedValue ( 0 ) ;
197-
198190 /**
199191 * Header visible value for animating in out
200192 */
@@ -214,57 +206,86 @@ export const ImageGallery = (props: Props) => {
214206 * photo attachments
215207 */
216208
217- const photos = messages . reduce ( ( acc : Photo [ ] , cur ) => {
218- const attachmentImages =
219- cur . attachments
220- ?. filter (
221- ( attachment ) =>
222- ( attachment . type === FileTypes . Giphy &&
223- ( attachment . giphy ?. [ giphyVersion ] ?. url ||
224- attachment . thumb_url ||
225- attachment . image_url ) ) ||
226- ( attachment . type === FileTypes . Image &&
227- ! attachment . title_link &&
228- ! attachment . og_scrape_url &&
229- getUrlOfImageAttachment ( attachment ) ) ||
230- ( isVideoPlayerAvailable ( ) && attachment . type === FileTypes . Video ) ,
231- )
232- . reverse ( ) || [ ] ;
233-
234- const attachmentPhotos = attachmentImages . map ( ( a ) => {
235- const imageUrl = getUrlOfImageAttachment ( a ) as string ;
236- const giphyURL = a . giphy ?. [ giphyVersion ] ?. url || a . thumb_url || a . image_url ;
237- const isInitiallyPaused = ! autoPlayVideo ;
238-
239- return {
240- channelId : cur . cid ,
241- created_at : cur . created_at ,
242- duration : 0 ,
243- id : `photoId-${ cur . id } -${ imageUrl } ` ,
244- messageId : cur . id ,
245- mime_type : a . type === 'giphy' ? getGiphyMimeType ( giphyURL ?? '' ) : a . mime_type ,
246- original_height : a . original_height ,
247- original_width : a . original_width ,
248- paused : isInitiallyPaused ,
249- progress : 0 ,
250- thumb_url : a . thumb_url ,
251- type : a . type ,
252- uri :
253- a . type === 'giphy'
254- ? giphyURL
255- : getResizedImageUrl ( {
256- height : fullWindowHeight ,
257- resizableCDNHosts,
258- url : imageUrl ,
259- width : fullWindowWidth ,
260- } ) ,
261- user : cur . user ,
262- user_id : cur . user_id ,
263- } ;
264- } ) ;
209+ const photos = useMemo (
210+ ( ) =>
211+ messages . reduce ( ( acc : Photo [ ] , cur ) => {
212+ const attachmentImages =
213+ cur . attachments
214+ ?. filter (
215+ ( attachment ) =>
216+ ( attachment . type === FileTypes . Giphy &&
217+ ( attachment . giphy ?. [ giphyVersion ] ?. url ||
218+ attachment . thumb_url ||
219+ attachment . image_url ) ) ||
220+ ( attachment . type === FileTypes . Image &&
221+ ! attachment . title_link &&
222+ ! attachment . og_scrape_url &&
223+ getUrlOfImageAttachment ( attachment ) ) ||
224+ ( isVideoPlayerAvailable ( ) && attachment . type === FileTypes . Video ) ,
225+ )
226+ . reverse ( ) || [ ] ;
227+
228+ const attachmentPhotos = attachmentImages . map ( ( a ) => {
229+ const imageUrl = getUrlOfImageAttachment ( a ) as string ;
230+ const giphyURL = a . giphy ?. [ giphyVersion ] ?. url || a . thumb_url || a . image_url ;
231+ const isInitiallyPaused = ! autoPlayVideo ;
232+
233+ return {
234+ channelId : cur . cid ,
235+ created_at : cur . created_at ,
236+ duration : 0 ,
237+ id : `photoId-${ cur . id } -${ imageUrl } ` ,
238+ messageId : cur . id ,
239+ mime_type : a . type === 'giphy' ? getGiphyMimeType ( giphyURL ?? '' ) : a . mime_type ,
240+ original_height : a . original_height ,
241+ original_width : a . original_width ,
242+ paused : isInitiallyPaused ,
243+ progress : 0 ,
244+ thumb_url : a . thumb_url ,
245+ type : a . type ,
246+ uri :
247+ a . type === 'giphy'
248+ ? giphyURL
249+ : getResizedImageUrl ( {
250+ height : fullWindowHeight ,
251+ resizableCDNHosts,
252+ url : imageUrl ,
253+ width : fullWindowWidth ,
254+ } ) ,
255+ user : cur . user ,
256+ user_id : cur . user_id ,
257+ } ;
258+ } ) ;
265259
266- return [ ...attachmentPhotos , ...acc ] as Photo [ ] ;
267- } , [ ] ) ;
260+ return [ ...attachmentPhotos , ...acc ] as Photo [ ] ;
261+ } , [ ] ) ,
262+ [ autoPlayVideo , fullWindowHeight , fullWindowWidth , giphyVersion , messages , resizableCDNHosts ] ,
263+ ) ;
264+
265+ /**
266+ * The URL for the images may differ because of dimensions passed as
267+ * part of the query.
268+ */
269+ const stripQueryFromUrl = ( url : string ) => url . split ( '?' ) [ 0 ] ;
270+
271+ const photoSelectedIndex = useMemo ( ( ) => {
272+ const idx = photos . findIndex (
273+ ( photo ) =>
274+ photo . messageId === selectedMessage ?. messageId &&
275+ stripQueryFromUrl ( photo . uri ) === stripQueryFromUrl ( selectedMessage ?. url || '' ) ,
276+ ) ;
277+
278+ return idx === - 1 ? 0 : idx ;
279+ } , [ photos , selectedMessage ] ) ;
280+
281+ /**
282+ * JS and UI index values, the JS follows the UI but is needed
283+ * for rendering the virtualized image list
284+ */
285+ const [ selectedIndex , setSelectedIndex ] = useState ( photoSelectedIndex ) ;
286+ const index = useSharedValue ( photoSelectedIndex ) ;
287+
288+ const [ imageGalleryAttachments , setImageGalleryAttachments ] = useState < Photo [ ] > ( photos ) ;
268289
269290 /**
270291 * Photos length needs to be kept as a const here so if the length
@@ -274,17 +295,6 @@ export const ImageGallery = (props: Props) => {
274295 */
275296 const photoLength = photos . length ;
276297
277- useEffect ( ( ) => {
278- setImageGalleryAttachments ( photos ) ;
279- // eslint-disable-next-line react-hooks/exhaustive-deps
280- } , [ ] ) ;
281-
282- /**
283- * The URL for the images may differ because of dimensions passed as
284- * part of the query.
285- */
286- const stripQueryFromUrl = ( url : string ) => url . split ( '?' ) [ 0 ] ;
287-
288298 /**
289299 * Set selected photo when changed via pressing in the message list
290300 */
@@ -306,8 +316,7 @@ export const ImageGallery = (props: Props) => {
306316 ) ;
307317
308318 runOnUI ( updatePosition ) ( newIndex ) ;
309- // eslint-disable-next-line react-hooks/exhaustive-deps
310- } , [ selectedMessage , photoLength ] ) ;
319+ } , [ selectedMessage , photos , index , translationX , fullWindowWidth ] ) ;
311320
312321 /**
313322 * Image heights are not provided and therefore need to be calculated.
@@ -318,22 +327,24 @@ export const ImageGallery = (props: Props) => {
318327 const uriForCurrentImage = imageGalleryAttachments [ selectedIndex ] ?. uri ;
319328
320329 useEffect ( ( ) => {
321- setCurrentImageHeight ( fullWindowHeight ) ;
330+ let currentImageHeight = fullWindowHeight ;
322331 const photo = imageGalleryAttachments [ index . value ] ;
323332 const height = photo ?. original_height ;
324333 const width = photo ?. original_width ;
325334
326335 if ( height && width ) {
327336 const imageHeight = Math . floor ( height * ( fullWindowWidth / width ) ) ;
328- setCurrentImageHeight ( imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ) ;
337+ currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ;
329338 } else if ( photo ?. uri ) {
330339 if ( photo . type === FileTypes . Image ) {
331340 Image . getSize ( photo . uri , ( width , height ) => {
332341 const imageHeight = Math . floor ( height * ( fullWindowWidth / width ) ) ;
333- setCurrentImageHeight ( imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ) ;
342+ currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ;
334343 } ) ;
335344 }
336345 }
346+
347+ setCurrentImageHeight ( currentImageHeight ) ;
337348 // eslint-disable-next-line react-hooks/exhaustive-deps
338349 } , [ uriForCurrentImage ] ) ;
339350
0 commit comments