Fix livestream countdown i18n
Ticket: 1228 ## Code changes - Pass through `getTimeAgoStr` so that the value gets localized. - Pass the simpler `number` around instead of the `moment` object for better memoization. ## Notable differences Due to how `getTimeAgoStr` is written, we now get to see the time actually counting down, vs "in a few seconds" currently in production. I think the counting-down behavior was the original intentional, since a 1s timer was used (otherwise, a 1-minute timer could be used) ... or maybe not since streams may not start on the dot.
This commit is contained in:
parent
321a6901b4
commit
3b98f73a0f
4 changed files with 41 additions and 30 deletions
|
@ -30,7 +30,7 @@ type Props = {
|
|||
claim: ?StreamClaim,
|
||||
hideComments: boolean,
|
||||
isCurrentClaimLive: boolean,
|
||||
release: any,
|
||||
releaseTimeMs: number,
|
||||
showLivestream: boolean,
|
||||
showScheduledInfo: boolean,
|
||||
uri: string,
|
||||
|
@ -44,7 +44,7 @@ export default function LivestreamLayout(props: Props) {
|
|||
claim,
|
||||
hideComments,
|
||||
isCurrentClaimLive,
|
||||
release,
|
||||
releaseTimeMs,
|
||||
showLivestream,
|
||||
showScheduledInfo,
|
||||
uri,
|
||||
|
@ -72,7 +72,7 @@ export default function LivestreamLayout(props: Props) {
|
|||
<div className={PRIMARY_PLAYER_WRAPPER_CLASS}>
|
||||
<FileRenderInitiator
|
||||
uri={claim.canonical_url}
|
||||
customAction={showScheduledInfo && <LivestreamScheduledInfo release={release} />}
|
||||
customAction={showScheduledInfo && <LivestreamScheduledInfo releaseTimeMs={releaseTimeMs} />}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,29 +5,36 @@ import * as ICONS from 'constants/icons';
|
|||
import Icon from 'component/common/icon';
|
||||
import moment from 'moment';
|
||||
import 'scss/component/livestream-scheduled-info.scss';
|
||||
import I18nMessage from 'component/i18nMessage';
|
||||
import { getTimeAgoStr } from 'util/time';
|
||||
|
||||
type Props = {
|
||||
release: any,
|
||||
releaseTimeMs: number,
|
||||
};
|
||||
|
||||
export default function LivestreamScheduledInfo(props: Props) {
|
||||
const { release } = props;
|
||||
const [startDateFromNow, setStartDateFromNow] = useState(release.fromNow());
|
||||
const { releaseTimeMs } = props;
|
||||
const [startDateFromNow, setStartDateFromNow] = useState('');
|
||||
const [inPast, setInPast] = useState('pending');
|
||||
|
||||
useEffect(() => {
|
||||
const calcTime = () => {
|
||||
setStartDateFromNow(release.fromNow());
|
||||
setInPast(release.isBefore(moment()));
|
||||
};
|
||||
calcTime();
|
||||
const intervalId = setInterval(calcTime, 1000);
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, [release]);
|
||||
const zeroDurationStr = '---';
|
||||
const timeAgoStr = getTimeAgoStr(releaseTimeMs, true, true, zeroDurationStr);
|
||||
|
||||
const startDate = release.format('MMMM Do, h:mm a');
|
||||
if (timeAgoStr === zeroDurationStr) {
|
||||
setInPast(true);
|
||||
} else {
|
||||
setStartDateFromNow(timeAgoStr);
|
||||
setInPast(releaseTimeMs < Date.now());
|
||||
}
|
||||
};
|
||||
|
||||
const intervalId = setInterval(calcTime, 1000);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [releaseTimeMs]);
|
||||
|
||||
const startDate = moment(releaseTimeMs).format('MMMM Do, h:mm a');
|
||||
|
||||
return (
|
||||
inPast !== 'pending' && (
|
||||
|
@ -36,7 +43,7 @@ export default function LivestreamScheduledInfo(props: Props) {
|
|||
<p className={'livestream-scheduled__time'}>
|
||||
{!inPast && (
|
||||
<span>
|
||||
<span>{__('Live %time_date%', { time_date: startDateFromNow })}</span>
|
||||
<I18nMessage tokens={{ time_date: startDateFromNow }}>Live %time_date%</I18nMessage>
|
||||
<br />
|
||||
<span className={'livestream-scheduled__date'}>{startDate}</span>
|
||||
</span>
|
||||
|
|
|
@ -59,12 +59,11 @@ export default function LivestreamPage(props: Props) {
|
|||
const isCurrentClaimLive = isChannelBroadcasting && activeLivestreamForChannel.claimId === claimId;
|
||||
const livestreamChannelId = channelClaimId || '';
|
||||
|
||||
// $FlowFixMe
|
||||
const release = moment.unix(claim.value.release_time);
|
||||
const releaseTime: moment = moment.unix(claim?.value?.release_time || 0);
|
||||
const stringifiedClaim = JSON.stringify(claim);
|
||||
|
||||
React.useEffect(() => {
|
||||
// TODO: This should not be needed one we unify the livestream player (?)
|
||||
// TODO: This should not be needed once we unify the livestream player (?)
|
||||
analytics.playerLoadedEvent('livestream', false);
|
||||
}, []);
|
||||
|
||||
|
@ -88,10 +87,10 @@ export default function LivestreamPage(props: Props) {
|
|||
}, [channelUrl, claim, doCommentSocketConnect, uri]);
|
||||
|
||||
const claimReleaseStartingSoonStatic = () =>
|
||||
release.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
||||
releaseTime.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
||||
|
||||
const claimReleaseStartedRecentlyStatic = () =>
|
||||
release.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
||||
releaseTime.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
||||
|
||||
// Find out current channels status + active live claim every 30 seconds (or 15 if not live)
|
||||
const fasterPoll = !isCurrentClaimLive && (claimReleaseStartingSoonStatic() || claimReleaseStartedRecentlyStatic());
|
||||
|
@ -105,14 +104,14 @@ export default function LivestreamPage(props: Props) {
|
|||
React.useEffect(() => {
|
||||
if (!isInitialized) return;
|
||||
|
||||
const claimReleaseInFuture = () => release.isAfter();
|
||||
const claimReleaseInPast = () => release.isBefore();
|
||||
const claimReleaseInFuture = () => releaseTime.isAfter();
|
||||
const claimReleaseInPast = () => releaseTime.isBefore();
|
||||
|
||||
const claimReleaseStartingSoon = () =>
|
||||
release.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
||||
releaseTime.isBetween(moment(), moment().add(LIVESTREAM_STARTS_SOON_BUFFER, 'minutes'));
|
||||
|
||||
const claimReleaseStartedRecently = () =>
|
||||
release.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
||||
releaseTime.isBetween(moment().subtract(LIVESTREAM_STARTED_RECENTLY_BUFFER, 'minutes'), moment());
|
||||
|
||||
const checkShowLivestream = () =>
|
||||
isChannelBroadcasting &&
|
||||
|
@ -141,7 +140,7 @@ export default function LivestreamPage(props: Props) {
|
|||
}
|
||||
|
||||
return () => clearInterval(intervalId);
|
||||
}, [chatDisabled, isChannelBroadcasting, release, isCurrentClaimLive, isInitialized]);
|
||||
}, [chatDisabled, isChannelBroadcasting, releaseTime, isCurrentClaimLive, isInitialized]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (uri && stringifiedClaim) {
|
||||
|
@ -181,7 +180,7 @@ export default function LivestreamPage(props: Props) {
|
|||
<LivestreamLayout
|
||||
uri={uri}
|
||||
hideComments={hideComments}
|
||||
release={release}
|
||||
releaseTimeMs={releaseTime.unix() * 1000}
|
||||
isCurrentClaimLive={isCurrentClaimLive}
|
||||
showLivestream={showLivestream}
|
||||
showScheduledInfo={showScheduledInfo}
|
||||
|
|
|
@ -36,7 +36,12 @@ export function hmsToSeconds(str: string) {
|
|||
|
||||
// Only intended use of future dates is for claims, in case of scheduled
|
||||
// publishes or livestreams, used in util/formatAriaLabel
|
||||
export function getTimeAgoStr(date: any, showFutureDate?: boolean, genericSecondsString?: boolean) {
|
||||
export function getTimeAgoStr(
|
||||
date: any,
|
||||
showFutureDate?: boolean,
|
||||
genericSecondsString?: boolean,
|
||||
zeroDurationStr: string = 'Just now'
|
||||
) {
|
||||
const suffixList = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'];
|
||||
let duration = 0;
|
||||
let suffix = '';
|
||||
|
@ -59,7 +64,7 @@ export function getTimeAgoStr(date: any, showFutureDate?: boolean, genericSecond
|
|||
str = suffix === 'seconds' ? 'in a few seconds' : 'in %duration% ' + suffix;
|
||||
duration = duration * -1;
|
||||
} else if (duration <= 0) {
|
||||
str = 'Just now';
|
||||
str = zeroDurationStr;
|
||||
} else {
|
||||
str = suffix === 'seconds' && genericSecondsString ? 'A few seconds ago' : '%duration% ' + suffix + ' ago';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue