fix notifications in a background tab (#402)

Part of the way to improving #390.

Before this fix, if you recieved a notification while Pinafore was in a background tab, nothing would happen, because most browsers (Edge, Firefox, Chrome) don't run rAF in background tabs. Furthermore, Chrome doesn't run rIC. In this PR we detect if we're in a background tab and then avoid rAF/rIC in that case.
This commit is contained in:
Nolan Lawson 2018-06-23 10:11:14 -07:00 committed by GitHub
parent 0d601f924e
commit 23ccec45d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 6 deletions

View file

@ -1,14 +1,13 @@
import throttle from 'lodash-es/throttle' import throttle from 'lodash-es/throttle'
import { mark, stop } from '../_utils/marks' import { mark, stop } from '../_utils/marks'
import { store } from '../_store/store' import { store } from '../_store/store'
import { scheduleIdleTask } from '../_utils/scheduleIdleTask'
import uniqBy from 'lodash-es/uniqBy' import uniqBy from 'lodash-es/uniqBy'
import uniq from 'lodash-es/uniq' import uniq from 'lodash-es/uniq'
import isEqual from 'lodash-es/isEqual' import isEqual from 'lodash-es/isEqual'
import { isMobile } from '../_utils/isMobile'
import { import {
insertTimelineItems as insertTimelineItemsInDatabase insertTimelineItems as insertTimelineItemsInDatabase
} from '../_database/timelines/insertion' } from '../_database/timelines/insertion'
import { runMediumPriorityTask } from '../_utils/runMediumPriorityTask'
const STREAMING_THROTTLE_DELAY = 3000 const STREAMING_THROTTLE_DELAY = 3000
@ -82,8 +81,7 @@ async function processFreshUpdates (instanceName, timelineName) {
} }
const lazilyProcessFreshUpdates = throttle((instanceName, timelineName) => { const lazilyProcessFreshUpdates = throttle((instanceName, timelineName) => {
const runTask = isMobile() ? scheduleIdleTask : requestAnimationFrame runMediumPriorityTask(() => {
runTask(() => {
/* no await */ processFreshUpdates(instanceName, timelineName) /* no await */ processFreshUpdates(instanceName, timelineName)
}) })
}, STREAMING_THROTTLE_DELAY) }, STREAMING_THROTTLE_DELAY)
@ -93,6 +91,7 @@ export function addStatusOrNotification (instanceName, timelineName, newStatusOr
} }
export function addStatusesOrNotifications (instanceName, timelineName, newStatusesOrNotifications) { export function addStatusesOrNotifications (instanceName, timelineName, newStatusesOrNotifications) {
console.log('addStatusesOrNotifications', Date.now())
let freshUpdates = store.getForTimeline(instanceName, timelineName, 'freshUpdates') || [] let freshUpdates = store.getForTimeline(instanceName, timelineName, 'freshUpdates') || []
freshUpdates = [].concat(freshUpdates).concat(newStatusesOrNotifications) freshUpdates = [].concat(freshUpdates).concat(newStatusesOrNotifications)
freshUpdates = uniqBy(freshUpdates, _ => _.id) freshUpdates = uniqBy(freshUpdates, _ => _.id)

View file

@ -1,5 +1,5 @@
import { setFavicon } from '../../_utils/setFavicon' import { setFavicon } from '../../_utils/setFavicon'
import { scheduleIdleTask } from '../../_utils/scheduleIdleTask' import { runMediumPriorityTask } from '../../_utils/runMediumPriorityTask'
let currentFaviconHasNotifications = false let currentFaviconHasNotifications = false
@ -8,7 +8,7 @@ export function notificationObservers (store) {
if (!process.browser) { if (!process.browser) {
return return
} }
scheduleIdleTask(() => { runMediumPriorityTask(() => {
if (currentFaviconHasNotifications === hasNotifications) { if (currentFaviconHasNotifications === hasNotifications) {
return return
} }

View file

@ -4,6 +4,7 @@ import { notificationObservers } from './notificationObservers'
import { onlineObservers } from './onlineObservers' import { onlineObservers } from './onlineObservers'
import { navObservers } from './navObservers' import { navObservers } from './navObservers'
import { autosuggestObservers } from './autosuggestObservers' import { autosuggestObservers } from './autosuggestObservers'
import { pageVisibilityObservers } from './pageVisibilityObservers'
export function observers (store) { export function observers (store) {
instanceObservers(store) instanceObservers(store)
@ -12,4 +13,5 @@ export function observers (store) {
onlineObservers(store) onlineObservers(store)
navObservers(store) navObservers(store)
autosuggestObservers(store) autosuggestObservers(store)
pageVisibilityObservers(store)
} }

View file

@ -0,0 +1,9 @@
export function pageVisibilityObservers (store) {
if (!process.browser) {
return
}
document.addEventListener('visibilitychange', () => {
store.set({pageVisibilityHidden: document.hidden})
})
}

View file

@ -0,0 +1,16 @@
import { scheduleIdleTask } from './scheduleIdleTask'
import { store } from '../_store/store'
import { isMobile } from './isMobile'
// Run a task that doesn't need to be processed immediately, but should
// probably be delayed if we're on a mobile device. Also run it sooner
// if we're in a hidden tab, since browsers throttle or don't run setTimeout/rAF/etc.
export function runMediumPriorityTask (fn) {
if (store.get().pageVisibilityHidden) {
fn()
} else if (isMobile()) {
scheduleIdleTask(fn)
} else {
requestAnimationFrame(fn)
}
}