LOADING: 'loading',
READY: 'ready',
- items: m.stream(),
+ items: m.stream([]),
thresholdItem: null,
loadMore: function() {
if (loader.state == loader.DONE || loader.state == loader.LOADING)
] : []
loader.state = loader.LOADING
loader.loadFunc(filters).then(function(resp) {
- var items = loader.items() || []
+ var items = loader.items()
Array.prototype.push.apply(items, resp.items)
if (resp.items.length == 0) {
loader.state = loader.DONE
var loader = this
Object.assign(loader, config, {
// Sorted items ready to display, merged from all children.
- items: m.stream(),
+ items: m.stream([]),
state: 'ready',
DONE: 'done',
LOADING: 'loading',
})
},
mergeItems: function() {
- // cutoff is the topmost (recent) of {bottom (oldest) entry of
- // any child that still has more pages left to fetch}
+ // We want to avoid moving items around on the screen once
+ // they're displayed.
+ //
+ // To this end, here we find the last safely displayable
+ // item ("cutoff") by getting the last item from each
+ // unfinished child, and taking the topmost (most recent)
+ // one of those.
+ //
+ // (If we were to display an item below that cutoff, the
+ // next page of results from an unfinished child could
+ // include items that get inserted above the cutoff,
+ // causing the cutoff item to move down.)
var cutoff
+ var cutoffUnknown = false
loader.children.forEach(function(child) {
+ if (child.state == child.DONE)
+ return
var items = child.items()
- if (items.length == 0 || child.state == child.DONE)
+ if (items.length == 0) {
+ // No idea what's coming in the next page.
+ cutoffUnknown = true
return
+ }
var last = items[items.length-1].modified_at
if (!cutoff || cutoff < last)
cutoff = last
})
+ if (cutoffUnknown)
+ return
var combined = []
loader.children.forEach(function(child) {
child.itemsDisplayed = 0
child.items().every(function(item) {
if (cutoff && item.modified_at < cutoff)
- // Some other children haven't caught up to this
- // point, so don't display this item or anything
- // after it.
+ // Don't display this item or anything after
+ // it (see "cutoff" comment above).
return false
combined.push(item)
child.itemsDisplayed++