Files
ClaudeDo/src/ClaudeDo.Ui/Views/Islands/TasksIslandView.axaml
T
mika kuns 1ef677609f refactor(ui): Icon-Faerbung zentral im ICON-PAINTING-Block
Inline Foreground/Stroke an Icons entfernt — ein lokaler Wert schlaegt jeden
Style, dadurch erreichten Hover/Checked/Disabled das Icon nicht. Farbe wird
jetzt per Klasse gewaehlt (.danger, .star-btn.on, .active), alle Zustaende
liegen in einem geordneten Block in IslandStyles.axaml.

- Path.plan-icon -> Path.icon-stroke (gilt jetzt fuer Button und ToggleButton)
- Icon.Activity als gefuellte Kontur (PathIcon fuellt, Stroke-Polyline gab Blobs)
- BloodBrightBrush als Hover-Ton fuer destruktive Icons
- icon-btn:disabled bleibt transparent statt Fluent-Grau
2026-08-27 11:29:44 +02:00

179 lines
9.2 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:islands="using:ClaudeDo.Ui.Views.Islands"
xmlns:uiconverters="using:ClaudeDo.Ui.Converters"
xmlns:ctl="using:ClaudeDo.Ui.Views.Controls"
xmlns:loc="using:ClaudeDo.Ui.Localization"
x:Class="ClaudeDo.Ui.Views.Islands.TasksIslandView"
x:DataType="vm:TasksIslandViewModel">
<DockPanel LastChildFill="True">
<!-- Header -->
<Border DockPanel.Dock="Top" Classes="island-header">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Classes="eyebrow" Text="{Binding HeaderEyebrow}"/>
<TextBlock Classes="display"
Text="{Binding HeaderTitle}"
TextTrimming="CharacterEllipsis"/>
<TextBlock Classes="meta"
Foreground="{DynamicResource TextMuteBrush}"
Text="{Binding Subtitle}"
TextTrimming="CharacterEllipsis"/>
<ctl:OperationIndicator Status="{Binding PlanningOperation}"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="4"
VerticalAlignment="Top">
<Border Classes="kbd" VerticalAlignment="Center" Margin="0,0,6,0"
IsVisible="{Binding HasStatusPill}">
<TextBlock Text="{Binding StatusPill}"/>
</Border>
<Button Classes="icon-btn" Classes.active="{Binding IsShowingCompleted}"
Command="{Binding ToggleShowCompletedCommand}"
ToolTip.Tip="{loc:Tr tasks.showCompletedTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.Eye}"/>
</Button>
<Button Classes="icon-btn" IsVisible="{Binding IsLetClaudeVisible}"
Command="{Binding LetClaudeHandleCommand}" ToolTip.Tip="{loc:Tr tasks.letClaudeTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.AgentSuggested}"/>
</Button>
<Button Classes="icon-btn" IsVisible="{Binding IsMergeReviewsVisible}"
Command="{Binding MergeReviewsCommand}" ToolTip.Tip="{loc:Tr tasks.mergeReviewsTip}">
<!-- Icon.GitBranch is line-art: stroke-rendered, PathIcon would fill the lines away -->
<Viewbox Width="16" Height="16">
<Path Classes="icon-stroke" Data="{StaticResource Icon.GitBranch}"/>
</Viewbox>
</Button>
<Button Classes="icon-btn" IsVisible="{Binding IsQuickClaudeVisible}"
Command="{Binding OpenQuickClaudeSessionCommand}" ToolTip.Tip="{loc:Tr tasks.quickClaudeTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.ArrowOut}"/>
</Button>
<Button Classes="icon-btn" IsVisible="{Binding IsMyDayList}"
Command="{Binding ClearDayCommand}" ToolTip.Tip="{loc:Tr tasks.clearDayTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.Broom}"/>
</Button>
<Button Classes="icon-btn" IsVisible="{Binding IsMyDayList}"
Command="{Binding ShowPrepLogCommand}" ToolTip.Tip="{loc:Tr tasks.planMyDayTip}">
<Viewbox Width="18" Height="18">
<Path Classes="icon-stroke" Data="{StaticResource Icon.PlanDay}"/>
</Viewbox>
</Button>
<Button Classes="icon-btn" Command="{Binding OpenListSettingsCommand}" ToolTip.Tip="{loc:Tr tasks.listSettingsTip}">
<PathIcon Width="15" Height="15" Data="{StaticResource Icon.Settings}"/>
</Button>
</StackPanel>
</Grid>
</Border>
<!-- Add-task row -->
<Border DockPanel.Dock="Top" Classes="add-task" Margin="16,14,16,8">
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0" Classes="add-task-plus" VerticalAlignment="Center">
<PathIcon Width="12" Height="12" Data="{StaticResource Icon.Plus}"
Foreground="{DynamicResource TextFaintBrush}"/>
</Border>
<TextBox Grid.Column="1" x:Name="AddTaskBox" Classes="add-task-input"
PlaceholderText="{loc:Tr tasks.addPlaceholder}"
Text="{Binding NewTaskTitle, Mode=TwoWay}"
VerticalAlignment="Center"
Margin="12,0,0,0">
<TextBox.KeyBindings>
<KeyBinding Gesture="Enter" Command="{Binding AddCommand}"/>
</TextBox.KeyBindings>
</TextBox>
<Border Grid.Column="2" Classes="kbd kbd-enter" VerticalAlignment="Center"
IsVisible="{Binding #AddTaskBox.IsFocused}">
<TextBlock Text="{loc:Tr tasks.enterKey}"/>
</Border>
</Grid>
</Border>
<!-- Notes pinned row (My Day only) -->
<Button DockPanel.Dock="Top"
Classes="btn" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Margin="16,0,16,8"
IsVisible="{Binding ShowNotesRow}"
Command="{Binding OpenNotesCommand}"
Content="{loc:Tr tasks.notesPinnedRow}"/>
<!-- Task list: one flat, virtualized ListBox. Rows is HeaderRow | TaskRowViewModel — group
headers are regular entries, not a separate ItemsControl per section, so a
VirtualizingStackPanel actually bounds the realized container count.
Inset lives on the panel, NOT on the ListBox: Avalonia 12 leaves ScrollViewer.Padding
out of the Extent, so at max scroll the last row would sit below the viewport and stay
unreachable. -->
<Panel>
<ListBox x:Name="RowsListBox"
ItemsSource="{Binding Rows}"
Background="Transparent"
BorderThickness="0">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Margin="10,4"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<!-- SelectedItem is never bound — selection is handled entirely by the inner row Button's
SelectCommand, mirroring the pre-virtualization ItemsControl. Avalonia's ListBox has
no "no selection" mode, so neutralize the app-wide selected/pointerover
ContentPresenter overlay (App.axaml) instead of letting it double up with
TaskRowView's own hover/selected style. -->
<Style Selector="ListBoxItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="CornerRadius" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Focusable" Value="{Binding Converter={x:Static uiconverters:NotHeaderRowConverter.Instance}}"/>
</Style>
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ListBoxItem:selected /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
</ListBox.Styles>
<ListBox.DataTemplates>
<DataTemplate DataType="vm:HeaderRow">
<Grid ColumnDefinitions="*,Auto" Margin="14,14,14,6">
<TextBlock Grid.Column="0" Classes="eyebrow section-label"
Classes.overdue="{Binding IsOverdue}"
Text="{Binding Label}" VerticalAlignment="Center"/>
<Button Grid.Column="1" Classes="icon-btn" IsVisible="{Binding HasAction}"
Command="{Binding ActionCommand}"
ToolTip.Tip="{loc:Tr tasks.clearCompletedTip}"
VerticalAlignment="Center">
<PathIcon Classes="danger" Data="{StaticResource Icon.Trash}" Width="13" Height="13"/>
</Button>
</Grid>
</DataTemplate>
<DataTemplate DataType="vm:TaskRowViewModel">
<Button Classes="flat" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Command="{Binding $parent[ListBox].((vm:TasksIslandViewModel)DataContext).SelectCommand}"
CommandParameter="{Binding}">
<islands:TaskRowView/>
</Button>
</DataTemplate>
</ListBox.DataTemplates>
</ListBox>
<!-- Empty state: shown below the add-task row once the list has zero visible tasks. -->
<StackPanel IsVisible="{Binding IsTasksEmptyHintVisible}"
HorizontalAlignment="Center" VerticalAlignment="Center"
MaxWidth="260" Spacing="6" IsHitTestVisible="False">
<TextBlock Text="{loc:Tr tasks.emptyHint}"
Foreground="{DynamicResource TextMuteBrush}"
TextAlignment="Center" TextWrapping="Wrap"/>
<TextBlock IsVisible="{Binding IsTasksEmptyRepoHintVisible}"
Classes="meta"
Text="{loc:Tr tasks.emptyHintNoWorkingDir}"
Foreground="{DynamicResource TextMuteBrush}"
TextAlignment="Center" TextWrapping="Wrap"/>
</StackPanel>
</Panel>
</DockPanel>
</UserControl>