/ src / modules / cmdpal / ext / Microsoft.CmdPal.Ext.Indexer / Helpers / DataPackageHelper.cs
DataPackageHelper.cs
 1  // Copyright (c) Microsoft Corporation
 2  // The Microsoft Corporation licenses this file to you under the MIT license.
 3  // See the LICENSE file in the project root for more information.
 4  
 5  #nullable enable
 6  
 7  using System;
 8  using System.IO;
 9  using System.Threading.Tasks;
10  using Microsoft.CommandPalette.Extensions;
11  using Windows.ApplicationModel.DataTransfer;
12  using Windows.Storage;
13  using File = System.IO.File;
14  
15  namespace Microsoft.CmdPal.Ext.Indexer.Helpers;
16  
17  internal static class DataPackageHelper
18  {
19      public static DataPackage? CreateDataPackageForPath(ICommandItem listItem, string? path)
20      {
21          if (string.IsNullOrWhiteSpace(path))
22          {
23              return null;
24          }
25  
26          // Capture now; don't rely on listItem still being valid later.
27          var title = listItem.Title;
28          var description = listItem.Subtitle;
29          var capturedPath = path;
30  
31          var dataPackage = new DataPackage
32          {
33              RequestedOperation = DataPackageOperation.Copy,
34              Properties =
35              {
36                  Title = title,
37                  Description = description,
38              },
39          };
40  
41          // Cheap + immediate.
42          dataPackage.SetText(capturedPath);
43  
44          // Expensive + only computed if the consumer asks for StorageItems.
45          dataPackage.SetDataProvider(StandardDataFormats.StorageItems, async void (request) =>
46          {
47              var deferral = request.GetDeferral();
48              try
49              {
50                  var items = await TryGetStorageItemAsync(capturedPath).ConfigureAwait(false);
51                  if (items is not null)
52                  {
53                      request.SetData(items);
54                  }
55  
56                  // If null: just don't provide StorageItems. Text still works.
57              }
58              catch
59              {
60                  // Swallow: better to provide partial data (text) than fail the whole package.
61              }
62              finally
63              {
64                  deferral.Complete();
65              }
66          });
67  
68          return dataPackage;
69      }
70  
71      private static async Task<IStorageItem[]?> TryGetStorageItemAsync(string filePath)
72      {
73          try
74          {
75              if (File.Exists(filePath))
76              {
77                  var file = await StorageFile.GetFileFromPathAsync(filePath);
78                  return [file];
79              }
80  
81              if (Directory.Exists(filePath))
82              {
83                  var folder = await StorageFolder.GetFolderFromPathAsync(filePath);
84                  return [folder];
85              }
86  
87              return null;
88          }
89          catch (UnauthorizedAccessException)
90          {
91              return null;
92          }
93          catch
94          {
95              return null;
96          }
97      }
98  }