@@ -11,6 +11,7 @@ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
1111import Animated , {
1212 clamp ,
1313 runOnJS ,
14+ useAnimatedReaction ,
1415 useAnimatedStyle ,
1516 useDerivedValue ,
1617 useSharedValue ,
@@ -64,6 +65,9 @@ export const MessageOverlayHostLayer = ({ BackgroundComponent }: MessageOverlayH
6465 const topH = useSharedValue < Rect > ( undefined ) ;
6566 const bottomH = useSharedValue < Rect > ( undefined ) ;
6667 const closeCorrectionY = useSharedValue ( 0 ) ;
68+ const topVisualY = useSharedValue ( 0 ) ;
69+ const messageVisualY = useSharedValue ( 0 ) ;
70+ const bottomVisualY = useSharedValue ( 0 ) ;
6771
6872 const topInset = insets . top ;
6973 // Due to edge-to-edge in combination with various libraries, Android sometimes reports
@@ -95,6 +99,9 @@ export const MessageOverlayHostLayer = ({ BackgroundComponent }: MessageOverlayH
9599 topH . value = undefined ;
96100 bottomH . value = undefined ;
97101 closeCorrectionY . value = 0 ;
102+ topVisualY . value = 0 ;
103+ messageVisualY . value = 0 ;
104+ bottomVisualY . value = 0 ;
98105 } ,
99106 setBottomH : ( rect ) => {
100107 bottomH . value = rect ;
@@ -106,7 +113,7 @@ export const MessageOverlayHostLayer = ({ BackgroundComponent }: MessageOverlayH
106113 topH . value = rect ;
107114 } ,
108115 } ) ,
109- [ bottomH , closeCorrectionY , messageH , topH ] ,
116+ [ bottomH , bottomVisualY , closeCorrectionY , messageH , messageVisualY , topH , topVisualY ] ,
110117 ) ;
111118
112119 useEffect ( ( ) => {
@@ -156,75 +163,123 @@ export const MessageOverlayHostLayer = ({ BackgroundComponent }: MessageOverlayH
156163 return solvedBottomTop - bottomH . value . y ;
157164 } ) ;
158165
166+ useAnimatedReaction (
167+ ( ) => {
168+ if ( ! topH . value ) return undefined ;
169+ const correction = isActive ? ( closing ? closeCorrectionY . value : messageShiftY . value ) : 0 ;
170+ return topH . value . y + correction ;
171+ } ,
172+ ( next , previous ) => {
173+ if ( next === undefined ) {
174+ topVisualY . value = 0 ;
175+ return ;
176+ }
177+
178+ if ( previous === undefined ) {
179+ topVisualY . value = next ;
180+ return ;
181+ }
182+
183+ topVisualY . value = withSpring ( next , { duration : DURATION } ) ;
184+ } ,
185+ [ isActive , closing ] ,
186+ ) ;
187+
188+ useAnimatedReaction (
189+ ( ) => {
190+ if ( ! messageH . value ) return undefined ;
191+ const correction = isActive ? ( closing ? closeCorrectionY . value : messageShiftY . value ) : 0 ;
192+ return messageH . value . y + correction ;
193+ } ,
194+ ( next , previous ) => {
195+ if ( next === undefined ) {
196+ messageVisualY . value = 0 ;
197+ return ;
198+ }
199+
200+ if ( previous === undefined ) {
201+ messageVisualY . value = next ;
202+ return ;
203+ }
204+
205+ messageVisualY . value = withSpring ( next , { duration : DURATION } ) ;
206+ } ,
207+ [ isActive , closing ] ,
208+ ) ;
209+
210+ useAnimatedReaction (
211+ ( ) => {
212+ if ( ! bottomH . value ) return undefined ;
213+ const correction = isActive ? ( closing ? closeCorrectionY . value : bottomShiftY . value ) : 0 ;
214+ return bottomH . value . y + correction ;
215+ } ,
216+ ( next , previous ) => {
217+ if ( next === undefined ) {
218+ bottomVisualY . value = 0 ;
219+ return ;
220+ }
221+
222+ if ( previous === undefined ) {
223+ bottomVisualY . value = next ;
224+ return ;
225+ }
226+
227+ bottomVisualY . value = withSpring ( next , { duration : DURATION } ) ;
228+ } ,
229+ [ isActive , closing ] ,
230+ ) ;
231+
159232 const topItemStyle = useAnimatedStyle ( ( ) => {
160- if ( ! topH . value ) return { height : 0 } ;
233+ if ( ! topVisualY . value || ! topH . value ) return { opacity : 0 } ;
161234 const horizontalPosition = I18nManager . isRTL ? { right : topH . value . x } : { left : topH . value . x } ;
162235 return {
163236 height : topH . value . h ,
164237 position : 'absolute' ,
165- top : topH . value . y ,
238+ top : topVisualY . value ,
239+ opacity : 1 ,
166240 width : topH . value . w ,
167241 ...horizontalPosition ,
168242 } ;
169243 } ) ;
170244
171245 const topItemTranslateStyle = useAnimatedStyle ( ( ) => {
172- const target = isActive ? ( closing ? closeCorrectionY . value : messageShiftY . value ) : 0 ;
173246 return {
174- transform : [
175- { scale : backdrop . value } ,
176- { translateY : withSpring ( target , { duration : DURATION } ) } ,
177- ] ,
247+ transform : [ { scale : backdrop . value } ] ,
178248 } ;
179- } , [ isActive , closing ] ) ;
249+ } ) ;
180250
181251 const bottomItemStyle = useAnimatedStyle ( ( ) => {
182- if ( ! bottomH . value ) return { height : 0 } ;
252+ if ( ! bottomVisualY . value || ! bottomH . value ) return { opacity : 0 } ;
183253 const horizontalPosition = I18nManager . isRTL
184254 ? { right : bottomH . value . x }
185255 : { left : bottomH . value . x } ;
186256 return {
187257 height : bottomH . value . h ,
188258 position : 'absolute' ,
189- top : bottomH . value . y ,
259+ top : bottomVisualY . value ,
260+ opacity : 1 ,
190261 width : bottomH . value . w ,
191262 ...horizontalPosition ,
192263 } ;
193264 } ) ;
194265
195266 const bottomItemTranslateStyle = useAnimatedStyle ( ( ) => {
196- const target = isActive ? ( closing ? closeCorrectionY . value : bottomShiftY . value ) : 0 ;
197267 return {
198- transform : [
199- { scale : backdrop . value } ,
200- { translateY : withSpring ( target , { duration : DURATION } ) } ,
201- ] ,
268+ transform : [ { scale : backdrop . value } ] ,
202269 } ;
203- } , [ isActive , closing ] ) ;
270+ } ) ;
204271
205272 const hostStyle = useAnimatedStyle ( ( ) => {
206273 if ( ! messageH . value ) return { height : 0 } ;
207274 return {
208275 height : messageH . value . h ,
209276 left : messageH . value . x ,
210277 position : 'absolute' ,
211- top : messageH . value . y ,
278+ top : messageVisualY . value ,
212279 width : messageH . value . w ,
213280 } ;
214281 } ) ;
215282
216- const hostTranslateStyle = useAnimatedStyle ( ( ) => {
217- const target = isActive ? ( closing ? closeCorrectionY . value : messageShiftY . value ) : 0 ;
218-
219- return {
220- transform : [
221- {
222- translateY : withSpring ( target , { duration : DURATION } ) ,
223- } ,
224- ] ,
225- } ;
226- } , [ isActive , closing ] ) ;
227-
228283 const tap = useMemo (
229284 ( ) =>
230285 Gesture . Tap ( )
@@ -288,7 +343,7 @@ export const MessageOverlayHostLayer = ({ BackgroundComponent }: MessageOverlayH
288343
289344 < Animated . View
290345 pointerEvents = 'box-none'
291- style = { [ hostStyle , hostTranslateStyle ] }
346+ style = { hostStyle }
292347 testID = 'message-overlay-message'
293348 >
294349 < PortalHost name = 'message-overlay' style = { StyleSheet . absoluteFillObject } />
0 commit comments