ResultHelper.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  using System;
  6  using System.Collections.Generic;
  7  using System.Threading.Tasks;
  8  using System.Windows;
  9  using System.Windows.Input;
 10  
 11  using Microsoft.PowerToys.Run.Plugin.System.Properties;
 12  using Wox.Plugin;
 13  using Wox.Plugin.Common.Win32;
 14  using Wox.Plugin.Logger;
 15  
 16  namespace Microsoft.PowerToys.Run.Plugin.System.Components
 17  {
 18      internal static class ResultHelper
 19      {
 20          private static bool executingEmptyRecycleBinTask;
 21  
 22          internal static bool ExecuteCommand(bool confirm, string confirmationMessage, Action command)
 23          {
 24              if (confirm)
 25              {
 26                  MessageBoxResult messageBoxResult = MessageBox.Show(
 27                      confirmationMessage,
 28                      Resources.Microsoft_plugin_sys_confirmation,
 29                      MessageBoxButton.YesNo,
 30                      MessageBoxImage.Warning);
 31  
 32                  if (messageBoxResult == MessageBoxResult.No)
 33                  {
 34                      return false;
 35                  }
 36              }
 37  
 38              command();
 39              return true;
 40          }
 41  
 42          internal static bool CopyToClipBoard(in string text)
 43          {
 44              try
 45              {
 46                  Clipboard.Clear();
 47                  Clipboard.SetText(text);
 48                  return true;
 49              }
 50              catch (Exception exception)
 51              {
 52                  Log.Exception("Can't copy to clipboard", exception, typeof(ResultHelper));
 53                  return false;
 54              }
 55          }
 56  
 57          internal static async void EmptyRecycleBinAsync(bool settingEmptyRBSuccesMsg)
 58          {
 59              if (executingEmptyRecycleBinTask)
 60              {
 61                  _ = MessageBox.Show(Resources.Microsoft_plugin_sys_RecycleBin_EmptyTaskRunning, "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name, MessageBoxButton.OK, MessageBoxImage.Information);
 62                  return;
 63              }
 64  
 65              await Task.Run(() => EmptyRecycleBinTask(settingEmptyRBSuccesMsg));
 66          }
 67  
 68          internal static List<ContextMenuResult> GetContextMenuForResult(Result result, bool settingEmptyRBSuccesMsg)
 69          {
 70              var contextMenu = new List<ContextMenuResult>();
 71  
 72              if (!(result?.ContextData is SystemPluginContext contextData))
 73              {
 74                  return contextMenu;
 75              }
 76  
 77              if (contextData.Type == ResultContextType.NetworkAdapterInfo)
 78              {
 79                  contextMenu.Add(new ContextMenuResult()
 80                  {
 81                      AcceleratorKey = Key.C,
 82                      AcceleratorModifiers = ModifierKeys.Control,
 83                      FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets",
 84                      Glyph = "\xE8C8",                       // E8C8 => Symbol: Copy
 85                      Title = Resources.Microsoft_plugin_sys_CopyDetails,
 86                      Action = _ => CopyToClipBoard(contextData.Data),
 87                  });
 88              }
 89  
 90              if (contextData.Type == ResultContextType.RecycleBinCommand)
 91              {
 92                  contextMenu.Add(new ContextMenuResult()
 93                  {
 94                      AcceleratorKey = Key.Delete,
 95                      AcceleratorModifiers = ModifierKeys.Shift, // Shift+Delete is the common key for deleting without recycle bin
 96                      FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets",
 97                      Glyph = "\xE74D",                       // E74D => Symbol: Delete
 98                      Title = Resources.Microsoft_plugin_sys_RecycleBin_contextMenu,
 99                      Action = _ =>
100                      {
101                          EmptyRecycleBinAsync(settingEmptyRBSuccesMsg);
102                          return true;
103                      },
104                  });
105              }
106  
107              return contextMenu;
108          }
109  
110          /// <summary>
111          /// Method to process the empty recycle bin command in a separate task
112          /// </summary>
113          private static void EmptyRecycleBinTask(bool settingEmptyRBSuccesMsg)
114          {
115              executingEmptyRecycleBinTask = true;
116  
117              // https://learn.microsoft.com/windows/win32/api/shellapi/nf-shellapi-shemptyrecyclebina/
118              // http://www.pinvoke.net/default.aspx/shell32/SHEmptyRecycleBin.html/
119              // If the recycle bin is already empty, it will return -2147418113 (0x8000FFFF (E_UNEXPECTED))
120              // If the user canceled the deletion task it will return 2147943623 (0x800704C7 (E_CANCELLED - The operation was canceled by the user.))
121              // On success it will return 0 (S_OK)
122              var result = NativeMethods.SHEmptyRecycleBin(IntPtr.Zero, 0);
123              if (result == (uint)HRESULT.E_UNEXPECTED)
124              {
125                  _ = MessageBox.Show(Resources.Microsoft_plugin_sys_RecycleBin_IsEmpty, "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name, MessageBoxButton.OK, MessageBoxImage.Information);
126              }
127              else if (result != (uint)HRESULT.S_OK && result != (uint)HRESULT.E_CANCELLED)
128              {
129                  var errorDesc = Win32Helpers.MessageFromHResult((int)result);
130                  var name = "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name;
131                  var message = $"{Resources.Microsoft_plugin_sys_RecycleBin_ErrorMsg} {errorDesc}";
132                  Log.Error(message + " - Please refer to https://msdn.microsoft.com/library/windows/desktop/aa378137 for more information.", typeof(Commands));
133                  _ = MessageBox.Show(message, name, MessageBoxButton.OK, MessageBoxImage.Error);
134              }
135  
136              if (result == (uint)HRESULT.S_OK && settingEmptyRBSuccesMsg)
137              {
138                  _ = MessageBox.Show(Resources.Microsoft_plugin_sys_RecycleBin_EmptySuccessMessage, "Plugin: " + Resources.Microsoft_plugin_sys_plugin_name, MessageBoxButton.OK, MessageBoxImage.Information);
139              }
140  
141              executingEmptyRecycleBinTask = false;
142          }
143      }
144  }