forked from cybrespace/pinafore
refactor virtual store to use realms
This commit is contained in:
parent
610e54469e
commit
687cc5c961
|
@ -1,7 +1,7 @@
|
|||
<Nav :page :dynamicPage :dynamicHref :dynamicIcon :dynamicLabel/>
|
||||
|
||||
{{#if virtual}}
|
||||
<VirtualListContainer storeKey="{{virtualStoreKey}}">
|
||||
<VirtualListContainer realm="{{virtualRealm}}">
|
||||
<main>
|
||||
<slot></slot>
|
||||
</main>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
shown="{{initialized}}"
|
||||
footerComponent="{{LoadingFooter}}"
|
||||
showFooter="{{initialized && runningUpdate}}"
|
||||
storeKey="{{timeline}}"
|
||||
realm="{{timeline}}"
|
||||
on:initializedVisibleItems="initialize()"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -31,13 +31,11 @@
|
|||
export default {
|
||||
oncreate () {
|
||||
this.observe('showFooter', showFooter => {
|
||||
this.store.set({showFooter: showFooter})
|
||||
this.store.setForRealm({showFooter: showFooter})
|
||||
})
|
||||
this.observe('items', (items) => {
|
||||
mark('set items')
|
||||
this.store.set({
|
||||
items: items
|
||||
})
|
||||
this.store.setForRealm({items: items})
|
||||
stop('set items')
|
||||
this.fireScrollToBottom = throttle(() => {
|
||||
this.fire('scrollToBottom')
|
||||
|
|
|
@ -13,73 +13,38 @@
|
|||
|
||||
const SCROLL_EVENT_DELAY = 300
|
||||
|
||||
const cachedVirtualStores = {}
|
||||
|
||||
if (process.browser && process.env.NODE_ENV !== 'production') {
|
||||
window.cachedVirtualStores = cachedVirtualStores
|
||||
}
|
||||
|
||||
export default {
|
||||
oncreate() {
|
||||
mark('onCreate VirtualListContainer')
|
||||
let node = this.refs.node
|
||||
let storeKey = this.get('storeKey')
|
||||
let cachedStore
|
||||
if (storeKey && (cachedStore = cachedVirtualStores[storeKey])) {
|
||||
this.store.set({
|
||||
scrollTop: cachedStore.state.scrollTop,
|
||||
scrollHeight: cachedStore.state.scrollHeight,
|
||||
offsetHeight: cachedStore.state.offsetHeight
|
||||
})
|
||||
this.store.set(cachedStore.state)
|
||||
|
||||
// rehydrate scroll top
|
||||
let cachedScrollTop = cachedStore.state.scrollTop || 0
|
||||
if (cachedScrollTop === 0) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('no need to force scroll top')
|
||||
}
|
||||
return
|
||||
}
|
||||
let initializedScrollTop = false
|
||||
let node = this.refs.node
|
||||
let realm = this.get('realm')
|
||||
this.store.set({currentRealm: realm})
|
||||
let scrollTop = this.store.get('scrollTop')
|
||||
if (scrollTop > 0) {
|
||||
this.observe('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('allVisibleItemsHaveHeight', allVisibleItemsHaveHeight)
|
||||
}
|
||||
if (!initializedScrollTop && allVisibleItemsHaveHeight && node) {
|
||||
initializedScrollTop = true
|
||||
if (!this.get('initializedScrollTop') && allVisibleItemsHaveHeight && node) {
|
||||
this.set({'initializedScrollTop': true})
|
||||
requestAnimationFrame(() => {
|
||||
mark('set scrollTop')
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('forcing scroll top to ', cachedScrollTop)
|
||||
console.log('forcing scroll top to ', scrollTop)
|
||||
}
|
||||
node.scrollTop = cachedScrollTop
|
||||
node.scrollTop = scrollTop
|
||||
stop('set scrollTop')
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.store.set({
|
||||
scrollTop: 0,
|
||||
this.store.setForRealm({
|
||||
scrollHeight: node.scrollHeight,
|
||||
offsetHeight: node.offsetHeight
|
||||
})
|
||||
}
|
||||
stop('onCreate VirtualListContainer')
|
||||
},
|
||||
ondestroy() {
|
||||
let storeKey = this.get('storeKey')
|
||||
if (storeKey) {
|
||||
let clonedState = this.store.cloneState()
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('caching scroll top', clonedState.scrollTop)
|
||||
}
|
||||
cachedVirtualStores[storeKey] = {
|
||||
state: clonedState
|
||||
}
|
||||
}
|
||||
},
|
||||
store: () => virtualListStore,
|
||||
events: {
|
||||
scroll(node, callback) {
|
||||
|
@ -116,7 +81,7 @@
|
|||
},
|
||||
methods: {
|
||||
onScroll(event) {
|
||||
this.store.set({
|
||||
this.store.setForRealm({
|
||||
scrollTop: event.target.scrollTop,
|
||||
scrollHeight: event.target.scrollHeight
|
||||
})
|
||||
|
|
|
@ -3,28 +3,12 @@ import { mark, stop } from '../../_utils/marks'
|
|||
|
||||
const VIEWPORT_RENDER_FACTOR = 4
|
||||
|
||||
const cloneKeys = [
|
||||
'items',
|
||||
'itemHeights',
|
||||
'scrollTop',
|
||||
'scrollHeight',
|
||||
'offsetHeight'
|
||||
]
|
||||
|
||||
class VirtualListStore extends Store {
|
||||
constructor(state) {
|
||||
super(state)
|
||||
this._batches = {}
|
||||
}
|
||||
|
||||
cloneState() {
|
||||
let res = {}
|
||||
for (let key of cloneKeys) {
|
||||
res[key] = this.get(key)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
batchUpdate(key, subKey, value) {
|
||||
let batch = this._batches[key]
|
||||
if (!batch) {
|
||||
|
@ -53,15 +37,42 @@ class VirtualListStore extends Store {
|
|||
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({
|
||||
items: [],
|
||||
realms: {},
|
||||
currentRealm: null,
|
||||
itemHeights: {},
|
||||
showFooter: false,
|
||||
footerHeight: 0
|
||||
})
|
||||
|
||||
virtualListStore.compute('items', ['currentRealm', 'realms'], (currentRealm, realms) => {
|
||||
return realms[currentRealm] && realms[currentRealm].items || []
|
||||
})
|
||||
|
||||
virtualListStore.compute('showFooter', ['currentRealm', 'realms'], (currentRealm, realms) => {
|
||||
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',
|
||||
['items', 'scrollTop', 'itemHeights', 'offsetHeight'],
|
||||
(items, scrollTop, itemHeights, offsetHeight) => {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<Layout page='tags'
|
||||
virtual="true"
|
||||
virtualStoreKey='account/{{params.accountId}}'
|
||||
virtualRealm='account/{{params.accountId}}'
|
||||
dynamicPage="{{profileName}}"
|
||||
dynamicHref="/accounts/{{params.accountId}}"
|
||||
dynamicLabel="{{shortProfileName}}"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<title>Pinafore – Federated</title>
|
||||
</:Head>
|
||||
|
||||
<Layout page='federated' virtual="true" virtualStoreKey="federated">
|
||||
<Layout page='federated' virtual="true" virtualRealm="federated">
|
||||
{{#if $isUserLoggedIn}}
|
||||
<LazyTimeline timeline='federated' />
|
||||
{{else}}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<title>Pinafore – Home</title>
|
||||
</:Head>
|
||||
|
||||
<Layout page='home' virtual="true" virtualStoreKey="home">
|
||||
<Layout page='home' virtual="true" virtualRealm="home">
|
||||
{{#if $isUserLoggedIn}}
|
||||
<LazyTimeline timeline='home' />
|
||||
{{else}}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<title>Pinafore – Local</title>
|
||||
</:Head>
|
||||
|
||||
<Layout page='local' virtual="true" virtualStoreKey="local">
|
||||
<Layout page='local' virtual="true" virtualRealm="local">
|
||||
{{#if $isUserLoggedIn}}
|
||||
<LazyTimeline timeline='local' />
|
||||
{{else}}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<title>Pinafore – Notifications</title>
|
||||
</:Head>
|
||||
|
||||
<Layout page='notifications' virtual="true" virtualStoreKey="federated">
|
||||
<Layout page='notifications' virtual="true" virtualRealm="federated">
|
||||
<HiddenFromSSR>
|
||||
<FreeTextLayout>
|
||||
<h1>Notifications</h1>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<Layout page='tags'
|
||||
virtual="true"
|
||||
virtualStoreKey='tag/{{params.tagName}}'
|
||||
virtualRealm='tag/{{params.tagName}}'
|
||||
dynamicPage="{{params.tagName}}"
|
||||
dynamicHref="/tags/{{params.tagName}}"
|
||||
dynamicLabel="{{'#' + params.tagName}}"
|
||||
|
|
Loading…
Reference in New Issue