feat(details): attach clipboard image on Ctrl+V in the task description
Extracts the clipboard bitmap read into a shared ClipboardBitmap helper (also used by the terminal view); the description TextBox now routes an image paste through AddFilesAsync as a unique paste-*.png attachment. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
d8f78056c1
commit
393e59460d
@@ -103,7 +103,8 @@
|
||||
<!-- Description -->
|
||||
<Panel IsVisible="{Binding IsDescriptionSection}">
|
||||
<!-- Edit mode: raw TextBox -->
|
||||
<TextBox Text="{Binding EditableDescription, Mode=TwoWay}"
|
||||
<TextBox x:Name="DescriptionBox"
|
||||
Text="{Binding EditableDescription, Mode=TwoWay}"
|
||||
AcceptsReturn="True"
|
||||
TextWrapping="Wrap"
|
||||
MinHeight="80"
|
||||
|
||||
@@ -3,6 +3,7 @@ using Avalonia.Input;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using ClaudeDo.Ui.Services;
|
||||
using ClaudeDo.Ui.ViewModels.Islands;
|
||||
|
||||
namespace ClaudeDo.Ui.Views.Islands.Detail;
|
||||
@@ -12,6 +13,41 @@ public partial class DescriptionStepsCard : UserControl
|
||||
public DescriptionStepsCard()
|
||||
{
|
||||
InitializeComponent();
|
||||
// Tunnel: the TextBox handles Ctrl+V itself (text only), so an image paste has to be caught first.
|
||||
DescriptionBox.AddHandler(KeyDownEvent, OnDescriptionPreviewKeyDown, RoutingStrategies.Tunnel);
|
||||
}
|
||||
|
||||
private void OnDescriptionPreviewKeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key != Key.V || !e.KeyModifiers.HasFlag(KeyModifiers.Control) || e.KeyModifiers.HasFlag(KeyModifiers.Alt))
|
||||
return;
|
||||
|
||||
// The clipboard read is async, so swallow the key and replay the text paste when there is no image.
|
||||
e.Handled = true;
|
||||
_ = PasteAsync();
|
||||
}
|
||||
|
||||
/// <summary>Attaches a clipboard bitmap as a PNG file; anything else falls back to the normal text paste.</summary>
|
||||
private async System.Threading.Tasks.Task PasteAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var bitmap = await ClipboardBitmap.TryGetAsync(TopLevel.GetTopLevel(this));
|
||||
if (bitmap is null || DataContext is not DetailsIslandViewModel vm)
|
||||
{
|
||||
DescriptionBox.Paste();
|
||||
return;
|
||||
}
|
||||
|
||||
using var png = new System.IO.MemoryStream();
|
||||
bitmap.Save(png);
|
||||
png.Position = 0;
|
||||
await vm.AddFilesAsync(new[] { (ClipboardImageTempStore.NewPngFileName(DateTime.UtcNow), (System.IO.Stream)png) });
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Paste is best-effort; a failed clipboard/encode must not surface as an unhandled UI exception.
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnCopyClick(object? sender, RoutedEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user