@@ -16,8 +16,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
-->
17
17
18
18
<template >
19
- <div ref =" wrapper" >
20
- <pre data-cy =" log-text" ><span
19
+ <div
20
+ ref =" scrollWrapper"
21
+ class =" h-100 overflow-auto px-4 pb-2"
22
+ >
23
+ <pre ref =" logText" data-cy =" log-text" ><span
21
24
v-for =" (log, index) in computedLogs"
22
25
:key =" index"
23
26
:class =" wordWrap ? 'text-pre-wrap' : 'text-pre'"
@@ -26,21 +29,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
26
29
v-if =" logs.length"
27
30
position =" fixed"
28
31
location =" bottom right"
29
- class =" ma-3 "
32
+ class =" ma-5 "
30
33
@click =" scrollToTop"
31
34
:icon =" $options.icons.mdiMouseMoveUp"
35
+ data-cy =" log-scroll-top"
32
36
/>
33
37
<!-- a div to use for autoscrolling -->
34
38
<div ref =" autoScrollEnd" ></div >
35
39
</div >
36
40
</template >
37
41
38
42
<script >
39
- import { useTemplateRef , watch , onBeforeUnmount } from ' vue'
43
+ import { useTemplateRef , watch , onBeforeUnmount , nextTick } from ' vue'
44
+ import { useScroll , useVModel , whenever } from ' @vueuse/core'
40
45
import { when } from ' @/utils'
41
46
import {
42
47
mdiMouseMoveUp
43
48
} from ' @mdi/js'
49
+
44
50
export default {
45
51
name: ' LogComponent' ,
46
52
@@ -70,28 +76,51 @@ export default {
70
76
}
71
77
},
72
78
73
- setup (props ) {
74
- const wrapperRef = useTemplateRef (' wrapper' )
79
+ emits: [
80
+ ' update:autoScroll'
81
+ ],
82
+
83
+ setup (props , { emit }) {
84
+ const logText = useTemplateRef (' logText' )
85
+ const scrollWrapper = useTemplateRef (' scrollWrapper' )
75
86
const autoScrollEndRef = useTemplateRef (' autoScrollEnd' )
76
87
88
+ const autoScroll = useVModel (props, ' autoScroll' , emit)
89
+ const { arrivedState , directions } = useScroll (scrollWrapper)
90
+
91
+ // Turn on autoscroll when user scrolls to bottom:
92
+ whenever (() => arrivedState .bottom && ! arrivedState .top , () => {
93
+ // (when page first loads both top and bottom are true)
94
+ autoScroll .value = true
95
+ })
96
+ // Turn off autoscroll when user scrolls up:
97
+ whenever (() => props .logs .length && directions .top , () => {
98
+ autoScroll .value = false
99
+ })
100
+
77
101
function scrollToEnd () {
78
102
autoScrollEndRef .value ? .scrollIntoView ({ behavior: ' smooth' })
79
103
}
80
104
81
- function scrollToTop () {
82
- wrapperRef .value ? .scrollIntoView ({ behavior: ' smooth' })
105
+ async function scrollToTop () {
106
+ autoScroll .value = false
107
+ // Wait for smooth scroll cancel to happen
108
+ await nextTick ()
109
+ scrollWrapper .value ? .scroll ({ top: 0 , left: 0 , behavior: ' smooth' })
83
110
}
84
111
85
112
const ro = new ResizeObserver (scrollToEnd)
86
113
87
- when (wrapperRef , () => {
114
+ when (logText , () => {
88
115
watch (
89
- () => props . autoScroll ,
116
+ autoScroll,
90
117
(val ) => {
91
118
if (val) {
92
119
scrollToEnd ()
93
- ro .observe (wrapperRef .value )
120
+ ro .observe (logText .value )
94
121
} else {
122
+ // When autoscroll is turned off, cancel any smooth scroll in progress:
123
+ scrollWrapper .value .scrollBy (0 , 0 )
95
124
ro .disconnect ()
96
125
}
97
126
},
0 commit comments