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:
@@ -101,6 +101,12 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
[ObservableProperty] private bool _isLetClaudeVisible;
|
||||
[ObservableProperty] private bool _isQuickClaudeVisible;
|
||||
|
||||
// Shared by QueuePlanningSubtasksAsync and FinalizePlanningSessionAsync — both are triggered
|
||||
// from a context menu that closes the instant a click lands, so there is no per-row surface
|
||||
// left standing to anchor an indicator to. The island header is the nearest surface still
|
||||
// visible after the menu closes.
|
||||
public OperationStatus PlanningOperation { get; } = new();
|
||||
|
||||
public event EventHandler? LetClaudeHandleRequested;
|
||||
|
||||
[RelayCommand]
|
||||
@@ -152,6 +158,15 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
Loc.LanguageChanged += _langChangedHandler;
|
||||
_reconcileTimer.Elapsed += (_, _) => Dispatcher.UIThread.Post(() => _ = ReconcileTickAsync());
|
||||
_reconcileTimer.Start();
|
||||
|
||||
// OperationStatus is a nested ObservableObject — [NotifyCanExecuteChangedFor] can't see
|
||||
// into it, so IsRunning changes are relayed by hand.
|
||||
PlanningOperation.PropertyChanged += (_, e) =>
|
||||
{
|
||||
if (e.PropertyName != nameof(OperationStatus.IsRunning)) return;
|
||||
QueuePlanningSubtasksCommand.NotifyCanExecuteChanged();
|
||||
FinalizePlanningSessionCommand.NotifyCanExecuteChanged();
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -1337,7 +1352,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
OpenPlanningConPtyRequested?.Invoke(row.Id, true);
|
||||
break;
|
||||
case UnfinishedPlanningModalResult.FinalizeNow:
|
||||
await _worker.FinalizePlanningSessionAsync(row.Id, queueAgentTasks: false);
|
||||
await FinalizePlanningSessionAsync(row);
|
||||
break;
|
||||
case UnfinishedPlanningModalResult.Discard:
|
||||
await TryDiscardPlanningWithRetryAsync(row.Id);
|
||||
@@ -1393,18 +1408,22 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
|
||||
/// </summary>
|
||||
public Func<string, Task<bool>>? ConfirmAsync { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
private bool CanRunPlanningOperation() => !PlanningOperation.IsRunning;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanRunPlanningOperation))]
|
||||
private async Task QueuePlanningSubtasksAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null || _worker is null) return;
|
||||
using var op = PlanningOperation.Begin(Loc.T("ops.planning.queuingSubtasks"));
|
||||
try { await _worker.QueuePlanningSubtasksAsync(row.Id); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
[RelayCommand(CanExecute = nameof(CanRunPlanningOperation))]
|
||||
private async Task FinalizePlanningSessionAsync(TaskRowViewModel? row)
|
||||
{
|
||||
if (row is null) return;
|
||||
using var op = PlanningOperation.Begin(Loc.T("ops.planning.finalizing"));
|
||||
try { await _worker!.FinalizePlanningSessionAsync(row.Id, queueAgentTasks: false); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user