forked from cybrespace/pinafore
itemHeights should be divided by realm
This commit is contained in:
parent
0d4ee2bba3
commit
2c2f84b870
|
@ -19,7 +19,7 @@
|
||||||
const asyncLayout = new AsyncLayout(() => '__footer__')
|
const asyncLayout = new AsyncLayout(() => '__footer__')
|
||||||
asyncLayout.observe('__footer__', this.refs.node, (rect) => {
|
asyncLayout.observe('__footer__', this.refs.node, (rect) => {
|
||||||
asyncLayout.disconnect()
|
asyncLayout.disconnect()
|
||||||
this.store.set({footerHeight: rect.height})
|
this.store.setForRealm({footerHeight: rect.height})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
store: () => virtualListStore,
|
store: () => virtualListStore,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<:Component {component}
|
<:Component {component}
|
||||||
virtualProps="{{props}}"
|
virtualProps="{{props}}"
|
||||||
virtualIndex="{{index}}"
|
virtualIndex="{{index}}"
|
||||||
virtualLength="{{$numItems}}"
|
virtualLength="{{numItems}}"
|
||||||
on:recalculateHeight="doRecalculateHeight()"/>
|
on:recalculateHeight="doRecalculateHeight()"/>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
asyncLayout.observe(key, this.refs.node, (rect) => {
|
asyncLayout.observe(key, this.refs.node, (rect) => {
|
||||||
asyncLayout.disconnect()
|
asyncLayout.disconnect()
|
||||||
// update all item heights in one batch for better perf
|
// update all item heights in one batch for better perf
|
||||||
this.store.batchUpdate('itemHeights', key, rect.height)
|
this.store.batchUpdateForRealm('itemHeights', key, rect.height)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,49 +6,18 @@ const VIEWPORT_RENDER_FACTOR = 4
|
||||||
class VirtualListStore extends RealmStore {
|
class VirtualListStore extends RealmStore {
|
||||||
constructor(state) {
|
constructor(state) {
|
||||||
super(state, /* maxSize */ 10)
|
super(state, /* maxSize */ 10)
|
||||||
this._batches = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
batchUpdate(key, subKey, value) {
|
|
||||||
let batch = this._batches[key]
|
|
||||||
if (!batch) {
|
|
||||||
batch = this._batches[key] = {}
|
|
||||||
}
|
|
||||||
batch[subKey] = value
|
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
let batch = this._batches[key]
|
|
||||||
if (!batch) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let updatedKeys = Object.keys(batch)
|
|
||||||
if (!updatedKeys.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mark('batchUpdate()')
|
|
||||||
let obj = this.get(key)
|
|
||||||
for (let otherKey of updatedKeys) {
|
|
||||||
obj[otherKey] = batch[otherKey]
|
|
||||||
}
|
|
||||||
delete this._batches[key]
|
|
||||||
let toSet = {}
|
|
||||||
toSet[key] = obj
|
|
||||||
this.set(toSet)
|
|
||||||
stop('batchUpdate()')
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const virtualListStore = new VirtualListStore({
|
const virtualListStore = new VirtualListStore()
|
||||||
itemHeights: {},
|
|
||||||
footerHeight: 0
|
|
||||||
})
|
|
||||||
|
|
||||||
virtualListStore.computeForRealm('items', [])
|
virtualListStore.computeForRealm('items', [])
|
||||||
virtualListStore.computeForRealm('showFooter', false)
|
virtualListStore.computeForRealm('showFooter', false)
|
||||||
|
virtualListStore.computeForRealm('footerHeight', 0)
|
||||||
virtualListStore.computeForRealm('scrollTop', 0)
|
virtualListStore.computeForRealm('scrollTop', 0)
|
||||||
virtualListStore.computeForRealm('scrollHeight', 0)
|
virtualListStore.computeForRealm('scrollHeight', 0)
|
||||||
virtualListStore.computeForRealm('offsetHeight', 0)
|
virtualListStore.computeForRealm('offsetHeight', 0)
|
||||||
|
virtualListStore.computeForRealm('itemHeights', {})
|
||||||
|
|
||||||
virtualListStore.compute('visibleItems',
|
virtualListStore.compute('visibleItems',
|
||||||
['items', 'scrollTop', 'itemHeights', 'offsetHeight'],
|
['items', 'scrollTop', 'itemHeights', 'offsetHeight'],
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
// with computeForRealm(). The maxSize determines how many realms to keep in the LRU cache.
|
// with computeForRealm(). The maxSize determines how many realms to keep in the LRU cache.
|
||||||
import { Store } from 'svelte/store.js'
|
import { Store } from 'svelte/store.js'
|
||||||
import QuickLRU from 'quick-lru'
|
import QuickLRU from 'quick-lru'
|
||||||
|
import { mark, stop } from './marks'
|
||||||
|
|
||||||
export class RealmStore extends Store {
|
export class RealmStore extends Store {
|
||||||
constructor(init, maxSize) {
|
constructor(init, maxSize) {
|
||||||
super(init)
|
super(init)
|
||||||
this.set({realms: new QuickLRU({maxSize: maxSize})})
|
this.set({realms: new QuickLRU({maxSize: maxSize})})
|
||||||
|
this._batches = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentRealm(realm) {
|
setCurrentRealm(realm) {
|
||||||
|
@ -29,4 +31,42 @@ export class RealmStore extends Store {
|
||||||
return (realmData && realmData[key]) || defaultValue
|
return (realmData && realmData[key]) || defaultValue
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update several values at once in a realm, assuming the key points
|
||||||
|
* to a plain old javascript object.
|
||||||
|
*/
|
||||||
|
batchUpdateForRealm(key, subKey, value) {
|
||||||
|
let realm = this.get('currentRealm')
|
||||||
|
let realmBatches = this._batches[realm]
|
||||||
|
if (!realmBatches) {
|
||||||
|
realmBatches = this._batches[realm] = {}
|
||||||
|
}
|
||||||
|
let batch = realmBatches[key]
|
||||||
|
if (!batch) {
|
||||||
|
batch = realmBatches[key] = {}
|
||||||
|
}
|
||||||
|
batch[subKey] = value
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
let batch = this._batches[realm] && this._batches[realm][key]
|
||||||
|
if (!batch) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let updatedKeys = Object.keys(batch)
|
||||||
|
if (!updatedKeys.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mark('batchUpdate')
|
||||||
|
let obj = this.get(key)
|
||||||
|
for (let otherKey of updatedKeys) {
|
||||||
|
obj[otherKey] = batch[otherKey]
|
||||||
|
}
|
||||||
|
delete this._batches[realm][key]
|
||||||
|
let realms = this.get('realms')
|
||||||
|
realms.set(realm, Object.assign(realms.get(realm) || {}, {[key]: obj}))
|
||||||
|
this.set({realms: realms})
|
||||||
|
stop('batchUpdate')
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue