feat(attachments): drag-and-drop file attachments on the detail pane

Drop a file anywhere on the detail pane to attach it: pane-wide drop target
with a 'Drop to attach' hover overlay (Copy cursor, gated on an idle selected
task), an explicit lingering confirmation/error line, plus an Attachments list
with size, remove, and an Add file… picker in the DETAILS card. ComposedPreview
now shows the reference files too. en/de keys added.
This commit is contained in:
Mika Kuns
2026-06-26 16:11:48 +02:00
parent f7e946e472
commit d8ff8cc110
7 changed files with 330 additions and 4 deletions
@@ -161,6 +161,58 @@
</StackPanel>
</Border>
<!-- Attachments section -->
<Border BorderBrush="{DynamicResource LineBrush}"
BorderThickness="0,1,0,0"
Padding="0,8,0,0">
<StackPanel Spacing="6">
<TextBlock Classes="section-label" Text="{loc:Tr details.attachments.sectionLabel}"/>
<!-- Attachment rows -->
<ItemsControl ItemsSource="{Binding Attachments}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:AttachmentRowViewModel">
<Grid ColumnDefinitions="*,Auto,Auto" Margin="0,2,0,2">
<TextBlock Grid.Column="0"
Text="{Binding FileName}"
VerticalAlignment="Center"
FontSize="{StaticResource FontSizeBody}"
Foreground="{DynamicResource TextDimBrush}"
TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Column="1"
Text="{Binding SizeText}"
VerticalAlignment="Center"
Margin="8,0"
FontSize="{StaticResource FontSizeBody}"
Foreground="{DynamicResource TextMuteBrush}"/>
<Button Grid.Column="2"
Classes="icon-btn"
ToolTip.Tip="{loc:Tr details.attachments.removeTip}"
Command="{Binding $parent[ItemsControl].((vm:DetailsIslandViewModel)DataContext).RemoveAttachmentCommand}"
CommandParameter="{Binding}">
<PathIcon Data="{StaticResource Icon.X}" Width="11" Height="11"/>
</Button>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Add file button -->
<Button Classes="btn"
Padding="8,3"
HorizontalAlignment="Left"
Click="OnAddFileClick"
Content="{loc:Tr details.attachments.addFile}"/>
<!-- Drop status / confirmation -->
<TextBlock Text="{Binding DropStatus}"
IsVisible="{Binding DropStatus, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
FontSize="{StaticResource FontSizeBody}"
Foreground="{DynamicResource TextMuteBrush}"
TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</DockPanel>