feat(ui): add reconcile tick to self-heal lost worker broadcasts

TasksIslandViewModel now runs a periodic tick that diffs the flat Items
collection against SQLite and patches properties in place (capped at 500
rows, sharing the Phase 1 delta sequence guard so it never overtakes a
fresher broadcast). Never rebuilds rows or triggers Regroup/LoadForList, so
it stays decoupled from the parallel Phase 2b virtualization work. The same
cadence now refreshes the long-lived Worktrees Overview, Log Visualizer, and
Merge Helper selection overlays; short-lived modals are untouched.
This commit is contained in:
mika kuns
2026-08-10 15:56:05 +02:00
parent 514d6111fe
commit 1cad264967
7 changed files with 381 additions and 4 deletions
@@ -41,8 +41,16 @@ public sealed partial class LogVisualizerViewModel : ViewModelBase
_worker = worker;
_copyToClipboard = copyToClipboard;
Rows.CollectionChanged += (_, _) => CopyLastCommand.NotifyCanExecuteChanged();
// Phase 3 reconcile tick: this overlay is long-lived (stays open while the user reads
// through the log), so refresh it on the same cadence as TasksIslandViewModel's tick
// instead of leaving it frozen at the moment it was opened.
_reconcileTimer.Elapsed += (_, _) =>
Avalonia.Threading.Dispatcher.UIThread.Post(() => _ = RefreshAsync());
_reconcileTimer.Start();
}
private readonly System.Timers.Timer _reconcileTimer = new(4_000);
[RelayCommand]
public async Task RefreshAsync()
{
@@ -65,7 +73,13 @@ public sealed partial class LogVisualizerViewModel : ViewModelBase
: Loc.T("modals.logVisualizer.count", Rows.Count);
}
[RelayCommand] private void Close() => CloseAction?.Invoke();
[RelayCommand]
private void Close()
{
_reconcileTimer.Stop();
_reconcileTimer.Dispose();
CloseAction?.Invoke();
}
private bool CanCopyLast() => Rows.Count > 0;