Skip to content

Commit b56d157

Browse files
authored
Merge pull request #76 from moazbuilds/fix/log-scroll-and-dublication
Fix/log scroll and dublication
2 parents 1e1f816 + f4c994b commit b56d157

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

src/cli/tui/routes/workflow/components/output/output-window.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,17 @@ export function OutputWindow(props: OutputWindowProps) {
111111
// Trigger load when near the top (within 3 lines) - skip if already loading
112112
if (scrollTop <= 3 && props.hasMoreAbove && props.onLoadMore && !props.isLoadingEarlier) {
113113
debug('[OutputWindow] Loading earlier lines...')
114+
const scrollHeightBefore = ref.scrollHeight
114115
const linesLoaded = props.onLoadMore()
115116
debug('[OutputWindow] Lines loaded: %d', linesLoaded)
116117
if (linesLoaded > 0) {
117-
ref.scrollTop = linesLoaded // Maintain view position
118+
// SolidJS updates DOM synchronously, so we can measure and adjust immediately
119+
const scrollHeightAfter = ref.scrollHeight
120+
const heightAdded = scrollHeightAfter - scrollHeightBefore
121+
// Maintain view position with small slack to prevent immediate re-trigger
122+
const slack = 5
123+
ref.scrollTop = scrollTop + heightAdded + slack
124+
debug('[OutputWindow] Scroll adjusted: heightAdded=%d, slack=%d, newScrollTop=%d', heightAdded, slack, ref.scrollTop)
118125
}
119126
}
120127
}

src/cli/tui/routes/workflow/hooks/useLogStream.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ function readLogFileIncremental(
109109
if (currentSize < state.lastFileSize) {
110110
logDebug('File truncated, doing full read. Old size: %d, new size: %d', state.lastFileSize, currentSize)
111111
const content = readFileSync(path, "utf-8")
112-
const lines = content.split("\n")
112+
// Filter empty lines to match incremental read behavior
113+
const lines = content.split("\n").filter(line => line !== '')
113114
state.lastFileSize = currentSize
114115
state.lastLineCount = lines.length
115116
return {
@@ -123,8 +124,9 @@ function readLogFileIncremental(
123124
// For small files, just do a full read (simpler and fast enough)
124125
if (currentSize < INCREMENTAL_THRESHOLD_BYTES) {
125126
const content = readFileSync(path, "utf-8")
126-
const lines = content.split("\n")
127-
const newLinesCount = lines.length - state.lastLineCount
127+
// Filter empty lines to match incremental read behavior
128+
const lines = content.split("\n").filter(line => line !== '')
129+
const newLinesCount = Math.max(0, lines.length - state.lastLineCount)
128130
state.lastFileSize = currentSize
129131
state.lastLineCount = lines.length
130132
return {
@@ -180,14 +182,15 @@ function readLogFileIncremental(
180182

181183
/**
182184
* Read entire log file (used for initial load or after truncation)
185+
* Filters empty lines to match incremental read behavior
183186
*/
184187
function readLogFileFull(path: string): string[] {
185188
try {
186189
if (!existsSync(path)) {
187190
return []
188191
}
189192
const content = readFileSync(path, "utf-8")
190-
return content.split("\n")
193+
return content.split("\n").filter(line => line !== '')
191194
} catch {
192195
return []
193196
}
@@ -499,8 +502,9 @@ export function useLogStream(
499502
const currentFileSize = getFileSize(logPath)
500503

501504
// Update incremental state
505+
// IMPORTANT: Track RAW line count, not filtered, to match readLogFileIncremental
502506
incrementalState.lastFileSize = currentFileSize
503-
incrementalState.lastLineCount = filteredLines.length
507+
incrementalState.lastLineCount = fileLines.length
504508

505509
// Update windowed state
506510
const trimCount = Math.max(0, filteredLines.length - maxWindow)

0 commit comments

Comments
 (0)