start on scroll to status in thread
This commit is contained in:
parent
37661f4c6a
commit
ad443af5cd
|
@ -36,7 +36,11 @@ async function addStatuses(instanceName, timelineName, newStatuses) {
|
|||
let newStatusIds = newStatuses.map(status => status.id)
|
||||
let oldStatusIds = store.getForTimeline(instanceName, timelineName, 'statusIds') || []
|
||||
let merged = mergeArrays(oldStatusIds, newStatusIds)
|
||||
store.setForTimeline(instanceName, timelineName, { statusIds: merged })
|
||||
store.setForTimeline(instanceName, timelineName, {
|
||||
statusIds: merged,
|
||||
// if it's a status (context) list, we need to scroll to the status in question
|
||||
scrollToStatusId: timelineName.startsWith('status/') && timelineName.split('/').slice(-1)[0]
|
||||
})
|
||||
stop('addStatuses')
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
<VirtualList component="{{StatusListItem}}"
|
||||
:makeProps
|
||||
items="{{$statusIds}}"
|
||||
on:scrollToBottom="onScrollToBottom()"
|
||||
scrollToItem="{{$scrollToStatusId}}"
|
||||
shown="{{$initialized}}"
|
||||
footerComponent="{{LoadingFooter}}"
|
||||
showFooter="{{$initialized && $runningUpdate}}"
|
||||
realm="{{$currentInstance + '/' + timeline}}"
|
||||
on:scrollToBottom="onScrollToBottom()"
|
||||
on:initializedVisibleItems="initialize()"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
export default {
|
||||
oncreate () {
|
||||
this.fireScrollToBottom = throttle(() => {
|
||||
this.fire('scrollToBottom')
|
||||
}, SCROLL_TO_BOTTOM_DELAY)
|
||||
this.observe('showFooter', showFooter => {
|
||||
this.store.setForRealm({showFooter: showFooter})
|
||||
})
|
||||
|
@ -37,11 +40,12 @@
|
|||
mark('set items')
|
||||
this.store.setForRealm({items: items})
|
||||
stop('set items')
|
||||
this.fireScrollToBottom = throttle(() => {
|
||||
this.fire('scrollToBottom')
|
||||
}, SCROLL_TO_BOTTOM_DELAY)
|
||||
})
|
||||
|
||||
this.observe('scrollToItem', (scrollToItem) => {
|
||||
mark('scrollToItem')
|
||||
this.store.setForRealm({scrollToItem: scrollToItem})
|
||||
stop('scrollToItem')
|
||||
})
|
||||
this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
|
||||
if (allVisibleItemsHaveHeight) {
|
||||
this.fire('initializedVisibleItems')
|
||||
|
|
|
@ -38,6 +38,18 @@
|
|||
scrollHeight: node.scrollHeight,
|
||||
offsetHeight: node.offsetHeight
|
||||
})
|
||||
this.observe('scrollToItemOffset', scrollToItemOffset => {
|
||||
console.log('scrollToItemOffset', scrollToItemOffset)
|
||||
if (!this.get('initializedScrollTop') && scrollToItemOffset && node) {
|
||||
this.set({'initializedScrollTop': true})
|
||||
requestAnimationFrame(() => {
|
||||
mark('set scrollToItemOffset')
|
||||
console.log('forcing scroll top to ', scrollToItemOffset)
|
||||
node.scrollTop = scrollToItemOffset
|
||||
stop('set scrollToItemOffset')
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
stop('onCreate VirtualListContainer')
|
||||
},
|
||||
|
@ -91,7 +103,8 @@
|
|||
},
|
||||
computed: {
|
||||
// TODO: bug in svelte/store – the observer in oncreate() never get removed without this hack
|
||||
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight
|
||||
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight,
|
||||
scrollToItemOffset: ($scrollToItemOffset) => $scrollToItemOffset
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -73,9 +73,13 @@ virtualListStore.compute('offsetHeight', ['currentRealm', 'realms'], (currentRea
|
|||
return realms[currentRealm] && realms[currentRealm].offsetHeight || 0
|
||||
})
|
||||
|
||||
virtualListStore.compute('scrollToItem', ['currentRealm', 'realms'], (currentRealm, realms) => {
|
||||
return realms[currentRealm] && realms[currentRealm].scrollToItem
|
||||
})
|
||||
|
||||
virtualListStore.compute('visibleItems',
|
||||
['items', 'scrollTop', 'itemHeights', 'offsetHeight'],
|
||||
(items, scrollTop, itemHeights, offsetHeight) => {
|
||||
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'itemsLeftToCalculateHeight'],
|
||||
(items, scrollTop, itemHeights, offsetHeight, itemsLeftToCalculateHeight) => {
|
||||
mark('compute visibleItems')
|
||||
let renderBuffer = VIEWPORT_RENDER_FACTOR * offsetHeight
|
||||
let visibleItems = []
|
||||
|
@ -87,14 +91,16 @@ virtualListStore.compute('visibleItems',
|
|||
let height = itemHeights[key] || 0
|
||||
let currentOffset = totalOffset
|
||||
totalOffset += height
|
||||
let isBelowViewport = (currentOffset < scrollTop)
|
||||
if (isBelowViewport) {
|
||||
if (scrollTop - renderBuffer > currentOffset) {
|
||||
continue // below the area we want to render
|
||||
}
|
||||
} else {
|
||||
if (currentOffset > (scrollTop + height + renderBuffer)) {
|
||||
break // above the area we want to render
|
||||
if (!itemsLeftToCalculateHeight) {
|
||||
let isBelowViewport = (currentOffset < scrollTop)
|
||||
if (!isBelowViewport) {
|
||||
if (scrollTop - renderBuffer > currentOffset) {
|
||||
continue // below the area we want to render
|
||||
}
|
||||
} else {
|
||||
if (currentOffset > (scrollTop + height + renderBuffer)) {
|
||||
break // above the area we want to render
|
||||
}
|
||||
}
|
||||
}
|
||||
visibleItems.push({
|
||||
|
@ -142,6 +148,45 @@ virtualListStore.compute('allVisibleItemsHaveHeight',
|
|||
return true
|
||||
})
|
||||
|
||||
// if we need to initialize the scroll at a particular item, then
|
||||
// we effectively have to calculate all visible item heights
|
||||
// TODO: technically not, we only need to calculate the items above it... or even estimate
|
||||
virtualListStore.compute('mustCalculateAllItemHeights',
|
||||
['scrollToItem'],
|
||||
(scrollToItem) => !!scrollToItem
|
||||
)
|
||||
|
||||
virtualListStore.compute('itemsLeftToCalculateHeight',
|
||||
['mustCalculateAllItemHeights', 'itemHeights', 'items'],
|
||||
(mustCalculateAllItemHeights, itemHeights, items) => {
|
||||
if (!mustCalculateAllItemHeights) {
|
||||
return false
|
||||
}
|
||||
for (let item of items) {
|
||||
if (!itemHeights[item]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
virtualListStore.compute('scrollToItemOffset',
|
||||
['mustCalculateAllItemHeights', 'itemsLeftToCalculateHeight', 'scrollToItem', 'items', 'itemHeights'],
|
||||
(mustCalculateAllItemHeights, itemsLeftToCalculateHeight, scrollToItem, items, itemHeights) => {
|
||||
if (!mustCalculateAllItemHeights || itemsLeftToCalculateHeight) {
|
||||
return null
|
||||
}
|
||||
let offset = 0
|
||||
for (let item of items) {
|
||||
if (item === scrollToItem) {
|
||||
break
|
||||
}
|
||||
offset += itemHeights[item]
|
||||
}
|
||||
return offset
|
||||
})
|
||||
|
||||
|
||||
if (process.browser && process.env.NODE_ENV !== 'production') {
|
||||
window.virtualListStore = virtualListStore
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ export function timelineComputations(store) {
|
|||
store.compute('runningUpdate', ['currentTimelineData'], (currentTimelineData) => currentTimelineData.runningUpdate)
|
||||
store.compute('initialized', ['currentTimelineData'], (currentTimelineData) => currentTimelineData.initialized)
|
||||
store.compute('lastStatusId', ['statusIds'], (statusIds) => statusIds.length && statusIds[statusIds.length - 1])
|
||||
store.compute('scrollToStatusId', ['currentTimelineData'], (currentTimelineData) => currentTimelineData.scrollToStatusId)
|
||||
}
|
Loading…
Reference in New Issue