@@ -73,6 +73,16 @@ const ItemSeparatorComponent = () => {
7373 return < View style = { [ styles . itemSeparator , itemSeparator ] } /> ;
7474} ;
7575
76+ const useLazyRef = < T , > ( getInitialValue : ( ) => T ) => {
77+ const ref = useRef < T | null > ( null ) ;
78+
79+ if ( ref . current === null ) {
80+ ref . current = getInitialValue ( ) ;
81+ }
82+
83+ return ref as React . RefObject < T > ;
84+ } ;
85+
7686const getIsAudioAttachmentPreview =
7787 ( soundPackageAvailable : boolean ) =>
7888 (
@@ -102,17 +112,17 @@ const UnMemoizedAttachmentUploadPreviewList = () => {
102112 ( ) => getIsAudioAttachmentPreview ( soundPackageAvailable ) ,
103113 [ soundPackageAvailable ] ,
104114 ) ;
105- const dataRef = useRef < LocalAttachment [ ] > ( [ ] ) ;
106- const previousDataRef = useRef < LocalAttachment [ ] > ( [ ] ) ;
115+ const dataRef = useLazyRef < LocalAttachment [ ] > ( ( ) => [ ] ) ;
116+ const previousDataRef = useLazyRef < LocalAttachment [ ] > ( ( ) => [ ] ) ;
107117 const previousNonAudioAttachmentsLengthRef = useRef ( 0 ) ;
108118 const contentWidthRef = useRef ( 0 ) ;
109119 const itemsContentWidthRef = useRef ( 0 ) ;
110120 const viewportWidthRef = useRef ( 0 ) ;
111121 const scrollOffsetXRef = useRef ( 0 ) ;
112- const attachmentCellWidthsRef = useRef < Record < string , number > > ( { } ) ;
113- const preparedRemovalIdsRef = useRef < Set < string > > ( new Set ( ) ) ;
114- const spacerReleaseFramesRef = useRef < Set < number > > ( new Set ( ) ) ;
115- const spacerReleaseTimeoutsRef = useRef < Set < ReturnType < typeof setTimeout > > > ( new Set ( ) ) ;
122+ const attachmentCellWidthsRef = useLazyRef < Record < string , number > > ( ( ) => ( { } ) ) ;
123+ const preparedRemovalIdsRef = useLazyRef < Set < string > > ( ( ) => new Set ( ) ) ;
124+ const spacerReleaseFramesRef = useLazyRef < Set < number > > ( ( ) => new Set ( ) ) ;
125+ const spacerReleaseTimeoutsRef = useLazyRef < Set < ReturnType < typeof setTimeout > > > ( ( ) => new Set ( ) ) ;
116126 const shouldScrollToEndOnContentSizeChangeRef = useRef ( false ) ;
117127 const trailingSpacerWidthRef = useRef ( 0 ) ;
118128 const [ trailingSpacerWidth , setTrailingSpacerWidth ] = useState ( 0 ) ;
@@ -198,47 +208,52 @@ const UnMemoizedAttachmentUploadPreviewList = () => {
198208
199209 spacerReleaseTimeoutsRef . current . add ( timeout ) ;
200210 } ,
201- [ setTrailingSpacerLayoutWidth ] ,
211+ [ setTrailingSpacerLayoutWidth , spacerReleaseFramesRef , spacerReleaseTimeoutsRef ] ,
202212 ) ;
203213
204- const getRemovalMetrics = useCallback ( ( ids : string [ ] , baseData : LocalAttachment [ ] ) => {
205- const removedIds = new Set ( ids ) ;
206- const fallbackCellWidth = baseData . length ? itemsContentWidthRef . current / baseData . length : 0 ;
207- const offsetBefore = scrollOffsetXRef . current ;
208- const oldMaxOffset = Math . max ( 0 , itemsContentWidthRef . current - viewportWidthRef . current ) ;
209- const wasNearEnd = oldMaxOffset - offsetBefore <= END_ANCHOR_THRESHOLD ;
210- let contentOffset = 0 ;
211- let removedContentWidth = 0 ;
212- let anchorCorrectionWidth = 0 ;
213-
214- baseData . forEach ( ( attachment ) => {
215- const attachmentId = attachment . localMetadata . id ;
216- const cellWidth = attachmentCellWidthsRef . current [ attachmentId ] ?? fallbackCellWidth ;
217-
218- if ( removedIds . has ( attachmentId ) ) {
219- removedContentWidth += cellWidth ;
220- if ( contentOffset <= offsetBefore ) {
221- anchorCorrectionWidth += cellWidth ;
214+ const getRemovalMetrics = useCallback (
215+ ( ids : string [ ] , baseData : LocalAttachment [ ] ) => {
216+ const removedIds = new Set ( ids ) ;
217+ const fallbackCellWidth = baseData . length
218+ ? itemsContentWidthRef . current / baseData . length
219+ : 0 ;
220+ const offsetBefore = scrollOffsetXRef . current ;
221+ const oldMaxOffset = Math . max ( 0 , itemsContentWidthRef . current - viewportWidthRef . current ) ;
222+ const wasNearEnd = oldMaxOffset - offsetBefore <= END_ANCHOR_THRESHOLD ;
223+ let contentOffset = 0 ;
224+ let removedContentWidth = 0 ;
225+ let anchorCorrectionWidth = 0 ;
226+
227+ baseData . forEach ( ( attachment ) => {
228+ const attachmentId = attachment . localMetadata . id ;
229+ const cellWidth = attachmentCellWidthsRef . current [ attachmentId ] ?? fallbackCellWidth ;
230+
231+ if ( removedIds . has ( attachmentId ) ) {
232+ removedContentWidth += cellWidth ;
233+ if ( contentOffset <= offsetBefore ) {
234+ anchorCorrectionWidth += cellWidth ;
235+ }
222236 }
223- }
224237
225- contentOffset += cellWidth ;
226- } ) ;
238+ contentOffset += cellWidth ;
239+ } ) ;
240+
241+ if ( ! removedContentWidth ) {
242+ return {
243+ removedContentWidth : 0 ,
244+ scrollCorrectionWidth : 0 ,
245+ } ;
246+ }
227247
228- if ( ! removedContentWidth ) {
229248 return {
230- removedContentWidth : 0 ,
231- scrollCorrectionWidth : 0 ,
249+ removedContentWidth,
250+ scrollCorrectionWidth : wasNearEnd
251+ ? removedContentWidth
252+ : Math . min ( anchorCorrectionWidth , removedContentWidth ) ,
232253 } ;
233- }
234-
235- return {
236- removedContentWidth,
237- scrollCorrectionWidth : wasNearEnd
238- ? removedContentWidth
239- : Math . min ( anchorCorrectionWidth , removedContentWidth ) ,
240- } ;
241- } , [ ] ) ;
254+ } ,
255+ [ attachmentCellWidthsRef ] ,
256+ ) ;
242257
243258 const applyRemovalScrollCorrection = useCallback (
244259 ( removedContentWidth : number , scrollCorrectionWidth : number ) => {
@@ -272,15 +287,21 @@ const UnMemoizedAttachmentUploadPreviewList = () => {
272287 applyRemovalScrollCorrection ( removedContentWidth , scrollCorrectionWidth ) ;
273288 ids . forEach ( ( id ) => preparedRemovalIdsRef . current . add ( id ) ) ;
274289 } ,
275- [ applyRemovalScrollCorrection , getRemovalMetrics , isRTL , prepareTrailingSpacer ] ,
290+ [
291+ applyRemovalScrollCorrection ,
292+ getRemovalMetrics ,
293+ isRTL ,
294+ preparedRemovalIdsRef ,
295+ prepareTrailingSpacer ,
296+ ] ,
276297 ) ;
277298
278299 const removeAttachments = useCallback (
279300 ( ids : string [ ] ) => {
280301 prepareForRemoval ( ids , dataRef . current ) ;
281302 attachmentManager . removeAttachments ( ids ) ;
282303 } ,
283- [ attachmentManager , prepareForRemoval ] ,
304+ [ attachmentManager , dataRef , prepareForRemoval ] ,
284305 ) ;
285306
286307 useLayoutEffect ( ( ) => {
@@ -310,7 +331,16 @@ const UnMemoizedAttachmentUploadPreviewList = () => {
310331
311332 previousDataRef . current = data ;
312333 dataRef . current = data ;
313- } , [ data , getRemovalMetrics , isRTL , prepareForRemoval , scheduleTrailingSpacerRelease ] ) ;
334+ } , [
335+ data ,
336+ dataRef ,
337+ getRemovalMetrics ,
338+ isRTL ,
339+ preparedRemovalIdsRef ,
340+ prepareForRemoval ,
341+ previousDataRef ,
342+ scheduleTrailingSpacerRelease ,
343+ ] ) ;
314344
315345 useEffect (
316346 ( ) => ( ) => {
@@ -319,7 +349,7 @@ const UnMemoizedAttachmentUploadPreviewList = () => {
319349 spacerReleaseTimeoutsRef . current . forEach ( clearTimeout ) ;
320350 spacerReleaseTimeoutsRef . current . clear ( ) ;
321351 } ,
322- [ ] ,
352+ [ spacerReleaseFramesRef , spacerReleaseTimeoutsRef ] ,
323353 ) ;
324354
325355 const renderAttachmentPreview = useCallback (
@@ -406,9 +436,12 @@ const UnMemoizedAttachmentUploadPreviewList = () => {
406436 viewportWidthRef . current = event . nativeEvent . layout . width ;
407437 } , [ ] ) ;
408438
409- const onAttachmentCellLayout = useCallback ( ( id : string , event : LayoutChangeEvent ) => {
410- attachmentCellWidthsRef . current [ id ] = event . nativeEvent . layout . width ;
411- } , [ ] ) ;
439+ const onAttachmentCellLayout = useCallback (
440+ ( id : string , event : LayoutChangeEvent ) => {
441+ attachmentCellWidthsRef . current [ id ] = event . nativeEvent . layout . width ;
442+ } ,
443+ [ attachmentCellWidthsRef ] ,
444+ ) ;
412445
413446 const onContentSizeChangeHandler = useCallback (
414447 ( width : number ) => {
0 commit comments