diff --git a/js/App.js b/js/App.js index 6ffe919..96bc038 100644 --- a/js/App.js +++ b/js/App.js @@ -11,13 +11,14 @@ import { import { theme } from '../config'; -import Settings from './scenes/Settings'; -import Profile from './scenes/Profile'; -import Compass from './scenes/Compass'; -import Demos from './scenes/Demos'; +import FTU from './scenes/FTU'; import Home from './scenes/Home'; import Item from './scenes/Item'; import Map from './scenes/Map'; +import Profile from './scenes/Profile'; +import Settings from './scenes/Settings'; +import Compass from './scenes/Compass'; +import Demos from './scenes/Demos'; import { connect } from 'react-redux'; import { watchLocation } from './store/actions'; @@ -28,6 +29,7 @@ export class App extends Component { super(props); this.routes = { + ftu: { component: FTU }, home: { component: Home }, item: { component: Item }, map: { component: Map }, diff --git a/js/components/ViewPagerIndicator.js b/js/components/ViewPagerIndicator.js new file mode 100644 index 0000000..852c53d --- /dev/null +++ b/js/components/ViewPagerIndicator.js @@ -0,0 +1,85 @@ +import React, { PropTypes } from 'react'; +import { + View, + Animated, + Dimensions, + StyleSheet, +} from 'react-native'; + +const { width } = Dimensions.get('window'); +const DOT_SIZE = 8; +const DOT_SPACING = 6; +const DOT_FULL_WIDTH = DOT_SIZE + DOT_SPACING * 2; + +/** + * This component is used to style the dots (or bullets) used by + * react-native-viewpager. It's a purely stateless functional component that is + * only concerned with rendering the dots and transitioning the active dot from + * one page of the view pager to another. + * + * @param pageCount {number} The total number of pages. + * @param activePage {number} The currently active page. + * @param scrollValue {Animated.Value} Used to transition the active dot. + * @param scrollOffset {number} Used to reset dot position after a transition. + * @return {Component} + */ +const ViewPagerIndicator = ({ + pageCount, + activePage, + scrollValue, + scrollOffset, +}) => { + // Initial left position of the active dot used during transition. + const offsetX = (width - DOT_FULL_WIDTH * pageCount) / 2 + + (activePage - scrollOffset) * DOT_FULL_WIDTH; + + // The CSS `left` property. + const left = scrollValue.interpolate({ + inputRange: [0, 1], + outputRange: [offsetX, offsetX + DOT_FULL_WIDTH], + }); + + // Create the elements for the inactive dots. + const indicators = []; + for (let i = 0; i < pageCount; i++) { + indicators.push( + + ); + } + + return ( + + {indicators} + + + ); +}; + +ViewPagerIndicator.propTypes = { + goToPage: PropTypes.func, + pageCount: PropTypes.number, + activePage: PropTypes.number, + scrollValue: PropTypes.object, + scrollOffset: PropTypes.number, +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + justifyContent: 'center', + marginBottom: 20, + }, + dot: { + width: DOT_SIZE, + height: DOT_SIZE, + borderRadius: DOT_SIZE / 2, + backgroundColor: 'rgba(255,255,255,0.5)', + marginHorizontal: DOT_SPACING, + }, + activeDot: { + position: 'absolute', + backgroundColor: '#fff', + }, +}); + +export default ViewPagerIndicator; diff --git a/js/images/ftu/background.jpg b/js/images/ftu/background.jpg new file mode 100644 index 0000000..7fff157 Binary files /dev/null and b/js/images/ftu/background.jpg differ diff --git a/js/scenes/Demos.js b/js/scenes/Demos.js index 0ae935e..7f78e37 100644 --- a/js/scenes/Demos.js +++ b/js/scenes/Demos.js @@ -29,6 +29,10 @@ export class List extends Component {
+ + Go to FTU scene + Go to Map scene diff --git a/js/scenes/FTU.js b/js/scenes/FTU.js new file mode 100644 index 0000000..9f670ed --- /dev/null +++ b/js/scenes/FTU.js @@ -0,0 +1,169 @@ +import React, { Component, PropTypes } from 'react'; +import { + View, + Image, + Text, + Button, + Dimensions, + StyleSheet, + Platform, +} from 'react-native'; +import ViewPager from 'react-native-viewpager'; +import ViewPagerIndicator from '../components/ViewPagerIndicator'; +import { connect } from 'react-redux'; +import { theme } from '../../config'; + +const CONTENT = [ + { + title: 'Hear the story of London\'s vibrant street art', + main: 'This month Project Magnet brings you a selection of amazing street art from around London.', + footer: 'Not in London? Tell us where you\'d like to go next.', + }, + { + title: 'Turn on notifications?', + main: 'Notifications can alert you when you\'re close to a point of interest, even when you\'re not inside the app.', + }, +]; + +export class FTU extends Component { + constructor(props) { + super(props); + + this.navigator = this.props.navigator; + + const PAGES = [ + () => this.renderPage1(), + () => this.renderPage2(), + ]; + const dataSource = new ViewPager.DataSource({ + pageHasChanged: (p1, p2) => p1 !== p2, + }); + + this.state = { + dataSource: dataSource.cloneWithPages(PAGES), + }; + } + + render() { + return ( + + + render()} + renderPageIndicator={() => } + style={styles.viewPager}/> + + + ); + } + + renderPage1() { + const DATA = CONTENT[0]; + + return ( + + {DATA.title.toUpperCase()} + {DATA.main} + + +