Skip to content

Commit 2303c84

Browse files
committed
Merge branch 'master' of github.com:okgrow/react-native-joyride
2 parents d03bec5 + f8e8472 commit 2303c84

File tree

6 files changed

+91
-14
lines changed

6 files changed

+91
-14
lines changed

example/App.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
3-
import { StyleSheet, Text, Image, View, TouchableOpacity } from 'react-native';
3+
import { StyleSheet, Text, Image, View, TouchableOpacity, Switch } from 'react-native';
44
import { Ionicons } from '@expo/vector-icons';
55

66
import { copilot, walkthroughable, CopilotStep } from '@okgrow/react-native-copilot';
@@ -46,6 +46,13 @@ const styles = StyleSheet.create({
4646
flex: 1,
4747
textAlign: 'center',
4848
},
49+
activeSwitchContainer: {
50+
flexDirection: 'row',
51+
justifyContent: 'space-between',
52+
marginBottom: 20,
53+
alignItems: 'center',
54+
paddingHorizontal: 40,
55+
},
4956
});
5057

5158
class App extends Component {
@@ -56,6 +63,10 @@ class App extends Component {
5663
}).isRequired,
5764
};
5865

66+
state = {
67+
secondStepActive: true,
68+
};
69+
5970
componentDidMount() {
6071
this.props.copilotEvents.on('stepChange', this.handleStepChange);
6172
this.props.start();
@@ -74,12 +85,21 @@ class App extends Component {
7485
</WalkthroughableText>
7586
</CopilotStep>
7687
<View style={styles.middleView}>
77-
<CopilotStep text="Here goes your profile picture!" order={2} name="secondText">
88+
<CopilotStep active={this.state.secondStepActive} text="Here goes your profile picture!" order={2} name="secondText">
7889
<WalkthroughableImage
7990
source={{ uri: 'https://pbs.twimg.com/profile_images/527584017189982208/l3wwN-l-_400x400.jpeg' }}
8091
style={styles.profilePhoto}
8192
/>
8293
</CopilotStep>
94+
<View style={styles.activeSwitchContainer}>
95+
<Text>Profile photo step activated?</Text>
96+
<View style={{ flexGrow: 1 }} />
97+
<Switch
98+
onValueChange={secondStepActive => this.setState({ secondStepActive })}
99+
value={this.state.secondStepActive}
100+
/>
101+
</View>
102+
83103
<TouchableOpacity style={styles.button} onPress={() => this.props.start()}>
84104
<Text style={styles.buttonText}>START THE TUTORIAL!</Text>
85105
</TouchableOpacity>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@okgrow/react-native-copilot",
3-
"version": "2.3.0",
3+
"version": "2.4.1",
44
"description": "Make an interactive step by step tour guide for you react-native app",
55
"main": "src/index.js",
66
"private": false,

src/components/ConnectedCopilotStep.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,41 @@ type Props = {
77
name: string,
88
text: string,
99
order: number,
10+
active?: boolean,
1011
_copilot: CopilotContext,
1112
children: React$Element
1213
};
1314

1415
class ConnectedCopilotStep extends Component<Props> {
16+
static defaultProps = {
17+
active: true,
18+
};
19+
1520
componentDidMount() {
21+
if (this.props.active) {
22+
this.register();
23+
}
24+
}
25+
26+
componentWillReceiveProps(nextProps) {
27+
if (nextProps.active !== this.props.active) {
28+
if (nextProps.active) {
29+
this.register();
30+
} else {
31+
this.unregister();
32+
}
33+
}
34+
}
35+
36+
componentWillUnmount() {
37+
this.unregister();
38+
}
39+
40+
setNativeProps(obj) {
41+
this.wrapper.setNativeProps(obj);
42+
}
43+
44+
register() {
1645
this.props._copilot.registerStep({
1746
name: this.props.name,
1847
text: this.props.text,
@@ -22,14 +51,10 @@ class ConnectedCopilotStep extends Component<Props> {
2251
});
2352
}
2453

25-
componentWillUnmount() {
54+
unregister() {
2655
this.props._copilot.unregisterStep(this.props.name);
2756
}
2857

29-
setNativeProps(obj) {
30-
this.wrapper.setNativeProps(obj);
31-
}
32-
3358
measure() {
3459
if (typeof __TEST__ !== 'undefined' && __TEST__) { // eslint-disable-line no-undef
3560
return new Promise(resolve => resolve({

src/components/CopilotModal.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class CopilotModal extends Component<Props, State> {
4646
overlay: typeof NativeModules.RNSVGSvgViewManager !== 'undefined' ? 'svg' : 'view',
4747
// If animated was not specified, rely on the default overlay type
4848
animated: typeof NativeModules.RNSVGSvgViewManager !== 'undefined',
49-
androidStatusBarVisible: true,
49+
androidStatusBarVisible: false,
5050
};
5151

5252
state = {
@@ -61,7 +61,7 @@ class CopilotModal extends Component<Props, State> {
6161
};
6262

6363
componentWillReceiveProps(nextProps: Props) {
64-
if (nextProps.visible === false) {
64+
if (this.props.visible === true && nextProps.visible === false) {
6565
this.reset();
6666
}
6767
}
@@ -97,7 +97,7 @@ class CopilotModal extends Component<Props, State> {
9797

9898
async _animateMove(obj = {}): void {
9999
const layout = await this.measure();
100-
if (this.props.androidStatusBarVisible && Platform.OS === 'android') {
100+
if (!this.props.androidStatusBarVisible && Platform.OS === 'android') {
101101
obj.top -= StatusBar.currentHeight; // eslint-disable-line no-param-reassign
102102
}
103103

src/hocs/copilot.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
55
import { View } from 'react-native';
66

77
import mitt from 'mitt';
8+
import hoistStatics from 'hoist-non-react-statics'
89

910
import CopilotModal from '../components/CopilotModal';
1011
import { OFFSET_WIDTH } from '../components/style';
@@ -198,7 +199,7 @@ const copilot = ({
198199
_copilot: PropTypes.object.isRequired,
199200
};
200201

201-
return Copilot;
202+
return hoistStatics(Copilot, WrappedComponent);
202203
};
203204

204205
export default copilot;

src/hocs/copilot.test.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// @flow
12
import React from 'react';
23
import { View, Modal } from 'react-native';
34
import renderer from 'react-test-renderer';
@@ -8,12 +9,16 @@ import SvgMask from '../components/SvgMask';
89

910
const WalkthroughableView = walkthroughable(View);
1011

11-
const SampleComponent = () => (
12+
type SampleComponentProps = {
13+
secondStepActive?: boolean
14+
};
15+
16+
const SampleComponent = ({ secondStepActive }: SampleComponentProps) => (
1217
<View>
1318
<CopilotStep order={0} name="step-1" text="This is the description for the first step">
1419
<WalkthroughableView />
1520
</CopilotStep>
16-
<CopilotStep order={1} name="step-2" text="This is the description for the second step">
21+
<CopilotStep order={1} name="step-2" active={secondStepActive} text="This is the description for the second step">
1722
<WalkthroughableView />
1823
</CopilotStep>
1924
<CopilotStep order={3} name="step-3" text="This is the description for the third step">
@@ -22,6 +27,10 @@ const SampleComponent = () => (
2227
</View>
2328
);
2429

30+
SampleComponent.defaultProps = {
31+
secondStepActive: true,
32+
};
33+
2534
it('only renders the component within a wrapper as long as tutorial has not been started', () => {
2635
const CopilotComponent = copilot()(SampleComponent);
2736

@@ -134,3 +143,25 @@ it('shows the custom tooltip component if specified', async () => {
134143
expect(tooltip.props.currentStep).toHaveProperty('order');
135144
expect(tooltip.props.currentStep).toHaveProperty('text');
136145
});
146+
147+
it('skips a step if disabled', async () => {
148+
const CopilotComponent = copilot()(SampleComponent);
149+
150+
const tree = renderer.create(<CopilotComponent secondStepActive={false} />);
151+
await tree.root.findByType(SampleComponent).props.start();
152+
153+
const textComponent = tree.root.findByProps({
154+
testID: 'stepDescription',
155+
});
156+
157+
expect(textComponent.props.children).toBe('This is the description for the first step');
158+
159+
await tree.root.instance.next();
160+
161+
expect(textComponent.props.children).not.toBe('This is the description for the second step');
162+
expect(textComponent.props.children).toBe('This is the description for the third step');
163+
164+
await tree.root.instance.prev();
165+
166+
expect(textComponent.props.children).toBe('This is the description for the first step');
167+
});

0 commit comments

Comments
 (0)