154 lines
4.8 KiB
JavaScript
Executable file
154 lines
4.8 KiB
JavaScript
Executable file
import React from 'react';
|
|
import Flux from '../lib/flux';
|
|
import {Messages} from '../i18n';
|
|
import TransitionGroup from '../lib/transitions/TransitionGroup';
|
|
|
|
import AuthenticationMixin from '../mixins/web/AuthenticationMixin';
|
|
import AuthenticationActionCreators from '../actions/AuthenticationActionCreators';
|
|
import AuthenticationStore from '../stores/AuthenticationStore';
|
|
import NewUserStepsStore from '../stores/NewUserStepsStore';
|
|
import InstantInviteActionCreators from '../actions/InstantInviteActionCreators';
|
|
import NewUserAccountStore from '../stores/NewUserAccountStore';
|
|
import NewUserActionCreators from '../actions/NewUserActionCreators';
|
|
import {NEW_USER_ONBOARDING_STEPS as STEPS} from '../Constants';
|
|
import TimerMixin from 'react-timer-mixin';
|
|
|
|
import Animated from '../lib/animated';
|
|
import {SLIDES, SLIDE_BUTTON_MESSAGES} from './onboarding/slides';
|
|
|
|
import '../styles/new_user_onboarding.styl';
|
|
import '../styles/guild_channels.styl';
|
|
|
|
const NewUserOnboarding = React.createClass({
|
|
mixins: [Flux.StoreListenerMixin(NewUserStepsStore, NewUserAccountStore), AuthenticationMixin, TimerMixin],
|
|
|
|
getInitialState() {
|
|
return {
|
|
opacity: new Animated.Value(1),
|
|
};
|
|
},
|
|
|
|
componentDidMount() {
|
|
if (AuthenticationStore.isAuthenticated()) {
|
|
AuthenticationActionCreators.startSession(AuthenticationStore.getToken());
|
|
}
|
|
},
|
|
|
|
componentWillUpdate(nextProps, nextState) {
|
|
// Ignore initial states and state changes
|
|
if (this.state.step === STEPS.INITIAL || nextState.step === STEPS.INITIAL) {
|
|
return;
|
|
}
|
|
|
|
// We are about to be in a slide transition, so set our local _animating boolean
|
|
if (this.state.step !== STEPS.DISABLED && nextState.step !== this.state.step && !this._animating) {
|
|
this._animating = true;
|
|
}
|
|
|
|
// We are transitioning out of the final slide, thus we need to navigate
|
|
// out We use a delay to ensure there's not an awkward wait time since the
|
|
// springs are non-deterministic by nature
|
|
if (nextState.step === STEPS.DISABLED && !this._animatingOut) {
|
|
// We only ever want to call this once, thus the boolean check and set
|
|
this._animatingOut = true;
|
|
this.setTimeout(() => {
|
|
InstantInviteActionCreators.transitionToInviteChannel(
|
|
this.props.params.guildId,
|
|
this.props.params.channelId,
|
|
parseInt(this.props.params.type)
|
|
);
|
|
}, 500);
|
|
}
|
|
},
|
|
|
|
render() {
|
|
const {ready, step, opacity} = this.state;
|
|
|
|
if (!ready) {
|
|
return null;
|
|
}
|
|
|
|
const nextMessage = SLIDE_BUTTON_MESSAGES[NewUserStepsStore.getNextStep()] || Messages.ONBOARDING_NEXT;
|
|
let slide = null;
|
|
if (SLIDES[step]) {
|
|
const Slide = SLIDES[step];
|
|
slide = (
|
|
<Slide
|
|
key={step}
|
|
onAnimationComplete={this.handleAnimationComplete}
|
|
onNext={this.handleStepNext}
|
|
onSkip={this.handleSkip}
|
|
nextStepMessage={nextMessage}
|
|
disableSkip={NewUserStepsStore.getNextStep() === STEPS.DISABLED}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Animated.div className="app fake theme-dark flex-horizontal flex-spacer" style={{opacity: opacity}}>
|
|
<div className="guilds-wrapper">
|
|
<img src={require('../images/onboarding/ui-placeholder-servers.svg')} width={52} height={322} />
|
|
</div>
|
|
<div className="flex-vertical channels-wrap">
|
|
<div className="flex-vertical flex-spacer">
|
|
<img src={require('../images/onboarding/ui-placeholder-header-server.svg')} />
|
|
</div>
|
|
<img src={require('../images/onboarding/ui-placeholder-account.svg')} />
|
|
</div>
|
|
<div className="content flex-vertical flex-spacer">
|
|
<div className="title-wrap">
|
|
<img
|
|
className="header-icons"
|
|
src={require('../images/onboarding/ui-placeholder-header-icons.svg')}
|
|
width={369}
|
|
height={26}
|
|
/>
|
|
</div>
|
|
<div className="content-users-wrap flex-horizontal">
|
|
<TransitionGroup component="div" className="page nuf-page slide-transition-group">
|
|
{slide}
|
|
</TransitionGroup>
|
|
</div>
|
|
</div>
|
|
</Animated.div>
|
|
);
|
|
},
|
|
|
|
handleAnimationComplete() {
|
|
if (this._animating && this.state.step !== STEPS.DISABLED) {
|
|
this._animating = false;
|
|
}
|
|
},
|
|
|
|
componentWillLeave(callback) {
|
|
Animated.timing(this.state.opacity, {
|
|
toValue: 0,
|
|
duration: 300,
|
|
}).start(callback);
|
|
},
|
|
|
|
handleStepNext() {
|
|
if (this._animating) {
|
|
return;
|
|
}
|
|
NewUserActionCreators.advanceStep();
|
|
},
|
|
|
|
handleSkip() {
|
|
if (this._animating) {
|
|
return;
|
|
}
|
|
NewUserActionCreators.skipOnboarding();
|
|
},
|
|
|
|
getStateFromStores() {
|
|
return NewUserStepsStore.getState();
|
|
},
|
|
});
|
|
|
|
export default NewUserOnboarding;
|
|
|
|
|
|
|
|
// WEBPACK FOOTER //
|
|
// ./discord_app/components/NewUserOnboarding.js
|