forked from cybrespace/pinafore
calculate listOffset to avoid profile offset issue
This commit is contained in:
parent
98b8ea1c67
commit
ef51842e6a
|
@ -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>
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
export default {
|
||||
oncreate() {
|
||||
let accountId = this.get('params').accountId
|
||||
let instanceName = this.store.get('currentInstance')
|
||||
updateProfileAndRelationship(accountId)
|
||||
},
|
||||
store: () => store,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue