perf(files): optimize virtual scroller computation

Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
pull/40917/head
John Molakvoæ 2023-10-15 15:37:12 +07:00
parent 116c396f0e
commit 77fdef1081
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF
5 changed files with 40 additions and 16 deletions

@ -20,7 +20,8 @@
-
-->
<template>
<td class="files-list__row-actions"
<td v-show="visible"
class="files-list__row-actions"
data-cy-files-list-row-actions>
<!-- Render actions -->
<CustomElementRender v-for="action in enabledRenderActions"

@ -28,7 +28,7 @@
:style="{ height: dndNoticeHeight }" />
<VirtualList ref="table"
:data-component="FileEntry"
:data-component="userConfig.grid_view ? FileEntryGrid : FileEntry"
:data-key="'source'"
:data-sources="nodes"
:grid-mode="userConfig.grid_view"
@ -92,7 +92,8 @@ import Vue from 'vue'
import { action as sidebarAction } from '../actions/sidebarAction.ts'
import { useUserConfigStore } from '../store/userconfig.ts'
import DragAndDropNotice from './DragAndDropNotice.vue'
import FileEntry from './FileEntryGrid.vue'
import FileEntry from './FileEntry.vue'
import FileEntryGrid from './FileEntryGrid.vue'
import FilesListHeader from './FilesListHeader.vue'
import FilesListTableFooter from './FilesListTableFooter.vue'
import FilesListTableHeader from './FilesListTableHeader.vue'
@ -141,6 +142,7 @@ export default Vue.extend({
data() {
return {
FileEntry,
FileEntryGrid,
headers: getFileListHeaders(),
scrollToIndex: 0,
dragover: false,

@ -18,7 +18,7 @@
<component :is="dataComponent"
v-for="({key, item}, i) in renderedItems"
:key="key"
:visible="(i >= bufferItems || index <= bufferItems) && (i < shownItems - bufferItems)"
:visible="(i >= bufferItems - 1 || index <= bufferItems) && (i <= shownItems - bufferItems)"
:source="item"
:index="i"
v-bind="extraProps" />
@ -114,7 +114,7 @@ export default Vue.extend({
},
rowCount() {
return Math.ceil((this.tableHeight - this.headerHeight) / this.itemHeight) + (this.bufferItems / this.columnCount) * 2
return Math.ceil((this.tableHeight - this.headerHeight) / this.itemHeight) + (this.bufferItems / this.columnCount) * 2 + 1
},
columnCount() {
if (!this.gridMode) {
@ -173,9 +173,19 @@ export default Vue.extend({
},
},
watch: {
scrollToIndex() {
this.index = this.scrollToIndex
this.$el.scrollTop = this.index * this.itemHeight + this.beforeHeight
scrollToIndex(index) {
this.scrollTo(index)
},
columnCount(columnCount, oldColumnCount) {
if (oldColumnCount === 0) {
// We're initializing, the scroll position
// is handled on mounted
console.debug('VirtualList: columnCount is 0, skipping scroll')
return
}
// If the column count changes in grid view,
// update the scroll position again
this.scrollTo(this.index)
},
},
@ -188,7 +198,7 @@ export default Vue.extend({
this.beforeHeight = before?.clientHeight ?? 0
this.headerHeight = thead?.clientHeight ?? 0
this.tableHeight = root?.clientHeight ?? 0
logger.debug('VirtualList resizeObserver updated')
logger.debug('VirtualList: resizeObserver updated')
this.onScroll()
}, 100, false))
@ -196,12 +206,13 @@ export default Vue.extend({
this.resizeObserver.observe(root)
this.resizeObserver.observe(thead)
this.$el.addEventListener('scroll', this.onScroll)
if (this.scrollToIndex) {
this.$el.scrollTop = Math.floor((this.index * this.itemHeight) / this.rowCount) + this.beforeHeight
this.scrollTo(this.scrollToIndex)
}
// Adding scroll listener AFTER the initial scroll to index
this.$el.addEventListener('scroll', this.onScroll)
this.$_recycledPool = {} as Record<string, any>
},
@ -212,9 +223,19 @@ export default Vue.extend({
},
methods: {
scrollTo(index: number) {
this.index = index
// Scroll to one row and a half before the index
const scrollTop = (Math.floor(index / this.columnCount) - 0.5) * this.itemHeight + this.beforeHeight
logger.debug('VirtualList: scrolling to index ' + index, { scrollTop, columnCount: this.columnCount })
this.$el.scrollTop = scrollTop
},
onScroll() {
const topScroll = this.$el.scrollTop - this.beforeHeight
const index = Math.floor(topScroll / this.itemHeight) * this.columnCount
// Max 0 to prevent negative index
this.index = Math.max(0, Math.floor(Math.round((this.$el.scrollTop - this.beforeHeight) / this.itemHeight) * this.columnCount))
this.index = Math.max(0, index)
this.$emit('scroll')
},
},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long