diff --git a/.changeset/log-viewer-dead-scroll.md b/.changeset/log-viewer-dead-scroll.md new file mode 100644 index 0000000..ba78c06 --- /dev/null +++ b/.changeset/log-viewer-dead-scroll.md @@ -0,0 +1,8 @@ +--- +"@aliou/pi-processes": patch +--- + +Fixed a dead zone in the `/ps:logs` overlay where up to a screenful of +scroll keypresses could be swallowed. The clamped viewport end is now +written back to the scroll anchor in both the truncated and full render +paths, so every keypress moves the view. diff --git a/extensions/processes-logs/components/log-file-viewer.ts b/extensions/processes-logs/components/log-file-viewer.ts index 60f63c9..7a36eb7 100644 --- a/extensions/processes-logs/components/log-file-viewer.ts +++ b/extensions/processes-logs/components/log-file-viewer.ts @@ -218,6 +218,11 @@ export class LogFileViewer { visible.length, Math.max(Math.min(height, visible.length), rawEnd), ); + // Write the clamped end back so the anchor always matches the screen. + // Otherwise scrolling mutates a stale anchor while the clamp above + // swallows the change, leaving a dead zone of up to a screenful of + // scroll keypresses. + if (!this.follow && this.anchorEnd !== null) this.anchorEnd = end; const start = Math.max(0, end - height); const matchSet = new Set(this.searchMatches); const currentMatchIndex = @@ -301,6 +306,9 @@ export class LogFileViewer { totalDisplayRows, Math.max(Math.min(height, totalDisplayRows), rawEnd), ); + // Same anchor normalization as the truncated path: keep the stored + // anchor truthful so scrollBy starts from the rendered bottom edge. + if (!this.follow && this.anchorEnd !== null) this.anchorEnd = end; const start = Math.max(0, end - height); const rendered = rows.slice(start, end).map((row) => row.text);