Added pasting and sending features
This commit is contained in:
@@ -3,6 +3,7 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace EbbesMemeClipboard.Services;
|
||||
|
||||
@@ -10,8 +11,6 @@ public sealed class ClipboardService : IClipboardService
|
||||
{
|
||||
public async Task CopyLocalFileAsync(string filePath)
|
||||
{
|
||||
bool isGif = ImageDecoding.IsGif(filePath);
|
||||
|
||||
var firstFrame = await Task.Run(() => ImageDecoding.DecodeFirstFrame(filePath));
|
||||
|
||||
var data = new DataObject();
|
||||
@@ -23,18 +22,36 @@ public sealed class ClipboardService : IClipboardService
|
||||
// WPF's DataObject.SetImage auto-converts to CF_DIB - no manual header work needed here.
|
||||
data.SetImage(firstFrame);
|
||||
|
||||
if (isGif)
|
||||
{
|
||||
// CF_HTML: the format most browser/rich-text paste targets use, and the only one of
|
||||
// the three that preserves animation for those targets (CF_DIB is a single frame).
|
||||
var bytes = await File.ReadAllBytesAsync(filePath);
|
||||
var fragment = $"<img src=\"data:image/gif;base64,{Convert.ToBase64String(bytes)}\">";
|
||||
data.SetData(DataFormats.Html, BuildCfHtml(fragment));
|
||||
}
|
||||
// "PNG": a registered clipboard format (not one of the classic CF_* constants) that
|
||||
// Chromium-based apps specifically look for and prefer over CF_DIB/CF_BITMAP when
|
||||
// reading a pasted image, because those older formats are lossy for transparency. This
|
||||
// covers Teams, Slack, Discord's web layer, and browsers - without it, paste into any of
|
||||
// them can silently produce nothing even though CF_DIB is present and perfectly valid.
|
||||
using var pngStream = new MemoryStream();
|
||||
var pngEncoder = new PngBitmapEncoder();
|
||||
pngEncoder.Frames.Add(BitmapFrame.Create(firstFrame));
|
||||
pngEncoder.Save(pngStream);
|
||||
pngStream.Position = 0;
|
||||
data.SetData("PNG", pngStream);
|
||||
|
||||
// CF_HTML: the other route those same web-based paste targets check, and the only one of
|
||||
// these formats that preserves animation for them, for GIFs.
|
||||
var bytes = await File.ReadAllBytesAsync(filePath);
|
||||
var fragment = $"<img src=\"data:{GetMimeType(filePath)};base64,{Convert.ToBase64String(bytes)}\">";
|
||||
data.SetData(DataFormats.Html, BuildCfHtml(fragment));
|
||||
|
||||
await SetClipboardWithRetryAsync(data);
|
||||
}
|
||||
|
||||
private static string GetMimeType(string filePath) =>
|
||||
Path.GetExtension(filePath).ToLowerInvariant() switch
|
||||
{
|
||||
".png" => "image/png",
|
||||
".jpg" or ".jpeg" => "image/jpeg",
|
||||
".gif" => "image/gif",
|
||||
_ => "application/octet-stream",
|
||||
};
|
||||
|
||||
private static async Task SetClipboardWithRetryAsync(DataObject data)
|
||||
{
|
||||
const int maxAttempts = 5;
|
||||
|
||||
Reference in New Issue
Block a user