fix(mobile): onboarding pager — measure page width so last slide shows "Start browsing"
scrollTo/onScroll used the full screen width, but the ScrollView viewport is narrower (card margins + padding), so the computed index desynced from the visible slide — the last slide kept showing "Next"/"Skip" instead of "Start browsing". Measure the real viewport width via onLayout and use it for paging, scrollTo and index. Caught on the emulator (uiautomator dump — FLAG_SECURE blocks screenshots). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
db23b63e46
commit
1875604c6d
1 changed files with 11 additions and 6 deletions
|
|
@ -10,7 +10,6 @@
|
||||||
*/
|
*/
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
Dimensions,
|
|
||||||
Modal,
|
Modal,
|
||||||
NativeScrollEvent,
|
NativeScrollEvent,
|
||||||
NativeSyntheticEvent,
|
NativeSyntheticEvent,
|
||||||
|
|
@ -97,7 +96,11 @@ export function OnboardingModal() {
|
||||||
const [visible, setVisible] = React.useState(false);
|
const [visible, setVisible] = React.useState(false);
|
||||||
const [index, setIndex] = React.useState(0);
|
const [index, setIndex] = React.useState(0);
|
||||||
const scrollRef = React.useRef<ScrollView>(null);
|
const scrollRef = React.useRef<ScrollView>(null);
|
||||||
const width = Dimensions.get('window').width;
|
// Szerokość STRONY = realna szerokość viewportu ScrollView (mierzona onLayout),
|
||||||
|
// NIE szerokość ekranu — karta ma marginesy + padding, więc ekran ≠ strona.
|
||||||
|
// Użycie szerokości ekranu rozjeżdżało paging vs scrollTo vs index (ostatni
|
||||||
|
// slajd pokazywał "Next" zamiast "Start browsing").
|
||||||
|
const [pageW, setPageW] = React.useState(0);
|
||||||
|
|
||||||
// Pierwsze odpalenie: pokaż jeśli jeszcze nie widziany.
|
// Pierwsze odpalenie: pokaż jeśli jeszcze nie widziany.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|
@ -134,13 +137,14 @@ export function OnboardingModal() {
|
||||||
(i: number) => {
|
(i: number) => {
|
||||||
const clamped = Math.max(0, Math.min(SLIDES.length - 1, i));
|
const clamped = Math.max(0, Math.min(SLIDES.length - 1, i));
|
||||||
setIndex(clamped);
|
setIndex(clamped);
|
||||||
scrollRef.current?.scrollTo({ x: clamped * width, animated: true });
|
if (pageW > 0) scrollRef.current?.scrollTo({ x: clamped * pageW, animated: true });
|
||||||
},
|
},
|
||||||
[width],
|
[pageW],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
const i = Math.round(e.nativeEvent.contentOffset.x / width);
|
if (pageW <= 0) return;
|
||||||
|
const i = Math.round(e.nativeEvent.contentOffset.x / pageW);
|
||||||
if (i !== index) setIndex(i);
|
if (i !== index) setIndex(i);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -164,10 +168,11 @@ export function OnboardingModal() {
|
||||||
pagingEnabled
|
pagingEnabled
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
onMomentumScrollEnd={onScroll}
|
onMomentumScrollEnd={onScroll}
|
||||||
|
onLayout={(e) => setPageW(e.nativeEvent.layout.width)}
|
||||||
style={styles.pager}
|
style={styles.pager}
|
||||||
>
|
>
|
||||||
{SLIDES.map((s, i) => (
|
{SLIDES.map((s, i) => (
|
||||||
<View key={i} style={[styles.slide, { width: width - 48 }]}>
|
<View key={i} style={[styles.slide, pageW > 0 && { width: pageW }]}>
|
||||||
<Text style={styles.icon}>{s.icon}</Text>
|
<Text style={styles.icon}>{s.icon}</Text>
|
||||||
<Text style={styles.title}>{s.title}</Text>
|
<Text style={styles.title}>{s.title}</Text>
|
||||||
<View style={styles.lines}>
|
<View style={styles.lines}>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue