make timeline components async (#204)

This commit is contained in:
Nolan Lawson 2018-04-21 08:45:41 -07:00 committed by GitHub
parent 36b8f15ba6
commit 78f44c7b51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 43 deletions

View file

@ -4,46 +4,41 @@
on:focusWithCapture="saveFocus(event)" on:focusWithCapture="saveFocus(event)"
on:blurWithCapture="clearFocus(event)" on:blurWithCapture="clearFocus(event)"
> >
{{#if virtual}} {{#await componentsPromise}}
<VirtualList component="{{VirtualListComponent}}" {{then result}}
realm="{{$currentInstance + '/' + timeline}}" <:Component {result.listComponent}
containerQuery=".container" component="{{result.listItemComponent}}"
:makeProps realm="{{$currentInstance + '/' + timeline}}"
items="{{$timelineItemIds}}" containerQuery=".container"
showFooter="{{$timelineInitialized && $runningUpdate}}" :makeProps
footerComponent="{{LoadingFooter}}" items="{{$timelineItemIds}}"
showHeader="{{$showHeader}}" showFooter="{{$timelineInitialized && $runningUpdate}}"
headerComponent="{{MoreHeaderVirtualWrapper}}" footerComponent="{{LoadingFooter}}"
:headerProps showHeader="{{$showHeader}}"
on:scrollToBottom="onScrollToBottom()" headerComponent="{{MoreHeaderVirtualWrapper}}"
on:scrollToTop="onScrollToTop()" :headerProps
on:scrollTopChanged="onScrollTopChanged(event)" :scrollToItem
on:initialized="initialize()" on:scrollToBottom="onScrollToBottom()"
on:noNeedToScroll="onNoNeedToScroll()" on:scrollToTop="onScrollToTop()"
on:scrollTopChanged="onScrollTopChanged(event)"
on:initialized="initialize()"
on:noNeedToScroll="onNoNeedToScroll()"
/> />
{{else}} {{catch error}}
<!-- if this is a status thread, it's easier to just render the <div>Error: component failed to load! Try reloading. {{error}}</div>
whole thing rather than use a virtual list --> {{/await}}
<PseudoVirtualList
component="{{VirtualListComponent}}"
realm="{{$currentInstance + '/' + timeline}}"
containerQuery=".container"
:makeProps
items="{{$timelineItemIds}}"
scrollToItem="{{scrollToItem}}"
on:initialized="initialize()"
/>
{{/if}}
</div> </div>
<script> <script>
import { store } from '../../_store/store' import { store } from '../../_store/store'
import StatusVirtualListItem from './StatusVirtualListItem.html'
import NotificationVirtualListItem from './NotificationVirtualListItem.html'
import Status from '../status/Status.html' import Status from '../status/Status.html'
import LoadingFooter from './LoadingFooter.html' import LoadingFooter from './LoadingFooter.html'
import MoreHeaderVirtualWrapper from './MoreHeaderVirtualWrapper.html' import MoreHeaderVirtualWrapper from './MoreHeaderVirtualWrapper.html'
import VirtualList from '../virtualList/VirtualList.html' import {
import PseudoVirtualList from '../pseudoVirtualList/PseudoVirtualList.html' importVirtualList,
importPseudoVirtualList,
importStatusVirtualListItem,
importNotificationVirtualListItem
} from '../../_utils/asyncModules'
import { timelines } from '../../_static/timelines' import { timelines } from '../../_static/timelines'
import { import {
getStatus as getStatusFromDatabase, getStatus as getStatusFromDatabase,
@ -81,8 +76,22 @@
scrollTop: 0 scrollTop: 0
}), }),
computed: { computed: {
VirtualListComponent: (timelineType) => { // For threads, it's simpler to just render all items as a pseudo-virtual list
return timelineType === 'notifications' ? NotificationVirtualListItem : StatusVirtualListItem // due to need to scroll to the right item and thus calculate all item heights up-front.
// Here we lazy-load both the virtual list component itself as well as the component
// it renders.
componentsPromise: (timelineType) => {
return Promise.all([
timelineType === 'status'
? importPseudoVirtualList()
: importVirtualList(),
timelineType === 'notifications'
? importNotificationVirtualListItem()
: importStatusVirtualListItem()
]).then(results => ({
listComponent: results[0],
listItemComponent: results[1]
}))
}, },
makeProps: ($currentInstance, timelineType, timelineValue) => async (itemId) => { makeProps: ($currentInstance, timelineType, timelineValue) => async (itemId) => {
let res = { let res = {
@ -120,9 +129,6 @@
timelineValue: (timeline) => { timelineValue: (timeline) => {
return timeline.split('/').slice(-1)[0] return timeline.split('/').slice(-1)[0]
}, },
// for threads, it's simpler to just render all items as a pseudo-virtual list
// due to need to scroll to the right item and thus calculate all item heights up-front
virtual: (timelineType) => timelineType !== 'status',
// Scroll to the first item if this is a "status in own thread" timeline. // Scroll to the first item if this is a "status in own thread" timeline.
// Don't scroll to the first item because it obscures the "back" button. // Don't scroll to the first item because it obscures the "back" button.
scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => ( scrollToItem: (timelineType, timelineValue, $firstTimelineItemId) => (
@ -138,10 +144,6 @@
} }
}, },
store: () => store, store: () => store,
components: {
VirtualList,
PseudoVirtualList
},
events: { events: {
focusWithCapture, focusWithCapture,
blurWithCapture blurWithCapture

View file

@ -24,4 +24,20 @@ export const importWebSocketClient = () => import(
export const importDialogs = () => import( export const importDialogs = () => import(
/* webpackChunkName: 'dialogs' */ '../_components/dialog/dialogs.js' /* webpackChunkName: 'dialogs' */ '../_components/dialog/dialogs.js'
) )
export const importVirtualList = () => import(
/* webpackChunkName: 'VirtualList.html' */ '../_components/virtualList/VirtualList.html'
).then(mod => mod.default)
export const importPseudoVirtualList = () => import(
/* webpackChunkName: 'PseudoVirtualList.html' */ '../_components/pseudoVirtualList/PseudoVirtualList.html'
).then(mod => mod.default)
export const importStatusVirtualListItem = () => import(
/* webpackChunkName: 'StatusVirtualListItem.html' */ '../_components/timeline/StatusVirtualListItem.html'
).then(mod => mod.default)
export const importNotificationVirtualListItem = () => import(
/* webpackChunkName: 'NotificationVirtualListItem.html' */ '../_components/timeline/NotificationVirtualListItem.html'
).then(mod => mod.default)