diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs
index d08c9ae2c..c46a6102d 100644
--- a/Flow.Launcher.Core/Configuration/Portable.cs
+++ b/Flow.Launcher.Core/Configuration/Portable.cs
@@ -172,7 +172,7 @@ namespace Flow.Launcher.Core.Configuration
"would you like to move it to a different location?", string.Empty,
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
- FilesFolders.OpenLocationInExporer(Constant.RootDirectory);
+ FilesFolders.OpenPath(Constant.RootDirectory);
Environment.Exit(0);
}
diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
index d5fc55da8..fa3f10fa7 100644
--- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj
+++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
@@ -11,6 +11,7 @@
false
false
false
+ en
@@ -52,10 +53,11 @@
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs
index fdea98b5d..df38ca608 100644
--- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs
+++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs
@@ -86,7 +86,7 @@ namespace Flow.Launcher.Core.Plugin
"Restart Flow Launcher to take effect?",
"Install plugin", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
- PluginManager.API.RestarApp();
+ PluginManager.API.RestartApp();
}
}
}
diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
index 31e1c7032..35486e794 100644
--- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs
+++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
@@ -20,21 +20,21 @@ namespace Flow.Launcher.Core.Plugin
public static List Plugins(List metadatas, PluginsSettings settings)
{
- var csharpPlugins = CSharpPlugins(metadatas).ToList();
+ var dotnetPlugins = DotNetPlugins(metadatas).ToList();
var pythonPlugins = PythonPlugins(metadatas, settings.PythonDirectory);
var executablePlugins = ExecutablePlugins(metadatas);
- var plugins = csharpPlugins.Concat(pythonPlugins).Concat(executablePlugins).ToList();
+ var plugins = dotnetPlugins.Concat(pythonPlugins).Concat(executablePlugins).ToList();
return plugins;
}
- public static IEnumerable CSharpPlugins(List source)
+ public static IEnumerable DotNetPlugins(List source)
{
var plugins = new List();
- var metadatas = source.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp);
+ var metadatas = source.Where(o => AllowedLanguage.IsDotNet(o.Language));
foreach (var metadata in metadatas)
{
- var milliseconds = Stopwatch.Debug($"|PluginsLoader.CSharpPlugins|Constructor init cost for {metadata.Name}", () =>
+ var milliseconds = Stopwatch.Debug($"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () =>
{
#if DEBUG
@@ -50,7 +50,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginsLoader.CSharpPlugins|Couldn't load assembly for {metadata.Name}", e);
+ Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for {metadata.Name}", e);
return;
}
var types = assembly.GetTypes();
@@ -61,7 +61,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (InvalidOperationException e)
{
- Log.Exception($"|PluginsLoader.CSharpPlugins|Can't find class implement IPlugin for <{metadata.Name}>", e);
+ Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find class implement IPlugin for <{metadata.Name}>", e);
return;
}
IPlugin plugin;
@@ -71,7 +71,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginsLoader.CSharpPlugins|Can't create instance for <{metadata.Name}>", e);
+ Log.Exception($"|PluginsLoader.DotNetPlugins|Can't create instance for <{metadata.Name}>", e);
return;
}
#endif
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index 873eb306e..ed3a6584d 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -13,11 +13,12 @@ namespace Flow.Launcher.Infrastructure.Image
{
public static class ImageLoader
{
- private static readonly ImageCache ImageCache = new ImageCache();
- private static BinaryStorage> _storage;
- private static readonly ConcurrentDictionary GuidToKey = new ConcurrentDictionary();
- private static IImageHashGenerator _hashGenerator;
+ private static readonly ImageCache _imageCache = new ImageCache();
+ private static readonly ConcurrentDictionary _guidToKey = new ConcurrentDictionary();
+ private static readonly bool _enableHashImage = true;
+ private static BinaryStorage> _storage;
+ private static IImageHashGenerator _hashGenerator;
private static readonly string[] ImageExtensions =
{
@@ -30,30 +31,30 @@ namespace Flow.Launcher.Infrastructure.Image
".ico"
};
-
public static void Initialize()
{
_storage = new BinaryStorage>("Image");
_hashGenerator = new ImageHashGenerator();
- ImageCache.Usage = LoadStorageToConcurrentDictionary();
+ _imageCache.Usage = LoadStorageToConcurrentDictionary();
foreach (var icon in new[] { Constant.DefaultIcon, Constant.ErrorIcon })
{
ImageSource img = new BitmapImage(new Uri(icon));
img.Freeze();
- ImageCache[icon] = img;
+ _imageCache[icon] = img;
}
+
Task.Run(() =>
{
Stopwatch.Normal("|ImageLoader.Initialize|Preload images cost", () =>
{
- ImageCache.Usage.AsParallel().ForAll(x =>
+ _imageCache.Usage.AsParallel().ForAll(x =>
{
Load(x.Key);
});
});
- Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.Usage.Count}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
+ Log.Info($"|ImageLoader.Initialize|Number of preload images is <{_imageCache.Usage.Count}>, Images Number: {_imageCache.CacheSize()}, Unique Items {_imageCache.UniqueImagesInCache()}");
});
}
@@ -61,7 +62,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
lock (_storage)
{
- _storage.Save(ImageCache.CleanupAndToDictionary());
+ _storage.Save(_imageCache.CleanupAndToDictionary());
}
}
@@ -99,17 +100,17 @@ namespace Flow.Launcher.Infrastructure.Image
private static ImageResult LoadInternal(string path, bool loadFullImage = false)
{
- ImageSource image;
- ImageType type = ImageType.Error;
+ ImageResult imageResult;
+
try
{
if (string.IsNullOrEmpty(path))
{
- return new ImageResult(ImageCache[Constant.ErrorIcon], ImageType.Error);
+ return new ImageResult(_imageCache[Constant.ErrorIcon], ImageType.Error);
}
- if (ImageCache.ContainsKey(path))
+ if (_imageCache.ContainsKey(path))
{
- return new ImageResult(ImageCache[path], ImageType.Cache);
+ return new ImageResult(_imageCache[path], ImageType.Cache);
}
if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
@@ -124,69 +125,93 @@ namespace Flow.Launcher.Infrastructure.Image
path = Path.Combine(Constant.ProgramDirectory, "Images", Path.GetFileName(path));
}
- if (Directory.Exists(path))
+ imageResult = GetThumbnailResult(ref path, loadFullImage);
+ }
+ catch (System.Exception e)
+ {
+ try
{
- /* Directories can also have thumbnails instead of shell icons.
- * Generating thumbnails for a bunch of folders while scrolling through
- * results from Everything makes a big impact on performance and
- * Flow.Launcher responsibility.
- * - Solution: just load the icon
- */
- type = ImageType.Folder;
- image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize,
- Constant.ThumbnailSize, ThumbnailOptions.IconOnly);
-
+ // Get thumbnail may fail for certain images on the first try, retry again has proven to work
+ imageResult = GetThumbnailResult(ref path, loadFullImage);
}
- else if (File.Exists(path))
+ catch (System.Exception e2)
{
- var extension = Path.GetExtension(path).ToLower();
- if (ImageExtensions.Contains(extension))
+ Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e);
+ Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2);
+
+ ImageSource image = _imageCache[Constant.ErrorIcon];
+ _imageCache[path] = image;
+ imageResult = new ImageResult(image, ImageType.Error);
+ }
+ }
+
+ return imageResult;
+ }
+
+ private static ImageResult GetThumbnailResult(ref string path, bool loadFullImage = false)
+ {
+ ImageSource image;
+ ImageType type = ImageType.Error;
+
+ if (Directory.Exists(path))
+ {
+ /* Directories can also have thumbnails instead of shell icons.
+ * Generating thumbnails for a bunch of folders while scrolling through
+ * results from Everything makes a big impact on performance and
+ * Flow.Launcher responsibility.
+ * - Solution: just load the icon
+ */
+ type = ImageType.Folder;
+ image = GetThumbnail(path, ThumbnailOptions.IconOnly);
+ }
+ else if (File.Exists(path))
+ {
+ var extension = Path.GetExtension(path).ToLower();
+ if (ImageExtensions.Contains(extension))
+ {
+ type = ImageType.ImageFile;
+ if (loadFullImage)
{
- type = ImageType.ImageFile;
- if (loadFullImage)
- {
- image = LoadFullImage(path);
- }
- else
- {
- /* Although the documentation for GetImage on MSDN indicates that
- * if a thumbnail is available it will return one, this has proved to not
- * be the case in many situations while testing.
- * - Solution: explicitly pass the ThumbnailOnly flag
- */
- image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize,
- Constant.ThumbnailSize, ThumbnailOptions.ThumbnailOnly);
- }
+ image = LoadFullImage(path);
}
else
{
- type = ImageType.File;
- image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize,
- Constant.ThumbnailSize, ThumbnailOptions.None);
+ /* Although the documentation for GetImage on MSDN indicates that
+ * if a thumbnail is available it will return one, this has proved to not
+ * be the case in many situations while testing.
+ * - Solution: explicitly pass the ThumbnailOnly flag
+ */
+ image = GetThumbnail(path, ThumbnailOptions.ThumbnailOnly);
}
}
else
{
- image = ImageCache[Constant.ErrorIcon];
- path = Constant.ErrorIcon;
- }
-
- if (type != ImageType.Error)
- {
- image.Freeze();
+ type = ImageType.File;
+ image = GetThumbnail(path, ThumbnailOptions.None);
}
}
- catch (System.Exception e)
+ else
{
- Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path}", e);
- type = ImageType.Error;
- image = ImageCache[Constant.ErrorIcon];
- ImageCache[path] = image;
+ image = _imageCache[Constant.ErrorIcon];
+ path = Constant.ErrorIcon;
}
+
+ if (type != ImageType.Error)
+ {
+ image.Freeze();
+ }
+
return new ImageResult(image, type);
}
- private static bool EnableImageHash = true;
+ private static BitmapSource GetThumbnail(string path, ThumbnailOptions option = ThumbnailOptions.ThumbnailOnly)
+ {
+ return WindowsThumbnailProvider.GetThumbnail(
+ path,
+ Constant.ThumbnailSize,
+ Constant.ThumbnailSize,
+ option);
+ }
public static ImageSource Load(string path, bool loadFullImage = false)
{
@@ -194,25 +219,27 @@ namespace Flow.Launcher.Infrastructure.Image
var img = imageResult.ImageSource;
if (imageResult.ImageType != ImageType.Error && imageResult.ImageType != ImageType.Cache)
- { // we need to get image hash
- string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null;
+ {
+ // we need to get image hash
+ string hash = _enableHashImage ? _hashGenerator.GetHashFromImage(img) : null;
if (hash != null)
{
- if (GuidToKey.TryGetValue(hash, out string key))
- { // image already exists
- img = ImageCache[key];
+ if (_guidToKey.TryGetValue(hash, out string key))
+ {
+ // image already exists
+ img = _imageCache[key];
}
else
- { // new guid
- GuidToKey[hash] = path;
+ {
+ // new guid
+ _guidToKey[hash] = path;
}
}
// update cache
- ImageCache[path] = img;
+ _imageCache[path] = img;
}
-
return img;
}
diff --git a/Flow.Launcher.Infrastructure/KeyConstant.cs b/Flow.Launcher.Infrastructure/KeyConstant.cs
new file mode 100644
index 000000000..317485176
--- /dev/null
+++ b/Flow.Launcher.Infrastructure/KeyConstant.cs
@@ -0,0 +1,9 @@
+namespace Flow.Launcher.Infrastructure
+{
+ public static class KeyConstant
+ {
+ public const string Ctrl = nameof(Ctrl);
+ public const string Alt = nameof(Alt);
+ public const string Space = nameof(Space);
+ }
+}
\ No newline at end of file
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index f0ad0381d..4e1a8d7d8 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -9,7 +9,9 @@ namespace Flow.Launcher.Infrastructure.UserSettings
{
public class Settings : BaseModel
{
- public string Hotkey { get; set; } = "Alt + Space";
+ public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
+ public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
+ public bool ShowOpenResultHotkey { get; set; } = true;
public string Language { get; set; } = "en";
public string Theme { get; set; } = Constant.DefaultTheme;
public bool UseDropShadowEffect { get; set; } = false;
diff --git a/Flow.Launcher.Plugin/AllowedLanguage.cs b/Flow.Launcher.Plugin/AllowedLanguage.cs
index 9f63c09fc..827958a7b 100644
--- a/Flow.Launcher.Plugin/AllowedLanguage.cs
+++ b/Flow.Launcher.Plugin/AllowedLanguage.cs
@@ -12,15 +12,26 @@
get { return "CSHARP"; }
}
+ public static string FSharp
+ {
+ get { return "FSHARP"; }
+ }
+
public static string Executable
{
get { return "EXECUTABLE"; }
}
+ public static bool IsDotNet(string language)
+ {
+ return language.ToUpper() == CSharp
+ || language.ToUpper() == FSharp;
+ }
+
public static bool IsAllowed(string language)
{
- return language.ToUpper() == Python.ToUpper()
- || language.ToUpper() == CSharp.ToUpper()
+ return IsDotNet(language)
+ || language.ToUpper() == Python.ToUpper()
|| language.ToUpper() == Executable.ToUpper();
}
}
diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
index 0c6df2b59..82fbb31d5 100644
--- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
+++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
@@ -1,4 +1,4 @@
-
+
netcoreapp3.1
@@ -55,7 +55,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher.Plugin/IPublicAPI.cs b/Flow.Launcher.Plugin/IPublicAPI.cs
index 7fa7cefe2..2e754a0ff 100644
--- a/Flow.Launcher.Plugin/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/IPublicAPI.cs
@@ -43,6 +43,12 @@ namespace Flow.Launcher.Plugin
///
/// Restart Flow Launcher
///
+ void RestartApp();
+
+ ///
+ /// Restart Flow Launcher
+ ///
+ [Obsolete("Use RestartApp instead. This method will be removed in Flow Launcher 1.3")]
void RestarApp();
///
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 7165804a4..17c2dc511 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -110,12 +110,12 @@ namespace Flow.Launcher.Plugin.SharedCommands
return File.Exists(filePath);
}
- public static void OpenLocationInExporer(string location)
+ public static void OpenPath(string fileOrFolderPath)
{
- var psi = new ProcessStartInfo { FileName = FileExplorerProgramName, UseShellExecute = true, Arguments = location };
+ var psi = new ProcessStartInfo { FileName = FileExplorerProgramName, UseShellExecute = true, Arguments = fileOrFolderPath };
try
{
- if (LocationExists(location))
+ if (LocationExists(fileOrFolderPath) || FileExits(fileOrFolderPath))
Process.Start(psi);
}
catch (Exception e)
@@ -123,7 +123,7 @@ namespace Flow.Launcher.Plugin.SharedCommands
#if DEBUG
throw e;
#else
- MessageBox.Show(string.Format("Unable to open location {0}, please check if it exists", location));
+ MessageBox.Show(string.Format("Unable to open the path {0}, please check if it exists", fileOrFolderPath));
#endif
}
}
diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj
index 2f54813e1..2dbf1a9d3 100644
--- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj
+++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj
@@ -10,6 +10,7 @@
false
+ en
@@ -46,10 +47,13 @@
-
+
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln
index 9f1ad9499..2827cf585 100644
--- a/Flow.Launcher.sln
+++ b/Flow.Launcher.sln
@@ -74,6 +74,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Browse
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Calculator", "Plugins\Flow.Launcher.Plugin.Calculator\Flow.Launcher.Plugin.Calculator.csproj", "{59BD9891-3837-438A-958D-ADC7F91F6F7E}"
EndProject
+Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "HelloWorldFSharp", "Plugins\HelloWorldFSharp\HelloWorldFSharp.fsproj", "{30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -313,6 +315,18 @@ Global
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x64.Build.0 = Release|Any CPU
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x86.ActiveCfg = Release|Any CPU
{59BD9891-3837-438A-958D-ADC7F91F6F7E}.Release|x86.Build.0 = Release|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Debug|x64.Build.0 = Debug|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Debug|x86.Build.0 = Debug|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Release|x64.ActiveCfg = Release|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Release|x64.Build.0 = Release|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Release|x86.ActiveCfg = Release|Any CPU
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -332,6 +346,7 @@ Global
{C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{9B130CC5-14FB-41FF-B310-0A95B6894C37} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{59BD9891-3837-438A-958D-ADC7F91F6F7E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
+ {30DDA7D9-3712-44F4-BD18-DC1C05B2DD9E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F26ACB50-3F6C-4907-B0C9-1ADACC1D0DED}
diff --git a/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs b/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs
new file mode 100644
index 000000000..7de5af79a
--- /dev/null
+++ b/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+namespace Flow.Launcher.Converters
+{
+ [ValueConversion(typeof(bool), typeof(Visibility))]
+ public class OpenResultHotkeyVisibilityConverter : IValueConverter
+ {
+ private const int MaxVisibleHotkeys = 9;
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var hotkeyNumber = int.MaxValue;
+
+ if (value is ListBoxItem listBoxItem)
+ {
+ ListBox listBox = ItemsControl.ItemsControlFromItemContainer(listBoxItem) as ListBox;
+ hotkeyNumber = listBox.ItemContainerGenerator.IndexFromContainer(listBoxItem) + 1;
+ }
+
+ return hotkeyNumber <= MaxVisibleHotkeys ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ }
+}
diff --git a/Flow.Launcher/Converters/OrdinalConverter.cs b/Flow.Launcher/Converters/OrdinalConverter.cs
new file mode 100644
index 000000000..970ed183c
--- /dev/null
+++ b/Flow.Launcher/Converters/OrdinalConverter.cs
@@ -0,0 +1,22 @@
+using System.Globalization;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+namespace Flow.Launcher.Converters
+{
+ public class OrdinalConverter : IValueConverter
+ {
+ public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is ListBoxItem listBoxItem)
+ {
+ ListBox listBox = ItemsControl.ItemsControlFromItemContainer(listBoxItem) as ListBox;
+ return listBox.ItemContainerGenerator.IndexFromContainer(listBoxItem) + 1;
+ }
+
+ return 0;
+ }
+
+ public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ }
+}
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index ab7cb57fc..5a32c7527 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -1,4 +1,4 @@
-
+
WinExe
@@ -11,6 +11,7 @@
false
false
false
+ en
@@ -65,7 +66,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml
index 24feb61ce..296f6aa8b 100644
--- a/Flow.Launcher/Languages/da.xaml
+++ b/Flow.Launcher/Languages/da.xaml
@@ -50,7 +50,9 @@
Genvejstast
Flow Launcher genvejstast
+ Åbn resultatmodifikatorer
Tilpasset søgegenvejstast
+ Vis hotkey
Slet
Rediger
Tilføj
diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml
index 08c95208d..91b7c7982 100644
--- a/Flow.Launcher/Languages/de.xaml
+++ b/Flow.Launcher/Languages/de.xaml
@@ -50,7 +50,9 @@
Tastenkombination
Flow Launcher Tastenkombination
+ Öffnen Sie die Ergebnismodifikatoren
Benutzerdefinierte Abfrage Tastenkombination
+ Hotkey anzeigen
Löschen
Bearbeiten
Hinzufügen
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 9fb79ff09..a292599b5 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -60,6 +60,8 @@
Hotkey
Flow Launcher Hotkey
+ Open Result Modifiers
+ Show Hotkey
Custom Query Hotkey
Delete
Edit
diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml
index a6085c325..f43cbb498 100644
--- a/Flow.Launcher/Languages/fr.xaml
+++ b/Flow.Launcher/Languages/fr.xaml
@@ -54,7 +54,9 @@
Raccourcis
Ouvrir Flow Launcher
+ Modificateurs de résultats ouverts
Requêtes personnalisées
+ Afficher le raccourci clavier
Supprimer
Modifier
Ajouter
diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml
index bc8a58c6b..aa29a8891 100644
--- a/Flow.Launcher/Languages/it.xaml
+++ b/Flow.Launcher/Languages/it.xaml
@@ -54,7 +54,9 @@
Tasti scelta rapida
Tasto scelta rapida Flow Launcher
+ Apri modificatori di risultato
Tasti scelta rapida per ricerche personalizzate
+ Mostra tasto di scelta rapida
Cancella
Modifica
Aggiungi
diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml
index 72ad872ef..34c38edf4 100644
--- a/Flow.Launcher/Languages/ja.xaml
+++ b/Flow.Launcher/Languages/ja.xaml
@@ -57,7 +57,9 @@
ホットキー
Flow Launcher ホットキー
+ 結果修飾子を開く
カスタムクエリ ホットキー
+ ホットキーを表示
削除
編集
追加
diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml
index 0352ec9e9..21f1f0273 100644
--- a/Flow.Launcher/Languages/ko.xaml
+++ b/Flow.Launcher/Languages/ko.xaml
@@ -54,7 +54,9 @@
핫키
Flow Launcher 핫키
+ 결과 수정 자 열기
사용자지정 쿼리 핫키
+ 단축키 표시
삭제
편집
추가
diff --git a/Flow.Launcher/Languages/nb-NO.xaml b/Flow.Launcher/Languages/nb-NO.xaml
index 3081bd0f6..1dbfcf5d4 100644
--- a/Flow.Launcher/Languages/nb-NO.xaml
+++ b/Flow.Launcher/Languages/nb-NO.xaml
@@ -54,7 +54,9 @@
Hurtigtast
Flow Launcher-hurtigtast
+ Åpne resultatmodifiserere
Egendefinerd spørringshurtigtast
+ Vis hurtigtast
Slett
Rediger
Legg til
diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml
index 681c0ade4..7d24d9067 100644
--- a/Flow.Launcher/Languages/nl.xaml
+++ b/Flow.Launcher/Languages/nl.xaml
@@ -50,7 +50,9 @@
Sneltoets
Flow Launcher Sneltoets
+ Open resultaatmodificatoren
Custom Query Sneltoets
+ Sneltoets weergeven
Verwijder
Bewerken
Toevoegen
diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml
index a430b9cac..4f26cfaaf 100644
--- a/Flow.Launcher/Languages/pl.xaml
+++ b/Flow.Launcher/Languages/pl.xaml
@@ -50,7 +50,9 @@
Skrót klawiszowy
Skrót klawiszowy Flow Launcher
+ Modyfikatory klawiszów otwierających wyniki
Skrót klawiszowy niestandardowych zapytań
+ Pokaż skrót klawiszowy
Usuń
Edytuj
Dodaj
diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml
index 584a73860..11d8b839e 100644
--- a/Flow.Launcher/Languages/pt-br.xaml
+++ b/Flow.Launcher/Languages/pt-br.xaml
@@ -54,7 +54,9 @@
Atalho
Atalho do Flow Launcher
+ Modificadores de resultado aberto
Atalho de Consulta Personalizada
+ Mostrar tecla de atalho
Apagar
Editar
Adicionar
diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml
index 17e90e5c5..b86fcf377 100644
--- a/Flow.Launcher/Languages/ru.xaml
+++ b/Flow.Launcher/Languages/ru.xaml
@@ -50,7 +50,9 @@
Горячие клавиши
Горячая клавиша Flow Launcher
+ Модификаторы открытого результата
Задаваемые горячие клавиши для запросов
+ Показать Hotkey
Удалить
Изменить
Добавить
diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml
index a2417386d..4ddbd839d 100644
--- a/Flow.Launcher/Languages/sk.xaml
+++ b/Flow.Launcher/Languages/sk.xaml
@@ -55,7 +55,9 @@
Klávesová skratka
Klávesová skratka pre Flow Launcher
+ Otvorte modifikátory výsledkov
Vlastná klávesová skratka pre dopyt
+ Zobraziť klávesovú skratku
Odstrániť
Upraviť
Pridať
diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml
index a1860e1bf..41f112af6 100644
--- a/Flow.Launcher/Languages/sr.xaml
+++ b/Flow.Launcher/Languages/sr.xaml
@@ -54,6 +54,8 @@
Prečica
Flow Launcher prečica
+ Отворите модификаторе резултата
+ покажи хоткеи
prečica za ručno dodat upit
Obriši
Izmeni
diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml
index 67704c75e..9e2624cc2 100644
--- a/Flow.Launcher/Languages/tr.xaml
+++ b/Flow.Launcher/Languages/tr.xaml
@@ -58,7 +58,9 @@
Kısayol Tuşu
Flow Launcher Kısayolu
+ Açık Sonuç Değiştiricileri
Özel Sorgu Kısayolları
+ Kısayol Tuşunu Göster
Sil
Düzenle
Ekle
diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml
index c3ca9d514..0343f9d0f 100644
--- a/Flow.Launcher/Languages/uk-UA.xaml
+++ b/Flow.Launcher/Languages/uk-UA.xaml
@@ -50,7 +50,9 @@
Гарячі клавіші
Гаряча клавіша Flow Launcher
+ Відкриті модифікатори результатів
Задані гарячі клавіші для запитів
+ Показати клавішу швидкого доступу
Видалити
Змінити
Додати
diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml
index d667df621..c8bdc6890 100644
--- a/Flow.Launcher/Languages/zh-cn.xaml
+++ b/Flow.Launcher/Languages/zh-cn.xaml
@@ -57,6 +57,8 @@
热键
Flow Launcher激活热键
+ 开放结果修饰符
+ 显示热键
自定义查询热键
删除
编辑
diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml
index b929f57be..322eaf32f 100644
--- a/Flow.Launcher/Languages/zh-tw.xaml
+++ b/Flow.Launcher/Languages/zh-tw.xaml
@@ -50,7 +50,9 @@
熱鍵
Flow Launcher 執行熱鍵
+ 開放結果修飾符
自定義熱鍵查詢
+ 顯示熱鍵
刪除
編輯
新增
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index b1b688913..23ca5b677 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -49,15 +49,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 16339fb1e..530e6443c 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -54,7 +54,7 @@ namespace Flow.Launcher
Application.Current.MainWindow.Close();
}
- public void RestarApp()
+ public void RestartApp()
{
_mainVM.MainWindowVisibility = Visibility.Hidden;
@@ -66,6 +66,11 @@ namespace Flow.Launcher
UpdateManager.RestartApp(Constant.ApplicationFileName);
}
+ public void RestarApp()
+ {
+ RestartApp();
+ }
+
public void CheckForNewUpdate()
{
_settingsVM.UpdateApp();
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 025249f1e..e57897d4a 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -33,6 +33,8 @@
Cursor="Hand" UseLayoutRounding="False">
+
+
@@ -46,6 +48,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index 8bd8c2788..fde804f2b 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -312,8 +312,9 @@
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+ Margin="0 5 0 0">
@@ -338,7 +348,7 @@
-
+
@@ -348,7 +358,7 @@
-
diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs
index 67245e1c2..aa54bb7c5 100644
--- a/Flow.Launcher/SettingWindow.xaml.cs
+++ b/Flow.Launcher/SettingWindow.xaml.cs
@@ -241,7 +241,7 @@ namespace Flow.Launcher
{
var directory = _viewModel.SelectedPlugin.PluginPair.Metadata.PluginDirectory;
if (!string.IsNullOrEmpty(directory))
- FilesFolders.OpenLocationInExporer(directory);
+ FilesFolders.OpenPath(directory);
}
}
#endregion
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index b63dc0fca..f18b74022 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -28,6 +28,8 @@ namespace Flow.Launcher.ViewModel
{
#region Private Fields
+ private const string DefaultOpenResultModifiers = "Alt";
+
private bool _isQueryRunning;
private Query _lastQuery;
private string _queryTextBeforeLeaveResults;
@@ -76,6 +78,7 @@ namespace Flow.Launcher.ViewModel
SetHotkey(_settings.Hotkey, OnHotkey);
SetCustomPluginHotkey();
+ SetOpenResultModifiers();
}
private void RegisterResultsUpdatedEvent()
@@ -279,6 +282,8 @@ namespace Flow.Launcher.ViewModel
public ICommand LoadHistoryCommand { get; set; }
public ICommand OpenResultCommand { get; set; }
+ public string OpenResultCommandModifiers { get; private set; }
+
public ImageSource Image => ImageLoader.Load(Constant.QueryTextBoxIconImagePath);
#endregion
@@ -598,6 +603,11 @@ namespace Flow.Launcher.ViewModel
}
}
+ private void SetOpenResultModifiers()
+ {
+ OpenResultCommandModifiers = _settings.OpenResultModifiers ?? DefaultOpenResultModifiers;
+ }
+
private void OnHotkey(object sender, HotkeyEventArgs e)
{
if (!ShouldIgnoreHotkeys())
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 69040ee25..0a9731f18 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -1,9 +1,11 @@
using System;
+using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Infrastructure.Logger;
+using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
@@ -11,14 +13,22 @@ namespace Flow.Launcher.ViewModel
{
public class ResultViewModel : BaseModel
{
- public ResultViewModel(Result result)
+ public ResultViewModel(Result result, Settings settings)
{
if (result != null)
{
Result = result;
}
+
+ Settings = settings;
}
+ public Settings Settings { get; private set; }
+
+ public Visibility ShowOpenResultHotkey => Settings.ShowOpenResultHotkey ? Visibility.Visible : Visibility.Hidden;
+
+ public string OpenResultModifiers => Settings.OpenResultModifiers;
+
public ImageSource Image
{
get
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 911cd5807..d30854180 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -156,7 +156,7 @@ namespace Flow.Launcher.ViewModel
private List NewResults(List newRawResults, string resultId)
{
var results = Results.ToList();
- var newResults = newRawResults.Select(r => new ResultViewModel(r)).ToList();
+ var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)).ToList();
var oldResults = results.Where(r => r.Result.PluginID == resultId).ToList();
// Find the same results in A (old results) and B (new newResults)
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index c374dd510..634c05d37 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -160,6 +160,7 @@ namespace Flow.Launcher.ViewModel
}
}
+ public List OpenResultModifiersList => new List { KeyConstant.Alt, KeyConstant.Ctrl, $"{KeyConstant.Ctrl}+{KeyConstant.Alt}" };
private Internationalization _translater => InternationalizationManager.Instance;
public List Languages => _translater.LoadAvailableLanguages();
public IEnumerable MaxResultsRange => Enumerable.Range(2, 16);
diff --git a/Plugins/Flow.Launcher.Plugin.Folder/ContextMenuLoader.cs b/Plugins/Flow.Launcher.Plugin.Folder/ContextMenuLoader.cs
index c083a95f6..561047932 100644
--- a/Plugins/Flow.Launcher.Plugin.Folder/ContextMenuLoader.cs
+++ b/Plugins/Flow.Launcher.Plugin.Folder/ContextMenuLoader.cs
@@ -89,7 +89,7 @@ namespace Flow.Launcher.Plugin.Folder
if (record.Type == ResultType.File)
File.Delete(record.FullPath);
else
- Directory.Delete(record.FullPath);
+ Directory.Delete(record.FullPath, true);
}
catch(Exception e)
{
diff --git a/Plugins/Flow.Launcher.Plugin.Folder/Main.cs b/Plugins/Flow.Launcher.Plugin.Folder/Main.cs
index 85f351ae2..dd85dfd18 100644
--- a/Plugins/Flow.Launcher.Plugin.Folder/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Folder/Main.cs
@@ -1,6 +1,6 @@
using System;
+using System.Collections;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
@@ -27,6 +27,8 @@ namespace Flow.Launcher.Plugin.Folder
private readonly PluginJsonStorage _storage;
private IContextMenu _contextMenuLoader;
+ private static Dictionary _envStringPaths;
+
public Main()
{
_storage = new PluginJsonStorage();
@@ -48,6 +50,7 @@ namespace Flow.Launcher.Plugin.Folder
_context = context;
_contextMenuLoader = new ContextMenuLoader(context);
InitialDriverList();
+ LoadEnvironmentStringPaths();
}
public List Query(Query query)
@@ -55,10 +58,19 @@ namespace Flow.Launcher.Plugin.Folder
var results = GetUserFolderResults(query);
string search = query.Search.ToLower();
- if (!IsDriveOrSharedFolder(search))
+ if (!IsDriveOrSharedFolder(search) && !IsEnvironmentVariableSearch(search))
+ {
return results;
+ }
- results.AddRange(QueryInternal_Directory_Exists(query));
+ if (IsEnvironmentVariableSearch(search))
+ {
+ results.AddRange(GetEnvironmentStringPathResults(search, query));
+ }
+ else
+ {
+ results.AddRange(QueryInternal_Directory_Exists(query.Search, query));
+ }
// todo why was this hack here?
foreach (var result in results)
@@ -69,10 +81,15 @@ namespace Flow.Launcher.Plugin.Folder
return results;
}
+ private static bool IsEnvironmentVariableSearch(string search)
+ {
+ return _envStringPaths != null && search.StartsWith("%");
+ }
+
private static bool IsDriveOrSharedFolder(string search)
{
if (search.StartsWith(@"\\"))
- { // share folder
+ { // shared folder
return true;
}
@@ -103,7 +120,7 @@ namespace Flow.Launcher.Plugin.Folder
{
try
{
- FilesFolders.OpenLocationInExporer(path);
+ FilesFolders.OpenPath(path);
return true;
}
catch (Exception ex)
@@ -146,14 +163,26 @@ namespace Flow.Launcher.Plugin.Folder
}
}
+ private void LoadEnvironmentStringPaths()
+ {
+ _envStringPaths = new Dictionary();
+
+ foreach (DictionaryEntry special in Environment.GetEnvironmentVariables())
+ {
+ if (Directory.Exists(special.Value.ToString()))
+ {
+ _envStringPaths.Add(special.Key.ToString().ToLower(), special.Value.ToString());
+ }
+ }
+ }
+
private static readonly char[] _specialSearchChars = new char[]
{
'?', '*', '>'
};
- private List QueryInternal_Directory_Exists(Query query)
+ private List QueryInternal_Directory_Exists(string search, Query query)
{
- var search = query.Search;
var results = new List();
var hasSpecial = search.IndexOfAny(_specialSearchChars) >= 0;
string incompleteName = "";
@@ -243,6 +272,63 @@ namespace Flow.Launcher.Plugin.Folder
return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList();
}
+ private List GetEnvironmentStringPathSuggestions(string search, Query query)
+ {
+ var results = new List();
+ foreach (var p in _envStringPaths)
+ {
+ if (p.Key.StartsWith(search))
+ {
+ results.Add(CreateFolderResult($"%{p.Key}%", p.Value, p.Value, query));
+ }
+ }
+ return results;
+ }
+
+ private List GetEnvironmentStringPathResults(string envStringSearch, Query query)
+ {
+ if (envStringSearch == "%")
+ { // return all environment string options as path suggestions
+ return GetEnvironmentStringPathSuggestions("", query);
+ }
+
+ var results = new List();
+ var search = envStringSearch.Substring(1);
+
+ if (search.EndsWith("%") && search.Length > 1)
+ { // query starts and ends with a %, find an exact match from env-string paths
+ var exactEnvStringPath = search.Substring(0, search.Length-1);
+
+ if (_envStringPaths.ContainsKey(exactEnvStringPath))
+ {
+ var expandedPath = _envStringPaths[exactEnvStringPath];
+ results.Add(CreateFolderResult($"%{exactEnvStringPath}%", expandedPath, expandedPath, query));
+ }
+ }
+ else if (search.Contains("%"))
+ { // query starts with a % and contains another % somewhere before the end
+ var splitSearch = search.Split("%");
+ var exactEnvStringPath = splitSearch[0];
+
+ // if there are more than 2 % characters in the query, don't bother
+ if (splitSearch.Length == 2 && _envStringPaths.ContainsKey(exactEnvStringPath))
+ {
+ var queryPartToReplace = $"%{exactEnvStringPath}%";
+ var expandedPath = _envStringPaths[exactEnvStringPath];
+ // replace the %envstring% part of the query with its expanded equivalent
+ var updatedSearch = envStringSearch.Replace(queryPartToReplace, expandedPath);
+
+ results.AddRange(QueryInternal_Directory_Exists(updatedSearch, query));
+ }
+ }
+ else
+ { // query simply starts wtih a %, suggest env-string paths that match the rest of the search
+ results.AddRange(GetEnvironmentStringPathSuggestions(search, query));
+ }
+
+ return results;
+ }
+
private static Result CreateFileResult(string filePath, Query query)
{
var result = new Result
@@ -255,7 +341,7 @@ namespace Flow.Launcher.Plugin.Folder
{
try
{
- FilesFolders.OpenLocationInExporer(filePath);
+ FilesFolders.OpenPath(filePath);
}
catch (Exception ex)
{
@@ -286,7 +372,7 @@ namespace Flow.Launcher.Plugin.Folder
Score = 500,
Action = c =>
{
- FilesFolders.OpenLocationInExporer(search);
+ FilesFolders.OpenPath(search);
return true;
}
};
diff --git a/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs
index 5b2804ed5..586513acd 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs
@@ -220,7 +220,7 @@ namespace Flow.Launcher.Plugin.PluginManagement
"Install plugin", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
- context.API.RestarApp();
+ context.API.RestartApp();
}
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
index 4bc5ba8cd..6208881d4 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
@@ -110,7 +110,7 @@
-
+
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
index f4f131279..0b57608c3 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
@@ -205,7 +205,7 @@ namespace Flow.Launcher.Plugin.Sys
IcoPath = "Images\\app.png",
Action = c =>
{
- context.API.RestarApp();
+ context.API.RestartApp();
return false;
}
},
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
index 21695ffcf..d159e9bc0 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj
@@ -8,6 +8,7 @@
Flow.Launcher.Plugin.WebSearch
false
false
+ en
diff --git a/Plugins/HelloWorldFSharp/HelloWorldFSharp.fsproj b/Plugins/HelloWorldFSharp/HelloWorldFSharp.fsproj
new file mode 100644
index 000000000..d688ab6a9
--- /dev/null
+++ b/Plugins/HelloWorldFSharp/HelloWorldFSharp.fsproj
@@ -0,0 +1,36 @@
+
+
+
+ netcoreapp3.1
+ false
+ false
+
+
+
+ ..\..\Output\Debug\Plugins\HelloWorldFSharp\
+ DEBUG;TRACE
+
+
+
+ ..\..\Output\Release\Plugins\HelloWorldFSharp\
+
+
+
+
+ PreserveNewest
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Plugins/HelloWorldFSharp/Images/app.png b/Plugins/HelloWorldFSharp/Images/app.png
new file mode 100644
index 000000000..8c9ca7971
Binary files /dev/null and b/Plugins/HelloWorldFSharp/Images/app.png differ
diff --git a/Plugins/HelloWorldFSharp/Main.fs b/Plugins/HelloWorldFSharp/Main.fs
new file mode 100644
index 000000000..15fd3afbd
--- /dev/null
+++ b/Plugins/HelloWorldFSharp/Main.fs
@@ -0,0 +1,31 @@
+namespace HelloWorldFSharp
+
+open Flow.Launcher.Plugin
+open System.Collections.Generic
+
+type HelloWorldFSharpPlugin() =
+
+ let mutable initContext = PluginInitContext()
+
+ interface IPlugin with
+ member this.Init (context: PluginInitContext) =
+ initContext <- context
+
+ member this.Query (query: Query) =
+ List [
+ Result (Title = "Hello World from F#",
+ SubTitle = sprintf "Query: %s" query.Search)
+
+ Result (Title = "Browse source code of this plugin",
+ SubTitle = "click to open in browser",
+ Action = (fun ctx ->
+ initContext.CurrentPluginMetadata.Website
+ |> System.Diagnostics.Process.Start
+ |> ignore
+ true))
+
+ Result (Title = "Trigger a tray message",
+ Action = (fun _ ->
+ initContext.API.ShowMsg ("Sample tray message", "from the F# plugin")
+ false))
+ ]
diff --git a/Plugins/HelloWorldFSharp/plugin.json b/Plugins/HelloWorldFSharp/plugin.json
new file mode 100644
index 000000000..845b93e4b
--- /dev/null
+++ b/Plugins/HelloWorldFSharp/plugin.json
@@ -0,0 +1,12 @@
+{
+ "ID": "8FF5D5C1F8194958A12E8668FB7ECC04",
+ "ActionKeyword": "hf",
+ "Name": "Hello World FSharp",
+ "Description": "Hello World FSharp",
+ "Author": "Ioannis G.",
+ "Version": "1.0.0",
+ "Language": "fsharp",
+ "Website": "https://github.com/Flow-Launcher/Flow.Launcher",
+ "ExecuteFileName": "HelloWorldFSharp.dll",
+ "IcoPath": "Images\\app.png"
+}
\ No newline at end of file