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