add loading footer
This commit is contained in:
parent
0d6cf813a8
commit
924e803d16
26
routes/_components/LoadingFooter.html
Normal file
26
routes/_components/LoadingFooter.html
Normal 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>
|
|
@ -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 |
|
@ -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) {
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
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) => {
|
||||
|
|
27
routes/_components/VirtualListFooter.html
Normal file
27
routes/_components/VirtualListFooter.html
Normal 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>
|
|
@ -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') {
|
||||
|
|
Loading…
Reference in a new issue