From b737811bdc51362069ed688ff9a2ca86d23f7591 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 25 May 2020 18:58:04 +1000 Subject: [PATCH] Add ContextMenu --- .../ContextMenu.cs | 199 ++++++++++++++++++ Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 6 +- 2 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs new file mode 100644 index 000000000..3ccffd45a --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using System.Windows; +using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin.SharedCommands; +using Flow.Launcher.Plugin.Explorer.Search; + +namespace Flow.Launcher.Plugin.Explorer +{ + internal class ContextMenu : IContextMenu + { + public List LoadContextMenus(Result selectedResult) + { + var contextMenus = new List(); + if (selectedResult.ContextData is SearchResult record) + { + if (record.Type == ResultType.File) + { + contextMenus.Add(CreateOpenWithEditorResult(record)); + contextMenus.Add(CreateOpenContainingFolderResult(record)); + } + + var icoPath = (record.Type == ResultType.File) ? Constants.FileImagePath : Constants.FolderImagePath; + var fileOrFolder = (record.Type == ResultType.File) ? "file" : "folder"; + contextMenus.Add(new Result + { + Title = "Copy path", + SubTitle = $"Copy the current {fileOrFolder} path to clipboard", + Action = (context) => + { + try + { + Clipboard.SetText(record.FullPath); + return true; + } + catch (Exception e) + { + var message = "Fail to set text in clipboard"; + LogException(message, e); + Main.Context.API.ShowMsg(message); + return false; + } + }, + IcoPath = Constants.CopyImagePath + }); + + contextMenus.Add(new Result + { + Title = $"Copy {fileOrFolder}", + SubTitle = $"Copy the {fileOrFolder} to clipboard", + Action = (context) => + { + try + { + Clipboard.SetFileDropList(new System.Collections.Specialized.StringCollection { record.FullPath }); + return true; + } + catch (Exception e) + { + var message = $"Fail to set {fileOrFolder} in clipboard"; + LogException(message, e); + Main.Context.API.ShowMsg(message); + return false; + } + + }, + IcoPath = icoPath + }); + + if (record.Type == ResultType.File || record.Type == ResultType.Folder) + contextMenus.Add(new Result + { + Title = $"Delete {fileOrFolder}", + SubTitle = $"Delete the selected {fileOrFolder}", + Action = (context) => + { + try + { + if (record.Type == ResultType.File) + File.Delete(record.FullPath); + else + Directory.Delete(record.FullPath, true); + } + catch (Exception e) + { + var message = $"Fail to delete {fileOrFolder} at {record.FullPath}"; + LogException(message, e); + Main.Context.API.ShowMsg(message); + return false; + } + + return true; + }, + IcoPath = Constants.DeleteFileFolderImagePath + }); + + if (record.Type == ResultType.File && CanRunAsDifferentUser(record.FullPath)) + contextMenus.Add(new Result + { + Title = "Run as different user", + Action = (context) => + { + try + { + Task.Run(() => ShellCommand.RunAsDifferentUser(record.FullPath.SetProcessStartInfo())); + } + catch (FileNotFoundException e) + { + var name = "Plugin: Folder"; + var message = $"File not found: {e.Message}"; + Main.Context.API.ShowMsg(name, message); + } + + return true; + }, + IcoPath = "Images/user.png" + }); + } + + return contextMenus; + } + + private Result CreateOpenContainingFolderResult(SearchResult record) + { + return new Result + { + Title = "Open containing folder", + Action = _ => + { + try + { + Process.Start("explorer.exe", $" /select,\"{record.FullPath}\""); + } + catch (Exception e) + { + var message = $"Fail to open file at {record.FullPath}"; + LogException(message, e); + Main.Context.API.ShowMsg(message); + return false; + } + + return true; + }, + IcoPath = Constants.FolderImagePath + }; + } + + + private Result CreateOpenWithEditorResult(SearchResult record) + { + string editorPath = "notepad.exe"; // TODO add the ability to create a custom editor + + var name = "Open With Editor: " + Path.GetFileNameWithoutExtension(editorPath); + return new Result + { + Title = name, + Action = _ => + { + try + { + Process.Start(editorPath, record.FullPath); + return true; + } + catch (Exception e) + { + var message = $"Fail to editor for file at {record.FullPath}"; + LogException(message, e); + Main.Context.API.ShowMsg(message); + return false; + } + }, + IcoPath = editorPath + }; + } + + public void LogException(string message, Exception e) + { + Log.Exception($"|Flow.Launcher.Plugin.Folder.ContextMenu|{message}", e); + } + + private bool CanRunAsDifferentUser(string path) + { + switch (Path.GetExtension(path)) + { + case ".exe": + case ".bat": + case ".msi": + return true; + + default: + return false; + + } + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index e23fbdb78..8bd6812d2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -16,6 +16,8 @@ namespace Flow.Launcher.Plugin.Explorer private SettingsViewModel _viewModel; + private IContextMenu _contextMenu; + public Control CreateSettingPanel() { return new ExplorerSettings(); @@ -24,14 +26,14 @@ namespace Flow.Launcher.Plugin.Explorer public void Init(PluginInitContext context) { Context = context; - _viewModel = new SettingsViewModel(); _settings = _viewModel.Settings; + _contextMenu = new ContextMenu(); } public List LoadContextMenus(Result selectedResult) { - return new List(); + return _contextMenu.LoadContextMenus(selectedResult); } public List Query(Query query)