Skip to content

Commit 68ab3a7

Browse files
committed
[WIP] fix(LogTable): implement virtual scrolling
1 parent f2c3f60 commit 68ab3a7

File tree

1 file changed

+44
-6
lines changed

1 file changed

+44
-6
lines changed

src/components/table/LogTable.vue

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
SPDX-License-Identifier: AGPL-3.0-or-later
44
-->
55
<template>
6-
<div class="log-table">
6+
<div ref="table" class="log-table" @scroll="debouncedHandleScrollPosition">
77
<LogDetailsModal v-if="currentRow"
88
:open.sync="isModalOpen"
99
:current-entry.sync="currentRow"
@@ -35,10 +35,17 @@
3535
</td>
3636
</tr>
3737

38-
<LogTableRow v-for="row, rowNumber in sortedRows"
39-
:key="rowNumber"
40-
:row="row"
41-
@show-details="showDetailsForRow" />
38+
<template v-for="(row, rowNumber) in sortedRows">
39+
<tr v-if="checkIfDummy(rowNumber)" :key="rowNumber" class="dummy">
40+
<td colspan="5" class="log-table__load-more">
41+
{{ t('logreader', 'Loading older log entries') }}
42+
</td>
43+
</tr>
44+
<LogTableRow v-else
45+
:key="rowNumber"
46+
:row="row"
47+
@show-details="showDetailsForRow" />
48+
</template>
4249
</tbody>
4350
<tfoot>
4451
<tr v-if="sortedByTime !== 'ascending'">
@@ -59,10 +66,11 @@
5966
<script setup lang="ts">
6067
import type { ILogEntry, ISortingOptions } from '../../interfaces'
6168
62-
import { computed, nextTick, ref } from 'vue'
69+
import { computed, nextTick, ref, watch } from 'vue'
6370
import { translate as t } from '@nextcloud/l10n'
6471
import { useSettingsStore } from '../../store/settings'
6572
import { useLogStore } from '../../store/logging'
73+
import { debounce } from '../../utils/debounce'
6674
6775
import IntersectionObserver from '../IntersectionObserver.vue'
6876
import LogDetailsModal from '../LogDetailsModal.vue'
@@ -109,6 +117,10 @@ const showDetailsForRow = (row: ILogEntry) => {
109117
isModalOpen.value = true
110118
}
111119
120+
/**
121+
* Reference to the table container, used to track current scroll position
122+
*/
123+
const table = ref<HTMLElement>()
112124
/**
113125
* Reference to the table body, used for keeping scroll position on loading more entries
114126
*/
@@ -146,6 +158,28 @@ const sortedRows = computed(() => {
146158
sorted.sort((a, b) => order(byLevel, sortedByLevel.value, a, b) || order(byApp, sortedByApp.value, a, b) || order(byTime, sortedByTime.value, a, b))
147159
return sorted
148160
})
161+
162+
const debouncedHandleScrollPosition = debounce(handleScrollPosition, 200)
163+
164+
const topLineIndex = ref(0)
165+
/**
166+
* Track current scroll position
167+
*/
168+
function handleScrollPosition() {
169+
topLineIndex.value = (table.value?.scrollTop ?? 0) / 42
170+
}
171+
172+
/**
173+
* Check how far is the row from current scroll position
174+
* @param index row number
175+
*/
176+
function checkIfDummy(index) {
177+
return index > topLineIndex.value + 100 || index < topLineIndex.value - 100
178+
}
179+
180+
watch(sortedRows, () => {
181+
handleScrollPosition()
182+
})
149183
</script>
150184

151185
<style lang="scss" scoped>
@@ -160,6 +194,10 @@ const sortedRows = computed(() => {
160194
table-layout: fixed;
161195
}
162196
197+
.dummy {
198+
height: 42px;
199+
}
200+
163201
&__load-more {
164202
text-align: center;
165203
padding-block: 4px;

0 commit comments

Comments
 (0)