add custom solution for virtual scrolling to ease ram and cpu use when scrolling for a long time
This commit is contained in:
parent
7397636914
commit
9eae4d07c1
5 changed files with 57 additions and 9 deletions
|
@ -35,7 +35,8 @@ const conversation = {
|
|||
data () {
|
||||
return {
|
||||
highlight: null,
|
||||
expanded: false
|
||||
expanded: false,
|
||||
height: '115px'
|
||||
}
|
||||
},
|
||||
props: [
|
||||
|
@ -44,7 +45,8 @@ const conversation = {
|
|||
'isPage',
|
||||
'pinnedStatusIdsObject',
|
||||
'inProfile',
|
||||
'profileUserId'
|
||||
'profileUserId',
|
||||
'hidden'
|
||||
],
|
||||
created () {
|
||||
if (this.isPage) {
|
||||
|
@ -102,6 +104,9 @@ const conversation = {
|
|||
},
|
||||
isExpanded () {
|
||||
return this.expanded || this.isPage
|
||||
},
|
||||
hiderStyle () {
|
||||
return this.hidden ? { height: this.height } : {}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
@ -112,7 +117,7 @@ const conversation = {
|
|||
const newConversationId = this.getConversationId(newVal)
|
||||
const oldConversationId = this.getConversationId(oldVal)
|
||||
if (newConversationId && oldConversationId && newConversationId === oldConversationId) {
|
||||
this.setHighlight(this.originalStatusId)
|
||||
this.setHighheightlight(this.originalStatusId)
|
||||
} else {
|
||||
this.fetchConversation()
|
||||
}
|
||||
|
@ -121,6 +126,10 @@ const conversation = {
|
|||
if (value) {
|
||||
this.fetchConversation()
|
||||
}
|
||||
},
|
||||
hidden (value) {
|
||||
this.height = `${this.$el.clientHeight}px`
|
||||
console.log('Element height:', this.height)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<template>
|
||||
<div
|
||||
:style="hiderStyle"
|
||||
class="timeline panel-default"
|
||||
:class="[isExpanded ? 'panel' : 'panel-disabled']"
|
||||
>
|
||||
<div
|
||||
v-if="isExpanded"
|
||||
v-if="isExpanded && !hidden"
|
||||
class="panel-heading conversation-heading"
|
||||
>
|
||||
<span class="title"> {{ $t('timeline.conversation') }} </span>
|
||||
|
@ -28,6 +29,7 @@
|
|||
:replies="getReplies(status.id)"
|
||||
:in-profile="inProfile"
|
||||
:profile-user-id="profileUserId"
|
||||
:hidden="hidden"
|
||||
class="status-fadein panel-body"
|
||||
@goto="setHighlight"
|
||||
@toggleExpanded="toggleExpanded"
|
||||
|
|
|
@ -34,7 +34,8 @@ const Status = {
|
|||
'inlineExpanded',
|
||||
'showPinned',
|
||||
'inProfile',
|
||||
'profileUserId'
|
||||
'profileUserId',
|
||||
'hidden'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
|
@ -121,7 +122,7 @@ const Status = {
|
|||
return this.mergedConfig.hideFilteredStatuses
|
||||
},
|
||||
hideStatus () {
|
||||
return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses)
|
||||
return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses) || this.hidden
|
||||
},
|
||||
isFocused () {
|
||||
// retweet or root of an expanded conversation
|
||||
|
|
|
@ -32,7 +32,8 @@ const Timeline = {
|
|||
return {
|
||||
paused: false,
|
||||
unfocused: false,
|
||||
bottomedOut: false
|
||||
bottomedOut: false,
|
||||
vScrollIndex: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -68,6 +69,12 @@ const Timeline = {
|
|||
},
|
||||
pinnedStatusIdsObject () {
|
||||
return keyBy(this.pinnedStatusIds)
|
||||
},
|
||||
displayingStatuses () {
|
||||
const amount = this.timeline.visibleStatuses.length
|
||||
const min = Math.max(0, this.vScrollIndex - 20)
|
||||
const max = Math.min(amount, this.vScrollIndex + 20)
|
||||
return this.timeline.visibleStatuses.slice(min, max).map(_ => _.id)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
@ -79,7 +86,7 @@ const Timeline = {
|
|||
const credentials = store.state.users.currentUser.credentials
|
||||
const showImmediately = this.timeline.visibleStatuses.length === 0
|
||||
|
||||
window.addEventListener('scroll', this.scrollLoad)
|
||||
window.addEventListener('scroll', throttle(this.scrollLoad, 100))
|
||||
|
||||
if (store.state.api.fetchers[this.timelineName]) { return false }
|
||||
|
||||
|
@ -142,7 +149,35 @@ const Timeline = {
|
|||
}
|
||||
})
|
||||
}, 1000, this),
|
||||
determineVisibleStatuses () {
|
||||
const statuses = this.$refs.timeline.children
|
||||
|
||||
const bodyBRect = document.body.getBoundingClientRect()
|
||||
const height = Math.max(bodyBRect.height, -(bodyBRect.y))
|
||||
|
||||
const centerOfScreen = window.pageYOffset + (window.innerHeight * 0.5)
|
||||
|
||||
// Approximate which status is in the middle of the screen and check how
|
||||
// far it is roughly from the viewport
|
||||
let approxIndex = Math.floor(statuses.length * (centerOfScreen / height))
|
||||
let err = statuses[approxIndex].getBoundingClientRect().y
|
||||
|
||||
// if the status is too far from viewport, check the next/previous ones if
|
||||
// they happen to be better
|
||||
while (err < -100) {
|
||||
approxIndex++
|
||||
err = statuses[approxIndex].getBoundingClientRect().y
|
||||
}
|
||||
while (err > 1000) {
|
||||
approxIndex--
|
||||
err = statuses[approxIndex].getBoundingClientRect().y
|
||||
}
|
||||
|
||||
// this status is now the center point for virtual scrolling
|
||||
this.vScrollIndex = approxIndex
|
||||
},
|
||||
scrollLoad (e) {
|
||||
this.determineVisibleStatuses()
|
||||
const bodyBRect = document.body.getBoundingClientRect()
|
||||
const height = Math.max(bodyBRect.height, -(bodyBRect.y))
|
||||
if (this.timeline.loading === false &&
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div :class="classes.body">
|
||||
<div class="timeline">
|
||||
<div ref="timeline" class="timeline">
|
||||
<template v-for="statusId in pinnedStatusIds">
|
||||
<conversation
|
||||
v-if="timeline.statusesObject[statusId]"
|
||||
|
@ -56,6 +56,7 @@
|
|||
:collapsable="true"
|
||||
:in-profile="inProfile"
|
||||
:profile-user-id="userId"
|
||||
:hidden="!displayingStatuses.includes(status.id)"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue