Merge pull request #5021 from menloresearch/chore/scroll-bottom-log

chore: scroll to bottom when have new log message
This commit is contained in:
Faisal Amir 2025-05-20 09:33:12 +07:00 committed by GitHub
commit cbad4396cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,7 +1,7 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { route } from '@/constants/routes' import { route } from '@/constants/routes'
import { useEffect, useState } from 'react' import { useEffect, useState, useRef } from 'react'
import { parseLogLine, readLogs } from '@/services/app' import { parseLogLine, readLogs } from '@/services/app'
import { listen } from '@tauri-apps/api/event' import { listen } from '@tauri-apps/api/event'
@ -23,6 +23,7 @@ const LOG_EVENT_NAME = 'log://log'
function LogsViewer() { function LogsViewer() {
const [logs, setLogs] = useState<LogEntry[]>([]) const [logs, setLogs] = useState<LogEntry[]>([])
const logsContainerRef = useRef<HTMLDivElement>(null)
useEffect(() => { useEffect(() => {
readLogs().then((logData) => { readLogs().then((logData) => {
@ -30,13 +31,25 @@ function LogsViewer() {
.filter((log) => log?.target === SERVER_LOG_TARGET) .filter((log) => log?.target === SERVER_LOG_TARGET)
.filter(Boolean) as LogEntry[] .filter(Boolean) as LogEntry[]
setLogs(logs) setLogs(logs)
// Scroll to bottom after initial logs are loaded
setTimeout(() => {
scrollToBottom()
}, 100)
}) })
let unsubscribe = () => {} let unsubscribe = () => {}
listen(LOG_EVENT_NAME, (event) => { listen(LOG_EVENT_NAME, (event) => {
const { message } = event.payload as { message: string } const { message } = event.payload as { message: string }
const log: LogEntry | undefined = parseLogLine(message) const log: LogEntry | undefined = parseLogLine(message)
if (log?.target === SERVER_LOG_TARGET) { if (log?.target === SERVER_LOG_TARGET) {
setLogs((prevLogs) => [...prevLogs, log]) setLogs((prevLogs) => {
const newLogs = [...prevLogs, log]
// Schedule scroll to bottom after state update
setTimeout(() => {
scrollToBottom()
}, 0)
return newLogs
})
} }
}).then((unsub) => { }).then((unsub) => {
unsubscribe = unsub unsubscribe = unsub
@ -46,6 +59,14 @@ function LogsViewer() {
} }
}, []) }, [])
// Function to scroll to the bottom of the logs container
const scrollToBottom = () => {
if (logsContainerRef.current) {
const { scrollHeight, clientHeight } = logsContainerRef.current
logsContainerRef.current.scrollTop = scrollHeight - clientHeight
}
}
// Function to get appropriate color for log level // Function to get appropriate color for log level
const getLogLevelColor = (level: string) => { const getLogLevelColor = (level: string) => {
switch (level) { switch (level) {
@ -70,7 +91,7 @@ function LogsViewer() {
return ( return (
<div className="flex flex-col h-full bg-main-view"> <div className="flex flex-col h-full bg-main-view">
<div className="flex-1 overflow-auto"> <div className="flex-1 overflow-auto" ref={logsContainerRef}>
<div className="font-mono p-2"> <div className="font-mono p-2">
{logs.length === 0 ? ( {logs.length === 0 ? (
<div className="text-center text-main-view-fg/50 py-8"> <div className="text-center text-main-view-fg/50 py-8">