@@ -7,10 +7,13 @@ import EmptyListPlaceholder from './EmptyListPlaceholder.vue';
7
7
import { Ban , SearchIcon , X } from ' lucide-vue-next' ;
8
8
import LogFilterBtn from ' @/components/Simulator/LogFilterBtn.vue' ;
9
9
import TextInput from ' ../global/inputs/TextInput.vue' ;
10
+ import { useScroll } from ' @vueuse/core' ;
11
+ import { useTemplateRef } from ' vue' ;
10
12
11
13
const nodeStore = useNodeStore ();
12
14
const uiStore = useUIStore ();
13
- const scrollContainer = ref <HTMLDivElement >();
15
+ const scrollContainer = useTemplateRef <HTMLElement >(' scrollContainer' );
16
+ const { y, isScrolling, arrivedState, directions } = useScroll (scrollContainer );
14
17
15
18
type ColorMapType = {
16
19
[key : string ]: string ;
@@ -23,13 +26,25 @@ const colorMap: ComputedRef<ColorMapType> = computed(() => ({
23
26
success: ' text-green-400' ,
24
27
}));
25
28
26
- watch (nodeStore .logs , () => {
27
- nextTick (() => {
28
- scrollContainer .value ?.scrollTo ({
29
- top: scrollContainer .value .scrollHeight ,
30
- behavior: ' smooth' ,
29
+ const wasAtBottom = ref (false );
30
+
31
+ watch (
32
+ () => nodeStore .logs .length ,
33
+ () => {
34
+ nextTick (() => {
35
+ if (! wasAtBottom .value && scrollContainer .value ) {
36
+ scrollContainer .value .scrollTop = scrollContainer .value .scrollHeight ;
37
+ }
31
38
});
32
- });
39
+ },
40
+ );
41
+
42
+ watch (y , () => {
43
+ if (directions .top ) {
44
+ wasAtBottom .value = true ;
45
+ } else if (arrivedState .bottom ) {
46
+ wasAtBottom .value = false ;
47
+ }
33
48
});
34
49
35
50
const scopes = ref ([' RPC' , ' GenVM' , ' Consensus' ]);
0 commit comments