Skip to content

Commit 26320ce

Browse files
authored
Merge pull request #58 from okgrow/feat/active-flag-for-steps
feat: Active flag for steps
2 parents 147b3ac + bbfdef2 commit 26320ce

File tree

3 files changed

+85
-9
lines changed

3 files changed

+85
-9
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>

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/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)