diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index fe80292be88..4a5eb39afc0 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -29,6 +29,13 @@ public class Result /// public string ActionKeywordAssigned { get; set; } + /// + /// This holds the text which can be provided by plugin to be copied to the + /// user's clipboard when Ctrl + C is pressed on a result. If the text is a file/directory path + /// flow will copy the actual file/folder instead of just the path text. + /// + public string CopyText { get; set; } = string.Empty; + /// /// This holds the text which can be provided by plugin to help Flow autocomplete text /// for user on the plugin result. If autocomplete action for example is tab, pressing tab will have diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index ec355a0ac11..25de530bc45 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -18,6 +18,9 @@ Copy Cut Paste + File + Folder + Text Game Mode Suspend the use of Hotkeys. diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 5d26433b511..714fcc53fa1 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -175,6 +175,9 @@ Style="{DynamicResource QueryBoxStyle}" Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Visibility="Visible"> + + + diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 02b27cf281c..366407182e0 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -52,7 +52,18 @@ public MainWindow() { InitializeComponent(); } + private void OnCopy(object sender, ExecutedRoutedEventArgs e) + { + if (QueryTextBox.SelectionLength == 0) + { + _viewModel.ResultCopy(string.Empty); + } + else if (!string.IsNullOrEmpty(QueryTextBox.Text)) + { + _viewModel.ResultCopy(QueryTextBox.SelectedText); + } + } private async void OnClosing(object sender, CancelEventArgs e) { _settings.WindowTop = Top; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 2395f8de273..0fe3bdf8052 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -19,6 +19,8 @@ using Microsoft.VisualStudio.Threading; using System.Threading.Channels; using ISavable = Flow.Launcher.Plugin.ISavable; +using System.IO; +using System.Collections.Specialized; namespace Flow.Launcher.ViewModel { @@ -423,6 +425,9 @@ private ResultsViewModel SelectedResults public ICommand OpenSettingCommand { get; set; } public ICommand ReloadPluginDataCommand { get; set; } public ICommand ClearQueryCommand { get; private set; } + + public ICommand CopyToClipboard { get; set; } + public ICommand AutocompleteQueryCommand { get; set; } public string OpenResultCommandModifiers { get; private set; } @@ -870,6 +875,52 @@ public void UpdateResultView(IEnumerable resultsForUpdates) Results.AddResults(resultsForUpdates, token); } + /// + /// This is the global copy method for an individual result. If no text is passed, + /// the method will work out what is to be copied based on the result, so plugin can offer the text + /// to be copied via the result model. If the text is a directory/file path, + /// then actual file/folder will be copied instead. + /// The result's subtitle text is the default text to be copied + /// + public void ResultCopy(string stringToCopy) + { + if (string.IsNullOrEmpty(stringToCopy)) + { + var result = Results.SelectedItem?.Result; + if (result != null) + { + string copyText = string.IsNullOrEmpty(result.CopyText) ? result.SubTitle : result.CopyText; + var isFile = File.Exists(copyText); + var isFolder = Directory.Exists(copyText); + if (isFile || isFolder) + { + var paths = new StringCollection(); + paths.Add(copyText); + + Clipboard.SetFileDropList(paths); + App.API.ShowMsg( + App.API.GetTranslation("copy") + +" " + + (isFile? App.API.GetTranslation("fileTitle") : App.API.GetTranslation("folderTitle")), + App.API.GetTranslation("completedSuccessfully")); + } + else + { + Clipboard.SetDataObject(copyText.ToString()); + App.API.ShowMsg( + App.API.GetTranslation("copy") + + " " + + App.API.GetTranslation("textTitle"), + App.API.GetTranslation("completedSuccessfully")); + } + } + + return; + } + + Clipboard.SetDataObject(stringToCopy); + } + #endregion } } \ No newline at end of file