1
- import React , { RefObject , useCallback , useEffect , useRef , useState } from 'react' ;
1
+ import React , { RefObject , useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
2
2
import { Image , ImageStyle , Keyboard , StyleSheet , ViewStyle } from 'react-native' ;
3
3
4
4
import { Gesture , GestureDetector } from 'react-native-gesture-handler' ;
@@ -125,7 +125,6 @@ export const ImageGallery = (props: Props) => {
125
125
numberOfImageGalleryGridColumns,
126
126
overlayOpacity,
127
127
} = props ;
128
- const [ imageGalleryAttachments , setImageGalleryAttachments ] = useState < Photo [ ] > ( [ ] ) ;
129
128
const { resizableCDNHosts } = useChatConfigContext ( ) ;
130
129
const {
131
130
theme : {
@@ -188,13 +187,6 @@ export const ImageGallery = (props: Props) => {
188
187
*/
189
188
const [ currentImageHeight , setCurrentImageHeight ] = useState < number > ( fullWindowHeight ) ;
190
189
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
-
198
190
/**
199
191
* Header visible value for animating in out
200
192
*/
@@ -214,57 +206,86 @@ export const ImageGallery = (props: Props) => {
214
206
* photo attachments
215
207
*/
216
208
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
+ } ) ;
265
259
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 ) ;
268
289
269
290
/**
270
291
* Photos length needs to be kept as a const here so if the length
@@ -274,17 +295,6 @@ export const ImageGallery = (props: Props) => {
274
295
*/
275
296
const photoLength = photos . length ;
276
297
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
-
288
298
/**
289
299
* Set selected photo when changed via pressing in the message list
290
300
*/
@@ -306,8 +316,7 @@ export const ImageGallery = (props: Props) => {
306
316
) ;
307
317
308
318
runOnUI ( updatePosition ) ( newIndex ) ;
309
- // eslint-disable-next-line react-hooks/exhaustive-deps
310
- } , [ selectedMessage , photoLength ] ) ;
319
+ } , [ selectedMessage , photos , index , translationX , fullWindowWidth ] ) ;
311
320
312
321
/**
313
322
* Image heights are not provided and therefore need to be calculated.
@@ -318,22 +327,24 @@ export const ImageGallery = (props: Props) => {
318
327
const uriForCurrentImage = imageGalleryAttachments [ selectedIndex ] ?. uri ;
319
328
320
329
useEffect ( ( ) => {
321
- setCurrentImageHeight ( fullWindowHeight ) ;
330
+ let currentImageHeight = fullWindowHeight ;
322
331
const photo = imageGalleryAttachments [ index . value ] ;
323
332
const height = photo ?. original_height ;
324
333
const width = photo ?. original_width ;
325
334
326
335
if ( height && width ) {
327
336
const imageHeight = Math . floor ( height * ( fullWindowWidth / width ) ) ;
328
- setCurrentImageHeight ( imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ) ;
337
+ currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ;
329
338
} else if ( photo ?. uri ) {
330
339
if ( photo . type === FileTypes . Image ) {
331
340
Image . getSize ( photo . uri , ( width , height ) => {
332
341
const imageHeight = Math . floor ( height * ( fullWindowWidth / width ) ) ;
333
- setCurrentImageHeight ( imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ) ;
342
+ currentImageHeight = imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight ;
334
343
} ) ;
335
344
}
336
345
}
346
+
347
+ setCurrentImageHeight ( currentImageHeight ) ;
337
348
// eslint-disable-next-line react-hooks/exhaustive-deps
338
349
} , [ uriForCurrentImage ] ) ;
339
350
0 commit comments