Skip to content

Commit

Permalink
Reuse clipboard dataPackage to avoid COM exception
Browse files Browse the repository at this point in the history
  • Loading branch information
Jorixon committed Dec 21, 2024
1 parent 82b20ae commit 7a8df6a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 16 deletions.
33 changes: 21 additions & 12 deletions src/GIMI-ModManager.WinUI/Services/ImageHandlerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,31 +103,40 @@ public static Task CopyImageToClipboardAsync(StorageFile file)
return Task.CompletedTask;
}

public async Task<bool> ClipboardContainsImageAsync()
public record ClipboardContainsImageResult(bool Result, DataPackageView? DataPackage = null);

public async Task<ClipboardContainsImageResult> ClipboardContainsImageAsync()
{
var package = Clipboard.GetContent();

if (package is null)
return false;
return new ClipboardContainsImageResult(false, package);

if (package.Contains(StandardDataFormats.Bitmap))
return true;
return new ClipboardContainsImageResult(true, package);


if (!package.Contains(StandardDataFormats.StorageItems))
return false;
return new ClipboardContainsImageResult(false, package);

var storageItems = await package.GetStorageItemsAsync();

return storageItems.Any(item =>
Constants.SupportedImageExtensions.Contains(Path.GetExtension(item.Name)));
var containsValidFileExtension =
storageItems.Any(item => Constants.SupportedImageExtensions.Contains(Path.GetExtension(item.Name), StringComparer.OrdinalIgnoreCase));

return new ClipboardContainsImageResult(containsValidFileExtension, package);
}

public async Task<Uri?> GetImageFromClipboardAsync()
public async Task<Uri?> GetImageFromClipboardAsync(DataPackageView? clipboardContent = null)
{
if (!await ClipboardContainsImageAsync().ConfigureAwait(false))
return null;
// Reuse the clipboard content if it's already been retrieved
// Calling Clipboard.GetContent() then GetStorageItemsAsync() twice gives a COMException, or at least seems to be the case

var package = clipboardContent ?? await ClipboardContainsImageAsync() switch
{
(true, { } dataPackage) => dataPackage,
_ => null
};

var package = Clipboard.GetContent();

if (package is null)
return null;
Expand All @@ -137,7 +146,7 @@ public async Task<bool> ClipboardContainsImageAsync()
var storageItems = await package.GetStorageItemsAsync();

var imageFile = storageItems.FirstOrDefault(item =>
Constants.SupportedImageExtensions.Contains(Path.GetExtension(item.Name)));
Constants.SupportedImageExtensions.Contains(Path.GetExtension(item.Name), StringComparer.OrdinalIgnoreCase));

if (imageFile is null || !File.Exists(imageFile.Path))
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,15 +306,15 @@ await CommandWrapper(async () =>
{
if (!IsModLoaded) return;

var clipboardHasValidImage = await _imageHandlerService.ClipboardContainsImageAsync();
var clipboardHasValidImageResult = await _imageHandlerService.ClipboardContainsImageAsync();

if (!clipboardHasValidImage)
if (!clipboardHasValidImageResult.Result)
{
_notificationService.ShowNotification("Clipboard does not contain a valid image", "", null);
return;
}

var imagePath = await _imageHandlerService.GetImageFromClipboardAsync();
var imagePath = await _imageHandlerService.GetImageFromClipboardAsync(clipboardHasValidImageResult.DataPackage);

if (imagePath == null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/GIMI-ModManager.WinUI/ViewModels/ModInstallerVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ private async Task PasteModImageAsync()
Uri? imageUri;
try
{
imageUri = await Task.Run(() => _imageHandlerService.GetImageFromClipboardAsync());
imageUri = await _imageHandlerService.GetImageFromClipboardAsync();
ImageSource = "Manual";
}
catch (Exception e)
Expand Down

0 comments on commit 7a8df6a

Please sign in to comment.