sforkowany z mirror/soapbox
TimelineQueueButtonHeader: convert to tsx
rodzic
577c391417
commit
697c028c4a
|
@ -1,119 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
import { throttle } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const settings = getSettings(state);
|
||||
|
||||
return {
|
||||
autoload: settings.get('autoloadTimelines'),
|
||||
};
|
||||
};
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class TimelineQueueButtonHeader extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
count: PropTypes.number,
|
||||
message: PropTypes.object.isRequired,
|
||||
threshold: PropTypes.number,
|
||||
intl: PropTypes.object.isRequired,
|
||||
autoload: PropTypes.bool,
|
||||
autoloadThreshold: PropTypes.number,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
count: 0,
|
||||
threshold: 400,
|
||||
autoload: true,
|
||||
autoloadThreshold: 50,
|
||||
};
|
||||
|
||||
state = {
|
||||
scrolled: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.attachScrollListener();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.detachScrollListener();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { scrollTop } = (document.scrollingElement || document.documentElement);
|
||||
const { count, onClick, autoload, autoloadThreshold } = this.props;
|
||||
|
||||
if (autoload && scrollTop <= autoloadThreshold && count !== prevProps.count) {
|
||||
onClick();
|
||||
}
|
||||
}
|
||||
|
||||
attachScrollListener() {
|
||||
window.addEventListener('scroll', this.handleScroll);
|
||||
}
|
||||
|
||||
detachScrollListener() {
|
||||
window.removeEventListener('scroll', this.handleScroll);
|
||||
}
|
||||
|
||||
handleScroll = throttle(() => {
|
||||
const { scrollTop } = (document.scrollingElement || document.documentElement);
|
||||
const { threshold, onClick, autoload, autoloadThreshold } = this.props;
|
||||
|
||||
if (autoload && scrollTop <= autoloadThreshold) {
|
||||
onClick();
|
||||
}
|
||||
|
||||
if (scrollTop > threshold) {
|
||||
this.setState({ scrolled: true });
|
||||
} else {
|
||||
this.setState({ scrolled: false });
|
||||
}
|
||||
}, 150, { trailing: true });
|
||||
|
||||
scrollUp = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
handleClick = e => {
|
||||
setTimeout(this.scrollUp, 10);
|
||||
this.props.onClick(e);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { count, message, intl } = this.props;
|
||||
const { scrolled } = this.state;
|
||||
|
||||
const visible = count > 0 && scrolled;
|
||||
|
||||
const classes = classNames('left-1/2 -translate-x-1/2 fixed top-20 z-50', {
|
||||
'hidden': !visible,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<a className='flex items-center bg-primary-600 hover:bg-primary-700 hover:scale-105 active:scale-100 transition-transform text-white rounded-full px-4 py-2 space-x-1.5 cursor-pointer whitespace-nowrap' onClick={this.handleClick}>
|
||||
<Icon src={require('@tabler/icons/icons/arrow-bar-to-up.svg')} />
|
||||
|
||||
{(count > 0) && (
|
||||
<Text theme='inherit' size='sm'>
|
||||
{intl.formatMessage(message, { count })}
|
||||
</Text>
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
import classNames from 'classnames';
|
||||
import { throttle } from 'lodash';
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useIntl, MessageDescriptor } from 'react-intl';
|
||||
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import { useSettings } from 'soapbox/hooks';
|
||||
|
||||
interface ITimelineQueueButtonHeader {
|
||||
onClick: () => void,
|
||||
count?: number,
|
||||
message: MessageDescriptor,
|
||||
threshold?: number,
|
||||
autoloadThreshold?: number,
|
||||
}
|
||||
|
||||
const TimelineQueueButtonHeader: React.FC<ITimelineQueueButtonHeader> = ({
|
||||
onClick,
|
||||
count = 0,
|
||||
message,
|
||||
threshold = 400,
|
||||
autoloadThreshold = 50,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const settings = useSettings();
|
||||
|
||||
const [scrolled, setScrolled] = useState<boolean>(false);
|
||||
const autoload = settings.get('autoloadTimelines') === true;
|
||||
|
||||
const handleScroll = useCallback(throttle(() => {
|
||||
const { scrollTop } = (document.scrollingElement || document.documentElement);
|
||||
|
||||
if (autoload && scrollTop <= autoloadThreshold) {
|
||||
onClick();
|
||||
}
|
||||
|
||||
if (scrollTop > threshold) {
|
||||
setScrolled(true);
|
||||
} else {
|
||||
setScrolled(false);
|
||||
}
|
||||
}, 150, { trailing: true }), []);
|
||||
|
||||
const scrollUp = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const handleClick: React.MouseEventHandler = () => {
|
||||
setTimeout(scrollUp, 10);
|
||||
onClick();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const visible = count > 0 && scrolled;
|
||||
|
||||
const classes = classNames('left-1/2 -translate-x-1/2 fixed top-20 z-50', {
|
||||
'hidden': !visible,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<a className='flex items-center bg-primary-600 hover:bg-primary-700 hover:scale-105 active:scale-100 transition-transform text-white rounded-full px-4 py-2 space-x-1.5 cursor-pointer whitespace-nowrap' onClick={handleClick}>
|
||||
<Icon src={require('@tabler/icons/icons/arrow-bar-to-up.svg')} />
|
||||
|
||||
{(count > 0) && (
|
||||
<Text theme='inherit' size='sm'>
|
||||
{intl.formatMessage(message, { count })}
|
||||
</Text>
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TimelineQueueButtonHeader;
|
Ładowanie…
Reference in New Issue