From 9cb26bb56b6b61e4e8577519347ada40a7751cd6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 17 Dec 2018 11:07:17 +0100 Subject: Add new first-time tutorial (#9531) * Prepare to load onboarding as a full page * Update the first-time introduction * Improve responsive design * Replace speech bubble with logo * Increase text size and reword first paragraph --- .../mastodon/features/introduction/index.js | 196 +++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 app/javascript/mastodon/features/introduction/index.js (limited to 'app/javascript/mastodon/features/introduction') diff --git a/app/javascript/mastodon/features/introduction/index.js b/app/javascript/mastodon/features/introduction/index.js new file mode 100644 index 000000000..6e0617f72 --- /dev/null +++ b/app/javascript/mastodon/features/introduction/index.js @@ -0,0 +1,196 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ReactSwipeableViews from 'react-swipeable-views'; +import classNames from 'classnames'; +import { connect } from 'react-redux'; +import { FormattedMessage } from 'react-intl'; +import { closeOnboarding } from '../../actions/onboarding'; +import screenHello from '../../../images/screen_hello.svg'; +import screenFederation from '../../../images/screen_federation.svg'; +import screenInteractions from '../../../images/screen_interactions.svg'; +import logoTransparent from '../../../images/logo_transparent.svg'; + +const FrameWelcome = ({ domain, onNext }) => ( +
+
+ +
+ +
+

+

{domain} }} />

+
+ +
+ +
+
+); + +FrameWelcome.propTypes = { + domain: PropTypes.string.isRequired, + onNext: PropTypes.func.isRequired, +}; + +const FrameFederation = ({ onNext }) => ( +
+
+ +
+ +
+
+

+

+
+ +
+

+

+
+ +
+

+

+
+
+ +
+ +
+
+); + +FrameFederation.propTypes = { + onNext: PropTypes.func.isRequired, +}; + +const FrameInteractions = ({ onNext }) => ( +
+
+ +
+ +
+
+

+

+
+ +
+

+

+
+ +
+

+

+
+
+ +
+ +
+
+); + +FrameInteractions.propTypes = { + onNext: PropTypes.func.isRequired, +}; + +@connect(state => ({ domain: state.getIn(['meta', 'domain']) })) +export default class Introduction extends React.PureComponent { + + static propTypes = { + domain: PropTypes.string.isRequired, + dispatch: PropTypes.func.isRequired, + }; + + state = { + currentIndex: 0, + }; + + componentWillMount () { + this.pages = [ + , + , + , + ]; + } + + componentDidMount() { + window.addEventListener('keyup', this.handleKeyUp); + } + + componentWillUnmount() { + window.addEventListener('keyup', this.handleKeyUp); + } + + handleDot = (e) => { + const i = Number(e.currentTarget.getAttribute('data-index')); + e.preventDefault(); + this.setState({ currentIndex: i }); + } + + handlePrev = () => { + this.setState(({ currentIndex }) => ({ + currentIndex: Math.max(0, currentIndex - 1), + })); + } + + handleNext = () => { + const { pages } = this; + + this.setState(({ currentIndex }) => ({ + currentIndex: Math.min(currentIndex + 1, pages.length - 1), + })); + } + + handleSwipe = (index) => { + this.setState({ currentIndex: index }); + } + + handleFinish = () => { + this.props.dispatch(closeOnboarding()); + } + + handleKeyUp = ({ key }) => { + switch (key) { + case 'ArrowLeft': + this.handlePrev(); + break; + case 'ArrowRight': + this.handleNext(); + break; + } + } + + render () { + const { currentIndex } = this.state; + const { pages } = this; + + return ( +
+ + {pages.map((page, i) => ( +
{page}
+ ))} +
+ +
+ {pages.map((_, i) => ( +
+ ))} +
+
+ ); + } + +} -- cgit