Fix older items possibly disappearing on timeline updates (#17980)

In some rare cases, when receiving statuses out of order from the streaming
API then polling from the REST API, it was possible for the
`expandNormalizedTimeline` function to remove older items from the timeline.

This commit ensures that any item from the replaced slice that is older
than the oldest item retrieved from the API gets added back to the replaced
slice.
signup-info-prompt
Claire 2022-04-07 11:27:35 +02:00 committed by GitHub
parent f382192862
commit 1b91359a45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 12 additions and 3 deletions

View File

@ -66,13 +66,22 @@ const expandNormalizedTimeline = (state, timeline, statuses, next, isPartial, is
// Then, try to find the furthest (if properly sorted, oldest) item in the timeline that // Then, try to find the furthest (if properly sorted, oldest) item in the timeline that
// is newer than the most recent fetched one, as it delimits a section comprised of only // is newer than the most recent fetched one, as it delimits a section comprised of only
// items present in `newIds` (or that were deleted from the server, so should be removed // items older or within `newIds` (or that were deleted from the server, so should be removed
// anyway). // anyway).
// Stop the gap *after* that item. // Stop the gap *after* that item.
const firstIndex = oldIds.take(lastIndex).findLastIndex(id => id !== null && compareId(id, newIds.first()) > 0) + 1; const firstIndex = oldIds.take(lastIndex).findLastIndex(id => id !== null && compareId(id, newIds.first()) > 0) + 1;
// Make sure we aren't inserting duplicates let insertedIds = ImmutableOrderedSet(newIds).withMutations(insertedIds => {
let insertedIds = ImmutableOrderedSet(newIds).subtract(oldIds.take(firstIndex), oldIds.skip(lastIndex)).toList(); // It is possible, though unlikely, that the slice we are replacing contains items older
// than the elements we got from the API. Get them and add them back at the back of the
// slice.
const olderIds = oldIds.slice(firstIndex, lastIndex).filter(id => id !== null && compareId(id, newIds.last()) < 0);
insertedIds.union(olderIds);
// Make sure we aren't inserting duplicates
insertedIds.subtract(oldIds.take(firstIndex), oldIds.skip(lastIndex));
}).toList();
// Finally, insert a gap marker if the data is marked as partial by the server // Finally, insert a gap marker if the data is marked as partial by the server
if (isPartial && (firstIndex === 0 || oldIds.get(firstIndex - 1) !== null)) { if (isPartial && (firstIndex === 0 || oldIds.get(firstIndex - 1) !== null)) {
insertedIds = insertedIds.unshift(null); insertedIds = insertedIds.unshift(null);