implement RealmStore

This commit is contained in:
Nolan Lawson 2018-01-30 21:55:23 -08:00
parent b8a7c34228
commit 8afe67c471
5 changed files with 47 additions and 46 deletions

View file

@ -29,7 +29,7 @@
export default { export default {
oncreate() { oncreate() {
mark('PseudoVirtualList oncreate()') mark('PseudoVirtualList oncreate()')
this.store.set({currentRealm: this.get('realm')}) this.store.setCurrentRealm(this.get('realm'))
// When re-rendering, assume all items are non-intersecting until told otherwise. // When re-rendering, assume all items are non-intersecting until told otherwise.
// We already have the heights cached. // We already have the heights cached.

View file

@ -1,21 +1,14 @@
import { Store } from 'svelte/store.js' import { RealmStore } from '../../_utils/RealmStore'
class PseudoVirtualListStore extends Store { class PseudoVirtualListStore extends RealmStore {
setForRealm(obj) { constructor(state) {
let realmName = this.get('currentRealm') super(state, /* maxSize */ 10)
let realms = this.get('realms') || {}
realms[realmName] = Object.assign(realms[realmName] || {}, obj)
this.set({realms: realms})
} }
} }
const pseudoVirtualListStore = new PseudoVirtualListStore() const pseudoVirtualListStore = new PseudoVirtualListStore()
pseudoVirtualListStore.compute('intersectionStates', pseudoVirtualListStore.computeForRealm('intersectionStates', {})
['realms', 'currentRealm'],
(realms, currentRealm) => {
return (realms && realms[currentRealm] && realms[currentRealm].intersectionStates) || {}
})
if (process.browser && process.env.NODE_NODE !== 'production') { if (process.browser && process.env.NODE_NODE !== 'production') {
window.pseudoVirtualListStore = pseudoVirtualListStore window.pseudoVirtualListStore = pseudoVirtualListStore

View file

@ -17,8 +17,7 @@
oncreate() { oncreate() {
mark('onCreate VirtualListContainer') mark('onCreate VirtualListContainer')
let node = this.refs.node let node = this.refs.node
let realm = this.get('realm') this.store.setCurrentRealm(this.get('realm'))
this.store.set({currentRealm: realm})
let scrollTop = this.store.get('scrollTop') let scrollTop = this.store.get('scrollTop')
if (scrollTop > 0) { if (scrollTop > 0) {
this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => { this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {

View file

@ -1,11 +1,11 @@
import { Store } from 'svelte/store.js'
import { mark, stop } from '../../_utils/marks' import { mark, stop } from '../../_utils/marks'
import { RealmStore } from '../../_utils/RealmStore'
const VIEWPORT_RENDER_FACTOR = 4 const VIEWPORT_RENDER_FACTOR = 4
class VirtualListStore extends Store { class VirtualListStore extends RealmStore {
constructor(state) { constructor(state) {
super(state) super(state, /* maxSize */ 10)
this._batches = {} this._batches = {}
} }
@ -37,41 +37,18 @@ class VirtualListStore extends Store {
stop('batchUpdate()') stop('batchUpdate()')
}) })
} }
setForRealm(obj) {
let realmName = this.get('currentRealm')
let realms = this.get('realms') || {}
realms[realmName] = Object.assign(realms[realmName] || {}, obj)
this.set({realms: realms})
}
} }
const virtualListStore = new VirtualListStore({ const virtualListStore = new VirtualListStore({
realms: {},
currentRealm: null,
itemHeights: {}, itemHeights: {},
footerHeight: 0 footerHeight: 0
}) })
virtualListStore.compute('items', ['currentRealm', 'realms'], (currentRealm, realms) => { virtualListStore.computeForRealm('items', [])
return realms[currentRealm] && realms[currentRealm].items || [] virtualListStore.computeForRealm('showFooter', false)
}) virtualListStore.computeForRealm('scrollTop', 0)
virtualListStore.computeForRealm('scrollHeight', 0)
virtualListStore.compute('showFooter', ['currentRealm', 'realms'], (currentRealm, realms) => { virtualListStore.computeForRealm('offsetHeight', 0)
return realms[currentRealm] && realms[currentRealm].showFooter
})
virtualListStore.compute('scrollTop', ['currentRealm', 'realms'], (currentRealm, realms) => {
return realms[currentRealm] && realms[currentRealm].scrollTop || 0
})
virtualListStore.compute('scrollHeight', ['currentRealm', 'realms'], (currentRealm, realms) => {
return realms[currentRealm] && realms[currentRealm].scrollHeight || 0
})
virtualListStore.compute('offsetHeight', ['currentRealm', 'realms'], (currentRealm, realms) => {
return realms[currentRealm] && realms[currentRealm].offsetHeight || 0
})
virtualListStore.compute('visibleItems', virtualListStore.compute('visibleItems',
['items', 'scrollTop', 'itemHeights', 'offsetHeight'], ['items', 'scrollTop', 'itemHeights', 'offsetHeight'],

View file

@ -0,0 +1,32 @@
// A store where you can divide data into "realms" that are backed with an LRU cache.
// Each realm has self-contained data that you can set with setForRealm() and compute
// with computeForRealm(). The maxSize determines how many realms to keep in the LRU cache.
import { Store } from 'svelte/store.js'
import QuickLRU from 'quick-lru'
export class RealmStore extends Store {
constructor(init, maxSize) {
super(init)
this.set({realms: new QuickLRU({maxSize: maxSize})})
}
setCurrentRealm(realm) {
this.set({currentRealm: realm})
}
setForRealm(obj) {
let realmName = this.get('currentRealm')
let realms = this.get('realms')
realms.set(realmName, Object.assign(realms.get(realmName) || {}, obj))
this.set({realms: realms})
}
computeForRealm(key, defaultValue) {
this.compute(key,
['realms', 'currentRealm'],
(realms, currentRealm) => {
let realmData = realms.get(currentRealm)
return (realmData && realmData[key]) || defaultValue
})
}
}