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"
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'" >
5966<script setup lang="ts">
6067import type { ILogEntry , ISortingOptions } from ' ../../interfaces'
6168
62- import { computed , nextTick , ref } from ' vue'
69+ import { computed , nextTick , ref , watch } from ' vue'
6370import { translate as t } from ' @nextcloud/l10n'
6471import { useSettingsStore } from ' ../../store/settings'
6572import { useLogStore } from ' ../../store/logging'
73+ import { debounce } from ' ../../utils/debounce'
6674
6775import IntersectionObserver from ' ../IntersectionObserver.vue'
6876import 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