feat(claude-do): [A4] WeeklyReport, DailyPrep und Planning-Aktionen auf OperationStatus umstellen
WeeklyReportModalViewModel.Generate, PrepPanelViewModel.PlanDayAsync und die beiden Planning-Aktionen (QueuePlanningSubtasksAsync, FinalizePlanningSessionAsync) laufen jetzt durch je eine OperationStatus + OperationIndicator statt handgebauter Spinner. Die beiden Planning-Aktionen teilen sich eine Instanz, angezeigt im Tasks-Island-Header, weil sie aus einem sofort schliessenden Kontextmenue ausgeloest werden und es keine dauerhafte Pro-Zeilen-Flaeche gibt, an die ein Indikator gehaengt werden koennte.
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Text;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using ClaudeDo.Ui.Helpers;
|
||||
using ClaudeDo.Ui.Localization;
|
||||
using ClaudeDo.Ui.Services;
|
||||
|
||||
namespace ClaudeDo.Ui.ViewModels.Islands;
|
||||
@@ -19,11 +20,23 @@ public sealed partial class PrepPanelViewModel : ViewModelBase, IDisposable
|
||||
|
||||
[ObservableProperty] private bool _isPrepRunning;
|
||||
|
||||
// Covers the gap between the click and the worker's PrepStartedEvent broadcast — IsPrepRunning
|
||||
// stays false until that event arrives, so without this the button click looks like a no-op.
|
||||
public OperationStatus PrepOperation { get; } = new();
|
||||
|
||||
public ObservableCollection<LogLineViewModel> PrepLog { get; } = new();
|
||||
|
||||
public bool ShowPrepEmptyState => !IsPrepRunning && PrepLog.Count == 0;
|
||||
|
||||
partial void OnIsPrepRunningChanged(bool value) => OnPropertyChanged(nameof(ShowPrepEmptyState));
|
||||
// The long-running broadcast-driven state (IsPrepRunning) and the click-to-event gap
|
||||
// (PrepOperation.IsRunning) both need to block a second click.
|
||||
public bool IsPlanDayEnabled => !IsPrepRunning && !PrepOperation.IsRunning;
|
||||
|
||||
partial void OnIsPrepRunningChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowPrepEmptyState));
|
||||
OnPropertyChanged(nameof(IsPlanDayEnabled));
|
||||
}
|
||||
|
||||
public PrepPanelViewModel(IWorkerClient worker)
|
||||
{
|
||||
@@ -37,6 +50,15 @@ public sealed partial class PrepPanelViewModel : ViewModelBase, IDisposable
|
||||
_worker.PrepFinishedEvent += _onPrepFinishedHandler;
|
||||
|
||||
PrepLog.CollectionChanged += (_, _) => OnPropertyChanged(nameof(ShowPrepEmptyState));
|
||||
|
||||
// OperationStatus is a nested ObservableObject — [NotifyCanExecuteChangedFor] can't see
|
||||
// into it, so IsRunning changes are relayed by hand.
|
||||
PrepOperation.PropertyChanged += (_, e) =>
|
||||
{
|
||||
if (e.PropertyName != nameof(OperationStatus.IsRunning)) return;
|
||||
PlanDayCommand.NotifyCanExecuteChanged();
|
||||
OnPropertyChanged(nameof(IsPlanDayEnabled));
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -46,9 +68,12 @@ public sealed partial class PrepPanelViewModel : ViewModelBase, IDisposable
|
||||
_worker.PrepFinishedEvent -= _onPrepFinishedHandler;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private bool CanPlanDay() => IsPlanDayEnabled;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanPlanDay))]
|
||||
private async System.Threading.Tasks.Task PlanDayAsync()
|
||||
{
|
||||
using var op = PrepOperation.Begin(Loc.T("ops.reports.runningDailyPrep"));
|
||||
try { await _worker.RunDailyPrepNowAsync(); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user