fix: poll for updates to timeago displays (#1232)

* fix: poll for updates to timeago displays

* code cleanup

* avoid some recomputes

* avoid costly recomputes
This commit is contained in:
Nolan Lawson 2019-05-26 16:01:14 -07:00 committed by GitHub
parent bf640b9b0f
commit dac4b493c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 32 deletions

View file

@ -29,4 +29,4 @@
}
}
}
</script>
</script>

View file

@ -13,11 +13,11 @@
<StatusAuthorName {...params} />
<StatusAuthorHandle {...params} />
{#if !isStatusInOwnThread}
<StatusRelativeDate {...params} />
<StatusRelativeDate {...params} {...timestampParams} />
{/if}
<StatusSidebar {...params} />
{#if spoilerText}
<StatusSpoiler {...params} on:recalculateHeight />
<StatusSpoiler {...params} {spoilerShown} on:recalculateHeight />
{/if}
{#if !showContent}
<StatusMentions {...params} />
@ -35,9 +35,9 @@
<StatusPoll {...params} />
{/if}
{#if isStatusInOwnThread}
<StatusDetails {...params} />
<StatusDetails {...params} {...timestampParams} />
{/if}
<StatusToolbar {...params} on:recalculateHeight />
<StatusToolbar {...params} {replyShown} on:recalculateHeight />
{#if replyShown}
<StatusComposeBox {...params} on:recalculateHeight />
{/if}
@ -277,13 +277,15 @@
originalStatus.media_attachments.length
),
originalAccountEmojis: ({ originalAccount }) => (originalAccount.emojis || []),
originalStatusEmojis: ({ originalStatus }) => (originalStatus.emojis || []),
originalAccountDisplayName: ({ originalAccount }) => (originalAccount.display_name || originalAccount.username),
originalAccountAccessibleName: ({ originalAccount, $omitEmojiInDisplayNames }) => {
return getAccountAccessibleName(originalAccount, $omitEmojiInDisplayNames)
},
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
absoluteFormattedDate: ({ createdAtDate }) => absoluteDateFormatter.format(new Date(createdAtDate)),
timeagoFormattedDate: ({ createdAtDate }) => formatTimeagoDate(createdAtDate),
createdAtDateTS: ({ createdAtDate }) => new Date(createdAtDate).getTime(),
absoluteFormattedDate: ({ createdAtDateTS }) => absoluteDateFormatter.format(createdAtDateTS),
timeagoFormattedDate: ({ createdAtDateTS, $now }) => formatTimeagoDate(createdAtDateTS, $now),
reblog: ({ status }) => status.reblog,
ariaLabel: ({ originalAccount, account, plainTextContent, timeagoFormattedDate, spoilerText,
showContent, reblog, notification, visibility, $omitEmojiInDisplayNames, $disableLongAriaLabels }) => (
@ -307,11 +309,22 @@
)),
content: ({ originalStatus }) => originalStatus.content || '',
showContent: ({ spoilerText, spoilerShown }) => !spoilerText || spoilerShown,
// These timestamp params may change every 10 seconds due to now() polling, so keep them
// separate from the generic `params` list to avoid costly recomputes.
timestampParams: ({ createdAtDate, createdAtDateTS, timeagoFormattedDate, absoluteFormattedDate }) => ({
createdAtDate,
createdAtDateTS,
timeagoFormattedDate,
absoluteFormattedDate
}),
// This params list deliberately does *not* include `spoilersShown` or `replyShown`, because these
// change frequently and would therefore cause costly recomputes if included here.
// The main goal here is to avoid typing by passing as many params as possible to child components.
params: ({ notification, notificationId, status, statusId, timelineType,
account, accountId, uuid, isStatusInNotification, isStatusInOwnThread,
originalAccount, originalAccountId, spoilerShown, visibility, replyShown,
originalAccount, originalAccountId, visibility,
replyVisibility, spoilerText, originalStatus, originalStatusId, inReplyToId,
createdAtDate, timeagoFormattedDate, enableShortcuts, absoluteFormattedDate, shortcutScope }) => ({
enableShortcuts, shortcutScope, originalStatusEmojis }) => ({
notification,
notificationId,
status,
@ -324,19 +337,15 @@
isStatusInOwnThread,
originalAccount,
originalAccountId,
spoilerShown,
visibility,
replyShown,
replyVisibility,
spoilerText,
originalStatus,
originalStatusId,
inReplyToId,
createdAtDate,
timeagoFormattedDate,
enableShortcuts,
absoluteFormattedDate,
shortcutScope
shortcutScope,
originalStatusEmojis
})
},
events: {

View file

@ -76,8 +76,9 @@
)
},
content: ({ originalStatus }) => (originalStatus.content || ''),
emojis: ({ originalStatus }) => originalStatus.emojis,
massagedContent: ({ content, emojis, $autoplayGifs }) => massageUserText(content, emojis, $autoplayGifs)
massagedContent: ({ content, originalStatusEmojis, $autoplayGifs }) => (
massageUserText(content, originalStatusEmojis, $autoplayGifs)
)
},
methods: {
hydrateContent () {

View file

@ -158,7 +158,6 @@
application: ({ originalStatus }) => originalStatus.application,
applicationName: ({ application }) => (application && application.name),
applicationWebsite: ({ application }) => (application && application.website),
createdAtDate: ({ originalStatus }) => originalStatus.created_at,
numReblogs: ({ overrideNumReblogs, originalStatus }) => {
if (typeof overrideNumReblogs === 'number') {
return overrideNumReblogs
@ -171,8 +170,8 @@
}
return originalStatus.favourites_count || 0
},
displayAbsoluteFormattedDate: ({ createdAtDate, $isMobileSize }) => (
$isMobileSize ? shortAbsoluteDateFormatter : absoluteDateFormatter).format(new Date(createdAtDate)
displayAbsoluteFormattedDate: ({ createdAtDateTS, $isMobileSize }) => (
($isMobileSize ? shortAbsoluteDateFormatter : absoluteDateFormatter).format(createdAtDateTS)
),
reblogsLabel: ({ numReblogs }) => {
// TODO: intl

View file

@ -64,10 +64,9 @@
Shortcut
},
computed: {
emojis: ({ originalStatus }) => originalStatus.emojis,
massagedSpoilerText: ({ spoilerText, emojis, $autoplayGifs }) => {
massagedSpoilerText: ({ spoilerText, originalStatusEmojis, $autoplayGifs }) => {
spoilerText = escapeHtml(spoilerText)
return emojifyText(spoilerText, emojis, $autoplayGifs)
return emojifyText(spoilerText, originalStatusEmojis, $autoplayGifs)
},
elementId: ({ uuid }) => `spoiler-${uuid}`
},

View file

@ -1,9 +1,10 @@
import { format } from '../_thirdparty/timeago/timeago'
import { mark, stop } from '../_utils/marks'
export function formatTimeagoDate (date) {
export function formatTimeagoDate (date, now) {
mark('formatTimeagoDate')
let res = format(date)
// use Math.max() to avoid things like "in 10 seconds" when the timestamps are slightly off
let res = format(date, Math.max(now, date))
stop('formatTimeagoDate')
return res
}

View file

@ -0,0 +1,47 @@
// For convenience, periodically re-compute the current time. This ensures freshness of
// displays like "x minutes ago" without having to jump through a lot of hoops.
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
import lifecycle from 'page-lifecycle/dist/lifecycle.mjs'
const POLL_INTERVAL = 10000
export function nowObservers (store) {
let interval
function updateNow () {
store.set({ now: Date.now() })
}
function startPolling () {
interval = setInterval(() => scheduleIdleTask(updateNow), POLL_INTERVAL)
}
function stopPolling () {
if (interval) {
clearInterval(interval)
interval = null
}
}
function restartPolling () {
stopPolling()
scheduleIdleTask(updateNow)
startPolling()
}
updateNow()
if (process.browser) {
startPolling()
lifecycle.addEventListener('statechange', e => {
if (e.newState === 'passive') {
console.log('stopping Date.now() observer...')
stopPolling()
} else if (e.newState === 'active') {
console.log('restarting Date.now() observer...')
restartPolling()
}
})
}
}

View file

@ -1,4 +1,5 @@
import { onlineObservers } from './onlineObservers'
import { nowObservers } from './nowObservers'
import { navObservers } from './navObservers'
import { pageVisibilityObservers } from './pageVisibilityObservers'
import { resizeObservers } from './resizeObservers'
@ -8,6 +9,7 @@ import { touchObservers } from './touchObservers'
export function observers (store) {
onlineObservers(store)
nowObservers(store)
navObservers(store)
pageVisibilityObservers(store)
resizeObservers(store)

View file

@ -4,7 +4,7 @@
* Contract: i@hust.cc
*/
var IndexMapEn = 'second_minute_hour_day_week_month_year'.split('_')
var IndexMapEn = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year']
var SEC_ARRAY = [60, 60, 24, 7, 365 / 7 / 12, 12]
/**
@ -63,16 +63,14 @@ function formatDiff (diff) {
* @param nowDate
* @returns {number}
*/
function diffSec (date) {
var nowDate = new Date()
var otherDate = new Date(date)
return (nowDate - otherDate) / 1000
function diffSec (date, now) {
return (now - date) / 1000
}
/**
* Created by hustcc on 18/5/20.
* Contract: i@hust.cc
*/
export function format (date) {
return formatDiff(diffSec(date))
export function format (date, now) {
return formatDiff(diffSec(date, now))
}