Set EmojiSelector visibility from props
This commit is contained in:
parent
c29d779bf5
commit
8b505c0488
|
@ -2,22 +2,25 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { ALLOWED_EMOJI } from 'gabsocial/utils/emoji_reacts';
|
import { ALLOWED_EMOJI } from 'gabsocial/utils/emoji_reacts';
|
||||||
import emojify from 'gabsocial/features/emoji/emoji';
|
import emojify from 'gabsocial/features/emoji/emoji';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export default class EmojiSelector extends React.Component {
|
export default class EmojiSelector extends React.Component {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onReact: PropTypes.func.isRequired,
|
onReact: PropTypes.func.isRequired,
|
||||||
|
visible: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onReact: () => {},
|
onReact: () => {},
|
||||||
|
visible: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { onReact } = this.props;
|
const { onReact, visible } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='emoji-react-selector'>
|
<div className={classNames('emoji-react-selector', { 'emoji-react-selector--visible': visible })}>
|
||||||
{ALLOWED_EMOJI.map((emoji, i) => (
|
{ALLOWED_EMOJI.map((emoji, i) => (
|
||||||
<button
|
<button
|
||||||
key={i}
|
key={i}
|
||||||
|
|
|
@ -35,6 +35,7 @@ export default class IconButton extends React.PureComponent {
|
||||||
animate: false,
|
animate: false,
|
||||||
overlay: false,
|
overlay: false,
|
||||||
tabIndex: '0',
|
tabIndex: '0',
|
||||||
|
onClick: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClick = (e) => {
|
handleClick = (e) => {
|
||||||
|
|
|
@ -77,6 +77,10 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
isStaff: false,
|
isStaff: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
emojiSelectorVisible: false,
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid checking props that are functions (and whose equality will always
|
// Avoid checking props that are functions (and whose equality will always
|
||||||
// evaluate to false. See react-immutable-pure-component for usage.
|
// evaluate to false. See react-immutable-pure-component for usage.
|
||||||
updateOnProps = [
|
updateOnProps = [
|
||||||
|
@ -102,6 +106,14 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleLikeButtonHover = e => {
|
||||||
|
this.setState({ emojiSelectorVisible: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLikeButtonLeave = e => {
|
||||||
|
this.setState({ emojiSelectorVisible: false });
|
||||||
|
}
|
||||||
|
|
||||||
handleReactClick = emoji => {
|
handleReactClick = emoji => {
|
||||||
return e => {
|
return e => {
|
||||||
const { me, status } = this.props;
|
const { me, status } = this.props;
|
||||||
|
@ -267,6 +279,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status, intl } = this.props;
|
const { status, intl } = this.props;
|
||||||
|
const { emojiSelectorVisible } = this.state;
|
||||||
|
|
||||||
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
|
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
|
||||||
|
|
||||||
|
@ -313,8 +326,12 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
<IconButton className='status__action-bar-button' disabled={!publicStatus} active={status.get('reblogged')} pressed={status.get('reblogged')} title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} icon={reblogIcon} onClick={this.handleReblogClick} />
|
<IconButton className='status__action-bar-button' disabled={!publicStatus} active={status.get('reblogged')} pressed={status.get('reblogged')} title={!publicStatus ? intl.formatMessage(messages.cannot_reblog) : intl.formatMessage(messages.reblog)} icon={reblogIcon} onClick={this.handleReblogClick} />
|
||||||
{reblogCount !== 0 && <Link to={`/@${status.getIn(['account', 'acct'])}/posts/${status.get('id')}/reblogs`} className='detailed-status__link'>{reblogCount}</Link>}
|
{reblogCount !== 0 && <Link to={`/@${status.getIn(['account', 'acct'])}/posts/${status.get('id')}/reblogs`} className='detailed-status__link'>{reblogCount}</Link>}
|
||||||
</div>
|
</div>
|
||||||
<div className='status__action-bar__counter status__action-bar__counter--favourite'>
|
<div
|
||||||
<EmojiSelector onReact={this.handleReactClick} />
|
className='status__action-bar__counter status__action-bar__counter--favourite'
|
||||||
|
onMouseEnter={this.handleLikeButtonHover}
|
||||||
|
onMouseLeave={this.handleLikeButtonLeave}
|
||||||
|
>
|
||||||
|
<EmojiSelector onReact={this.handleReactClick} visible={emojiSelectorVisible} />
|
||||||
<IconButton
|
<IconButton
|
||||||
className='status__action-bar-button star-icon'
|
className='status__action-bar-button star-icon'
|
||||||
animate
|
animate
|
||||||
|
|
|
@ -81,6 +81,10 @@ class ActionBar extends React.PureComponent {
|
||||||
isStaff: false,
|
isStaff: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
emojiSelectorVisible: false,
|
||||||
|
}
|
||||||
|
|
||||||
handleReplyClick = () => {
|
handleReplyClick = () => {
|
||||||
const { me } = this.props;
|
const { me } = this.props;
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -108,6 +112,20 @@ class ActionBar extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMobile = () => window.matchMedia('only screen and (max-width: 895px)').matches;
|
||||||
|
|
||||||
|
handleLikeButtonHover = e => {
|
||||||
|
if (!this.isMobile()) this.setState({ emojiSelectorVisible: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLikeButtonLeave = e => {
|
||||||
|
if (!this.isMobile()) this.setState({ emojiSelectorVisible: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLikeButtonClick = e => {
|
||||||
|
if (this.isMobile()) this.setState({ emojiSelectorVisible: true });
|
||||||
|
}
|
||||||
|
|
||||||
handleReactClick = emoji => {
|
handleReactClick = emoji => {
|
||||||
return e => {
|
return e => {
|
||||||
const { me } = this.props;
|
const { me } = this.props;
|
||||||
|
@ -185,8 +203,16 @@ class ActionBar extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
document.addEventListener('click', e => {
|
||||||
|
if (!document.querySelector('.detailed-status__button--favourite').contains(e.target))
|
||||||
|
this.setState({ emojiSelectorVisible: false });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { status, intl, me, isStaff } = this.props;
|
const { status, intl, me, isStaff } = this.props;
|
||||||
|
const { emojiSelectorVisible } = this.state;
|
||||||
|
|
||||||
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
|
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
|
||||||
const mutingConversation = status.get('muted');
|
const mutingConversation = status.get('muted');
|
||||||
|
@ -265,8 +291,13 @@ class ActionBar extends React.PureComponent {
|
||||||
text='Boost'
|
text='Boost'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='detailed-status__button detailed-status__button--favourite'>
|
<div
|
||||||
<EmojiSelector onReact={this.handleReactClick} />
|
className='detailed-status__button detailed-status__button--favourite'
|
||||||
|
onMouseEnter={this.handleLikeButtonHover}
|
||||||
|
onMouseLeave={this.handleLikeButtonLeave}
|
||||||
|
onClick={this.handleLikeButtonClick}
|
||||||
|
>
|
||||||
|
<EmojiSelector onReact={this.handleReactClick} visible={emojiSelectorVisible} />
|
||||||
<IconButton
|
<IconButton
|
||||||
className='star-icon'
|
className='star-icon'
|
||||||
animate
|
animate
|
||||||
|
@ -274,7 +305,7 @@ class ActionBar extends React.PureComponent {
|
||||||
title={intl.formatMessage(messages.favourite)}
|
title={intl.formatMessage(messages.favourite)}
|
||||||
icon='thumbs-up'
|
icon='thumbs-up'
|
||||||
emoji={meEmojiReact}
|
emoji={meEmojiReact}
|
||||||
onClick={this.handleReactClick(meEmojiReact || '👍')}
|
// onClick={this.handleReactClick(meEmojiReact || '👍')}
|
||||||
text='Like'
|
text='Like'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -66,6 +66,11 @@
|
||||||
transition: 0.1s;
|
transition: 0.1s;
|
||||||
z-index: 999;
|
z-index: 999;
|
||||||
|
|
||||||
|
&--visible {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
&__emoji {
|
&__emoji {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -90,21 +95,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailed-status__button--favourite:hover {
|
|
||||||
.emoji-react-selector {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status__action-bar__counter--favourite {
|
.status__action-bar__counter--favourite {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:hover .emoji-react-selector {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media(max-width: 455px) {
|
@media(max-width: 455px) {
|
||||||
position: static;
|
position: static;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue