Fix custom emoji in emoji picker, persist skin tone (#5258)
parent
967e70663f
commit
d2dee6ea43
|
@ -31,6 +31,19 @@ let EmojiPicker, Emoji; // load asynchronously
|
||||||
const backgroundImageFn = () => `${assetHost}/emoji/sheet.png`;
|
const backgroundImageFn = () => `${assetHost}/emoji/sheet.png`;
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
||||||
|
|
||||||
|
const categoriesSort = [
|
||||||
|
'recent',
|
||||||
|
'custom',
|
||||||
|
'people',
|
||||||
|
'nature',
|
||||||
|
'foods',
|
||||||
|
'activity',
|
||||||
|
'places',
|
||||||
|
'objects',
|
||||||
|
'symbols',
|
||||||
|
'flags',
|
||||||
|
];
|
||||||
|
|
||||||
class ModifierPickerMenu extends React.PureComponent {
|
class ModifierPickerMenu extends React.PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -141,6 +154,9 @@ class EmojiPickerMenu extends React.PureComponent {
|
||||||
arrowOffsetLeft: PropTypes.string,
|
arrowOffsetLeft: PropTypes.string,
|
||||||
arrowOffsetTop: PropTypes.string,
|
arrowOffsetTop: PropTypes.string,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
|
skinTone: PropTypes.number.isRequired,
|
||||||
|
onSkinTone: PropTypes.func.isRequired,
|
||||||
|
autoPlay: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -151,7 +167,6 @@ class EmojiPickerMenu extends React.PureComponent {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
modifierOpen: false,
|
modifierOpen: false,
|
||||||
modifier: 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDocumentClick = e => {
|
handleDocumentClick = e => {
|
||||||
|
@ -214,20 +229,18 @@ class EmojiPickerMenu extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleModifierChange = modifier => {
|
handleModifierChange = modifier => {
|
||||||
if (modifier !== this.state.modifier) {
|
this.props.onSkinTone(modifier);
|
||||||
this.setState({ modifier });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { loading, style, intl } = this.props;
|
const { loading, style, intl, custom_emojis, autoPlay, skinTone } = this.props;
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <div style={{ width: 299 }} />;
|
return <div style={{ width: 299 }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = intl.formatMessage(messages.emoji);
|
const title = intl.formatMessage(messages.emoji);
|
||||||
const { modifierOpen, modifier } = this.state;
|
const { modifierOpen } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames('emoji-picker-dropdown__menu', { selecting: modifierOpen })} style={style} ref={this.setRef}>
|
<div className={classNames('emoji-picker-dropdown__menu', { selecting: modifierOpen })} style={style} ref={this.setRef}>
|
||||||
|
@ -235,20 +248,22 @@ class EmojiPickerMenu extends React.PureComponent {
|
||||||
perLine={8}
|
perLine={8}
|
||||||
emojiSize={22}
|
emojiSize={22}
|
||||||
sheetSize={32}
|
sheetSize={32}
|
||||||
|
custom={buildCustomEmojis(custom_emojis, autoPlay)}
|
||||||
color=''
|
color=''
|
||||||
emoji=''
|
emoji=''
|
||||||
set='twitter'
|
set='twitter'
|
||||||
title={title}
|
title={title}
|
||||||
i18n={this.getI18n()}
|
i18n={this.getI18n()}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
skin={modifier}
|
include={categoriesSort}
|
||||||
|
skin={skinTone}
|
||||||
showPreview={false}
|
showPreview={false}
|
||||||
backgroundImageFn={backgroundImageFn}
|
backgroundImageFn={backgroundImageFn}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModifierPicker
|
<ModifierPicker
|
||||||
active={modifierOpen}
|
active={modifierOpen}
|
||||||
modifier={modifier}
|
modifier={skinTone}
|
||||||
onOpen={this.handleModifierOpen}
|
onOpen={this.handleModifierOpen}
|
||||||
onClose={this.handleModifierClose}
|
onClose={this.handleModifierClose}
|
||||||
onChange={this.handleModifierChange}
|
onChange={this.handleModifierChange}
|
||||||
|
@ -267,6 +282,8 @@ export default class EmojiPickerDropdown extends React.PureComponent {
|
||||||
autoPlay: PropTypes.bool,
|
autoPlay: PropTypes.bool,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
onPickEmoji: PropTypes.func.isRequired,
|
onPickEmoji: PropTypes.func.isRequired,
|
||||||
|
onSkinTone: PropTypes.func.isRequired,
|
||||||
|
skinTone: PropTypes.number.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -279,8 +296,6 @@ export default class EmojiPickerDropdown extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onShowDropdown = () => {
|
onShowDropdown = () => {
|
||||||
const { autoPlay } = this.props;
|
|
||||||
|
|
||||||
this.setState({ active: true });
|
this.setState({ active: true });
|
||||||
|
|
||||||
if (!EmojiPicker) {
|
if (!EmojiPicker) {
|
||||||
|
@ -288,9 +303,8 @@ export default class EmojiPickerDropdown extends React.PureComponent {
|
||||||
|
|
||||||
EmojiPickerAsync().then(EmojiMart => {
|
EmojiPickerAsync().then(EmojiMart => {
|
||||||
EmojiPicker = EmojiMart.Picker;
|
EmojiPicker = EmojiMart.Picker;
|
||||||
Emoji = EmojiMart.Emoji;
|
Emoji = EmojiMart.Emoji;
|
||||||
// populate custom emoji in search
|
|
||||||
EmojiMart.emojiIndex.search('', { custom: buildCustomEmojis(this.props.custom_emojis, autoPlay) });
|
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
@ -327,7 +341,7 @@ export default class EmojiPickerDropdown extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, onPickEmoji } = this.props;
|
const { intl, onPickEmoji, autoPlay, onSkinTone, skinTone } = this.props;
|
||||||
const title = intl.formatMessage(messages.emoji);
|
const title = intl.formatMessage(messages.emoji);
|
||||||
const { active, loading } = this.state;
|
const { active, loading } = this.state;
|
||||||
|
|
||||||
|
@ -347,6 +361,9 @@ export default class EmojiPickerDropdown extends React.PureComponent {
|
||||||
loading={loading}
|
loading={loading}
|
||||||
onClose={this.onHideDropdown}
|
onClose={this.onHideDropdown}
|
||||||
onPick={onPickEmoji}
|
onPick={onPickEmoji}
|
||||||
|
autoPlay={autoPlay}
|
||||||
|
onSkinTone={onSkinTone}
|
||||||
|
skinTone={skinTone}
|
||||||
/>
|
/>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import EmojiPickerDropdown from '../components/emoji_picker_dropdown';
|
import EmojiPickerDropdown from '../components/emoji_picker_dropdown';
|
||||||
|
import { changeSetting } from '../../../actions/settings';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
custom_emojis: state.get('custom_emojis'),
|
custom_emojis: state.get('custom_emojis'),
|
||||||
autoPlay: state.getIn(['meta', 'auto_play_gif']),
|
autoPlay: state.getIn(['meta', 'auto_play_gif']),
|
||||||
|
skinTone: state.getIn(['settings', 'skinTone']),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps)(EmojiPickerDropdown);
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
onSkinTone: skinTone => {
|
||||||
|
dispatch(changeSetting(['skinTone'], skinTone));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(EmojiPickerDropdown);
|
||||||
|
|
|
@ -7,6 +7,8 @@ import uuid from '../uuid';
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
onboarded: false,
|
onboarded: false,
|
||||||
|
|
||||||
|
skinTone: 1,
|
||||||
|
|
||||||
home: ImmutableMap({
|
home: ImmutableMap({
|
||||||
shows: ImmutableMap({
|
shows: ImmutableMap({
|
||||||
reblog: true,
|
reblog: true,
|
||||||
|
|
|
@ -2653,19 +2653,36 @@ button.icon-button.active i.fa-retweet {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes heartbeat {
|
||||||
0% {
|
from {
|
||||||
opacity: 1;
|
transform: scale(1);
|
||||||
|
transform-origin: center center;
|
||||||
|
animation-timing-function: ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
10% {
|
||||||
opacity: 0.5;
|
transform: scale(0.91);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
17% {
|
||||||
|
transform: scale(0.98);
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
33% {
|
||||||
|
transform: scale(0.87);
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
45% {
|
||||||
|
transform: scale(1);
|
||||||
|
animation-timing-function: ease-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pulse-loading {
|
.pulse-loading {
|
||||||
animation: pulse 1s ease-in-out infinite;
|
animation: heartbeat 1.5s ease-in-out infinite both;
|
||||||
animation-direction: alternate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-picker-dropdown__menu {
|
.emoji-picker-dropdown__menu {
|
||||||
|
|
Loading…
Reference in New Issue