2018-08-29 22:03:29 -07:00
|
|
|
import { database } from '../_database/database'
|
2019-08-17 14:36:13 -07:00
|
|
|
import { decode as decodeBlurhash, init as initBlurhash } from '../_utils/blurhash'
|
|
|
|
import { mark, stop } from '../_utils/marks'
|
2018-08-29 22:03:29 -07:00
|
|
|
|
|
|
|
async function getNotification (instanceName, timelineType, timelineValue, itemId) {
|
|
|
|
return {
|
|
|
|
timelineType,
|
|
|
|
timelineValue,
|
|
|
|
notification: await database.getNotification(instanceName, itemId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getStatus (instanceName, timelineType, timelineValue, itemId) {
|
|
|
|
return {
|
|
|
|
timelineType,
|
|
|
|
timelineValue,
|
|
|
|
status: await database.getStatus(instanceName, itemId)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-17 14:36:13 -07:00
|
|
|
function tryInitBlurhash () {
|
|
|
|
try {
|
|
|
|
initBlurhash()
|
|
|
|
} catch (err) {
|
|
|
|
console.error('could not start blurhash worker', err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function decodeAllBlurhashes (statusOrNotification) {
|
|
|
|
const status = statusOrNotification.status || statusOrNotification.notification.status
|
|
|
|
if (status && status.media_attachments) {
|
|
|
|
mark(`decodeBlurhash-${status.id}`)
|
|
|
|
await Promise.all(status.media_attachments.map(async media => {
|
|
|
|
if (media.blurhash) {
|
|
|
|
try {
|
|
|
|
media.decodedBlurhash = await decodeBlurhash(media.blurhash)
|
|
|
|
} catch (err) {
|
|
|
|
console.warn('Could not decode blurhash, ignoring', err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
stop(`decodeBlurhash-${status.id}`)
|
|
|
|
}
|
|
|
|
return statusOrNotification
|
|
|
|
}
|
|
|
|
|
2018-08-29 22:03:29 -07:00
|
|
|
export function createMakeProps (instanceName, timelineType, timelineValue) {
|
|
|
|
let taskCount = 0
|
|
|
|
let pending = []
|
|
|
|
|
2019-08-17 14:36:13 -07:00
|
|
|
tryInitBlurhash() // start the blurhash worker a bit early to save time
|
|
|
|
|
2018-08-29 22:03:29 -07:00
|
|
|
// The worker-powered indexeddb promises can resolve in arbitrary order,
|
|
|
|
// causing the timeline to load in a jerky way. With this function, we
|
|
|
|
// wait for all promises to resolve before resolving them all in one go.
|
|
|
|
function awaitAllTasksComplete () {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
taskCount--
|
|
|
|
pending.push(resolve)
|
|
|
|
if (taskCount === 0) {
|
|
|
|
pending.forEach(_ => _())
|
|
|
|
pending = []
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-08-17 14:36:13 -07:00
|
|
|
async function fetchFromIndexedDB (itemId) {
|
|
|
|
mark(`fetchFromIndexedDB-${itemId}`)
|
|
|
|
try {
|
|
|
|
const res = await (timelineType === 'notifications'
|
|
|
|
? getNotification(instanceName, timelineType, timelineValue, itemId)
|
|
|
|
: getStatus(instanceName, timelineType, timelineValue, itemId))
|
|
|
|
return res
|
|
|
|
} finally {
|
|
|
|
stop(`fetchFromIndexedDB-${itemId}`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-29 22:03:29 -07:00
|
|
|
return (itemId) => {
|
|
|
|
taskCount++
|
|
|
|
|
2019-08-17 14:36:13 -07:00
|
|
|
return fetchFromIndexedDB(itemId)
|
|
|
|
.then(decodeAllBlurhashes)
|
|
|
|
.then(statusOrNotification => {
|
|
|
|
return awaitAllTasksComplete().then(() => statusOrNotification)
|
|
|
|
})
|
2018-08-29 22:03:29 -07:00
|
|
|
}
|
|
|
|
}
|