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:
parent
0d601f924e
commit
23ccec45d0
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
9
routes/_store/observers/pageVisibilityObservers.js
Normal file
9
routes/_store/observers/pageVisibilityObservers.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export function pageVisibilityObservers (store) {
|
||||||
|
if (!process.browser) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
store.set({pageVisibilityHidden: document.hidden})
|
||||||
|
})
|
||||||
|
}
|
16
routes/_utils/runMediumPriorityTask.js
Normal file
16
routes/_utils/runMediumPriorityTask.js
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue