fix(ui): render Output log directly on the console, not as a nested card

The Output tab embedded SessionTerminalView, which is itself a bordered terminal
card with its own header — a card inside the console card. Render the log lines
directly on the console body instead (the console already provides the terminal
chrome, traffic lights, and status chip), with auto-scroll moved to code-behind.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-06-04 20:27:03 +02:00
parent b840655163
commit 71a3765c07
2 changed files with 55 additions and 11 deletions

View File

@@ -1,7 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
xmlns:islands="using:ClaudeDo.Ui.Views.Islands"
xmlns:loc="using:ClaudeDo.Ui.Localization"
x:DataType="vm:DetailsIslandViewModel"
x:Class="ClaudeDo.Ui.Views.Islands.Detail.WorkConsole">
@@ -139,15 +138,28 @@
<!-- ── Tab body ── -->
<Grid>
<!-- Output: embedded terminal, inset so it reads as its own card -->
<islands:SessionTerminalView
IsVisible="{Binding IsOutputTab}"
Margin="10,8,10,10"
Entries="{Binding Log}"
Label="{Binding SessionLabel}"
IsRunning="{Binding IsRunning}"
IsDone="{Binding IsDone}"
IsFailed="{Binding IsFailed}" />
<!-- Output: log rendered directly on the console body (no nested card) -->
<ScrollViewer Name="LogScroll"
IsVisible="{Binding IsOutputTab}"
VerticalScrollBarVisibility="Visible"
AllowAutoHide="False"
Padding="12,8,12,12">
<ItemsControl ItemsSource="{Binding Log}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:LogLineViewModel">
<Grid ColumnDefinitions="60,*" Margin="0,1">
<TextBlock Grid.Column="0"
Classes="log-ts"
Text="{Binding TimestampFormatted}" />
<SelectableTextBlock Grid.Column="1"
Text="{Binding Text}" Tag="{Binding ClassName}"
Foreground="{DynamicResource TextDimBrush}"
TextWrapping="Wrap" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!-- Session: review (top) + merge/worktree + outcomes — each gated on state -->
<ScrollViewer IsVisible="{Binding IsSessionTab}" Padding="14,10">

View File

@@ -1,8 +1,40 @@
using System;
using System.Collections.Specialized;
using Avalonia.Controls;
using ClaudeDo.Ui.ViewModels.Islands;
namespace ClaudeDo.Ui.Views.Islands.Detail;
public partial class WorkConsole : UserControl
{
public WorkConsole() => InitializeComponent();
private INotifyCollectionChanged? _log;
public WorkConsole()
{
InitializeComponent();
DataContextChanged += OnDataContextChanged;
}
private void OnDataContextChanged(object? sender, EventArgs e)
{
if (_log is not null)
_log.CollectionChanged -= OnLogChanged;
_log = (DataContext as DetailsIslandViewModel)?.Log;
if (_log is not null)
_log.CollectionChanged += OnLogChanged;
}
private void OnLogChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action != NotifyCollectionChangedAction.Add) return;
EventHandler? handler = null;
handler = (_, _) =>
{
LogScroll.LayoutUpdated -= handler;
LogScroll.ScrollToEnd();
};
LogScroll.LayoutUpdated += handler;
}
}