add loading footer

This commit is contained in:
Nolan Lawson 2018-01-21 16:07:11 -08:00
parent 0d6cf813a8
commit 924e803d16
6 changed files with 88 additions and 12 deletions

View file

@ -0,0 +1,26 @@
<div class="loading-footer">
<LoadingSpinner size={{48}} />
<span class="loading-footer-info">
Loading more...
</span>
</div>
<style>
.loading-footer {
padding: 20px 0 10px;
display: flex;
align-items: center;
justify-content: center;
}
.loading-footer-info {
margin-left: 20px;
font-size: 1.3em;
}
</style>
<script>
import LoadingSpinner from './LoadingSpinner.html'
export default {
components: {
LoadingSpinner
}
}
</script>

View file

@ -1,10 +1,10 @@
<svg class="loading-spinner-icon {{maskStyle ? 'mask-style' : ''}}">
<svg class="loading-spinner-icon {{maskStyle ? 'mask-style' : ''}}"
style="width: {{size || 64}}px; height: {{size || 64}}px;"
>
<use xlink:href="#fa-spinner" />
</svg>
<style>
.loading-spinner-icon {
width: 64px;
height: 64px;
fill: var(--svg-fill);
animation: spin 2s infinite linear;
}

Before

Width:  |  Height:  |  Size: 503 B

After

Width:  |  Height:  |  Size: 533 B

View file

@ -4,6 +4,8 @@
items="{{keyedStatuses}}"
on:scrollToBottom="onScrollToBottom()"
shown="{{initialized}}"
footerComponent="{{LoadingFooter}}"
showFooter="{{initialized && runningUpdate}}"
/>
</div>
<style>
@ -15,6 +17,7 @@
import { store } from '../_utils/store'
import { getTimeline } from '../_utils/mastodon/timelines'
import StatusListItem from './StatusListItem.html'
import LoadingFooter from './LoadingFooter.html'
import VirtualList from './VirtualList.html'
import { splice, push } from 'svelte-extras'
import worker from 'workerize-loader!../_utils/database/database'
@ -40,6 +43,7 @@
},
data: () => ({
StatusListItem: StatusListItem,
LoadingFooter: LoadingFooter,
statuses: [],
runningUpdate: false,
initialized: false
@ -69,8 +73,8 @@
mark('onScrollToBottom')
this.set({ runningUpdate: true })
let newStatuses = await this.fetchStatusesAndPossiblyFallBack()
this.addStatuses(newStatuses)
this.set({ runningUpdate: false })
this.addStatuses(newStatuses)
stop('onScrollToBottom')
},
addStatuses(newStatuses) {

View file

@ -1,13 +1,16 @@
<!-- TODO: setting height is hacky, just make this element the scroller -->
<div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;">
{{#each $visibleItems as item @key}}
<VirtualListItem :component
offset="{{item.offset}}"
props="{{item.props}}"
key="{{item.key}}"
index="{{item.index}}"
/>
<VirtualListItem :component
offset="{{item.offset}}"
props="{{item.props}}"
key="{{item.key}}"
index="{{item.index}}"
/>
{{/each}}
{{#if $showFooter}}
<VirtualListFooter component="{{footerComponent}}"/>
{{/if}}
</div>
<style>
.virtual-list {
@ -17,6 +20,7 @@
</style>
<script>
import VirtualListItem from './VirtualListItem'
import VirtualListFooter from './VirtualListFooter.html'
import { virtualListStore } from '../_utils/virtualListStore'
import throttle from 'lodash/throttle'
import { mark, stop } from '../_utils/marks'
@ -26,6 +30,9 @@
export default {
oncreate () {
this.observe('showFooter', showFooter => {
this.store.set({showFooter: showFooter})
})
this.observe('items', (items) => {
mark('set items')
this.store.set({
@ -55,7 +62,8 @@
}),
store: () => virtualListStore,
components: {
VirtualListItem
VirtualListItem,
VirtualListFooter
},
computed: {
distanceFromBottom: ($scrollHeight, $scrollTop, $offsetHeight) => {

View file

@ -0,0 +1,27 @@
<div class="virtual-list-footer"
ref:node
style="transform: translateY({{$heightWithoutFooter}}px);" >
<:Component {component} />
</div>
<style>
.virtual-list-footer {
position: absolute;
top: 0;
width: 100%;
}
</style>
<script>
import { virtualListStore } from '../_utils/virtualListStore'
import { AsyncLayout } from '../_utils/AsyncLayout'
export default {
oncreate() {
const asyncLayout = new AsyncLayout(() => '__footer__')
asyncLayout.observe('__footer__', this.refs.node, (rect) => {
asyncLayout.disconnect()
this.store.set({footerHeight: rect.height})
})
},
store: () => virtualListStore,
}
</script>

View file

@ -42,6 +42,8 @@ class VirtualListStore extends Store {
const virtualListStore = new VirtualListStore({
items: [],
itemHeights: {},
showFooter: false,
footerHeight: 0
})
virtualListStore.compute('visibleItems',
@ -79,7 +81,9 @@ virtualListStore.compute('visibleItems',
return visibleItems
})
virtualListStore.compute('height', ['items', 'itemHeights'], (items, itemHeights) => {
virtualListStore.compute('heightWithoutFooter',
['items', 'itemHeights'],
(items, itemHeights) => {
let sum = 0
let i = -1
let len = items.length
@ -89,6 +93,13 @@ virtualListStore.compute('height', ['items', 'itemHeights'], (items, itemHeights
return sum
})
virtualListStore.compute('height',
['heightWithoutFooter', 'showFooter', 'footerHeight'],
(heightWithoutFooter, showFooter, footerHeight) => {
return showFooter ? (heightWithoutFooter + footerHeight) : heightWithoutFooter
})
virtualListStore.compute('numItems', ['items'], (items) => items.length)
if (process.browser && process.env.NODE_ENV !== 'production') {