Update poll remaining time just like with status timestamps (#10466)
parent
d07b0c038f
commit
daab45d4ae
|
@ -9,41 +9,12 @@ import Motion from 'mastodon/features/ui/util/optional_motion';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
import escapeTextContentForBrowser from 'escape-html';
|
import escapeTextContentForBrowser from 'escape-html';
|
||||||
import emojify from 'mastodon/features/emoji/emoji';
|
import emojify from 'mastodon/features/emoji/emoji';
|
||||||
|
import RelativeTimestamp from './relative_timestamp';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
moments: { id: 'time_remaining.moments', defaultMessage: 'Moments remaining' },
|
|
||||||
seconds: { id: 'time_remaining.seconds', defaultMessage: '{number, plural, one {# second} other {# seconds}} left' },
|
|
||||||
minutes: { id: 'time_remaining.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}} left' },
|
|
||||||
hours: { id: 'time_remaining.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}} left' },
|
|
||||||
days: { id: 'time_remaining.days', defaultMessage: '{number, plural, one {# day} other {# days}} left' },
|
|
||||||
closed: { id: 'poll.closed', defaultMessage: 'Closed' },
|
closed: { id: 'poll.closed', defaultMessage: 'Closed' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const SECOND = 1000;
|
|
||||||
const MINUTE = 1000 * 60;
|
|
||||||
const HOUR = 1000 * 60 * 60;
|
|
||||||
const DAY = 1000 * 60 * 60 * 24;
|
|
||||||
|
|
||||||
const timeRemainingString = (intl, date, now) => {
|
|
||||||
const delta = date.getTime() - now;
|
|
||||||
|
|
||||||
let relativeTime;
|
|
||||||
|
|
||||||
if (delta < 10 * SECOND) {
|
|
||||||
relativeTime = intl.formatMessage(messages.moments);
|
|
||||||
} else if (delta < MINUTE) {
|
|
||||||
relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) });
|
|
||||||
} else if (delta < HOUR) {
|
|
||||||
relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) });
|
|
||||||
} else if (delta < DAY) {
|
|
||||||
relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) });
|
|
||||||
} else {
|
|
||||||
relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) });
|
|
||||||
}
|
|
||||||
|
|
||||||
return relativeTime;
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
|
const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => {
|
||||||
obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
|
obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -146,7 +117,7 @@ class Poll extends ImmutablePureComponent {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeRemaining = poll.get('expired') ? intl.formatMessage(messages.closed) : timeRemainingString(intl, new Date(poll.get('expires_at')), intl.now());
|
const timeRemaining = poll.get('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') || poll.get('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);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,11 @@ const messages = defineMessages({
|
||||||
minutes: { id: 'relative_time.minutes', defaultMessage: '{number}m' },
|
minutes: { id: 'relative_time.minutes', defaultMessage: '{number}m' },
|
||||||
hours: { id: 'relative_time.hours', defaultMessage: '{number}h' },
|
hours: { id: 'relative_time.hours', defaultMessage: '{number}h' },
|
||||||
days: { id: 'relative_time.days', defaultMessage: '{number}d' },
|
days: { id: 'relative_time.days', defaultMessage: '{number}d' },
|
||||||
|
moments_remaining: { id: 'time_remaining.moments', defaultMessage: 'Moments remaining' },
|
||||||
|
seconds_remaining: { id: 'time_remaining.seconds', defaultMessage: '{number, plural, one {# second} other {# seconds}} left' },
|
||||||
|
minutes_remaining: { id: 'time_remaining.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}} left' },
|
||||||
|
hours_remaining: { id: 'time_remaining.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}} left' },
|
||||||
|
days_remaining: { id: 'time_remaining.days', defaultMessage: '{number, plural, one {# day} other {# days}} left' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const dateFormatOptions = {
|
const dateFormatOptions = {
|
||||||
|
@ -86,6 +91,26 @@ export const timeAgoString = (intl, date, now, year) => {
|
||||||
return relativeTime;
|
return relativeTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const timeRemainingString = (intl, date, now) => {
|
||||||
|
const delta = date.getTime() - now;
|
||||||
|
|
||||||
|
let relativeTime;
|
||||||
|
|
||||||
|
if (delta < 10 * SECOND) {
|
||||||
|
relativeTime = intl.formatMessage(messages.moments_remaining);
|
||||||
|
} else if (delta < MINUTE) {
|
||||||
|
relativeTime = intl.formatMessage(messages.seconds_remaining, { number: Math.floor(delta / SECOND) });
|
||||||
|
} else if (delta < HOUR) {
|
||||||
|
relativeTime = intl.formatMessage(messages.minutes_remaining, { number: Math.floor(delta / MINUTE) });
|
||||||
|
} else if (delta < DAY) {
|
||||||
|
relativeTime = intl.formatMessage(messages.hours_remaining, { number: Math.floor(delta / HOUR) });
|
||||||
|
} else {
|
||||||
|
relativeTime = intl.formatMessage(messages.days_remaining, { number: Math.floor(delta / DAY) });
|
||||||
|
}
|
||||||
|
|
||||||
|
return relativeTime;
|
||||||
|
};
|
||||||
|
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
class RelativeTimestamp extends React.Component {
|
class RelativeTimestamp extends React.Component {
|
||||||
|
|
||||||
|
@ -93,6 +118,7 @@ class RelativeTimestamp extends React.Component {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
timestamp: PropTypes.string.isRequired,
|
timestamp: PropTypes.string.isRequired,
|
||||||
year: PropTypes.number.isRequired,
|
year: PropTypes.number.isRequired,
|
||||||
|
futureDate: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -145,10 +171,10 @@ class RelativeTimestamp extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { timestamp, intl, year } = this.props;
|
const { timestamp, intl, year, futureDate } = this.props;
|
||||||
|
|
||||||
const date = new Date(timestamp);
|
const date = new Date(timestamp);
|
||||||
const relativeTime = timeAgoString(intl, date, this.state.now, year);
|
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<time dateTime={timestamp} title={intl.formatDate(date, dateFormatOptions)}>
|
<time dateTime={timestamp} title={intl.formatDate(date, dateFormatOptions)}>
|
||||||
|
|
Reference in New Issue