calculate listOffset to avoid profile offset issue

This commit is contained in:
Nolan Lawson 2018-03-22 17:33:42 -07:00
parent 98b8ea1c67
commit ef51842e6a
4 changed files with 35 additions and 14 deletions

View file

@ -1,5 +1,7 @@
<VirtualListContainer :realm :containerQuery >
<div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;">
<div class="virtual-list {{shown ? '' : 'hidden'}}"
style="height: {{$height}}px;"
ref:node >
<VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/>
{{#if $visibleItems}}
{{#each $visibleItems as visibleItem @key}}
@ -85,6 +87,7 @@
if (scrollTop === 0) {
this.fireScrollToTop()
}
this.calculateListOffset()
})
},
data: () => ({
@ -104,6 +107,19 @@
scrollTop: ($scrollTop) => $scrollTop,
// TODO: bug in svelte store, shouldn't need to do this
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight,
},
methods: {
calculateListOffset() {
// TODO: better way to get the offset top?
let node = this.refs.node
if (!node) {
return
}
mark('calculateListOffset')
let listOffset = node.offsetParent.offsetTop
this.store.setForRealm({listOffset})
stop('calculateListOffset')
}
}
}
</script>

View file

@ -2,7 +2,7 @@ import { mark, stop } from '../../_utils/marks'
import { RealmStore } from '../../_utils/RealmStore'
import { reselect } from '../../_utils/reselect'
const RENDER_BUFFER_FACTOR = 5
const RENDER_BUFFER_FACTOR = 1.5
class VirtualListStore extends RealmStore {
constructor (state) {
@ -20,16 +20,18 @@ virtualListStore.computeForRealm('headerHeight', 0)
virtualListStore.computeForRealm('scrollTop', 0)
virtualListStore.computeForRealm('scrollHeight', 0)
virtualListStore.computeForRealm('offsetHeight', 0)
virtualListStore.computeForRealm('listOffset', 0)
virtualListStore.computeForRealm('itemHeights', {})
virtualListStore.compute('rawVisibleItems',
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'showHeader', 'headerHeight'],
(items, scrollTop, itemHeights, offsetHeight, showHeader, headerHeight) => {
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'showHeader', 'headerHeight', 'listOffset'],
(items, scrollTop, itemHeights, offsetHeight, showHeader, headerHeight, listOffset) => {
window.rawVisibleItemsComputed = (window.rawVisibleItemsComputed || 0) + 1
mark('compute visibleItems')
if (!items) {
return null
}
let effectiveScrollTop = scrollTop - listOffset
let renderBuffer = RENDER_BUFFER_FACTOR * offsetHeight
let visibleItems = []
let totalOffset = showHeader ? headerHeight : 0
@ -40,13 +42,13 @@ virtualListStore.compute('rawVisibleItems',
let height = itemHeights[key] || 0
let currentOffset = totalOffset
totalOffset += height
let isAboveViewport = (currentOffset < scrollTop)
let isAboveViewport = (currentOffset < effectiveScrollTop)
if (isAboveViewport) {
if ((scrollTop - height - renderBuffer) > currentOffset) {
if ((effectiveScrollTop - height - renderBuffer) > currentOffset) {
continue // above the area we want to render
}
} else {
if (currentOffset > (scrollTop + offsetHeight + renderBuffer)) {
if (currentOffset > (effectiveScrollTop + offsetHeight + renderBuffer)) {
break // below the area we want to render
}
}

View file

@ -30,7 +30,6 @@
export default {
oncreate() {
let accountId = this.get('params').accountId
let instanceName = this.store.get('currentInstance')
updateProfileAndRelationship(accountId)
},
store: () => store,

View file

@ -3,16 +3,20 @@
let hasBoundingRectBug
function rectsAreEqual (rectA, rectB) {
return rectA.height === rectB.height &&
rectA.top === rectB.top &&
rectA.width === rectB.width &&
rectA.bottom === rectB.bottom &&
rectA.left === rectB.left &&
rectA.right === rectB.right
}
export function getRectFromEntry (entry) {
if (typeof hasBoundingRectBug !== 'boolean') {
const boundingRect = entry.target.getBoundingClientRect()
const observerRect = entry.boundingClientRect
hasBoundingRectBug = boundingRect.height !== observerRect.height ||
boundingRect.top !== observerRect.top ||
boundingRect.width !== observerRect.width ||
boundingRect.bottom !== observerRect.bottom ||
boundingRect.left !== observerRect.left ||
boundingRect.right !== observerRect.right
hasBoundingRectBug = !rectsAreEqual(boundingRect, observerRect)
}
return hasBoundingRectBug ? entry.target.getBoundingClientRect() : entry.boundingClientRect
}