Skip to content

Commit 4618ea3

Browse files
committed
fix: context menu shared value synchronicity
1 parent 4e8acc1 commit 4618ea3

1 file changed

Lines changed: 86 additions & 31 deletions

File tree

package/src/contexts/overlayContext/MessageOverlayHostLayer.tsx

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Gesture, GestureDetector } from 'react-native-gesture-handler';
1111
import 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

Comments
 (0)