From f3ffa37ff3712311f11d6451a4506bcc386c1213 Mon Sep 17 00:00:00 2001 From: Pr0metheus2 Date: Mon, 12 Oct 2026 13:11:53 +0200 Subject: [PATCH] Fix: Preserve reading position after a small log-file shrink When a monitored log file shrinks, LogExpert reloads it as a new file. Even removing one trailing character could therefore move the view away from the line being read and turn Follow tail back on. This change saves the visible position before an automatic reload and restores it when the reloaded file has the same number of lines or one fewer. A substantial drop in line count keeps the existing reset behavior for rotation. Verification: 40 related tests passed; the full suite passed with 1,014 passed and 7 skipped. The five-step manual reproduction confirmed that the reading position is restored after removing the character --- .../Controls/LogWindow/LogWindow.cs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs b/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs index 63d42349..64d11b11 100644 --- a/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs +++ b/src/LogExpert.UI/Controls/LogWindow/LogWindow.cs @@ -152,6 +152,7 @@ internal partial class LogWindow : DockContent, ILogPaintContextUI, ILogView, IL private bool _noSelectionUpdates; private ReloadMemento _reloadMemento; + private int? _lineCountBeforeAutomaticReload; private int _reloadOverloadCounter; private SortedList _rowHeightList = []; private int _selectedCol; // set by context menu event for column headers only @@ -928,6 +929,7 @@ private void OnLogFileReaderFinishedLoading (object sender, EventArgs e) } _reloadMemento = null; + _lineCountBeforeAutomaticReload = null; } [SupportedOSPlatform("windows")] @@ -3091,9 +3093,20 @@ private void EnterLoadFileStatus () private void PositionAfterReload (ReloadMemento reloadMemento) { var lineCount = _logFileReader.LineCount; + if (_lineCountBeforeAutomaticReload is int previousLineCount) + { + // A tail edit can lose at most one line; a rotation to a short new file should reset the view. + if (lineCount < previousLineCount - 1 || reloadMemento.FirstDisplayedLine >= lineCount) + { + return; + } + + FollowTailChanged(false, false); + } + RestorePositionWithoutTimeSync(new GridPosition( - _reloadMemento.CurrentLine < lineCount ? _reloadMemento.CurrentLine : -1, - _reloadMemento.FirstDisplayedLine < lineCount ? _reloadMemento.FirstDisplayedLine : -1)); + reloadMemento.CurrentLine < lineCount ? reloadMemento.CurrentLine : -1, + reloadMemento.FirstDisplayedLine < lineCount ? reloadMemento.FirstDisplayedLine : -1)); } [SupportedOSPlatform("windows")] @@ -3222,6 +3235,17 @@ private void ReloadNewFile () if (_reloadOverloadCounter <= 1) { CancelPendingLineNavigation(); + var firstDisplayedLine = RowToLine(dataGridView.FirstDisplayedScrollingRowIndex); + if (!_guiStateArgs.FollowTail && firstDisplayedLine >= 0) + { + _lineCountBeforeAutomaticReload = _visibleRows.Map.LineCount; + _reloadMemento = new ReloadMemento + { + CurrentLine = CurrentLineNum, + FirstDisplayedLine = firstDisplayedLine + }; + } + SavePersistenceData(false); _ = _loadingFinishedEvent.Reset(); _ = _externaLoadingFinishedEvent.Reset(); @@ -7742,6 +7766,8 @@ public void Reload () CancelPendingLineNavigation(); SavePersistenceData(false); + _lineCountBeforeAutomaticReload = null; + _reloadMemento = new ReloadMemento { CurrentLine = CurrentLineNum,