Hovercard: refactor with HoverRefWrapper
This commit is contained in:
parent
c0051df335
commit
1d90950e59
5 changed files with 62 additions and 42 deletions
50
app/soapbox/components/hover_ref_wrapper.js
Normal file
50
app/soapbox/components/hover_ref_wrapper.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
openProfileHoverCard,
|
||||||
|
closeProfileHoverCard,
|
||||||
|
} from 'soapbox/actions/profile_hover_card';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { debounce } from 'lodash';
|
||||||
|
import { isMobile } from 'soapbox/is_mobile';
|
||||||
|
|
||||||
|
const showProfileHoverCard = debounce((dispatch, ref, accountId) => {
|
||||||
|
dispatch(openProfileHoverCard(ref, accountId));
|
||||||
|
}, 1200);
|
||||||
|
|
||||||
|
const handleMouseEnter = (dispatch, ref, accountId) => {
|
||||||
|
return e => {
|
||||||
|
if (!isMobile(window.innerWidth))
|
||||||
|
showProfileHoverCard(dispatch, ref, accountId);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseLeave = (dispatch) => {
|
||||||
|
return e => {
|
||||||
|
showProfileHoverCard.cancel();
|
||||||
|
setTimeout(() => dispatch(closeProfileHoverCard()), 300);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HoverRefWrapper = ({ accountId, children }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const ref = useRef();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className='hover-ref-wrapper'
|
||||||
|
onMouseEnter={handleMouseEnter(dispatch, ref, accountId)}
|
||||||
|
onMouseLeave={handleMouseLeave(dispatch)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
HoverRefWrapper.propTypes = {
|
||||||
|
accountId: PropTypes.string,
|
||||||
|
children: PropTypes.node,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HoverRefWrapper;
|
|
@ -45,7 +45,7 @@ export const ProfileHoverCard = ({ visible }) => {
|
||||||
|
|
||||||
const accountId = useSelector(state => state.getIn(['profile_hover_card', 'accountId']));
|
const accountId = useSelector(state => state.getIn(['profile_hover_card', 'accountId']));
|
||||||
const account = useSelector(state => accountId && getAccount(state, accountId));
|
const account = useSelector(state => accountId && getAccount(state, accountId));
|
||||||
const targetRef = useSelector(state => state.getIn(['profile_hover_card', 'ref']));
|
const targetRef = useSelector(state => state.getIn(['profile_hover_card', 'ref', 'current']));
|
||||||
const badges = account ? getBadges(account) : [];
|
const badges = account ? getBadges(account) : [];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -18,9 +18,8 @@ import classNames from 'classnames';
|
||||||
import Icon from 'soapbox/components/icon';
|
import Icon from 'soapbox/components/icon';
|
||||||
import PollContainer from 'soapbox/containers/poll_container';
|
import PollContainer from 'soapbox/containers/poll_container';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { isMobile } from '../../../app/soapbox/is_mobile';
|
|
||||||
import { debounce } from 'lodash';
|
|
||||||
import { getDomain } from 'soapbox/utils/accounts';
|
import { getDomain } from 'soapbox/utils/accounts';
|
||||||
|
import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper';
|
||||||
|
|
||||||
// We use the component (and not the container) since we do not want
|
// We use the component (and not the container) since we do not want
|
||||||
// to use the progress bar to show download progress
|
// to use the progress bar to show download progress
|
||||||
|
@ -255,20 +254,6 @@ class Status extends ImmutablePureComponent {
|
||||||
this.handleToggleMediaVisibility();
|
this.handleToggleMediaVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
showProfileHoverCard = debounce(() => {
|
|
||||||
const { onShowProfileHoverCard, status } = this.props;
|
|
||||||
onShowProfileHoverCard(this.profileNode, status.getIn(['account', 'id']));
|
|
||||||
}, 1200);
|
|
||||||
|
|
||||||
handleProfileHover = e => {
|
|
||||||
if (!isMobile(window.innerWidth)) this.showProfileHoverCard();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleProfileLeave = e => {
|
|
||||||
this.showProfileHoverCard.cancel();
|
|
||||||
this.props.onClearProfileHoverCard();
|
|
||||||
}
|
|
||||||
|
|
||||||
_properStatus() {
|
_properStatus() {
|
||||||
const { status } = this.props;
|
const { status } = this.props;
|
||||||
|
|
||||||
|
@ -283,10 +268,6 @@ class Status extends ImmutablePureComponent {
|
||||||
this.node = c;
|
this.node = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
setProfileRef = c => {
|
|
||||||
this.profileNode = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let media = null;
|
let media = null;
|
||||||
let poll = null;
|
let poll = null;
|
||||||
|
@ -481,7 +462,8 @@ class Status extends ImmutablePureComponent {
|
||||||
<img src={favicon} alt='' title={domain} />
|
<img src={favicon} alt='' title={domain} />
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
<div className='status__profile' ref={this.setProfileRef} onMouseEnter={this.handleProfileHover} onMouseLeave={this.handleProfileLeave}>
|
<HoverRefWrapper accountId={status.getIn(['account', 'id'])}>
|
||||||
|
<div className='status__profile'>
|
||||||
<div className='status__avatar'>
|
<div className='status__avatar'>
|
||||||
<NavLink to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='floating-link' />
|
<NavLink to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='floating-link' />
|
||||||
{statusAvatar}
|
{statusAvatar}
|
||||||
|
@ -490,6 +472,7 @@ class Status extends ImmutablePureComponent {
|
||||||
<DisplayName account={status.get('account')} others={otherAccounts} />
|
<DisplayName account={status.get('account')} others={otherAccounts} />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
</HoverRefWrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!group && status.get('group') && (
|
{!group && status.get('group') && (
|
||||||
|
|
|
@ -35,10 +35,6 @@ import {
|
||||||
groupRemoveStatus,
|
groupRemoveStatus,
|
||||||
} from '../actions/groups';
|
} from '../actions/groups';
|
||||||
import { getSettings } from '../actions/settings';
|
import { getSettings } from '../actions/settings';
|
||||||
import {
|
|
||||||
openProfileHoverCard,
|
|
||||||
closeProfileHoverCard,
|
|
||||||
} from 'soapbox/actions/profile_hover_card';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
|
@ -210,14 +206,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
dispatch(groupRemoveStatus(groupId, statusId));
|
dispatch(groupRemoveStatus(groupId, statusId));
|
||||||
},
|
},
|
||||||
|
|
||||||
onShowProfileHoverCard(ref, accountId) {
|
|
||||||
dispatch(openProfileHoverCard(ref, accountId));
|
|
||||||
},
|
|
||||||
|
|
||||||
onClearProfileHoverCard() {
|
|
||||||
setTimeout(() => dispatch(closeProfileHoverCard()), 300);
|
|
||||||
},
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status));
|
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status));
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&--visible {
|
&--visible {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
Loading…
Reference in a new issue