Files
ClaudeDo/src/ClaudeDo.Ui/Views/Controls/OperationIndicator.axaml.cs
T
mika kuns 589b9e75f3 fix(ui): unfreeze the operation spinner and attribute rebind churn
Three causes behind the stuck indicator:
- OperationStatus.End did not retire the generation, so tick work posted
  while the dispatcher was blocked drained afterwards and set
  ShowIndicator back to true on a finished operation.
- The startup update check ran in Task.Run; OperationStatus writes its
  observable properties on the calling thread, so the final
  ShowIndicator=false never reached the binding.
- OperationIndicator overwrote its own DataContext from the Status
  property, which re-targeted the call-site binding. It now scopes the
  DataContext to an inner panel and collapses itself when Status is
  null; every call site switched from DataContext= to Status=.

Also gates the footer connection pill in the command body instead of
CanExecute (a disabled command greyed out the ONLINE chip), and extends
OperationTiming: pid per line, 4 MB rollover, fast successes dropped
(failures always kept), and DetailsIsland.BindAsync now carries the
selection trigger via TasksIslandViewModel.SelectFrom.
2026-08-12 13:50:05 +02:00

36 lines
1.3 KiB
C#

using Avalonia;
using Avalonia.Controls;
using ClaudeDo.Ui.Services;
namespace ClaudeDo.Ui.Views.Controls;
public partial class OperationIndicator : UserControl
{
public static readonly StyledProperty<OperationStatus?> StatusProperty =
AvaloniaProperty.Register<OperationIndicator, OperationStatus?>(nameof(Status));
public OperationStatus? Status
{
get => GetValue(StatusProperty);
set => SetValue(StatusProperty, value);
}
public OperationIndicator()
{
InitializeComponent();
IsVisible = false;
}
/// A null `Status` leaves the inner panel's DataContext null, so its `IsVisible="{Binding
/// ShowIndicator}"` can't resolve and falls back to the property default — *visible*. That
/// renders a label-less spinner plus the stalled hint forever. Collapse the whole control
/// instead. Deliberately a direct set, not a binding: no call site binds `IsVisible` on the
/// indicator, and a local value would win over one anyway.
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == StatusProperty)
IsVisible = change.GetNewValue<OperationStatus?>() is not null;
}
}