mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into update_ui
This commit is contained in:
commit
47a69a322d
53 changed files with 511 additions and 128 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
@ -52,10 +53,11 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FSharp.Core" Version="4.7.1" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="squirrel.windows" Version="1.5.2" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="2.2.4">
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.2.8">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,21 +20,21 @@ namespace Flow.Launcher.Core.Plugin
|
|||
|
||||
public static List<PluginPair> Plugins(List<PluginMetadata> 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<PluginPair> CSharpPlugins(List<PluginMetadata> source)
|
||||
public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
|
||||
{
|
||||
var plugins = new List<PluginPair>();
|
||||
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
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
public static class ImageLoader
|
||||
{
|
||||
private static readonly ImageCache ImageCache = new ImageCache();
|
||||
private static BinaryStorage<Dictionary<string, int>> _storage;
|
||||
private static readonly ConcurrentDictionary<string, string> GuidToKey = new ConcurrentDictionary<string, string>();
|
||||
private static IImageHashGenerator _hashGenerator;
|
||||
private static readonly ImageCache _imageCache = new ImageCache();
|
||||
private static readonly ConcurrentDictionary<string, string> _guidToKey = new ConcurrentDictionary<string, string>();
|
||||
private static readonly bool _enableHashImage = true;
|
||||
|
||||
private static BinaryStorage<Dictionary<string, int>> _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<Dictionary<string, int>>("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;
|
||||
}
|
||||
|
||||
|
|
|
|||
9
Flow.Launcher.Infrastructure/KeyConstant.cs
Normal file
9
Flow.Launcher.Infrastructure/KeyConstant.cs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
|
||||
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="2.2.4">
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.2.8">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ namespace Flow.Launcher.Plugin
|
|||
/// <summary>
|
||||
/// Restart Flow Launcher
|
||||
/// </summary>
|
||||
void RestartApp();
|
||||
|
||||
/// <summary>
|
||||
/// Restart Flow Launcher
|
||||
/// </summary>
|
||||
[Obsolete("Use RestartApp instead. This method will be removed in Flow Launcher 1.3")]
|
||||
void RestarApp();
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
@ -46,10 +47,13 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" Version="4.13.1" />
|
||||
<PackageReference Include="Moq" Version="4.14.1" />
|
||||
<PackageReference Include="nunit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
22
Flow.Launcher/Converters/OrdinalConverter.cs
Normal file
22
Flow.Launcher/Converters/OrdinalConverter.cs
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
|
|
@ -65,7 +66,7 @@
|
|||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="2.2.4">
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="3.2.8">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Genvejstast</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher genvejstast</system:String>
|
||||
<system:String x:Key="openResultModifiers">Åbn resultatmodifikatorer</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Tilpasset søgegenvejstast</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Vis hotkey</system:String>
|
||||
<system:String x:Key="delete">Slet</system:String>
|
||||
<system:String x:Key="edit">Rediger</system:String>
|
||||
<system:String x:Key="add">Tilføj</system:String>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Tastenkombination</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher Tastenkombination</system:String>
|
||||
<system:String x:Key="openResultModifiers">Öffnen Sie die Ergebnismodifikatoren</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Benutzerdefinierte Abfrage Tastenkombination</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Hotkey anzeigen</system:String>
|
||||
<system:String x:Key="delete">Löschen</system:String>
|
||||
<system:String x:Key="edit">Bearbeiten</system:String>
|
||||
<system:String x:Key="add">Hinzufügen</system:String>
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Hotkey</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher Hotkey</system:String>
|
||||
<system:String x:Key="openResultModifiers">Open Result Modifiers</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Show Hotkey</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Custom Query Hotkey</system:String>
|
||||
<system:String x:Key="delete">Delete</system:String>
|
||||
<system:String x:Key="edit">Edit</system:String>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Raccourcis</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Ouvrir Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Modificateurs de résultats ouverts</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Requêtes personnalisées</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Afficher le raccourci clavier</system:String>
|
||||
<system:String x:Key="delete">Supprimer</system:String>
|
||||
<system:String x:Key="edit">Modifier</system:String>
|
||||
<system:String x:Key="add">Ajouter</system:String>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Tasti scelta rapida</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Tasto scelta rapida Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Apri modificatori di risultato</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Tasti scelta rapida per ricerche personalizzate</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Mostra tasto di scelta rapida</system:String>
|
||||
<system:String x:Key="delete">Cancella</system:String>
|
||||
<system:String x:Key="edit">Modifica</system:String>
|
||||
<system:String x:Key="add">Aggiungi</system:String>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">ホットキー</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher ホットキー</system:String>
|
||||
<system:String x:Key="openResultModifiers">結果修飾子を開く</system:String>
|
||||
<system:String x:Key="customQueryHotkey">カスタムクエリ ホットキー</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">ホットキーを表示</system:String>
|
||||
<system:String x:Key="delete">削除</system:String>
|
||||
<system:String x:Key="edit">編集</system:String>
|
||||
<system:String x:Key="add">追加</system:String>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">핫키</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher 핫키</system:String>
|
||||
<system:String x:Key="openResultModifiers">결과 수정 자 열기</system:String>
|
||||
<system:String x:Key="customQueryHotkey">사용자지정 쿼리 핫키</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">단축키 표시</system:String>
|
||||
<system:String x:Key="delete">삭제</system:String>
|
||||
<system:String x:Key="edit">편집</system:String>
|
||||
<system:String x:Key="add">추가</system:String>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Hurtigtast</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher-hurtigtast</system:String>
|
||||
<system:String x:Key="openResultModifiers">Åpne resultatmodifiserere</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Egendefinerd spørringshurtigtast</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Vis hurtigtast</system:String>
|
||||
<system:String x:Key="delete">Slett</system:String>
|
||||
<system:String x:Key="edit">Rediger</system:String>
|
||||
<system:String x:Key="add">Legg til</system:String>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Sneltoets</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher Sneltoets</system:String>
|
||||
<system:String x:Key="openResultModifiers">Open resultaatmodificatoren</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Custom Query Sneltoets</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Sneltoets weergeven</system:String>
|
||||
<system:String x:Key="delete">Verwijder</system:String>
|
||||
<system:String x:Key="edit">Bewerken</system:String>
|
||||
<system:String x:Key="add">Toevoegen</system:String>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Skrót klawiszowy</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Skrót klawiszowy Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Modyfikatory klawiszów otwierających wyniki</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Skrót klawiszowy niestandardowych zapytań</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Pokaż skrót klawiszowy</system:String>
|
||||
<system:String x:Key="delete">Usuń</system:String>
|
||||
<system:String x:Key="edit">Edytuj</system:String>
|
||||
<system:String x:Key="add">Dodaj</system:String>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Atalho</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Atalho do Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Modificadores de resultado aberto</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Atalho de Consulta Personalizada</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Mostrar tecla de atalho</system:String>
|
||||
<system:String x:Key="delete">Apagar</system:String>
|
||||
<system:String x:Key="edit">Editar</system:String>
|
||||
<system:String x:Key="add">Adicionar</system:String>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Горячие клавиши</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Горячая клавиша Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Модификаторы открытого результата</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Задаваемые горячие клавиши для запросов</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Показать Hotkey</system:String>
|
||||
<system:String x:Key="delete">Удалить</system:String>
|
||||
<system:String x:Key="edit">Изменить</system:String>
|
||||
<system:String x:Key="add">Добавить</system:String>
|
||||
|
|
|
|||
|
|
@ -55,7 +55,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Klávesová skratka</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Klávesová skratka pre Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Otvorte modifikátory výsledkov</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Vlastná klávesová skratka pre dopyt</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Zobraziť klávesovú skratku</system:String>
|
||||
<system:String x:Key="delete">Odstrániť</system:String>
|
||||
<system:String x:Key="edit">Upraviť</system:String>
|
||||
<system:String x:Key="add">Pridať</system:String>
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Prečica</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher prečica</system:String>
|
||||
<system:String x:Key="openResultModifiers">Отворите модификаторе резултата</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">покажи хоткеи</system:String>
|
||||
<system:String x:Key="customQueryHotkey">prečica za ručno dodat upit</system:String>
|
||||
<system:String x:Key="delete">Obriši</system:String>
|
||||
<system:String x:Key="edit">Izmeni</system:String>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Kısayol Tuşu</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher Kısayolu</system:String>
|
||||
<system:String x:Key="openResultModifiers">Açık Sonuç Değiştiricileri</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Özel Sorgu Kısayolları</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Kısayol Tuşunu Göster</system:String>
|
||||
<system:String x:Key="delete">Sil</system:String>
|
||||
<system:String x:Key="edit">Düzenle</system:String>
|
||||
<system:String x:Key="add">Ekle</system:String>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--Setting Hotkey-->
|
||||
<system:String x:Key="hotkey">Гарячі клавіші</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Гаряча клавіша Flow Launcher</system:String>
|
||||
<system:String x:Key="openResultModifiers">Відкриті модифікатори результатів</system:String>
|
||||
<system:String x:Key="customQueryHotkey">Задані гарячі клавіші для запитів</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">Показати клавішу швидкого доступу</system:String>
|
||||
<system:String x:Key="delete">Видалити</system:String>
|
||||
<system:String x:Key="edit">Змінити</system:String>
|
||||
<system:String x:Key="add">Додати</system:String>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@
|
|||
<!--设置,热键-->
|
||||
<system:String x:Key="hotkey">热键</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher激活热键</system:String>
|
||||
<system:String x:Key="openResultModifiers">开放结果修饰符</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">显示热键</system:String>
|
||||
<system:String x:Key="customQueryHotkey">自定义查询热键</system:String>
|
||||
<system:String x:Key="delete">删除</system:String>
|
||||
<system:String x:Key="edit">编辑</system:String>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@
|
|||
<!--設置,熱鍵-->
|
||||
<system:String x:Key="hotkey">熱鍵</system:String>
|
||||
<system:String x:Key="flowlauncherHotkey">Flow Launcher 執行熱鍵</system:String>
|
||||
<system:String x:Key="openResultModifiers">開放結果修飾符</system:String>
|
||||
<system:String x:Key="customQueryHotkey">自定義熱鍵查詢</system:String>
|
||||
<system:String x:Key="showOpenResultHotkey">顯示熱鍵</system:String>
|
||||
<system:String x:Key="delete">刪除</system:String>
|
||||
<system:String x:Key="edit">編輯</system:String>
|
||||
<system:String x:Key="add">新增</system:String>
|
||||
|
|
|
|||
|
|
@ -49,15 +49,15 @@
|
|||
<KeyBinding Key="Enter" Command="{Binding OpenResultCommand}"></KeyBinding>
|
||||
<KeyBinding Key="Enter" Modifiers="Ctrl" Command="{Binding OpenResultCommand}"></KeyBinding>
|
||||
<KeyBinding Key="Enter" Modifiers="Alt" Command="{Binding OpenResultCommand}"></KeyBinding>
|
||||
<KeyBinding Key="D1" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="0"></KeyBinding>
|
||||
<KeyBinding Key="D2" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="1"></KeyBinding>
|
||||
<KeyBinding Key="D3" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="2"></KeyBinding>
|
||||
<KeyBinding Key="D4" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="3"></KeyBinding>
|
||||
<KeyBinding Key="D5" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="4"></KeyBinding>
|
||||
<KeyBinding Key="D6" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="5"></KeyBinding>
|
||||
<KeyBinding Key="D7" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="6"></KeyBinding>
|
||||
<KeyBinding Key="D8" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="7"></KeyBinding>
|
||||
<KeyBinding Key="D9" Modifiers="Alt" Command="{Binding OpenResultCommand}" CommandParameter="8"></KeyBinding>
|
||||
<KeyBinding Key="D1" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="0"></KeyBinding>
|
||||
<KeyBinding Key="D2" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="1"></KeyBinding>
|
||||
<KeyBinding Key="D3" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="2"></KeyBinding>
|
||||
<KeyBinding Key="D4" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="3"></KeyBinding>
|
||||
<KeyBinding Key="D5" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="4"></KeyBinding>
|
||||
<KeyBinding Key="D6" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="5"></KeyBinding>
|
||||
<KeyBinding Key="D7" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="6"></KeyBinding>
|
||||
<KeyBinding Key="D8" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="7"></KeyBinding>
|
||||
<KeyBinding Key="D9" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="8"></KeyBinding>
|
||||
</Window.InputBindings>
|
||||
<Grid Width="750">
|
||||
<Border Style="{DynamicResource WindowBorderStyle}" MouseDown="OnMouseDown" CornerRadius="5" >
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
Cursor="Hand" UseLayoutRounding="False">
|
||||
<Grid.Resources>
|
||||
<converter:HighlightTextConverter x:Key="HighlightTextConverter"/>
|
||||
<converter:OrdinalConverter x:Key="OrdinalConverter" />
|
||||
<converter:OpenResultHotkeyVisibilityConverter x:Key="OpenResultHotkeyVisibilityConverter" />
|
||||
</Grid.Resources>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
|
|
@ -46,6 +48,19 @@
|
|||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" x:Name="SubTitleRowDefinition" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Visibility="{Binding ShowOpenResultHotkey}">
|
||||
<TextBlock Margin="0 5 5 0" Style="{DynamicResource ItemSubTitleStyle}" HorizontalAlignment="Right" Opacity="0.8" >
|
||||
<TextBlock.Visibility>
|
||||
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}" Converter="{StaticResource ResourceKey=OpenResultHotkeyVisibilityConverter}" />
|
||||
</TextBlock.Visibility>
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}+{1}">
|
||||
<Binding Path="OpenResultModifiers" />
|
||||
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}" Converter="{StaticResource ResourceKey=OrdinalConverter}" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<TextBlock Style="{DynamicResource ItemTitleStyle}" DockPanel.Dock="Left"
|
||||
VerticalAlignment="Center" ToolTip="{Binding Result.Title}" x:Name="Title"
|
||||
Text="{Binding Result.Title}">
|
||||
|
|
|
|||
|
|
@ -312,8 +312,9 @@
|
|||
<Grid Margin="30 10 30 10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="80" />
|
||||
<RowDefinition Height="25" />
|
||||
<RowDefinition Height="340" />
|
||||
<RowDefinition Height="35" />
|
||||
<RowDefinition Height="70" />
|
||||
<RowDefinition Height="250" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Center"
|
||||
|
|
@ -322,13 +323,22 @@
|
|||
<flowlauncher:HotkeyControl x:Name="HotkeyControl" HotkeyChanged="OnHotkeyChanged"
|
||||
Loaded="OnHotkeyControlLoaded" Height="35"/>
|
||||
</StackPanel>
|
||||
<TextBlock VerticalAlignment="Center" Grid.Row="1" Margin="0,3,10,2"
|
||||
Text="{DynamicResource customQueryHotkey}" FontSize="14" />
|
||||
<ListView ItemsSource="{Binding Settings.CustomPluginHotkeys}"
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center"
|
||||
Margin="0,4,0,3">
|
||||
<TextBlock VerticalAlignment="Center" Margin="0 0 10 0" Text="{DynamicResource openResultModifiers}" FontSize="14" />
|
||||
<ComboBox Margin="0 0 0 0" Width="120"
|
||||
ItemsSource="{Binding OpenResultModifiersList}"
|
||||
SelectedItem="{Binding Settings.OpenResultModifiers}" FontSize="14" />
|
||||
<CheckBox Margin="30 0 0 0" IsChecked="{Binding Settings.ShowOpenResultHotkey}" VerticalAlignment="Center">
|
||||
<TextBlock Text="{DynamicResource showOpenResultHotkey}" FontSize="14" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Row="2" VerticalAlignment="Center" Margin="0 23 10 2" Text="{DynamicResource customQueryHotkey}" FontSize="14" />
|
||||
<ListView Grid.Row="3" ItemsSource="{Binding Settings.CustomPluginHotkeys}"
|
||||
SelectedItem="{Binding SelectedCustomPluginHotkey}"
|
||||
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}"
|
||||
BorderBrush="DarkGray" BorderThickness="1"
|
||||
Margin="0 5 0 0" Grid.Row="2">
|
||||
Margin="0 5 0 0">
|
||||
<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="{DynamicResource hotkey}" Width="180">
|
||||
|
|
@ -338,7 +348,7 @@
|
|||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn Header="{DynamicResource actionKeywords}" Width="500">
|
||||
<GridViewColumn Header="{DynamicResource actionKeywords}" Width="546">
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate DataType="userSettings:CustomPluginHotkey">
|
||||
<TextBlock Text="{Binding ActionKeyword}" />
|
||||
|
|
@ -348,7 +358,7 @@
|
|||
</GridView>
|
||||
</ListView.View>
|
||||
</ListView>
|
||||
<StackPanel Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
<StackPanel Grid.Row="4" HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
Orientation="Horizontal" Width="360">
|
||||
<Button Click="OnDeleteCustomHotkeyClick" Width="100"
|
||||
Margin="10" Content="{DynamicResource delete}" />
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ namespace Flow.Launcher.ViewModel
|
|||
private List<ResultViewModel> NewResults(List<Result> 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)
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
public List<string> OpenResultModifiersList => new List<string> { KeyConstant.Alt, KeyConstant.Ctrl, $"{KeyConstant.Ctrl}+{KeyConstant.Alt}" };
|
||||
private Internationalization _translater => InternationalizationManager.Instance;
|
||||
public List<Language> Languages => _translater.LoadAvailableLanguages();
|
||||
public IEnumerable<int> MaxResultsRange => Enumerable.Range(2, 16);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<Settings> _storage;
|
||||
private IContextMenu _contextMenuLoader;
|
||||
|
||||
private static Dictionary<string, string> _envStringPaths;
|
||||
|
||||
public Main()
|
||||
{
|
||||
_storage = new PluginJsonStorage<Settings>();
|
||||
|
|
@ -48,6 +50,7 @@ namespace Flow.Launcher.Plugin.Folder
|
|||
_context = context;
|
||||
_contextMenuLoader = new ContextMenuLoader(context);
|
||||
InitialDriverList();
|
||||
LoadEnvironmentStringPaths();
|
||||
}
|
||||
|
||||
public List<Result> 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<string, string>();
|
||||
|
||||
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<Result> QueryInternal_Directory_Exists(Query query)
|
||||
private List<Result> QueryInternal_Directory_Exists(string search, Query query)
|
||||
{
|
||||
var search = query.Search;
|
||||
var results = new List<Result>();
|
||||
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<Result> GetEnvironmentStringPathSuggestions(string search, Query query)
|
||||
{
|
||||
var results = new List<Result>();
|
||||
foreach (var p in _envStringPaths)
|
||||
{
|
||||
if (p.Key.StartsWith(search))
|
||||
{
|
||||
results.Add(CreateFolderResult($"%{p.Key}%", p.Value, p.Value, query));
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private List<Result> GetEnvironmentStringPathResults(string envStringSearch, Query query)
|
||||
{
|
||||
if (envStringSearch == "%")
|
||||
{ // return all environment string options as path suggestions
|
||||
return GetEnvironmentStringPathSuggestions("", query);
|
||||
}
|
||||
|
||||
var results = new List<Result>();
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@
|
|||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.18362.2005" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<PackageReference Include="NLog" Version="4.7.0-rc1" />
|
||||
<PackageReference Include="NLog" Version="4.7.0" />
|
||||
<PackageReference Include="System.Runtime" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ namespace Flow.Launcher.Plugin.Sys
|
|||
IcoPath = "Images\\app.png",
|
||||
Action = c =>
|
||||
{
|
||||
context.API.RestarApp();
|
||||
context.API.RestartApp();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<AssemblyName>Flow.Launcher.Plugin.WebSearch</AssemblyName>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
|
|||
36
Plugins/HelloWorldFSharp/HelloWorldFSharp.fsproj
Normal file
36
Plugins/HelloWorldFSharp/HelloWorldFSharp.fsproj
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<OutputPath>..\..\Output\Debug\Plugins\HelloWorldFSharp\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<OutputPath>..\..\Output\Release\Plugins\HelloWorldFSharp\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Images\app.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="plugin.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Compile Include="Main.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="FSharp.Core" Version="4.7.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
BIN
Plugins/HelloWorldFSharp/Images/app.png
Normal file
BIN
Plugins/HelloWorldFSharp/Images/app.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
31
Plugins/HelloWorldFSharp/Main.fs
Normal file
31
Plugins/HelloWorldFSharp/Main.fs
Normal file
|
|
@ -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> [
|
||||
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))
|
||||
]
|
||||
12
Plugins/HelloWorldFSharp/plugin.json
Normal file
12
Plugins/HelloWorldFSharp/plugin.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
Loading…
Reference in a new issue