Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#40 - Usage inside scrollview issue fixed #112

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 67 additions & 5 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as React from 'react'
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
Expand All @@ -21,22 +22,22 @@ const uri =
// Add <TourGuideProvider/> at the root of you app!
function App() {
return (
<TourGuideProvider {...{ borderRadius: 16, androidStatusBarVisible: true }}>
<TourGuideProvider {...{ borderRadius: 16, androidStatusBarVisible: true }} preventOutsideInteraction>
<AppContent />
</TourGuideProvider>
)
}

const AppContent = () => {
const iconProps = { size: 40, color: '#888' }

const scrollRef = React.useRef(null);
// Use Hooks to control!
const { start, canStart, stop, eventEmitter } = useTourGuideController()

React.useEffect(() => {
// start at mount
if (canStart) {
start()
start(1,scrollRef)
}
}, [canStart]) // wait until everything is registered

Expand All @@ -47,11 +48,71 @@ const AppContent = () => {
return () => eventEmitter.off('*', null)
}, [])
return (
<ScrollView
ref={(r)=> {scrollRef.current = r}}
contentContainerStyle={{ flexGrow: 1 }}
scrollEventThrottle={16}
keyboardShouldPersistTaps={'always'}
>
<View style={styles.container}>
{/* Use TourGuideZone only to wrap */}
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<Text style={styles.title}>
{'Welcome to the demo of\n"rn-tourguide"'}
</Text>
<TourGuideZone
keepTooltipPosition
zone={2}
zone={6}
text={'A react-native-copilot remastered! 🎉'}
borderRadius={16}
>
Expand Down Expand Up @@ -92,7 +153,7 @@ const AppContent = () => {
<TourGuideZone zone={5}>
<Ionicons name='ios-navigate' {...iconProps} />
</TourGuideZone>
<TourGuideZone zone={6} shape={'circle'}>
<TourGuideZone zone={2} shape={'circle'}>
<Ionicons name='ios-rainy' {...iconProps} />
</TourGuideZone>
</View>
Expand Down Expand Up @@ -120,6 +181,7 @@ const AppContent = () => {
/>
) : null}
</View>
</ScrollView>
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/TourGuideContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface ITourGuideContext {
registerStep?(key: string, step: IStep): void
unregisterStep?(key: string, stepName: string): void
getCurrentStep?(key: string): IStep | undefined
start?(key: string, fromStep?: number): void
start?(key: string, fromStep?: number, scrollRef?: React.RefObject<any>): void
stop?(key: string): void
}

Expand Down
57 changes: 46 additions & 11 deletions src/components/TourGuideProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import mitt, { Emitter } from 'mitt'
import * as React from 'react'
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'
import {
findNodeHandle,
StyleProp,
StyleSheet,
View,
ViewStyle,
} from 'react-native'
import { TourGuideContext, Ctx } from './TourGuideContext'
import { useIsMounted } from '../hooks/useIsMounted'
import { IStep, Labels, StepObject, Steps } from '../types'
Expand Down Expand Up @@ -49,6 +55,7 @@ export const TourGuideProvider = ({
dismissOnPress = false,
preventOutsideInteraction = false,
}: TourGuideProviderProps) => {
const [scrollRef, setScrollRef] = useState<React.RefObject<any>>()
const [tourKey, setTourKey] = useState<string | '_default'>('_default')
const [visible, updateVisible] = useState<Ctx<boolean | undefined>>({
_default: false,
Expand Down Expand Up @@ -133,15 +140,36 @@ export const TourGuideProvider = ({
})
}

const setCurrentStep = (key: string, step?: IStep) =>
new Promise<void>((resolve) => {
updateCurrentStep((currentStep) => {
const newStep = { ...currentStep }
newStep[key] = step
eventEmitter[key]?.emit('stepChange', step)
return newStep
})
resolve()
const setCurrentStep = async (key: string, step?: IStep) =>
new Promise<void>(async (resolve) => {
if (scrollRef && step) {
await step.wrapper.measureLayout(
findNodeHandle(scrollRef.current),
(_x: number, y: number, _w: number, h: number) => {
const yOffsett = y > 0 ? y - h / 2 : 0
scrollRef.current.scrollTo({ y: yOffsett, animated: false })
},
)
setTimeout(() => {
updateCurrentStep((currentStep) => {
const newStep = { ...currentStep }
newStep[key] = step
eventEmitter[key]?.emit('stepChange', step)
return newStep
})
resolve()
}, 100);
}
else {
updateCurrentStep((currentStep) => {
const newStep = { ...currentStep }
newStep[key] = step
eventEmitter[key]?.emit('stepChange', step)
return newStep
})
resolve()
}

})

const getNextStep = (
Expand Down Expand Up @@ -212,7 +240,14 @@ export const TourGuideProvider = ({

const getCurrentStep = (key: string) => currentStep[key]

const start = async (key: string, fromStep?: number) => {
const start = async (
key: string,
fromStep?: number,
_scrollRef?: React.RefObject<any>,
) => {
if (!scrollRef) {
setScrollRef(_scrollRef)
}
const currentStep = fromStep
? (steps[key] as StepObject)[fromStep]
: getFirstStep(key)
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useTourGuideController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export const useTourGuideController = (tourKey?: string) => {

const key = tourKey ?? '_default'

const _start = (fromStep?: number) => {
const _start = (fromStep?: number,scrollRef?: React.RefObject<any>) => {
if (setTourKey) {
setTourKey(key)
}
if (start) {
start(key, fromStep)
start(key, fromStep,scrollRef)
}
}
const _stop = () => {
Expand Down