start on virtual list
This commit is contained in:
parent
d5ac34eb73
commit
3ef701fd57
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -6829,9 +6829,7 @@
|
|||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
},
|
||||
"svelte": {
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-1.51.0.tgz",
|
||||
"integrity": "sha512-lqa9eAZ4ZQLMWsoyynAogUtib7HhHnrJJaS93uRgZU5cfXquBVR+FkKVK41LdlwffmOfOjbUin6pT8e/LZUwjA=="
|
||||
"version": "github:nolanlawson/svelte#c5cd9fc76e069faa364e5c2c6343ddaf2adc4dcf"
|
||||
},
|
||||
"svelte-extras": {
|
||||
"version": "1.6.0",
|
||||
|
|
|
@ -31,10 +31,10 @@
|
|||
"npm-run-all": "^4.1.2",
|
||||
"performance-now": "^2.1.0",
|
||||
"pify": "^3.0.0",
|
||||
"sapper": "^0.3.1",
|
||||
"sapper": "^0.3.2",
|
||||
"serve-static": "^1.13.1",
|
||||
"style-loader": "^0.19.1",
|
||||
"svelte": "^1.50.0",
|
||||
"svelte": "github:nolanlawson/svelte#master-8057884",
|
||||
"svelte-extras": "^1.6.0",
|
||||
"svelte-loader": "^2.3.3",
|
||||
"svelte-transitions": "^1.1.1",
|
||||
|
|
17
routes/_components/StatusListItem.html
Normal file
17
routes/_components/StatusListItem.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<div class="list-item">
|
||||
<Status status="{{virtualProps}}" />
|
||||
</div>
|
||||
<style>
|
||||
.list-item {
|
||||
border-bottom: 1px solid var(--main-border);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import Status from './Status.html'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Status
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,33 +1,27 @@
|
|||
<ul>
|
||||
{{#each statuses as status}}
|
||||
<li>
|
||||
<Status :status />
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<div class="timeline">
|
||||
<VirtualList component="{{StatusListItem}}" items="{{statuses}}" />
|
||||
</div>
|
||||
<style>
|
||||
ul {
|
||||
list-style: none;
|
||||
.timeline {
|
||||
padding-right: 10px;
|
||||
}
|
||||
li {
|
||||
border-bottom: 1px solid var(--main-border);
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import { store } from '../_utils/store'
|
||||
import { getHomeTimeline } from '../_utils/mastodon/oauth'
|
||||
import fixture from '../_utils/fixture.json'
|
||||
import Status from './Status.html'
|
||||
import StatusListItem from './StatusListItem.html'
|
||||
import VirtualList from './VirtualList.html'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
target: 'home',
|
||||
statuses: fixture
|
||||
statuses: fixture,
|
||||
StatusListItem: StatusListItem
|
||||
}),
|
||||
store: () => store,
|
||||
components: {
|
||||
Status
|
||||
VirtualList
|
||||
}
|
||||
}
|
||||
</script>
|
70
routes/_components/VirtualList.html
Normal file
70
routes/_components/VirtualList.html
Normal file
|
@ -0,0 +1,70 @@
|
|||
<div class="virtual-list" ref:node style="height: {{height}}px;">
|
||||
{{#each visibleItems as visibleItem, index}}
|
||||
<VirtualListItem :component
|
||||
:intersectionObserver
|
||||
virtualOffset="{{visibleItem.offset}}"
|
||||
virtualProps="{{visibleItem.props}}"
|
||||
virtualIndex="{{index}}" />
|
||||
{{/each}}
|
||||
</div>
|
||||
<style>
|
||||
.virtual-list {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
import VirtualListItem from './VirtualListItem'
|
||||
|
||||
function sum(arr) {
|
||||
return arr.reduce((a, b) => a + b, 0)
|
||||
}
|
||||
|
||||
export default {
|
||||
oncreate() {
|
||||
let intersectionObserver = new IntersectionObserver((entries) => {
|
||||
let totalHeight = sum(entries.map(entry => entry.boundingClientRect.height))
|
||||
let offset = 0
|
||||
let offsets = []
|
||||
entries.forEach(entry => {
|
||||
offsets.push(offset)
|
||||
offset += entry.boundingClientRect.height
|
||||
})
|
||||
this.set({
|
||||
height: totalHeight,
|
||||
offsets: offsets
|
||||
})
|
||||
console.log('entries', entries.map(entry => entry.target.getAttribute('data-virtual-index')))
|
||||
}, {
|
||||
root: this.refs.node
|
||||
})
|
||||
this.set({
|
||||
intersectionObserver: intersectionObserver
|
||||
})
|
||||
},
|
||||
ondestroy() {
|
||||
let intersectionObserver = this.get('intersectionObserver')
|
||||
if (intersectionObserver) {
|
||||
intersectionObserver.disconnect()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visibleItems: (items, offsets) => {
|
||||
return items.map((item, idx) => ({
|
||||
props: item,
|
||||
offset: offsets[idx]
|
||||
}))
|
||||
}
|
||||
},
|
||||
data: () => ({
|
||||
scrollHeight: 0,
|
||||
component: null,
|
||||
intersectionObserver: null,
|
||||
items: [],
|
||||
offsets: [],
|
||||
height: 400
|
||||
}),
|
||||
components: {
|
||||
VirtualListItem
|
||||
}
|
||||
}
|
||||
</script>
|
29
routes/_components/VirtualListItem.html
Normal file
29
routes/_components/VirtualListItem.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
<div class="virtual-list-item"
|
||||
ref:node
|
||||
style="transform: translate3d(0, {{virtualOffset}}px, 0);"
|
||||
data-virtual-index="{{virtualIndex}}">
|
||||
<:Component {component} :virtualProps :virtualIndex :intersectionObserver />
|
||||
</div>
|
||||
<style>
|
||||
.virtual-list-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
will-change: transform;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
export default {
|
||||
oncreate() {
|
||||
this.observe('intersectionObserver', (intersectionObserver) => {
|
||||
if (intersectionObserver) {
|
||||
intersectionObserver.observe(this.refs.node)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
showRefs () {
|
||||
console.log(this.refs)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue