260 lines
7.1 KiB
JavaScript
260 lines
7.1 KiB
JavaScript
|
import React from 'react';
|
||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||
|
import classNames from 'classnames';
|
||
|
import platform from 'platform';
|
||
|
import Flux from '../lib/flux';
|
||
|
import {UserSettingsSections, DownloadLinks} from '../Constants';
|
||
|
import UserStore from '../stores/UserStore';
|
||
|
import i18n from '../i18n';
|
||
|
import UserSettingsActionCreators from '../actions/UserSettingsModalActionCreators';
|
||
|
import Backdrop from './common/Backdrop';
|
||
|
import AnalyticsUtils from '../utils/AnalyticsUtils';
|
||
|
import '../styles/download_apps.styl';
|
||
|
import Storage from '../lib/Storage';
|
||
|
|
||
|
const BASE_DOWNLOAD_URL = `${location.protocol}${process.env.API_ENDPOINT}/download`;
|
||
|
|
||
|
function makeDesktopDownloadURL(platform, ptb = false, format) {
|
||
|
let url = BASE_DOWNLOAD_URL;
|
||
|
if (ptb) {
|
||
|
url += '/ptb';
|
||
|
}
|
||
|
const formatParam = format ? `&format=${format}` : '';
|
||
|
return `${url}?platform=${platform}${formatParam}`;
|
||
|
}
|
||
|
|
||
|
const DownloadApps = React.createClass({
|
||
|
mixins: [PureRenderMixin, Flux.StoreListenerMixin(UserStore)],
|
||
|
|
||
|
statics: {
|
||
|
modalConfig: {
|
||
|
key: 'download-apps',
|
||
|
backdropStyle: Backdrop.LIGHT,
|
||
|
},
|
||
|
},
|
||
|
|
||
|
getInitialState() {
|
||
|
return {
|
||
|
ptb: false,
|
||
|
desktop: {
|
||
|
key: 'desktop',
|
||
|
platforms: [
|
||
|
{
|
||
|
os: i18n.Messages.PLATFORM_OSX,
|
||
|
icon: 'apple',
|
||
|
url: ptb => makeDesktopDownloadURL('osx', ptb),
|
||
|
},
|
||
|
{
|
||
|
os: i18n.Messages.PLATFORM_WINDOWS,
|
||
|
icon: 'windows',
|
||
|
url: ptb => makeDesktopDownloadURL('win', ptb),
|
||
|
},
|
||
|
{
|
||
|
os: i18n.Messages.PLATFORM_LINUX,
|
||
|
icon: 'linux',
|
||
|
url: [
|
||
|
{
|
||
|
url: ptb => makeDesktopDownloadURL('linux', ptb, 'deb'),
|
||
|
text: i18n.Messages.DEB,
|
||
|
},
|
||
|
{
|
||
|
url: ptb => makeDesktopDownloadURL('linux', ptb, 'tar.gz'),
|
||
|
text: i18n.Messages.TAR_GZ,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
mobile: {
|
||
|
key: 'mobile',
|
||
|
platforms: [
|
||
|
{
|
||
|
os: i18n.Messages.PLATFORM_IOS,
|
||
|
icon: 'ios',
|
||
|
url: () => DownloadLinks.IOS,
|
||
|
},
|
||
|
{
|
||
|
os: i18n.Messages.PLATFORM_ANDROID,
|
||
|
icon: 'android',
|
||
|
url: () => DownloadLinks.ANDROID,
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getStateFromStores() {
|
||
|
const user = UserStore.getCurrentUser();
|
||
|
return {
|
||
|
claimed: user == null || user.isClaimed(),
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getDefaultProps() {
|
||
|
return {
|
||
|
source: 'Unspecified',
|
||
|
};
|
||
|
},
|
||
|
|
||
|
componentWillMount() {
|
||
|
this.detectActiveOS();
|
||
|
},
|
||
|
|
||
|
detectActiveOS() {
|
||
|
switch (platform.os.family) {
|
||
|
case 'OS X':
|
||
|
return this.handleMouseEnter(this.state.desktop.key + 0);
|
||
|
case 'Windows':
|
||
|
return this.handleMouseEnter(this.state.desktop.key + 1);
|
||
|
case 'Ubuntu':
|
||
|
case 'Debian':
|
||
|
case 'Fedora':
|
||
|
case 'Red Hat':
|
||
|
case 'SuSE':
|
||
|
case 'Linux':
|
||
|
return this.handleMouseEnter(this.state.desktop.key + 2);
|
||
|
case 'iOS':
|
||
|
return this.handleMouseEnter(this.state.mobile.key + 0);
|
||
|
case 'Android':
|
||
|
return this.handleMouseEnter(this.state.mobile.key + 1);
|
||
|
default:
|
||
|
return null;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
renderPlatforms(platforms, key, ptb = false) {
|
||
|
return platforms.map(({os, icon, url}, i) => {
|
||
|
const platformKey = key + i;
|
||
|
const classes = classNames({platform: true, active: this.state.active === platformKey});
|
||
|
return (
|
||
|
<DownloadApp
|
||
|
key={platformKey}
|
||
|
os={os}
|
||
|
icon={icon}
|
||
|
url={url}
|
||
|
claimed={this.state.claimed}
|
||
|
className={classes}
|
||
|
onClick={this.handleClick.bind(this, os, ptb)}
|
||
|
onMouseEnter={this.handleMouseEnter.bind(this, platformKey)}
|
||
|
ptb={ptb}
|
||
|
/>
|
||
|
);
|
||
|
}, this);
|
||
|
},
|
||
|
|
||
|
render() {
|
||
|
let footer;
|
||
|
if (this.state.ptb) {
|
||
|
footer = i18n.Messages.DOWNLOAD_DESKTOP_PTB_FOOTER.format({onClick: this.showStable});
|
||
|
} else {
|
||
|
footer = i18n.Messages.DOWNLOAD_DESKTOP_STABLE_FOOTER.format({onClick: this.showPTB});
|
||
|
}
|
||
|
return (
|
||
|
<div className="download-apps">
|
||
|
<div className="inner">
|
||
|
<div className="platforms-wrap">
|
||
|
<p className="header">{i18n.Messages.DOWNLOAD_DESKTOP_TITLE}</p>
|
||
|
<ul className="platforms">
|
||
|
{this.renderPlatforms(this.state.desktop.platforms, this.state.desktop.key, this.state.ptb)}
|
||
|
</ul>
|
||
|
<p className="footer">{footer}</p>
|
||
|
</div>
|
||
|
<div className="platforms-wrap">
|
||
|
<p className="header">{i18n.Messages.DOWNLOAD_MOBILE_TITLE}</p>
|
||
|
<ul className="platforms">
|
||
|
{this.renderPlatforms(this.state.mobile.platforms, this.state.mobile.key)}
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
},
|
||
|
|
||
|
showStable() {
|
||
|
this.setState({ptb: false});
|
||
|
},
|
||
|
|
||
|
showPTB() {
|
||
|
this.setState({ptb: true});
|
||
|
},
|
||
|
|
||
|
handleClick(os, ptb = false) {
|
||
|
// citron note: so hack. just temp.
|
||
|
if (Storage.get('token') || Storage.get('fingerprint')) {
|
||
|
AnalyticsUtils.track('Download App', {
|
||
|
Platform: os,
|
||
|
PTB: ptb,
|
||
|
Released: true,
|
||
|
'Has E-Mail': this.state.claimed,
|
||
|
'Referring Location': this.props.source,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (!this.state.claimed) {
|
||
|
UserSettingsActionCreators.open(UserSettingsSections.ACCOUNT);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
handleMouseEnter(platformKey) {
|
||
|
this.setState({active: platformKey});
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const DownloadButton = ({url, ptb, text, onClick}) => {
|
||
|
return (
|
||
|
<a href={url} target="_blank" className="download-button" onClick={onClick}>
|
||
|
{text}
|
||
|
{ptb ? ' PTB' : ''}
|
||
|
</a>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
const DownloadApp = React.createClass({
|
||
|
mixins: [PureRenderMixin],
|
||
|
|
||
|
propTypes: {
|
||
|
os: React.PropTypes.string.isRequired,
|
||
|
icon: React.PropTypes.string.isRequired,
|
||
|
ptb: React.PropTypes.bool,
|
||
|
},
|
||
|
|
||
|
render() {
|
||
|
const {icon, ptb, url, onClick, onMouseEnter, className, claimed, os} = this.props;
|
||
|
const iconClassName = classNames('icon', icon);
|
||
|
|
||
|
let buttons;
|
||
|
let downloadButtonsClass;
|
||
|
if (Array.isArray(url)) {
|
||
|
downloadButtonsClass = 'list';
|
||
|
buttons = url.map((urlObj, i) => {
|
||
|
const url = claimed ? urlObj.url(ptb) : null;
|
||
|
return <DownloadButton ptb={ptb} url={url} onClick={onClick} key={`${url}-${i}`} text={urlObj.text} />;
|
||
|
});
|
||
|
} else {
|
||
|
const btnUrl = claimed ? url(ptb) : null;
|
||
|
buttons = <DownloadButton ptb={ptb} url={btnUrl} onClick={onClick} text={i18n.Messages.DOWNLOAD} />;
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<li className={className} onMouseEnter={onMouseEnter}>
|
||
|
<div className="content-wrapper">
|
||
|
<div className="icon-wrap">
|
||
|
<div className={iconClassName} />
|
||
|
<div className={`active ${iconClassName}`} />
|
||
|
</div>
|
||
|
<p>{os}</p>
|
||
|
<div className={classNames('download-buttons', downloadButtonsClass)}>
|
||
|
{buttons}
|
||
|
</div>
|
||
|
</div>
|
||
|
</li>
|
||
|
);
|
||
|
},
|
||
|
});
|
||
|
|
||
|
export default DownloadApps;
|
||
|
|
||
|
|
||
|
|
||
|
// WEBPACK FOOTER //
|
||
|
// ./discord_app/components/DownloadApps.js
|