2017-12-31 03:08:54 +05:30
|
|
|
// @flow
|
|
|
|
|
|
|
|
import React from 'react';
|
|
|
|
import { TransitionMotion, spring, presets } from 'react-motion';
|
|
|
|
import { FormattedMessage as Message } from 'react-intl';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import LocaleItem from './LocaleItem';
|
|
|
|
import messages from './languageSwitcher.intl.json';
|
|
|
|
import styles from './languageSwitcher.scss';
|
|
|
|
|
|
|
|
import thatFuckingPumpkin from './images/that_fucking_pumpkin.svg';
|
|
|
|
import mayTheForceBeWithYou from './images/may_the_force_be_with_you.svg';
|
|
|
|
import biteMyShinyMetalAss from './images/bite_my_shiny_metal_ass.svg';
|
|
|
|
import iTookAnArrowInMyKnee from './images/i_took_an_arrow_in_my_knee.svg';
|
|
|
|
|
|
|
|
import type { LocalesMap } from './LanguageSwitcher';
|
|
|
|
|
|
|
|
const itemHeight = 51;
|
|
|
|
|
|
|
|
export default class LanguageList extends React.Component<{
|
2019-05-21 20:53:13 +05:30
|
|
|
selectedLocale: string,
|
2017-12-31 03:08:54 +05:30
|
|
|
langs: LocalesMap,
|
|
|
|
onChangeLang: (lang: string) => void,
|
|
|
|
}> {
|
|
|
|
emptyListStateInner: ?HTMLDivElement;
|
|
|
|
|
|
|
|
render() {
|
2019-05-21 20:53:13 +05:30
|
|
|
const { selectedLocale, langs } = this.props;
|
2017-12-31 03:08:54 +05:30
|
|
|
const isListEmpty = Object.keys(langs).length === 0;
|
|
|
|
const firstLocale = Object.keys(langs)[0] || null;
|
|
|
|
const emptyCaption = this.getEmptyCaption();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<TransitionMotion
|
|
|
|
defaultStyles={this.getItemsWithDefaultStyles()}
|
|
|
|
styles={this.getItemsWithStyles()}
|
|
|
|
willLeave={this.willLeave}
|
|
|
|
willEnter={this.willEnter}
|
|
|
|
>
|
|
|
|
{(items) => (
|
|
|
|
<div className={styles.languagesList}>
|
|
|
|
<div
|
|
|
|
className={classNames(styles.emptyLanguagesListWrapper, {
|
|
|
|
[styles.emptyLanguagesListVisible]: isListEmpty,
|
|
|
|
})}
|
|
|
|
style={{
|
|
|
|
height: isListEmpty && this.emptyListStateInner ? this.emptyListStateInner.clientHeight : 0,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
ref={(elem: ?HTMLDivElement) => this.emptyListStateInner = elem}
|
|
|
|
className={styles.emptyLanguagesList}
|
|
|
|
>
|
|
|
|
<img
|
|
|
|
src={emptyCaption.src}
|
|
|
|
alt={emptyCaption.caption}
|
|
|
|
className={styles.emptyLanguagesListCaption}
|
|
|
|
/>
|
|
|
|
<div className={styles.emptyLanguagesListSubtitle}>
|
|
|
|
<Message {...messages.weDoNotSupportThisLang} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{items.map(({key: locale, data: definition, style}) => (
|
|
|
|
<div
|
|
|
|
key={locale}
|
|
|
|
style={style}
|
|
|
|
className={classNames(styles.languageItem, {
|
2019-05-21 20:53:13 +05:30
|
|
|
[styles.activeLanguageItem]: locale === selectedLocale,
|
2017-12-31 03:08:54 +05:30
|
|
|
[styles.firstLanguageItem]: locale === firstLocale,
|
|
|
|
})}
|
|
|
|
onClick={this.onChangeLang(locale)}
|
|
|
|
>
|
|
|
|
<LocaleItem locale={definition} />
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</TransitionMotion>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
getEmptyCaption() {
|
|
|
|
const emptyCaptions = [
|
|
|
|
{
|
|
|
|
// Homestuck
|
|
|
|
src: thatFuckingPumpkin,
|
|
|
|
caption: 'That fucking pumpkin',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Star Wars
|
|
|
|
src: mayTheForceBeWithYou,
|
|
|
|
caption: 'May The Force Be With You',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Futurama
|
|
|
|
src: biteMyShinyMetalAss,
|
|
|
|
caption: 'Bite my shiny metal ass',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// The Elder Scrolls V: Skyrim
|
|
|
|
src: iTookAnArrowInMyKnee,
|
|
|
|
caption: 'I took an arrow in my knee',
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
return emptyCaptions[Math.floor(Math.random() * emptyCaptions.length)];
|
|
|
|
}
|
|
|
|
|
|
|
|
onChangeLang(lang: string) {
|
|
|
|
return (event: SyntheticMouseEvent<HTMLElement>) => {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
this.props.onChangeLang(lang);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getItemsWithDefaultStyles = () => this.getItemsWithStyles({ useSpring: false });
|
|
|
|
|
|
|
|
getItemsWithStyles = ({ useSpring }: { useSpring?: bool } = { useSpring: true }) =>
|
|
|
|
Object.keys({...this.props.langs})
|
|
|
|
.reduce((previous, key) => [
|
|
|
|
...previous,
|
|
|
|
{
|
|
|
|
key,
|
|
|
|
data: this.props.langs[key],
|
|
|
|
style: {
|
|
|
|
height: useSpring ? spring(itemHeight, presets.gentle) : itemHeight,
|
|
|
|
opacity: useSpring ? spring(1, presets.gentle) : 1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
], []);
|
|
|
|
|
|
|
|
willEnter() {
|
|
|
|
return {
|
|
|
|
height: 0,
|
|
|
|
opacity: 1,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
willLeave() {
|
|
|
|
return {
|
|
|
|
height: spring(0),
|
|
|
|
opacity: spring(0),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|