better offline support

This commit is contained in:
Nolan Lawson 2018-03-11 12:11:06 -07:00
parent a2ac4f1735
commit 9c0fbdabd2
2 changed files with 35 additions and 12 deletions

View file

@ -5,14 +5,17 @@ import { toast } from '../_utils/toast'
import { mark, stop } from '../_utils/marks' import { mark, stop } from '../_utils/marks'
import { mergeArrays } from '../_utils/arrays' import { mergeArrays } from '../_utils/arrays'
import { byItemIds } from '../_utils/sorting' import { byItemIds } from '../_utils/sorting'
import isEqual from 'lodash/isEqual'
const FETCH_LIMIT = 20 const FETCH_LIMIT = 20
async function fetchTimelineItems (instanceName, accessToken, timelineName, lastTimelineItemId, online) { async function fetchTimelineItems (instanceName, accessToken, timelineName, lastTimelineItemId, online) {
mark('fetchTimelineItems') mark('fetchTimelineItems')
let items let items
let stale = false
if (!online) { if (!online) {
items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT) items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT)
stale = true
} else { } else {
try { try {
items = await getTimeline(instanceName, accessToken, timelineName, lastTimelineItemId, FETCH_LIMIT) items = await getTimeline(instanceName, accessToken, timelineName, lastTimelineItemId, FETCH_LIMIT)
@ -21,24 +24,33 @@ async function fetchTimelineItems (instanceName, accessToken, timelineName, last
console.error(e) console.error(e)
toast.say('Internet request failed. Showing offline content.') toast.say('Internet request failed. Showing offline content.')
items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT) items = await database.getTimeline(instanceName, timelineName, lastTimelineItemId, FETCH_LIMIT)
stale = true
} }
} }
stop('fetchTimelineItems') stop('fetchTimelineItems')
return items return { items, stale }
} }
async function addTimelineItems (instanceName, timelineName, newItems) { async function addTimelineItems (instanceName, timelineName, items, stale) {
console.log('addTimelineItems, length:', newItems.length) console.log('addTimelineItems, length:', items.length)
mark('addTimelineItems') mark('addTimelineItems')
let newIds = newItems.map(item => item.id) let newIds = items.map(item => item.id)
addTimelineItemIds(instanceName, timelineName, newIds) addTimelineItemIds(instanceName, timelineName, newIds, stale)
stop('addTimelineItems') stop('addTimelineItems')
} }
export async function addTimelineItemIds (instanceName, timelineName, newIds) { export async function addTimelineItemIds (instanceName, timelineName, newIds, newStale) {
let oldIds = store.getForTimeline(instanceName, timelineName, 'timelineItemIds') || [] let oldIds = store.getForTimeline(instanceName, timelineName, 'timelineItemIds') || []
let merged = mergeArrays(oldIds, newIds) let oldStale = store.getForTimeline(instanceName, timelineName, 'timelineItemIdsAreStale')
store.setForTimeline(instanceName, timelineName, { timelineItemIds: merged })
let mergedIds = mergeArrays(oldIds, newIds)
if (!isEqual(oldIds, mergedIds)) {
store.setForTimeline(instanceName, timelineName, {timelineItemIds: mergedIds})
}
if (oldStale !== newStale) {
store.setForTimeline(instanceName, timelineName, {timelineItemIdsAreStale: newStale})
}
} }
async function fetchTimelineItemsAndPossiblyFallBack () { async function fetchTimelineItemsAndPossiblyFallBack () {
@ -49,8 +61,8 @@ async function fetchTimelineItemsAndPossiblyFallBack () {
let lastTimelineItemId = store.get('lastTimelineItemId') let lastTimelineItemId = store.get('lastTimelineItemId')
let online = store.get('online') let online = store.get('online')
let newItems = await fetchTimelineItems(instanceName, accessToken, timelineName, lastTimelineItemId, online) let { items, stale } = await fetchTimelineItems(instanceName, accessToken, timelineName, lastTimelineItemId, online)
addTimelineItems(instanceName, timelineName, newItems) addTimelineItems(instanceName, timelineName, items, stale)
stop('fetchTimelineItemsAndPossiblyFallBack') stop('fetchTimelineItemsAndPossiblyFallBack')
} }
@ -69,7 +81,17 @@ export function initializeTimeline () {
export async function setupTimeline () { export async function setupTimeline () {
mark('setupTimeline') mark('setupTimeline')
if (!store.get('timelineItemIds')) { // If we don't have any item ids, or if the current item ids are stale
// (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 timelineItemIds = store.get('timelineItemIds')
let timelineItemIdsAreStale = store.get('timelineItemIdsAreStale')
let currentTimeline = store.get('currentTimeline')
if (!timelineItemIds ||
timelineItemIdsAreStale ||
currentTimeline.startsWith('status/')) {
await fetchTimelineItemsAndPossiblyFallBack() await fetchTimelineItemsAndPossiblyFallBack()
} }
stop('setupTimeline') stop('setupTimeline')
@ -85,7 +107,7 @@ export async function showMoreItemsForTimeline (instanceName, timelineName) {
mark('showMoreItemsForTimeline') mark('showMoreItemsForTimeline')
let itemIdsToAdd = store.getForTimeline(instanceName, timelineName, 'itemIdsToAdd') let itemIdsToAdd = store.getForTimeline(instanceName, timelineName, 'itemIdsToAdd')
itemIdsToAdd = itemIdsToAdd.sort(byItemIds).reverse() itemIdsToAdd = itemIdsToAdd.sort(byItemIds).reverse()
addTimelineItemIds(instanceName, timelineName, itemIdsToAdd) addTimelineItemIds(instanceName, timelineName, itemIdsToAdd, false)
store.setForTimeline(instanceName, timelineName, { store.setForTimeline(instanceName, timelineName, {
itemIdsToAdd: [], itemIdsToAdd: [],
shouldShowHeader: false, shouldShowHeader: false,

View file

@ -17,6 +17,7 @@ export function timelineComputations (store) {
computeForTimeline(store, 'itemIdsToAdd', null) computeForTimeline(store, 'itemIdsToAdd', null)
computeForTimeline(store, 'showHeader', false) computeForTimeline(store, 'showHeader', false)
computeForTimeline(store, 'shouldShowHeader', false) computeForTimeline(store, 'shouldShowHeader', false)
computeForTimeline(store, 'timelineItemIdsAreStale', false)
store.compute('firstTimelineItemId', ['timelineItemIds'], (timelineItemIds) => { store.compute('firstTimelineItemId', ['timelineItemIds'], (timelineItemIds) => {
return timelineItemIds && timelineItemIds[0] return timelineItemIds && timelineItemIds[0]