Skip to content

Commit e2b6df8

Browse files
committed
Refactor code by making smaller code chunkes
1 parent 2291c89 commit e2b6df8

File tree

1 file changed

+45
-40
lines changed

1 file changed

+45
-40
lines changed

ts/features/tour/components/TourOverlay.tsx

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");
3838
const SCROLL_SETTLE_MS = 400;
3939
const VISIBLE_MARGIN = 16;
4040

41+
/**
42+
* Synchronous on Fabric via JSI. The callback fires inline,
43+
* so the return value is available immediately.
44+
*/
45+
const measureInWindow = (view: View): TourItemMeasurement | undefined => {
46+
const result: { value: TourItemMeasurement | undefined } = {
47+
value: undefined
48+
};
49+
view.measureInWindow((x, y, width, height) => {
50+
if (width !== 0 || height !== 0) {
51+
result.value = { x, y, width, height };
52+
}
53+
});
54+
return result.value;
55+
};
56+
4157
export const TourOverlay = () => {
4258
const { getMeasurement, getConfig, getScrollRef } = useTourContext();
4359
const isActive = useIOSelector(isTourActiveSelector);
@@ -46,27 +62,25 @@ export const TourOverlay = () => {
4662
const items = useIOSelector(tourItemsForActiveGroupSelector);
4763

4864
const overlayRef = useRef<View>(null);
49-
const overlayOffsetRef = useRef({ x: 0, y: 0 });
5065
const isFirstMeasurement = useRef(true);
5166
const measureGeneration = useRef(0);
5267

53-
// Local visibility state: stays true during fade-out
5468
const [visible, setVisible] = useState(false);
5569

56-
const cutoutX = useSharedValue(0);
57-
const cutoutY = useSharedValue(0);
58-
const cutoutW = useSharedValue(0);
59-
const cutoutH = useSharedValue(0);
60-
const opacity = useSharedValue(0);
61-
const cutoutOpacity = useSharedValue(1);
62-
6370
const [measurement, setMeasurement] = useState<
6471
TourItemMeasurement | undefined
6572
>(undefined);
6673
const [tooltipConfig, setTooltipConfig] = useState<
6774
{ title: string; description: string } | undefined
6875
>(undefined);
6976

77+
const cutoutX = useSharedValue(0);
78+
const cutoutY = useSharedValue(0);
79+
const cutoutW = useSharedValue(0);
80+
const cutoutH = useSharedValue(0);
81+
const opacity = useSharedValue(0);
82+
const cutoutOpacity = useSharedValue(1);
83+
7084
// When tour becomes active, mount the overlay and reset first-measurement flag
7185
useEffect(() => {
7286
if (isActive) {
@@ -84,19 +98,6 @@ export const TourOverlay = () => {
8498
}
8599
}, [isActive, visible, opacity]);
86100

87-
const measureOverlayOffset = useCallback(() => {
88-
if (!overlayRef.current) {
89-
return { x: 0, y: 0 };
90-
}
91-
const result = { x: 0, y: 0 };
92-
overlayRef.current.measureInWindow((x, y) => {
93-
result.x = x;
94-
result.y = y;
95-
});
96-
overlayOffsetRef.current = result;
97-
return result;
98-
}, []);
99-
100101
const scrollIntoViewIfNeeded = useCallback(
101102
async (
102103
gId: string,
@@ -170,25 +171,29 @@ export const TourOverlay = () => {
170171
config: { title: string; description: string } | undefined,
171172
didScroll: boolean
172173
) => {
173-
if (isFirstMeasurement.current) {
174-
// First step: position cutout immediately, then fade the overlay in
175-
isFirstMeasurement.current = false;
174+
const updateStep = () => {
176175
setMeasurement(padded);
177176
setTooltipConfig(config);
177+
};
178+
179+
const positionCutout = () => {
178180
cutoutX.value = padded.x;
179181
cutoutY.value = padded.y;
180182
cutoutW.value = padded.width;
181183
cutoutH.value = padded.height;
184+
};
185+
186+
if (isFirstMeasurement.current) {
187+
// First step: position cutout immediately, then fade the overlay in
188+
isFirstMeasurement.current = false;
189+
updateStep();
190+
positionCutout();
182191
cutoutOpacity.value = 1;
183192
opacity.value = withTiming(1, { duration: ANIMATION_DURATION });
184193
} else if (didScroll) {
185194
// Already faded out before scrolling — reposition and fade in
186-
cutoutX.value = padded.x;
187-
cutoutY.value = padded.y;
188-
cutoutW.value = padded.width;
189-
cutoutH.value = padded.height;
190-
setMeasurement(padded);
191-
setTooltipConfig(config);
195+
positionCutout();
196+
updateStep();
192197
cutoutOpacity.value = withTiming(1, {
193198
duration: ANIMATION_DURATION,
194199
easing: STEP_EASING
@@ -198,10 +203,6 @@ export const TourOverlay = () => {
198203
// Cancel any lingering animation on cutoutOpacity from a previous
199204
// step to ensure the completion callback fires reliably.
200205
cancelAnimation(cutoutOpacity);
201-
const updateStepUI = () => {
202-
setMeasurement(padded);
203-
setTooltipConfig(config);
204-
};
205206
cutoutOpacity.value = withTiming(
206207
0,
207208
{ duration: ANIMATION_DURATION, easing: STEP_EASING },
@@ -210,7 +211,7 @@ export const TourOverlay = () => {
210211
cutoutY.value = padded.y;
211212
cutoutW.value = padded.width;
212213
cutoutH.value = padded.height;
213-
runOnJS(updateStepUI)();
214+
runOnJS(updateStep)();
214215
cutoutOpacity.value = withTiming(1, {
215216
duration: ANIMATION_DURATION,
216217
easing: STEP_EASING
@@ -254,11 +255,16 @@ export const TourOverlay = () => {
254255

255256
const { measurement: m, didScroll } = scrollResult;
256257

257-
const offset = measureOverlayOffset();
258+
// Measure overlay position to convert page coords → overlay-relative coords
259+
const overlayOffset = overlayRef.current
260+
? measureInWindow(overlayRef.current)
261+
: undefined;
262+
const ox = overlayOffset?.x ?? 0;
263+
const oy = overlayOffset?.y ?? 0;
258264

259265
const padded: TourItemMeasurement = {
260-
x: m.x - offset.x - CUTOUT_PADDING,
261-
y: m.y - offset.y - CUTOUT_PADDING,
266+
x: m.x - ox - CUTOUT_PADDING,
267+
y: m.y - oy - CUTOUT_PADDING,
262268
width: m.width + CUTOUT_PADDING * 2,
263269
height: m.height + CUTOUT_PADDING * 2
264270
};
@@ -272,7 +278,6 @@ export const TourOverlay = () => {
272278
getMeasurement,
273279
getConfig,
274280
scrollIntoViewIfNeeded,
275-
measureOverlayOffset,
276281
applyCutout
277282
]);
278283

0 commit comments

Comments
 (0)