pinafore/src/routes/_actions/timeline.js

163 lines
6.6 KiB
JavaScript
Raw Normal View History

2018-01-28 21:09:39 +00:00
import { store } from '../_store/store'
2018-02-08 16:22:14 +00:00
import { getTimeline } from '../_api/timelines'
2018-12-22 23:37:51 +00:00
import { toast } from '../_components/toast/toast'
2018-01-28 01:34:08 +00:00
import { mark, stop } from '../_utils/marks'
import { concat, mergeArrays } from '../_utils/arrays'
import { compareTimelineItemSummaries } from '../_utils/sorting'
import isEqual from 'lodash-es/isEqual'
import { database } from '../_database/database'
import { getStatus, getStatusContext } from '../_api/statuses'
import { emit } from '../_utils/eventBus'
import { TIMELINE_BATCH_SIZE } from '../_static/timelines'
import { timelineItemToSummary } from '../_utils/timelineItemToSummary'
2018-01-28 01:34:08 +00:00
async function storeFreshTimelineItemsInDatabase (instanceName, timelineName, items) {
await database.insertTimelineItems(instanceName, timelineName, items)
if (timelineName.startsWith('status/')) {
// For status threads, we want to be sure to update the favorite/reblog counts even if
// this is a stale "view" of the status. See 119-status-counts-update.js for
// an example of why we need this.
items.forEach(item => {
emit('statusUpdated', item)
})
}
}
async function fetchTimelineItemsFromNetwork (instanceName, accessToken, timelineName, lastTimelineItemId) {
if (timelineName.startsWith('status/')) { // special case - this is a list of descendents and ancestors
let statusId = timelineName.split('/').slice(-1)[0]
let statusRequest = getStatus(instanceName, accessToken, statusId)
let contextRequest = getStatusContext(instanceName, accessToken, statusId)
let [ status, context ] = await Promise.all([statusRequest, contextRequest])
return concat(context.ancestors, status, context.descendants)
} else { // normal timeline
return getTimeline(instanceName, accessToken, timelineName, lastTimelineItemId, null, TIMELINE_BATCH_SIZE)
}
}
2018-02-09 06:29:29 +00:00
async function fetchTimelineItems (instanceName, accessToken, timelineName, lastTimelineItemId, online) {
mark('fetchTimelineItems')
let items
2018-03-11 19:11:06 +00:00
let stale = false
2018-01-28 01:34:08 +00:00
if (!online) {
items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, TIMELINE_BATCH_SIZE)
2018-03-11 19:11:06 +00:00
stale = true
2018-01-28 01:34:08 +00:00
} else {
try {
console.log('fetchTimelineItemsFromNetwork')
items = await fetchTimelineItemsFromNetwork(instanceName, accessToken, timelineName, lastTimelineItemId)
/* no await */ storeFreshTimelineItemsInDatabase(instanceName, timelineName, items)
2018-01-28 01:34:08 +00:00
} catch (e) {
console.error(e)
toast.say('Internet request failed. Showing offline content.')
items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, TIMELINE_BATCH_SIZE)
2018-03-11 19:11:06 +00:00
stale = true
2018-01-28 01:34:08 +00:00
}
}
stop('fetchTimelineItems')
2018-03-11 19:11:06 +00:00
return { items, stale }
2018-01-28 01:34:08 +00:00
}
2018-03-11 19:11:06 +00:00
async function addTimelineItems (instanceName, timelineName, items, stale) {
console.log('addTimelineItems, length:', items.length)
mark('addTimelineItemSummaries')
let newSummaries = items.map(timelineItemToSummary)
addTimelineItemSummaries(instanceName, timelineName, newSummaries, stale)
stop('addTimelineItemSummaries')
2018-02-11 21:46:57 +00:00
}
export async function addTimelineItemSummaries (instanceName, timelineName, newSummaries, newStale) {
let oldSummaries = store.getForTimeline(instanceName, timelineName, 'timelineItemSummaries') || []
let oldStale = store.getForTimeline(instanceName, timelineName, 'timelineItemSummariesAreStale')
2018-03-11 19:11:06 +00:00
let mergedSummaries = mergeArrays(oldSummaries, newSummaries, compareTimelineItemSummaries)
2018-03-11 19:11:06 +00:00
if (!isEqual(oldSummaries, mergedSummaries)) {
store.setForTimeline(instanceName, timelineName, { timelineItemSummaries: mergedSummaries })
2018-03-11 19:11:06 +00:00
}
if (oldStale !== newStale) {
store.setForTimeline(instanceName, timelineName, { timelineItemSummariesAreStale: newStale })
2018-03-11 19:11:06 +00:00
}
2018-01-28 01:34:08 +00:00
}
2018-02-09 06:29:29 +00:00
async function fetchTimelineItemsAndPossiblyFallBack () {
mark('fetchTimelineItemsAndPossiblyFallBack')
let {
currentTimeline,
currentInstance,
accessToken,
lastTimelineItemId,
online
} = store.get()
2018-01-28 01:34:08 +00:00
let { items, stale } = await fetchTimelineItems(currentInstance, accessToken, currentTimeline, lastTimelineItemId, online)
addTimelineItems(currentInstance, currentTimeline, items, stale)
stop('fetchTimelineItemsAndPossiblyFallBack')
2018-01-28 01:34:08 +00:00
}
2018-02-09 06:29:29 +00:00
export async function setupTimeline () {
mark('setupTimeline')
// If we don't have any item summaries, or if the current item summaries are stale
2018-03-11 19:11:06 +00:00
// (i.e. via offline mode), then we need to re-fetch
// Also do this if it's a thread, because threads change pretty frequently and
// we don't have a good way to update them.
let {
timelineItemSummaries,
timelineItemSummariesAreStale,
currentTimeline
} = store.get()
if (!timelineItemSummaries ||
timelineItemSummariesAreStale ||
2018-03-11 19:11:06 +00:00
currentTimeline.startsWith('status/')) {
await fetchTimelineItemsAndPossiblyFallBack()
2018-01-28 01:34:08 +00:00
}
stop('setupTimeline')
2018-01-28 01:34:08 +00:00
}
2018-03-10 18:54:16 +00:00
export async function fetchTimelineItemsOnScrollToBottom (instanceName, timelineName) {
console.log('setting runningUpdate: true')
2018-01-28 01:34:08 +00:00
store.setForTimeline(instanceName, timelineName, { runningUpdate: true })
await fetchTimelineItemsAndPossiblyFallBack()
console.log('setting runningUpdate: false')
store.setForTimeline(instanceName, timelineName, { runningUpdate: false })
2018-02-09 06:29:29 +00:00
}
2018-02-12 03:15:21 +00:00
2018-03-10 18:54:16 +00:00
export async function showMoreItemsForTimeline (instanceName, timelineName) {
mark('showMoreItemsForTimeline')
let itemSummariesToAdd = store.getForTimeline(instanceName, timelineName, 'timelineItemSummariesToAdd')
itemSummariesToAdd = itemSummariesToAdd.sort(compareTimelineItemSummaries).reverse()
addTimelineItemSummaries(instanceName, timelineName, itemSummariesToAdd, false)
2018-02-12 03:15:21 +00:00
store.setForTimeline(instanceName, timelineName, {
timelineItemSummariesToAdd: [],
2018-02-12 03:15:21 +00:00
shouldShowHeader: false,
showHeader: false
})
2018-03-10 18:54:16 +00:00
stop('showMoreItemsForTimeline')
2018-02-14 03:35:46 +00:00
}
2018-03-10 06:31:26 +00:00
2018-03-10 18:54:16 +00:00
export async function showMoreItemsForCurrentTimeline () {
let { currentInstance, currentTimeline } = store.get()
2018-03-10 18:54:16 +00:00
return showMoreItemsForTimeline(
currentInstance,
currentTimeline
2018-03-10 18:54:16 +00:00
)
}
export async function showMoreItemsForThread (instanceName, timelineName) {
mark('showMoreItemsForThread')
let itemSummariesToAdd = store.getForTimeline(instanceName, timelineName, 'timelineItemSummariesToAdd')
let timelineItemSummaries = store.getForTimeline(instanceName, timelineName, 'timelineItemSummaries')
let timelineItemIds = new Set(timelineItemSummaries.map(_ => _.id))
2018-03-10 18:54:16 +00:00
// TODO: update database and do the thread merge correctly
for (let itemSummaryToAdd of itemSummariesToAdd) {
if (!timelineItemIds.has(itemSummaryToAdd.id)) {
timelineItemSummaries.push(itemSummaryToAdd)
}
}
2018-03-10 06:31:26 +00:00
store.setForTimeline(instanceName, timelineName, {
timelineItemSummariesToAdd: [],
timelineItemSummaries: timelineItemSummaries
2018-03-10 06:31:26 +00:00
})
2018-03-10 18:54:16 +00:00
stop('showMoreItemsForThread')
2018-03-10 06:31:26 +00:00
}