feat(ui): add WorkConsole detail component
Standalone terminal-styled card with traffic-light title bar, roadblock band, and three tabs (Output / Actions / Session). Renders fully via design-time sample data; does not touch DetailsIslandView. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,145 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using ClaudeDo.Ui.ViewModels.Islands;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Ui.ViewModels.Islands.Detail;
|
||||||
|
|
||||||
|
public sealed class WorkConsoleChildOutcomeRowViewModel
|
||||||
|
{
|
||||||
|
public required string Title { get; init; }
|
||||||
|
public bool HasRoadblock { get; init; }
|
||||||
|
public string RoadblockText { get; init; } = "";
|
||||||
|
public required string StatusLabel { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed partial class WorkConsoleViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
// ── Tab selection ──────────────────────────────────────────────
|
||||||
|
[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;
|
||||||
|
|
||||||
|
// ── Info header ────────────────────────────────────────────────
|
||||||
|
[ObservableProperty] private string _model = "";
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(TurnsText))]
|
||||||
|
private int _turns;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(DiffAddText))]
|
||||||
|
private int _diffAdditions;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(DiffDelText))]
|
||||||
|
private int _diffDeletions;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||||
|
private bool _isRunning;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||||
|
private bool _isDone;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||||
|
private bool _isFailed;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
[NotifyPropertyChangedFor(nameof(ShowRoadblock))]
|
||||||
|
private bool _isCancelled;
|
||||||
|
|
||||||
|
[ObservableProperty] private string _sessionLabel = "";
|
||||||
|
|
||||||
|
public string TurnsText => $"{Turns} turns";
|
||||||
|
public string DiffAddText => $"+{DiffAdditions}";
|
||||||
|
public string DiffDelText => $"-{DiffDeletions}";
|
||||||
|
|
||||||
|
// ── Roadblock ──────────────────────────────────────────────────
|
||||||
|
public bool ShowRoadblock => IsFailed || IsCancelled;
|
||||||
|
|
||||||
|
[ObservableProperty] private string _roadblockMessage = "";
|
||||||
|
[ObservableProperty] private bool _showContinue;
|
||||||
|
[ObservableProperty] private bool _showResetAndRetry;
|
||||||
|
|
||||||
|
[RelayCommand] private void Continue() { }
|
||||||
|
[RelayCommand] private void ResetAndRetry() { }
|
||||||
|
|
||||||
|
// ── Actions tab ────────────────────────────────────────────────
|
||||||
|
public ObservableCollection<string> MergeTargetBranches { get; } = new();
|
||||||
|
|
||||||
|
[ObservableProperty] private string? _selectedMergeTarget;
|
||||||
|
[ObservableProperty] private bool _canMergeAll;
|
||||||
|
[ObservableProperty] private string _mergeAllDisabledReason = "";
|
||||||
|
[ObservableProperty] private string? _mergeAllError;
|
||||||
|
|
||||||
|
[RelayCommand] private void OpenDiff() { }
|
||||||
|
[RelayCommand] private void OpenWorktree() { }
|
||||||
|
[RelayCommand] private void ReviewCombinedDiff() { }
|
||||||
|
[RelayCommand] private void MergeAll() { }
|
||||||
|
|
||||||
|
// ── Session tab ────────────────────────────────────────────────
|
||||||
|
[ObservableProperty] private bool _isWaitingForReview;
|
||||||
|
[ObservableProperty] private string _reviewFeedback = "";
|
||||||
|
|
||||||
|
public ObservableCollection<WorkConsoleChildOutcomeRowViewModel> ChildOutcomes { get; } = new();
|
||||||
|
public bool HasChildOutcomes => ChildOutcomes.Count > 0;
|
||||||
|
|
||||||
|
[RelayCommand] private void ApproveReview() { }
|
||||||
|
[RelayCommand] private void RejectReview() { }
|
||||||
|
[RelayCommand] private void ParkReview() { }
|
||||||
|
[RelayCommand] private void CancelReview() { }
|
||||||
|
|
||||||
|
public ObservableCollection<LogLineViewModel> Log { get; } = new();
|
||||||
|
|
||||||
|
public WorkConsoleViewModel()
|
||||||
|
{
|
||||||
|
ChildOutcomes.CollectionChanged += (_, _) => OnPropertyChanged(nameof(HasChildOutcomes));
|
||||||
|
|
||||||
|
// ── Design-time sample data ────────────────────────────────
|
||||||
|
_model = "sonnet";
|
||||||
|
_turns = 40;
|
||||||
|
_diffAdditions = 84;
|
||||||
|
_diffDeletions = 31;
|
||||||
|
_isRunning = true;
|
||||||
|
_sessionLabel = "feat/work-console";
|
||||||
|
|
||||||
|
MergeTargetBranches.Add("main");
|
||||||
|
MergeTargetBranches.Add("develop");
|
||||||
|
_selectedMergeTarget = "main";
|
||||||
|
_canMergeAll = true;
|
||||||
|
|
||||||
|
Log.Add(new LogLineViewModel { Kind = LogKind.Sys, Text = "Starting claude session…" });
|
||||||
|
Log.Add(new LogLineViewModel { Kind = LogKind.Claude, Text = "Reading DetailsIslandView.axaml to understand existing layout." });
|
||||||
|
Log.Add(new LogLineViewModel { Kind = LogKind.Tool, Text = "Read(src/ClaudeDo.Ui/Views/Islands/DetailsIslandView.axaml)" });
|
||||||
|
Log.Add(new LogLineViewModel { Kind = LogKind.Claude, Text = "Building WorkConsole component with three tabs." });
|
||||||
|
Log.Add(new LogLineViewModel { Kind = LogKind.Stdout, Text = "dotnet build succeeded — 0 error(s)" });
|
||||||
|
|
||||||
|
ChildOutcomes.Add(new WorkConsoleChildOutcomeRowViewModel
|
||||||
|
{
|
||||||
|
Title = "Add WorkConsole XAML",
|
||||||
|
StatusLabel = "Done"
|
||||||
|
});
|
||||||
|
ChildOutcomes.Add(new WorkConsoleChildOutcomeRowViewModel
|
||||||
|
{
|
||||||
|
Title = "Wire ViewModel bindings",
|
||||||
|
HasRoadblock = true,
|
||||||
|
RoadblockText = "Missing token",
|
||||||
|
StatusLabel = "Failed"
|
||||||
|
});
|
||||||
|
|
||||||
|
// To preview roadblock state: _isFailed = true; _roadblockMessage = "Session ended unexpectedly"; _showResetAndRetry = true; _isRunning = false;
|
||||||
|
// To preview review state: _isWaitingForReview = true; _isDone = false; _isRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
249
src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml
Normal file
249
src/ClaudeDo.Ui/Views/Islands/Detail/WorkConsole.axaml
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands.Detail"
|
||||||
|
xmlns:islands="using:ClaudeDo.Ui.Views.Islands"
|
||||||
|
xmlns:loc="using:ClaudeDo.Ui.Localization"
|
||||||
|
x:DataType="vm:WorkConsoleViewModel"
|
||||||
|
x:Class="ClaudeDo.Ui.Views.Islands.Detail.WorkConsole">
|
||||||
|
|
||||||
|
<Design.DataContext>
|
||||||
|
<vm:WorkConsoleViewModel />
|
||||||
|
</Design.DataContext>
|
||||||
|
|
||||||
|
<UserControl.Styles>
|
||||||
|
<Style Selector="Button.tab-btn">
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<Setter Property="BorderThickness" Value="0" />
|
||||||
|
<Setter Property="Padding" Value="12,8" />
|
||||||
|
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||||
|
<Setter Property="FontSize" Value="{StaticResource FontSizeMono}" />
|
||||||
|
<Setter Property="Foreground" Value="{StaticResource TextMuteBrush}" />
|
||||||
|
<Setter Property="CornerRadius" Value="0" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Button.tab-btn:pointerover /template/ ContentPresenter">
|
||||||
|
<Setter Property="Background" Value="{StaticResource Surface2Brush}" />
|
||||||
|
<Setter Property="TextElement.Foreground" Value="{StaticResource TextDimBrush}" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="Button.tab-btn.active /template/ ContentPresenter">
|
||||||
|
<Setter Property="Background" Value="{StaticResource Surface3Brush}" />
|
||||||
|
<Setter Property="TextElement.Foreground" Value="{StaticResource AccentBrush}" />
|
||||||
|
</Style>
|
||||||
|
</UserControl.Styles>
|
||||||
|
|
||||||
|
<!-- Outer terminal card — Padding="0" so header/strip span edge-to-edge -->
|
||||||
|
<Border Classes="terminal" Padding="0">
|
||||||
|
<DockPanel LastChildFill="True">
|
||||||
|
|
||||||
|
<!-- ── Title bar ── -->
|
||||||
|
<Grid DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto"
|
||||||
|
Background="{DynamicResource Surface2Brush}" Height="28">
|
||||||
|
|
||||||
|
<!-- Traffic-light dots -->
|
||||||
|
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="6"
|
||||||
|
Margin="12,0" VerticalAlignment="Center">
|
||||||
|
<Ellipse Classes="dot-red" />
|
||||||
|
<Ellipse Classes="dot-yellow" />
|
||||||
|
<Ellipse Classes="dot-green" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Info header: model · turns · +add -del -->
|
||||||
|
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
|
<TextBlock Classes="meta" Text="{Binding Model}"
|
||||||
|
Foreground="{DynamicResource TextMuteBrush}" />
|
||||||
|
<TextBlock Classes="meta" Text="·"
|
||||||
|
Foreground="{DynamicResource TextFaintBrush}" />
|
||||||
|
<TextBlock Classes="meta" Text="{Binding TurnsText}"
|
||||||
|
Foreground="{DynamicResource TextMuteBrush}" />
|
||||||
|
<TextBlock Classes="meta" Text="·"
|
||||||
|
Foreground="{DynamicResource TextFaintBrush}" />
|
||||||
|
<TextBlock Classes="diff-add" Text="{Binding DiffAddText}" />
|
||||||
|
<TextBlock Classes="diff-del" Text="{Binding DiffDelText}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Status chips (LIVE / DONE / FAILED) -->
|
||||||
|
<Panel Grid.Column="2" Margin="0,0,8,0" VerticalAlignment="Center">
|
||||||
|
<Border Classes="live-chip pulsing"
|
||||||
|
IsVisible="{Binding IsRunning}">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="5" VerticalAlignment="Center">
|
||||||
|
<Ellipse VerticalAlignment="Center" />
|
||||||
|
<TextBlock Text="{loc:Tr session.chipLive}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
<Border Classes="live-chip done"
|
||||||
|
IsVisible="{Binding IsDone}">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="5" VerticalAlignment="Center">
|
||||||
|
<Ellipse VerticalAlignment="Center" Fill="{DynamicResource MossBrush}" />
|
||||||
|
<TextBlock Text="{loc:Tr session.chipDone}" VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource MossBrush}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
<Border Classes="live-chip failed"
|
||||||
|
IsVisible="{Binding IsFailed}">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="5" VerticalAlignment="Center">
|
||||||
|
<Ellipse VerticalAlignment="Center" Fill="{DynamicResource BloodBrush}" />
|
||||||
|
<TextBlock Text="{loc:Tr session.chipFailed}" VerticalAlignment="Center"
|
||||||
|
Foreground="{DynamicResource BloodBrush}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- ── Roadblock band ── -->
|
||||||
|
<Border DockPanel.Dock="Top"
|
||||||
|
IsVisible="{Binding ShowRoadblock}"
|
||||||
|
Background="{DynamicResource ErrorTintBrush}"
|
||||||
|
BorderBrush="{DynamicResource BloodBrush}"
|
||||||
|
BorderThickness="0,1"
|
||||||
|
Padding="14,8">
|
||||||
|
<StackPanel Spacing="6">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<PathIcon Data="{StaticResource Icon.Warning}"
|
||||||
|
Foreground="{DynamicResource BloodBrush}"
|
||||||
|
Width="14" Height="14" VerticalAlignment="Center" />
|
||||||
|
<TextBlock Classes="meta" Text="{Binding RoadblockMessage}"
|
||||||
|
Foreground="{DynamicResource BloodBrush}"
|
||||||
|
TextWrapping="Wrap" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<Button Classes="btn accent" Content="Continue"
|
||||||
|
Command="{Binding ContinueCommand}"
|
||||||
|
IsVisible="{Binding ShowContinue}" />
|
||||||
|
<Button Classes="btn" Content="Reset & Retry"
|
||||||
|
Command="{Binding ResetAndRetryCommand}"
|
||||||
|
IsVisible="{Binding ShowResetAndRetry}" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- ── Tab strip ── -->
|
||||||
|
<Border DockPanel.Dock="Top"
|
||||||
|
Background="{DynamicResource Surface2Brush}"
|
||||||
|
BorderBrush="{DynamicResource LineBrush}"
|
||||||
|
BorderThickness="0,0,0,1">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Button Classes="tab-btn"
|
||||||
|
Classes.active="{Binding IsOutputTab}"
|
||||||
|
Content="Output"
|
||||||
|
Command="{Binding SelectTabCommand}"
|
||||||
|
CommandParameter="output" />
|
||||||
|
<Button Classes="tab-btn"
|
||||||
|
Classes.active="{Binding IsActionsTab}"
|
||||||
|
Content="Actions"
|
||||||
|
Command="{Binding SelectTabCommand}"
|
||||||
|
CommandParameter="actions" />
|
||||||
|
<Button Classes="tab-btn"
|
||||||
|
Classes.active="{Binding IsSessionTab}"
|
||||||
|
Content="Session"
|
||||||
|
Command="{Binding SelectTabCommand}"
|
||||||
|
CommandParameter="session" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- ── Tab body ── -->
|
||||||
|
<Grid>
|
||||||
|
|
||||||
|
<!-- Output: embedded SessionTerminalView -->
|
||||||
|
<islands:SessionTerminalView
|
||||||
|
IsVisible="{Binding IsOutputTab}"
|
||||||
|
Entries="{Binding Log}"
|
||||||
|
Label="{Binding SessionLabel}"
|
||||||
|
IsRunning="{Binding IsRunning}"
|
||||||
|
IsDone="{Binding IsDone}"
|
||||||
|
IsFailed="{Binding IsFailed}" />
|
||||||
|
|
||||||
|
<!-- Actions: merge-target + worktree controls -->
|
||||||
|
<ScrollViewer IsVisible="{Binding IsActionsTab}" Padding="14,10">
|
||||||
|
<StackPanel Spacing="10">
|
||||||
|
<StackPanel Spacing="4">
|
||||||
|
<TextBlock Classes="field-label" Text="Merge target" />
|
||||||
|
<ComboBox ItemsSource="{Binding MergeTargetBranches}"
|
||||||
|
SelectedItem="{Binding SelectedMergeTarget, Mode=TwoWay}"
|
||||||
|
HorizontalAlignment="Stretch" />
|
||||||
|
</StackPanel>
|
||||||
|
<WrapPanel Orientation="Horizontal">
|
||||||
|
<Button Classes="btn" Content="Open Diff" Margin="0,0,8,8"
|
||||||
|
Command="{Binding OpenDiffCommand}" />
|
||||||
|
<Button Classes="btn" Margin="0,0,8,8"
|
||||||
|
Command="{Binding OpenWorktreeCommand}">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||||
|
<TextBlock Text="Worktree" />
|
||||||
|
<PathIcon Data="{StaticResource Icon.ArrowOut}" Width="11" Height="11" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Classes="btn" Content="Review Combined Diff" Margin="0,0,8,8"
|
||||||
|
Command="{Binding ReviewCombinedDiffCommand}" />
|
||||||
|
<Button Classes="btn accent" Content="Merge All Subtasks" Margin="0,0,0,8"
|
||||||
|
Command="{Binding MergeAllCommand}"
|
||||||
|
IsEnabled="{Binding CanMergeAll}"
|
||||||
|
ToolTip.Tip="{Binding MergeAllDisabledReason}" />
|
||||||
|
</WrapPanel>
|
||||||
|
<TextBlock Text="{Binding MergeAllError}"
|
||||||
|
Foreground="{DynamicResource BloodBrush}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
IsVisible="{Binding MergeAllError,
|
||||||
|
Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<!-- Session: review block + child outcomes -->
|
||||||
|
<ScrollViewer IsVisible="{Binding IsSessionTab}" Padding="14,10">
|
||||||
|
<StackPanel Spacing="10">
|
||||||
|
|
||||||
|
<!-- Review block -->
|
||||||
|
<StackPanel Spacing="8" IsVisible="{Binding IsWaitingForReview}">
|
||||||
|
<TextBlock Classes="section-label" Text="REVIEW" Margin="0,0,0,2" />
|
||||||
|
<TextBlock Classes="field-label" Text="Feedback" />
|
||||||
|
<TextBox Text="{Binding ReviewFeedback, Mode=TwoWay}"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
MinHeight="60"
|
||||||
|
MaxHeight="180"
|
||||||
|
PlaceholderText="Optional feedback for the next run…"
|
||||||
|
Padding="8"
|
||||||
|
Background="{DynamicResource Surface2Brush}"
|
||||||
|
BorderBrush="{DynamicResource LineBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="8" />
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<Button Classes="btn accent" Content="Approve"
|
||||||
|
Command="{Binding ApproveReviewCommand}" />
|
||||||
|
<Button Classes="btn" Content="Reject"
|
||||||
|
Command="{Binding RejectReviewCommand}" />
|
||||||
|
<Button Classes="btn" Content="Park"
|
||||||
|
Command="{Binding ParkReviewCommand}" />
|
||||||
|
<Button Classes="btn" Content="Cancel"
|
||||||
|
Command="{Binding CancelReviewCommand}" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Child outcomes -->
|
||||||
|
<StackPanel Spacing="6" IsVisible="{Binding HasChildOutcomes}">
|
||||||
|
<TextBlock Classes="section-label" Text="OUTCOMES" Margin="0,0,0,2" />
|
||||||
|
<ItemsControl ItemsSource="{Binding ChildOutcomes}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="vm:WorkConsoleChildOutcomeRowViewModel">
|
||||||
|
<Grid ColumnDefinitions="*,Auto,Auto" Margin="0,2">
|
||||||
|
<TextBlock Grid.Column="0" Text="{Binding Title}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
<TextBlock Grid.Column="1" Text="{Binding RoadblockText}"
|
||||||
|
IsVisible="{Binding HasRoadblock}"
|
||||||
|
Foreground="#E0A030"
|
||||||
|
Margin="8,0" VerticalAlignment="Center" />
|
||||||
|
<TextBlock Grid.Column="2" Text="{Binding StatusLabel}"
|
||||||
|
Opacity="0.75" VerticalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</DockPanel>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace ClaudeDo.Ui.Views.Islands.Detail;
|
||||||
|
|
||||||
|
public partial class WorkConsole : UserControl
|
||||||
|
{
|
||||||
|
public WorkConsole() => InitializeComponent();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user