From the 2026-08-11 unpushed-commit review (Low). Both in `src/ClaudeDo.Ui/Views/Islands/TaskRowView.axaml`. **Visual verification by the user is required — do not claim either is fixed without a screenshot; list both as open visual checks in the result.** ## A) Chain step badge is drawn under the task card Commit `eb66ae7` moved `Border.chain-step-badge` from column 0 into column 1 with `Margin ClaudeDo-Task: 9ec7d4ea-272b-4645-8da4-41ff3621f2f0
279 lines
14 KiB
XML
279 lines
14 KiB
XML
<UserControl xmlns="https://github.com/avaloniaui"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:vm="using:ClaudeDo.Ui.ViewModels.Islands"
|
|
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
|
|
xmlns:loc="using:ClaudeDo.Ui.Localization"
|
|
x:Class="ClaudeDo.Ui.Views.Islands.TaskRowView"
|
|
x:DataType="vm:TaskRowViewModel">
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Above-row indicator: dashed placeholder gap showing where the dragged row will land -->
|
|
<Grid Grid.Row="0" Height="52" IsVisible="{Binding DropHintAbove}">
|
|
<Rectangle Margin="4,3" Stroke="{DynamicResource MossBrush}" StrokeThickness="1.5"
|
|
StrokeDashArray="4,3" Fill="Transparent" RadiusX="8" RadiusY="8"/>
|
|
</Grid>
|
|
|
|
<!-- Indent wrapper: col 0 = 24px child/chain indent track, col 1 = content -->
|
|
<Grid Grid.Row="1" ColumnDefinitions="Auto,*">
|
|
|
|
<!-- Indent track (only while the parent/chain-head shares this view; orphaned rows render flat).
|
|
Auto + Width: collapses to 0 on rows with no chain/child relation, so those stay flat. -->
|
|
<Border Grid.Column="0" Width="24" VerticalAlignment="Stretch">
|
|
<Border.IsVisible>
|
|
<MultiBinding Converter="{x:Static BoolConverters.Or}">
|
|
<Binding Path="ShowAsChild"/>
|
|
<Binding Path="ShowAsChainMember"/>
|
|
</MultiBinding>
|
|
</Border.IsVisible>
|
|
<Rectangle Width="1" Fill="{DynamicResource LineBrush}"
|
|
HorizontalAlignment="Right" Margin="0,4"/>
|
|
</Border>
|
|
|
|
<!-- Main task card -->
|
|
<Border Grid.Column="1" Classes="task-row"
|
|
Margin="0,2"
|
|
Classes.selected="{Binding IsSelected}"
|
|
Classes.dragging="{Binding IsDragging}"
|
|
Classes.drop-target="{Binding IsDropTarget}"
|
|
Classes.done="{Binding Done}"
|
|
ContextRequested="OnRowContextRequested">
|
|
<Grid ColumnDefinitions="0,18,32,*,Auto,Auto,32" Margin="6,8,10,8">
|
|
|
|
<!-- Chevron toggle (only for planning parent tasks) -->
|
|
<Button Grid.Column="1"
|
|
IsVisible="{Binding IsPlanningParent}"
|
|
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).ToggleExpandCommand}"
|
|
CommandParameter="{Binding}"
|
|
Classes="icon-btn"
|
|
Width="18" Height="18"
|
|
VerticalAlignment="Center"
|
|
ToolTip.Tip="{loc:Tr tasks.toggleSubtasksTip}">
|
|
<Panel>
|
|
<PathIcon Width="12" Height="12" Data="{StaticResource Icon.ChevronDown}"
|
|
Foreground="{DynamicResource TextDimBrush}" IsVisible="{Binding IsExpanded}"/>
|
|
<PathIcon Width="12" Height="12" Data="{StaticResource Icon.ChevronRight}"
|
|
Foreground="{DynamicResource TextDimBrush}" IsVisible="{Binding !IsExpanded}"/>
|
|
</Panel>
|
|
</Button>
|
|
|
|
<!-- Done toggle -->
|
|
<Button Grid.Column="2" Classes="flat" VerticalAlignment="Top"
|
|
Margin="0,2,0,0"
|
|
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).ToggleDoneCommand}"
|
|
CommandParameter="{Binding}">
|
|
<Ellipse Width="18" Height="18" Classes="task-check"
|
|
Classes.done="{Binding Done}"/>
|
|
</Button>
|
|
|
|
<!-- Title + chip row + live tail -->
|
|
<StackPanel Grid.Column="3" Spacing="6" VerticalAlignment="Center">
|
|
<Grid ColumnDefinitions="*,Auto" VerticalAlignment="Center">
|
|
<Grid Grid.Column="0" ColumnDefinitions="Auto,*" VerticalAlignment="Center">
|
|
<TextBlock Grid.Column="0" Classes="meta" Text="{Binding Number, StringFormat='#{0}'}"
|
|
IsVisible="{Binding ShowNumberBadge}"
|
|
VerticalAlignment="Center" Margin="0,0,6,0"/>
|
|
<TextBlock Grid.Column="1"
|
|
Classes="task-title"
|
|
Text="{Binding Title}" FontSize="{StaticResource FontSizeTaskTitle}"
|
|
Foreground="{DynamicResource TextBrush}"
|
|
TextWrapping="Wrap"
|
|
FontStyle="{Binding IsDraft, Converter={StaticResource BoolToItalic}}"
|
|
Opacity="{Binding IsDraft, Converter={StaticResource BoolToDraftOpacity}}"
|
|
TextDecorations="{Binding Done, Converter={StaticResource StrikeIfTrue}}"/>
|
|
</Grid>
|
|
|
|
<!-- Badges: DRAFT and planning session -->
|
|
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="4"
|
|
VerticalAlignment="Center" Margin="4,0,0,0">
|
|
<Border Classes="badge draft" IsVisible="{Binding IsDraft}">
|
|
<TextBlock Text="{loc:Tr tasks.badgeDraft}"/>
|
|
</Border>
|
|
<Border Classes="badge planned" IsVisible="{Binding IsPlanned}">
|
|
<TextBlock Text="{loc:Tr tasks.badgePlanned}"/>
|
|
</Border>
|
|
<Border Classes="badge"
|
|
Classes.planning="{Binding IsPlanActive}"
|
|
Classes.planned="{Binding IsPlanFinalized}"
|
|
IsVisible="{Binding IsPlanningParent}">
|
|
<TextBlock Text="{Binding PlanningBadge}"/>
|
|
</Border>
|
|
<Border Classes="badge manual" IsVisible="{Binding IsManual}"
|
|
ToolTip.Tip="{loc:Tr tasks.manualTip}">
|
|
<TextBlock Text="{Binding ManualBadge}"/>
|
|
</Border>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- Chip row -->
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
|
|
<!-- Roadblock badge -->
|
|
<PathIcon Width="13" Height="13" VerticalAlignment="Center"
|
|
Data="{StaticResource Icon.Warning}"
|
|
Foreground="#E0A800"
|
|
IsVisible="{Binding HasRoadblock}"
|
|
ToolTip.Tip="{Binding RoadblockTooltip}"/>
|
|
|
|
<!-- Agent-suggested badge -->
|
|
<PathIcon Width="10" Height="10" VerticalAlignment="Center"
|
|
Data="{StaticResource Icon.AgentSuggested}"
|
|
Foreground="#5C8FA8"
|
|
IsVisible="{Binding IsAgentSuggested}"
|
|
ToolTip.Tip="{loc:Tr tasks.agentSuggestedTip}"/>
|
|
|
|
<!-- Status chip. When a ConPTY session is open it reads "Interactive" and is tappable —
|
|
it jumps to that pane in Mission Control. -->
|
|
<Border Classes="chip"
|
|
IsVisible="{Binding ShowStatusChip}"
|
|
Tapped="OnStatusChipTapped"
|
|
ToolTip.Tip="{Binding StatusChipTooltip}"
|
|
Classes.interactive="{Binding HasInteractiveSession}"
|
|
Classes.parked="{Binding IsParked}"
|
|
Classes.running="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=Running}"
|
|
Classes.review="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=WaitingForReview}"
|
|
Classes.children="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=WaitingForChildren}"
|
|
Classes.done="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=Done}"
|
|
Classes.error="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=Failed}"
|
|
Classes.queued="{Binding Status, Converter={StaticResource EqStatus}, ConverterParameter=Queued}">
|
|
<TextBlock Text="{Binding StatusLabel}"/>
|
|
</Border>
|
|
|
|
<!-- Dequeue button (visible when row is Queued, or planning parent has queued subtasks) -->
|
|
<Button Classes="icon-btn dequeue-btn"
|
|
IsVisible="{Binding CanRemoveFromQueue}"
|
|
ToolTip.Tip="{loc:Tr tasks.removeFromQueueTip}"
|
|
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).RemoveFromQueueCommand}"
|
|
CommandParameter="{Binding}">
|
|
<PathIcon Width="10" Height="10" Data="{StaticResource Icon.X}"/>
|
|
</Button>
|
|
|
|
<!-- List chip with dot -->
|
|
<Border Classes="chip chip-list" IsVisible="{Binding ShowListChip}">
|
|
<StackPanel Orientation="Horizontal" Spacing="5" VerticalAlignment="Center">
|
|
<Ellipse Width="6" Height="6"
|
|
Fill="{DynamicResource MossBrush}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock Text="{Binding ListName}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Branch chip -->
|
|
<Border Classes="chip chip-branch" IsVisible="{Binding HasBranch}">
|
|
<StackPanel Orientation="Horizontal" Spacing="4" VerticalAlignment="Center">
|
|
<PathIcon Width="10" Height="10"
|
|
Data="{StaticResource Icon.GitBranch}"
|
|
Foreground="{DynamicResource TextDimBrush}"/>
|
|
<TextBlock Text="{Binding Branch}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Diff chip -->
|
|
<Border Classes="chip chip-diff" IsVisible="{Binding HasDiff}">
|
|
<StackPanel Orientation="Horizontal" Spacing="4" VerticalAlignment="Center">
|
|
<TextBlock Classes="diff-add" Text="{Binding DiffAdditionsText}"/>
|
|
<TextBlock Classes="diff-del" Text="{Binding DiffDeletionsText}"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Chain-after chip: the head-relative fallback when this row isn't rendered as a
|
|
rail member (planning child, or the head is filtered out of this view). -->
|
|
<Border Classes="chip chip-tag"
|
|
IsVisible="{Binding ChainAfterLabel, Converter={StaticResource NotNullToBool}}">
|
|
<TextBlock>
|
|
<Run Text="{loc:Tr tasks.chainAfterPrefix}"/>
|
|
<Run Text=" "/>
|
|
<Run Text="{Binding ChainAfterLabel}"/>
|
|
</TextBlock>
|
|
</Border>
|
|
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
<!-- Refine button, replaced by a spinner while the refine run is in flight -->
|
|
<Panel Grid.Column="5">
|
|
<Button Classes="icon-btn refine-btn"
|
|
IsVisible="{Binding CanRefine}"
|
|
VerticalAlignment="Top" Margin="0,2,0,0"
|
|
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).RefineTaskCommand}"
|
|
CommandParameter="{Binding}"
|
|
ToolTip.Tip="{loc:Tr tasks.refineTip}">
|
|
<Viewbox Width="16" Height="16">
|
|
<Path Classes="plan-icon" Data="{StaticResource Icon.Refine}"/>
|
|
</Viewbox>
|
|
</Button>
|
|
<Ellipse Classes="spinner"
|
|
IsVisible="{Binding IsRefining}"
|
|
VerticalAlignment="Top" Margin="0,4,2,0"
|
|
ToolTip.Tip="{loc:Tr tasks.refiningTip}"/>
|
|
</Panel>
|
|
|
|
<!-- Star toggle -->
|
|
<Button Grid.Column="6" Classes="icon-btn star-btn"
|
|
Classes.on="{Binding IsStarred}"
|
|
VerticalAlignment="Top" Margin="0,2,0,0"
|
|
Command="{Binding $parent[ItemsControl].((vm:TasksIslandViewModel)DataContext).ToggleStarCommand}"
|
|
CommandParameter="{Binding}"
|
|
ToolTip.Tip="{loc:Tr details.starTip}">
|
|
<PathIcon Width="14" Height="14" Data="{StaticResource Icon.Star}"/>
|
|
</Button>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Chain step badge: centered on the rail line, half laid over the card's left edge.
|
|
Lives in col 1 with a negative margin so it never widens the Auto indent column.
|
|
Declared after the card so it paints on top instead of underneath it. -->
|
|
<Border Grid.Column="1" Classes="chain-step-badge"
|
|
IsVisible="{Binding ShowAsChainMember}"
|
|
HorizontalAlignment="Left" VerticalAlignment="Center"
|
|
Margin="-8,0,0,0">
|
|
<TextBlock Text="{Binding ChainStep}"/>
|
|
</Border>
|
|
|
|
</Grid>
|
|
|
|
<!-- Below-row indicator: only expands when visible (used for the last row of a section) -->
|
|
<Grid Grid.Row="2" Height="52" IsVisible="{Binding DropHintBelow}">
|
|
<Rectangle Margin="4,3" Stroke="{DynamicResource MossBrush}" StrokeThickness="1.5"
|
|
StrokeDashArray="4,3" Fill="Transparent" RadiusX="8" RadiusY="8"/>
|
|
</Grid>
|
|
|
|
<!-- Hidden schedule anchor (its Flyout is shown from the context menu) -->
|
|
<Button Grid.Row="1" x:Name="ScheduleAnchor"
|
|
Width="1" Height="1" Opacity="0"
|
|
HorizontalAlignment="Left" VerticalAlignment="Top"
|
|
IsHitTestVisible="False" Focusable="False">
|
|
<Button.Flyout>
|
|
<Flyout Placement="Bottom" ShowMode="Standard">
|
|
<Border Background="{DynamicResource Surface2Brush}"
|
|
BorderBrush="{DynamicResource LineBrush}"
|
|
BorderThickness="1" CornerRadius="10"
|
|
Padding="16" Width="300">
|
|
<StackPanel Spacing="12">
|
|
<TextBlock Classes="title" Text="{loc:Tr tasks.scheduleTitle}"/>
|
|
|
|
<StackPanel Spacing="6">
|
|
<TextBlock Classes="eyebrow" Text="{loc:Tr tasks.scheduleWhen}"
|
|
Foreground="{DynamicResource TextDimBrush}" Opacity="0.6"/>
|
|
<ctl:ThemedDatePicker x:Name="ScheduleDate" ShowTime="True"
|
|
HorizontalAlignment="Stretch"/>
|
|
</StackPanel>
|
|
|
|
<StackPanel Orientation="Horizontal" Spacing="8"
|
|
HorizontalAlignment="Right" Margin="0,4,0,0">
|
|
<Button Classes="btn" Content="{loc:Tr tasks.cancel}" Click="OnScheduleCancelClick" MinWidth="76"/>
|
|
<Button Content="{loc:Tr tasks.scheduleConfirm}" Classes="accent" Click="OnScheduleSetClick" MinWidth="76"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
</Flyout>
|
|
</Button.Flyout>
|
|
</Button>
|
|
|
|
</Grid>
|
|
</UserControl>
|