refactor VirtualList to be more self-contained
This commit is contained in:
parent
24e8bdbd86
commit
acc1ce396d
|
@ -1,19 +1,11 @@
|
||||||
<:Window bind:online />
|
<:Window bind:online />
|
||||||
<Nav :page />
|
<Nav :page />
|
||||||
|
|
||||||
{{#if virtual}}
|
<div class="container">
|
||||||
<VirtualListContainer realm="{{$currentInstance + '/' + virtualRealm}}">
|
|
||||||
<main>
|
<main>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</main>
|
</main>
|
||||||
</VirtualListContainer>
|
</div>
|
||||||
{{else}}
|
|
||||||
<div class="container">
|
|
||||||
<main>
|
|
||||||
<slot></slot>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
<script>
|
<script>
|
||||||
import Nav from './Nav.html';
|
import Nav from './Nav.html';
|
||||||
import VirtualListContainer from './virtualList/VirtualListContainer.html'
|
import VirtualListContainer from './virtualList/VirtualListContainer.html'
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
this.store.setForRealm({intersectionStates: intersectionStates})
|
this.store.setForRealm({intersectionStates: intersectionStates})
|
||||||
|
|
||||||
this.set({intersectionObserver: new IntersectionObserver(this.onIntersection.bind(this), {
|
this.set({intersectionObserver: new IntersectionObserver(this.onIntersection.bind(this), {
|
||||||
root: document.getElementsByClassName('container')[0], // TODO: fix this
|
root: document.querySelector('.container'),
|
||||||
rootMargin: '300% 0px'
|
rootMargin: '300% 0px'
|
||||||
})})
|
})})
|
||||||
this.observe('allItemsHaveHeight', allItemsHaveHeight => {
|
this.observe('allItemsHaveHeight', allItemsHaveHeight => {
|
||||||
|
@ -80,8 +80,7 @@
|
||||||
}
|
}
|
||||||
this.set({scrolledToPosition: true})
|
this.set({scrolledToPosition: true})
|
||||||
console.log('scrollToPosition', rect.top)
|
console.log('scrollToPosition', rect.top)
|
||||||
// TODO: there should be some cleaner way to grab the container element
|
let container = document.querySelector('.container')
|
||||||
let container = document.getElementsByClassName('container')[0]
|
|
||||||
if (!container) {
|
if (!container) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;">
|
<VirtualListContainer :realm >
|
||||||
|
<div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;">
|
||||||
<VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/>
|
<VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/>
|
||||||
{{#if $visibleItems}}
|
{{#if $visibleItems}}
|
||||||
{{#each $visibleItems as visibleItem @key}}
|
{{#each $visibleItems as visibleItem @key}}
|
||||||
|
@ -11,9 +12,10 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if $showFooter}}
|
{{#if $showFooter}}
|
||||||
<VirtualListFooter component="{{footerComponent}}"/>
|
<VirtualListFooter component="{{footerComponent}}" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
</VirtualListContainer>
|
||||||
<style>
|
<style>
|
||||||
.virtual-list {
|
.virtual-list {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -21,6 +23,7 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
|
import VirtualListContainer from './VirtualListContainer.html'
|
||||||
import VirtualListLazyItem from './VirtualListLazyItem'
|
import VirtualListLazyItem from './VirtualListLazyItem'
|
||||||
import VirtualListFooter from './VirtualListFooter.html'
|
import VirtualListFooter from './VirtualListFooter.html'
|
||||||
import VirtualListHeader from './VirtualListHeader.html'
|
import VirtualListHeader from './VirtualListHeader.html'
|
||||||
|
@ -86,6 +89,7 @@
|
||||||
}),
|
}),
|
||||||
store: () => virtualListStore,
|
store: () => virtualListStore,
|
||||||
components: {
|
components: {
|
||||||
|
VirtualListContainer,
|
||||||
VirtualListLazyItem,
|
VirtualListLazyItem,
|
||||||
VirtualListFooter,
|
VirtualListFooter,
|
||||||
VirtualListHeader
|
VirtualListHeader
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
<div class="container"
|
<slot></slot>
|
||||||
on:scroll="onScroll(event)"
|
|
||||||
on:fullscreen="onFullscreenChange()"
|
|
||||||
ref:node>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
<script>
|
<script>
|
||||||
import { virtualListStore } from './virtualListStore'
|
import { virtualListStore } from './virtualListStore'
|
||||||
|
|
||||||
import throttle from 'lodash/throttle'
|
import throttle from 'lodash/throttle'
|
||||||
import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen'
|
import { isFullscreen, attachFullscreenListener, detachFullscreenListener } from '../../_utils/fullscreen'
|
||||||
import { mark, stop } from '../../_utils/marks'
|
import { mark, stop } from '../../_utils/marks'
|
||||||
|
@ -16,7 +10,9 @@
|
||||||
export default {
|
export default {
|
||||||
oncreate() {
|
oncreate() {
|
||||||
mark('onCreate VirtualListContainer')
|
mark('onCreate VirtualListContainer')
|
||||||
let node = this.refs.node
|
let node = document.querySelector('.container')
|
||||||
|
this.setupScroll(node)
|
||||||
|
this.setupFullscreen()
|
||||||
this.store.setCurrentRealm(this.get('realm'))
|
this.store.setCurrentRealm(this.get('realm'))
|
||||||
let scrollTop = this.store.get('scrollTop')
|
let scrollTop = this.store.get('scrollTop')
|
||||||
if (scrollTop > 0) {
|
if (scrollTop > 0) {
|
||||||
|
@ -40,46 +36,47 @@
|
||||||
}
|
}
|
||||||
stop('onCreate VirtualListContainer')
|
stop('onCreate VirtualListContainer')
|
||||||
},
|
},
|
||||||
|
ondestroy() {
|
||||||
|
this.teardownScroll()
|
||||||
|
this.teardownFullscreen()
|
||||||
|
},
|
||||||
store: () => virtualListStore,
|
store: () => virtualListStore,
|
||||||
events: {
|
methods: {
|
||||||
scroll(node, callback) {
|
setupScroll(node) {
|
||||||
const onScroll = throttle(event => {
|
if (!node) {
|
||||||
mark('onScroll')
|
return
|
||||||
|
}
|
||||||
|
this.scrollListener = throttle(event => {
|
||||||
if (this.get('fullscreen')) {
|
if (this.get('fullscreen')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
callback(event)
|
this.onScroll(event)
|
||||||
stop('onScroll')
|
|
||||||
}, SCROLL_EVENT_DELAY, {
|
}, SCROLL_EVENT_DELAY, {
|
||||||
leading: true,
|
leading: true,
|
||||||
trailing: true
|
trailing: true
|
||||||
})
|
})
|
||||||
node.addEventListener('scroll', onScroll)
|
node.addEventListener('scroll', this.scrollListener)
|
||||||
|
},
|
||||||
return {
|
teardownScroll() {
|
||||||
teardown() {
|
let node = document.querySelector('.container')
|
||||||
node.removeEventListener('scroll', onScroll)
|
if (node) {
|
||||||
}
|
node.removeEventListener('scroll', this.scrollListener)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fullscreen(node, callback) {
|
setupFullscreen() {
|
||||||
const onFullscreen = (() => {
|
this.onFullscreenChange = this.onFullscreenChange.bind(this)
|
||||||
callback()
|
attachFullscreenListener(this.onFullscreenChange)
|
||||||
})
|
},
|
||||||
attachFullscreenListener(onFullscreen)
|
teardownFullscreen() {
|
||||||
return {
|
detachFullscreenListener(this.onFullscreenChange)
|
||||||
teardown() {
|
|
||||||
detachFullscreenListener(onFullscreen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
onScroll(event) {
|
onScroll(event) {
|
||||||
|
mark('onScroll')
|
||||||
this.store.setForRealm({
|
this.store.setForRealm({
|
||||||
scrollTop: event.target.scrollTop,
|
scrollTop: event.target.scrollTop,
|
||||||
scrollHeight: event.target.scrollHeight
|
scrollHeight: event.target.scrollHeight
|
||||||
})
|
})
|
||||||
|
stop('onScroll')
|
||||||
},
|
},
|
||||||
onFullscreenChange() {
|
onFullscreenChange() {
|
||||||
mark('onFullscreenChange')
|
mark('onFullscreenChange')
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
<title>Pinafore – {{profileName}}</title>
|
<title>Pinafore – {{profileName}}</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='tags'
|
<Layout page='tags'>
|
||||||
virtual="true"
|
|
||||||
virtualRealm='account/{{params.accountId}}' >
|
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
<DynamicPageBanner title="{{profileName}}" />
|
<DynamicPageBanner title="{{profileName}}" />
|
||||||
{{#if $currentAccountProfile}}
|
{{#if $currentAccountProfile}}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<title>Pinafore – Favorites</title>
|
<title>Pinafore – Favorites</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='favorites' virtual="true" virtualRealm="favorites">
|
<Layout page='favorites'>
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
{{#if $pinnedPage !== '/favorites'}}
|
{{#if $pinnedPage !== '/favorites'}}
|
||||||
<DynamicPageBanner title="Favorites" icon="#fa-star"/>
|
<DynamicPageBanner title="Favorites" icon="#fa-star"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<title>Pinafore – Federated</title>
|
<title>Pinafore – Federated</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='federated' virtual="true" virtualRealm="federated">
|
<Layout page='federated'>
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
{{#if $pinnedPage !== '/federated'}}
|
{{#if $pinnedPage !== '/federated'}}
|
||||||
<DynamicPageBanner title="Federated Timeline" icon="#fa-globe"/>
|
<DynamicPageBanner title="Federated Timeline" icon="#fa-globe"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<title>Pinafore – Home</title>
|
<title>Pinafore – Home</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='home' virtual="true" virtualRealm="home">
|
<Layout page='home'>
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
<LazyTimeline timeline='home' />
|
<LazyTimeline timeline='home' />
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<title>Pinafore – {{listTitle}}</title>
|
<title>Pinafore – {{listTitle}}</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='lists' virtual="true" virtualRealm="list/{{params.listId}}">
|
<Layout page='lists'>
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
{{#if $pinnedPage !== `/lists/${params.listId}`}}
|
{{#if $pinnedPage !== `/lists/${params.listId}`}}
|
||||||
<DynamicPageBanner title="{{listTitle}}" icon="#fa-bars"/>
|
<DynamicPageBanner title="{{listTitle}}" icon="#fa-bars"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<title>Pinafore – Local</title>
|
<title>Pinafore – Local</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='local' virtual="true" virtualRealm="local">
|
<Layout page='local'>
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
{{#if $pinnedPage !== '/local'}}
|
{{#if $pinnedPage !== '/local'}}
|
||||||
<DynamicPageBanner title="Local Timeline" icon="#fa-users"/>
|
<DynamicPageBanner title="Local Timeline" icon="#fa-users"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<title>Pinafore – Notifications</title>
|
<title>Pinafore – Notifications</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='notifications' virtual="true" virtualRealm="notifications">
|
<Layout page='notifications'>
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
<LazyTimeline timeline='notifications' />
|
<LazyTimeline timeline='notifications' />
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
<title>Pinafore – #{{params.tagName}}</title>
|
<title>Pinafore – #{{params.tagName}}</title>
|
||||||
</:Head>
|
</:Head>
|
||||||
|
|
||||||
<Layout page='tags'
|
<Layout page='tags'>
|
||||||
virtual="true"
|
|
||||||
virtualRealm='tag/{{params.tagName}}' >
|
|
||||||
{{#if $isUserLoggedIn}}
|
{{#if $isUserLoggedIn}}
|
||||||
<DynamicPageBanner title="{{'#' + params.tagName}}"/>
|
<DynamicPageBanner title="{{'#' + params.tagName}}"/>
|
||||||
<LazyTimeline timeline='tag/{{params.tagName}}' />
|
<LazyTimeline timeline='tag/{{params.tagName}}' />
|
||||||
|
|
Loading…
Reference in a new issue