forked from cybrespace/mastodon
Fix expiring polls not being displayed as such in the WebUI (#11835)
* Fix expiring polls not being displayed as such in the WebUI * Reset expiration state and timer when a poll changes * Refactor timer logic in `_setupTimer`, only set expiration if props have changed * Refactor and do not use deprecated React lifecycles
This commit is contained in:
parent
1882ca673d
commit
524187b653
|
@ -32,8 +32,38 @@ class Poll extends ImmutablePureComponent {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
selected: {},
|
selected: {},
|
||||||
|
expired: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static getDerivedStateFromProps (props, state) {
|
||||||
|
const { poll, intl } = props;
|
||||||
|
const expired = poll.get('expired') || (new Date(poll.get('expires_at'))).getTime() < intl.now();
|
||||||
|
return (expired === state.expired) ? null : { expired };
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this._setupTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate () {
|
||||||
|
this._setupTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
clearTimeout(this._timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_setupTimer () {
|
||||||
|
const { poll, intl } = this.props;
|
||||||
|
clearTimeout(this._timer);
|
||||||
|
if (!this.state.expired) {
|
||||||
|
const delay = (new Date(poll.get('expires_at'))).getTime() - intl.now();
|
||||||
|
this._timer = setTimeout(() => {
|
||||||
|
this.setState({ expired: true });
|
||||||
|
}, delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleOptionChange = e => {
|
handleOptionChange = e => {
|
||||||
const { target: { value } } = e;
|
const { target: { value } } = e;
|
||||||
|
|
||||||
|
@ -68,12 +98,11 @@ class Poll extends ImmutablePureComponent {
|
||||||
this.props.dispatch(fetchPoll(this.props.poll.get('id')));
|
this.props.dispatch(fetchPoll(this.props.poll.get('id')));
|
||||||
};
|
};
|
||||||
|
|
||||||
renderOption (option, optionIndex) {
|
renderOption (option, optionIndex, showResults) {
|
||||||
const { poll, disabled } = this.props;
|
const { poll, disabled } = this.props;
|
||||||
const percent = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
|
const percent = poll.get('votes_count') === 0 ? 0 : (option.get('votes_count') / poll.get('votes_count')) * 100;
|
||||||
const leading = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
|
const leading = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') > other.get('votes_count'));
|
||||||
const active = !!this.state.selected[`${optionIndex}`];
|
const active = !!this.state.selected[`${optionIndex}`];
|
||||||
const showResults = poll.get('voted') || poll.get('expired');
|
|
||||||
|
|
||||||
let titleEmojified = option.get('title_emojified');
|
let titleEmojified = option.get('title_emojified');
|
||||||
if (!titleEmojified) {
|
if (!titleEmojified) {
|
||||||
|
@ -112,19 +141,20 @@ class Poll extends ImmutablePureComponent {
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { poll, intl } = this.props;
|
const { poll, intl } = this.props;
|
||||||
|
const { expired } = this.state;
|
||||||
|
|
||||||
if (!poll) {
|
if (!poll) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeRemaining = poll.get('expired') ? intl.formatMessage(messages.closed) : <RelativeTimestamp timestamp={poll.get('expires_at')} futureDate />;
|
const timeRemaining = expired ? intl.formatMessage(messages.closed) : <RelativeTimestamp timestamp={poll.get('expires_at')} futureDate />;
|
||||||
const showResults = poll.get('voted') || poll.get('expired');
|
const showResults = poll.get('voted') || expired;
|
||||||
const disabled = this.props.disabled || Object.entries(this.state.selected).every(item => !item);
|
const disabled = this.props.disabled || Object.entries(this.state.selected).every(item => !item);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='poll'>
|
<div className='poll'>
|
||||||
<ul>
|
<ul>
|
||||||
{poll.get('options').map((option, i) => this.renderOption(option, i))}
|
{poll.get('options').map((option, i) => this.renderOption(option, i, showResults))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className='poll__footer'>
|
<div className='poll__footer'>
|
||||||
|
|
Loading…
Reference in New Issue