2017-12-31 03:08:54 +05:30
|
|
|
import React from 'react';
|
|
|
|
import { TransitionMotion, spring, presets } from 'react-motion';
|
|
|
|
import { FormattedMessage as Message } from 'react-intl';
|
2019-12-08 01:13:08 +05:30
|
|
|
import clsx from 'clsx';
|
2019-12-07 16:58:52 +05:30
|
|
|
|
2017-12-31 03:08:54 +05:30
|
|
|
import LocaleItem from './LocaleItem';
|
|
|
|
import messages from './languageSwitcher.intl.json';
|
2019-12-07 16:58:52 +05:30
|
|
|
import { LocalesMap } from './LanguageSwitcher';
|
2017-12-31 03:08:54 +05:30
|
|
|
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';
|
|
|
|
|
|
|
|
const itemHeight = 51;
|
|
|
|
|
|
|
|
export default class LanguageList extends React.Component<{
|
2019-12-07 16:58:52 +05:30
|
|
|
selectedLocale: string;
|
|
|
|
langs: LocalesMap;
|
|
|
|
onChangeLang: (lang: string) => void;
|
2017-12-31 03:08:54 +05:30
|
|
|
}> {
|
2019-12-07 16:58:52 +05:30
|
|
|
emptyListStateInner: HTMLDivElement | null;
|
2019-11-27 14:33:32 +05:30
|
|
|
|
|
|
|
render() {
|
|
|
|
const { selectedLocale, langs } = this.props;
|
|
|
|
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 => (
|
2019-12-28 16:43:11 +05:30
|
|
|
<div className={styles.languagesList} data-testid="language-list">
|
2019-11-27 14:33:32 +05:30
|
|
|
<div
|
2019-12-08 01:13:08 +05:30
|
|
|
className={clsx(styles.emptyLanguagesListWrapper, {
|
2019-11-27 14:33:32 +05:30
|
|
|
[styles.emptyLanguagesListVisible]: isListEmpty,
|
|
|
|
})}
|
|
|
|
style={{
|
|
|
|
height:
|
|
|
|
isListEmpty && this.emptyListStateInner
|
|
|
|
? this.emptyListStateInner.clientHeight
|
|
|
|
: 0,
|
|
|
|
}}
|
2017-12-31 03:08:54 +05:30
|
|
|
>
|
2019-11-27 14:33:32 +05:30
|
|
|
<div
|
2019-12-07 16:58:52 +05:30
|
|
|
ref={(elem: HTMLDivElement | null) =>
|
2019-11-27 14:33:32 +05:30
|
|
|
(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}
|
2019-12-08 01:13:08 +05:30
|
|
|
className={clsx(styles.languageItem, {
|
2019-11-27 14:33:32 +05:30
|
|
|
[styles.activeLanguageItem]: locale === selectedLocale,
|
|
|
|
[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) {
|
2019-12-07 16:58:52 +05:30
|
|
|
return (event: React.MouseEvent<HTMLElement>) => {
|
2019-11-27 14:33:32 +05:30
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
this.props.onChangeLang(lang);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
getItemsWithDefaultStyles = () =>
|
|
|
|
this.getItemsWithStyles({ useSpring: false });
|
|
|
|
|
|
|
|
getItemsWithStyles = (
|
|
|
|
{ useSpring }: { useSpring?: boolean } = { 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),
|
|
|
|
};
|
|
|
|
}
|
2017-12-31 03:08:54 +05:30
|
|
|
}
|