Browse Source

Prevent duplicated files during drag-and-drop (#19864)

Julien Lebosquain 1 week ago
parent
commit
037d7621d1

+ 11 - 0
src/Avalonia.Base/Input/Platform/DataObjectToDataTransferWrapper.cs

@@ -28,6 +28,7 @@ internal sealed class DataObjectToDataTransferWrapper(IDataObject dataObject)
         var items = new List<PlatformDataTransferItem>();
         var nonFileFormats = new List<DataFormat>();
         var nonFileFormatStrings = new List<string>();
+        var hasFiles = false;
 
         foreach (var formatString in DataObject.GetDataFormats())
         {
@@ -35,18 +36,28 @@ internal sealed class DataObjectToDataTransferWrapper(IDataObject dataObject)
 
             if (formatString == DataFormats.Files)
             {
+                if (hasFiles)
+                    continue;
+
                 // This is not ideal as we're reading the filenames ahead of time to generate the appropriate items.
                 // We don't really care about that for this legacy wrapper.
                 if (DataObject.Get(formatString) is IEnumerable<IStorageItem> storageItems)
                 {
+                    hasFiles = true;
+
                     foreach (var storageItem in storageItems)
                         items.Add(PlatformDataTransferItem.Create(DataFormat.File, storageItem));
                 }
             }
             else if (formatString == DataFormats.FileNames)
             {
+                if (hasFiles)
+                    continue;
+
                 if (DataObject.Get(formatString) is IEnumerable<string> fileNames)
                 {
+                    hasFiles = true;
+
                     foreach (var fileName in fileNames)
                     {
                         if (StorageProviderHelpers.TryCreateBclStorageItem(fileName) is { } storageItem)

+ 6 - 0
src/Avalonia.X11/Clipboard/X11Clipboard.cs

@@ -327,15 +327,21 @@ namespace Avalonia.X11.Clipboard
         {
             List<DataFormat>? nonFileFormats = null;
             var items = new List<IAsyncDataTransferItem>();
+            var hasFiles = false;
 
             foreach (var format in formats)
             {
                 if (DataFormat.File.Equals(format))
                 {
+                    if (hasFiles)
+                        continue;
+
                     // We're reading the filenames ahead of time to generate the appropriate items.
                     // This is async, so it should be fine.
                     if (await reader.TryGetAsync(format) is IEnumerable<IStorageItem> storageItems)
                     {
+                        hasFiles = true;
+
                         foreach (var storageItem in storageItems)
                             items.Add(PlatformDataTransferItem.Create(DataFormat.File, storageItem));
                     }

+ 3 - 3
src/Windows/Avalonia.Win32/OleDataObjectHelper.cs

@@ -29,15 +29,15 @@ internal static class OleDataObjectHelper
             tymed = TYMED.TYMED_HGLOBAL
         };
 
-    public static unsafe object? TryGet(this Win32Com.IDataObject _oleDataObject, DataFormat format)
+    public static unsafe object? TryGet(this Win32Com.IDataObject oleDataObject, DataFormat format)
     {
         var formatEtc = format.ToFormatEtc();
 
-        if (_oleDataObject.QueryGetData(&formatEtc) != (uint)HRESULT.S_OK)
+        if (oleDataObject.QueryGetData(&formatEtc) != (uint)HRESULT.S_OK)
             return null;
 
         var medium = new STGMEDIUM();
-        if (_oleDataObject.GetData(&formatEtc, &medium) != (uint)HRESULT.S_OK)
+        if (oleDataObject.GetData(&formatEtc, &medium) != (uint)HRESULT.S_OK)
             return null;
 
         try

+ 6 - 0
src/Windows/Avalonia.Win32/OleDataObjectToDataTransferWrapper.cs

@@ -54,15 +54,21 @@ internal sealed class OleDataObjectToDataTransferWrapper(Win32Com.IDataObject ol
     {
         List<DataFormat>? nonFileFormats = null;
         var items = new List<PlatformDataTransferItem>();
+        var hasFiles = false;
 
         foreach (var format in Formats)
         {
             if (DataFormat.File.Equals(format))
             {
+                if (hasFiles)
+                    continue;
+
                 // This is not ideal as we're reading the filenames ahead of time to generate the appropriate items.
                 // However, it's unlikely to be a heavy operation.
                 if (_oleDataObject.TryGet(format) is IEnumerable<IStorageItem> storageItems)
                 {
+                    hasFiles = true;
+
                     foreach (var storageItem in storageItems)
                         items.Add(PlatformDataTransferItem.Create(DataFormat.File, storageItem));
                 }