From ac9bae95465346a68a9623a36e8459586dc25638 Mon Sep 17 00:00:00 2001 From: mika kuns Date: Thu, 4 Jun 2026 20:18:36 +0200 Subject: [PATCH] =?UTF-8?q?feat(ui):=20rework=20work=20console=20=E2=80=94?= =?UTF-8?q?=20single=20Session=20tab,=20right-aligned=20header,=20turns=20?= =?UTF-8?q?x/y?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Merge "Actions" + "Session" into one state-aware Session tab: review controls on top, then merge/worktree management, then child outcomes — each gated on the current state, with an empty-state hint when there's nothing to manage. This is the home the real merge/diff work (task 09eb5d52) will slot into. - Move the model · turns · diff info block to the right of the title bar. - Show turns as current/max using the resolved turn budget (task → list → global). - Output terminal now fills the console body cleanly: clip the console to its rounded corners and inset the embedded terminal instead of clipping its bottom. Co-Authored-By: Claude Opus 4.7 --- .../Islands/DetailsIslandViewModel.cs | 40 +++- .../Views/Islands/Detail/WorkConsole.axaml | 180 +++++++++--------- .../Views/Islands/SessionTerminalView.axaml | 2 +- 3 files changed, 130 insertions(+), 92 deletions(-) diff --git a/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs b/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs index c73429d..babbc2d 100644 --- a/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs +++ b/src/ClaudeDo.Ui/ViewModels/Islands/DetailsIslandViewModel.cs @@ -133,23 +133,42 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase EditableTitle, EditableDescription, Subtasks.Select(s => (s.Title, s.Done))); // ── Work console (redesign) ──────────────────────────────────────── + // Two tabs: Output (live log) and Session (review + merge/worktree + + // outcomes, each section gated on the relevant state). [ObservableProperty] [NotifyPropertyChangedFor(nameof(IsOutputTab))] - [NotifyPropertyChangedFor(nameof(IsActionsTab))] [NotifyPropertyChangedFor(nameof(IsSessionTab))] private string _selectedTab = "output"; public bool IsOutputTab => SelectedTab == "output"; - public bool IsActionsTab => SelectedTab == "actions"; public bool IsSessionTab => SelectedTab == "session"; [RelayCommand] private void SelectTab(string? tab) => SelectedTab = tab ?? "output"; - public string TurnsText => $"{Turns} turns"; + // Merge/worktree controls only matter once there's a worktree to manage + // (standalone task), or a planning parent / improvement parent with children. + public bool ShowMergeSection => + WorktreePath != null || Task?.IsPlanningParent == true || HasChildOutcomes; + + // Nothing to manage yet (idle/queued/running standalone): show a hint. + public bool ShowSessionEmpty => + !IsWaitingForReview && !ShowMergeSection && !HasChildOutcomes; + + private void NotifySessionSections() + { + OnPropertyChanged(nameof(ShowMergeSection)); + OnPropertyChanged(nameof(ShowSessionEmpty)); + } + + public string TurnsText => $"{Turns}/{EffectiveMaxTurns}"; public string DiffAddText => $"+{DiffAdditions}"; public string DiffDelText => $"-{DiffDeletions}"; + // Resolved turn budget: per-task override → list default → global default. + public int EffectiveMaxTurns => + TaskMaxTurns is decimal t ? (int)t : (_listMaxTurns ?? _globalMaxTurns); + public bool ShowRoadblock => IsFailed || IsCancelled; public string RoadblockMessage => IsFailed ? "The session ended with an error." : @@ -201,6 +220,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase OnPropertyChanged(nameof(IsAgentSectionEnabled)); OnPropertyChanged(nameof(ShowRoadblock)); OnPropertyChanged(nameof(RoadblockMessage)); + NotifySessionSections(); } [ObservableProperty] private string? _model; @@ -223,7 +243,13 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase private string? _listAgentName; partial void OnTaskModelSelectionChanged(string? value) { RecomputeModelBadge(); QueueAgentSave(); } - partial void OnTaskMaxTurnsChanged(decimal? value) { RecomputeTurnsBadge(); QueueAgentSave(); } + partial void OnTaskMaxTurnsChanged(decimal? value) + { + RecomputeTurnsBadge(); + OnPropertyChanged(nameof(EffectiveMaxTurns)); + OnPropertyChanged(nameof(TurnsText)); + QueueAgentSave(); + } private void RecomputeModelBadge() { @@ -460,6 +486,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase { RecomputeCanMergeAll(); ReviewCombinedDiffCommand.NotifyCanExecuteChanged(); + NotifySessionSections(); }; PrepLog.CollectionChanged += (_, _) => OnPropertyChanged(nameof(ShowPrepEmptyState)); @@ -637,6 +664,8 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase RecomputeModelBadge(); RecomputeTurnsBadge(); RecomputeAgentBadge(); + OnPropertyChanged(nameof(EffectiveMaxTurns)); + OnPropertyChanged(nameof(TurnsText)); } finally { @@ -1113,8 +1142,11 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase { OpenDiffCommand.NotifyCanExecuteChanged(); OpenWorktreeCommand.NotifyCanExecuteChanged(); + NotifySessionSections(); } + partial void OnTaskChanged(TaskRowViewModel? value) => NotifySessionSections(); + [RelayCommand] private void CloseDetails() => CloseDetail?.Invoke(); diff --git a/src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml b/src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml index 27daaaa..6e25b8c 100644 --- a/src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml +++ b/src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml @@ -26,8 +26,9 @@ - - + + @@ -42,47 +43,50 @@ - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -124,11 +128,6 @@ Content="Output" Command="{Binding SelectTabCommand}" CommandParameter="output" /> - - +