[Glitch] Add more tips to onboarding flow in web UI
Port c35e3cb6ac
to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
pull/2493/head
parent
4537b4b961
commit
e0b401e295
|
@ -46,6 +46,16 @@ class Follows extends React.PureComponent {
|
||||||
render () {
|
render () {
|
||||||
const { onBack, isLoading, suggestions, account } = this.props;
|
const { onBack, isLoading, suggestions, account } = this.props;
|
||||||
|
|
||||||
|
let loadedContent;
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
loadedContent = (new Array(8)).fill().map((_, i) => <EmptyAccount key={i} />);
|
||||||
|
} else if (suggestions.isEmpty()) {
|
||||||
|
loadedContent = <div className='follow-recommendations__empty'><FormattedMessage id='onboarding.follows.empty' defaultMessage='Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.' /></div>;
|
||||||
|
} else {
|
||||||
|
loadedContent = suggestions.map(suggestion => <Account id={suggestion.get('account')} key={suggestion.get('account')} />);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column>
|
<Column>
|
||||||
<ColumnBackButton onClick={onBack} />
|
<ColumnBackButton onClick={onBack} />
|
||||||
|
@ -59,12 +69,10 @@ class Follows extends React.PureComponent {
|
||||||
<ProgressIndicator steps={7} completed={account.get('following_count') * 1} />
|
<ProgressIndicator steps={7} completed={account.get('following_count') * 1} />
|
||||||
|
|
||||||
<div className='follow-recommendations'>
|
<div className='follow-recommendations'>
|
||||||
{isLoading ? (new Array(8)).fill().map((_, i) => <EmptyAccount key={i} />) : suggestions.map(suggestion => (
|
{loadedContent}
|
||||||
<Account id={suggestion.get('account')} key={suggestion.get('account')} />
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' values={{ strong: text => <strong>{text}</strong> }} /></p>
|
<p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' /></p>
|
||||||
|
|
||||||
<div className='onboarding__footer'>
|
<div className='onboarding__footer'>
|
||||||
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.actions.back' defaultMessage='Take me back' /></button>
|
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.actions.back' defaultMessage='Take me back' /></button>
|
||||||
|
|
|
@ -5,14 +5,15 @@ import PropTypes from 'prop-types';
|
||||||
import { me, domain } from 'flavours/glitch/initial_state';
|
import { me, domain } from 'flavours/glitch/initial_state';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage, FormattedHTMLMessage } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from 'flavours/glitch/components/icon';
|
import Icon from 'flavours/glitch/components/icon';
|
||||||
import ArrowSmallRight from './components/arrow_small_right';
|
import ArrowSmallRight from './components/arrow_small_right';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import SwipeableViews from 'react-swipeable-views';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
shareableMessage: { id: 'onboarding.share.message', defaultMessage: 'I\'m {username} on Mastodon! Come follow me at {url}' },
|
shareableMessage: { id: 'onboarding.share.message', defaultMessage: 'I\'m {username} on #Mastodon! Come follow me at {url}' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
@ -80,6 +81,60 @@ class CopyPasteText extends React.PureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TipCarousel extends React.PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
index: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
handleSwipe = index => {
|
||||||
|
this.setState({ index });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChangeIndex = e => {
|
||||||
|
this.setState({ index: Number(e.currentTarget.getAttribute('data-index')) });
|
||||||
|
};
|
||||||
|
|
||||||
|
handleKeyDown = e => {
|
||||||
|
switch(e.key) {
|
||||||
|
case 'ArrowLeft':
|
||||||
|
e.preventDefault();
|
||||||
|
this.setState(({ index }, { children }) => ({ index: Math.abs(index - 1) % children.length }));
|
||||||
|
break;
|
||||||
|
case 'ArrowRight':
|
||||||
|
e.preventDefault();
|
||||||
|
this.setState(({ index }, { children }) => ({ index: (index + 1) % children.length }));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { children } = this.props;
|
||||||
|
const { index } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='tip-carousel' tabIndex='0' onKeyDown={this.handleKeyDown}>
|
||||||
|
<SwipeableViews onChangeIndex={this.handleSwipe} index={index} enableMouseEvents tabIndex='-1'>
|
||||||
|
{children}
|
||||||
|
</SwipeableViews>
|
||||||
|
|
||||||
|
<div className='media-modal__pagination'>
|
||||||
|
{children.map((_, i) => (
|
||||||
|
<button key={i} className={classNames('media-modal__page-dot', { active: i === index })} data-index={i} onClick={this.handleChangeIndex}>
|
||||||
|
{i + 1}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class Share extends React.PureComponent {
|
class Share extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -105,6 +160,12 @@ class Share extends React.PureComponent {
|
||||||
|
|
||||||
<CopyPasteText value={intl.formatMessage(messages.shareableMessage, { username: `@${account.get('username')}@${domain}`, url })} />
|
<CopyPasteText value={intl.formatMessage(messages.shareableMessage, { username: `@${account.get('username')}@${domain}`, url })} />
|
||||||
|
|
||||||
|
<TipCarousel>
|
||||||
|
<div><p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.verification' defaultMessage='<strong>Did you know?</strong> You can verify your account by putting a link to your Mastodon profile on your own website and adding the website to your profile. No fees or documents necessary!' /></p></div>
|
||||||
|
<div><p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.migration' defaultMessage='<strong>Did you know?</strong> If you feel like {domain} is not a great server choice for you in the future, you can move to another Mastodon server without losing your followers. You can even host your own server!' values={{ domain }} /></p></div>
|
||||||
|
<div><p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.2fa' defaultMessage='<strong>Did you know?</strong> You can secure your account by setting up two-factor authentication in your account settings. It works with any TOTP app of your choice, no phone number necessary!' /></p></div>
|
||||||
|
</TipCarousel>
|
||||||
|
|
||||||
<p className='onboarding__lead'><FormattedMessage id='onboarding.share.next_steps' defaultMessage='Possible next steps:' /></p>
|
<p className='onboarding__lead'><FormattedMessage id='onboarding.share.next_steps' defaultMessage='Possible next steps:' /></p>
|
||||||
|
|
||||||
<div className='onboarding__links'>
|
<div className='onboarding__links'>
|
||||||
|
|
|
@ -1145,6 +1145,29 @@ $ui-header-height: 55px;
|
||||||
.account:last-child {
|
.account:last-child {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__empty {
|
||||||
|
text-align: center;
|
||||||
|
color: $darker-text-color;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-carousel {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
border-color: $highlight-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.media-modal__pagination {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-paste-text {
|
.copy-paste-text {
|
||||||
|
@ -1319,4 +1342,9 @@ $ui-header-height: 55px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
background-color: $highlight-text-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue