diff --git a/Flow.Launcher/Images/mainsearch.png b/Doc/mainsearch.png
similarity index 100%
rename from Flow.Launcher/Images/mainsearch.png
rename to Doc/mainsearch.png
diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs
index 3dba35f8d..de6ed1b29 100644
--- a/Flow.Launcher.Infrastructure/Constant.cs
+++ b/Flow.Launcher.Infrastructure/Constant.cs
@@ -30,7 +30,7 @@ namespace Flow.Launcher.Infrastructure
public static string PythonPath;
- public static readonly string QueryTextBoxIconImagePath = $"{ProgramDirectory}\\Images\\mainsearch.png";
+ public static readonly string QueryTextBoxIconImagePath = $"{ProgramDirectory}\\Images\\mainsearch.svg";
public const string DefaultTheme = "Darker";
diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs
index 8e2832690..78fa099c9 100644
--- a/Flow.Launcher.Infrastructure/Http/Http.cs
+++ b/Flow.Launcher.Infrastructure/Http/Http.cs
@@ -75,23 +75,31 @@ namespace Flow.Launcher.Infrastructure.Http
};
}
- public static async Task Download([NotNull] string url, [NotNull] string filePath)
+ public static async Task DownloadAsync([NotNull] string url, [NotNull] string filePath)
{
- using var response = await client.GetAsync(url);
- if (response.StatusCode == HttpStatusCode.OK)
+ try
{
- await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
- await response.Content.CopyToAsync(fileStream);
+ using var response = await client.GetAsync(url);
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ await using var fileStream = new FileStream(filePath, FileMode.CreateNew);
+ await response.Content.CopyToAsync(fileStream);
+ }
+ else
+ {
+ throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
+ }
}
- else
+ catch (HttpRequestException e)
{
- throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>");
+ Log.Exception("Infrastructure.Http", "Http Request Error", e, "DownloadAsync");
+ throw;
}
}
///
/// Asynchrously get the result as string from url.
- /// When supposing the result is long and large, try using GetStreamAsync to avoid reading as string
+ /// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string
///
///
///
@@ -101,19 +109,33 @@ namespace Flow.Launcher.Infrastructure.Http
return GetAsync(new Uri(url.Replace("#", "%23")));
}
+ ///
+ /// Asynchrously get the result as string from url.
+ /// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string
+ ///
+ ///
+ ///
public static async Task GetAsync([NotNull] Uri url)
{
Log.Debug($"|Http.Get|Url <{url}>");
- using var response = await client.GetAsync(url);
- var content = await response.Content.ReadAsStringAsync();
- if (response.StatusCode == HttpStatusCode.OK)
+ try
{
- return content;
+ using var response = await client.GetAsync(url);
+ var content = await response.Content.ReadAsStringAsync();
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ return content;
+ }
+ else
+ {
+ throw new HttpRequestException(
+ $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
+ }
}
- else
+ catch (HttpRequestException e)
{
- throw new HttpRequestException(
- $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>");
+ Log.Exception("Infrastructure.Http", "Http Request Error", e, "GetAsync");
+ throw;
}
}
@@ -124,9 +146,17 @@ namespace Flow.Launcher.Infrastructure.Http
///
public static async Task GetStreamAsync([NotNull] string url)
{
- Log.Debug($"|Http.Get|Url <{url}>");
- var response = await client.GetAsync(url);
- return await response.Content.ReadAsStreamAsync();
+ try
+ {
+ Log.Debug($"|Http.Get|Url <{url}>");
+ var response = await client.GetAsync(url);
+ return await response.Content.ReadAsStreamAsync();
+ }
+ catch (HttpRequestException e)
+ {
+ Log.Exception("Infrastructure.Http", "Http Request Error", e, "GetStreamAsync");
+ throw;
+ }
}
}
}
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 39b2087aa..c3b56b904 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -1,4 +1,4 @@
-
+
WinExe
@@ -81,7 +81,8 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
@@ -93,8 +94,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/Flow.Launcher/Images/mainsearch.svg b/Flow.Launcher/Images/mainsearch.svg
new file mode 100644
index 000000000..5d28abdb3
--- /dev/null
+++ b/Flow.Launcher/Images/mainsearch.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index a275a2c16..234fe5091 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -74,7 +74,7 @@
Are you sure you want to delete {0} plugin hotkey?
Query window shadow effect
Shadow effect has a substantial usage of GPU.
- Not recommended if you computer performance is limited.
+ Not recommended if your computer performance is limited.
HTTP Proxy
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index 07bb96339..a2cfe569d 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -6,6 +6,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="clr-namespace:Flow.Launcher.Converters"
+ xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
mc:Ignorable="d"
Title="Flow Launcher"
Topmost="True"
@@ -92,7 +93,8 @@
-
+
-
+
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index a749eae52..af472cf06 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -285,7 +285,7 @@ namespace Flow.Launcher.ViewModel
public string OpenResultCommandModifiers { get; private set; }
- public ImageSource Image => ImageLoader.Load(Constant.QueryTextBoxIconImagePath);
+ public string Image => Constant.QueryTextBoxIconImagePath;
#endregion
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 00a0e1ae5..4c65f2b9f 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
@@ -12,9 +13,9 @@ namespace Flow.Launcher.ViewModel
{
public class ResultViewModel : BaseModel
{
- public class LazyAsync : Lazy>
+ public class LazyAsync : Lazy>
{
- private T defaultValue;
+ private readonly T defaultValue;
private readonly Action _updateCallback;
public new T Value
@@ -23,21 +24,27 @@ namespace Flow.Launcher.ViewModel
{
if (!IsValueCreated)
{
- base.Value.ContinueWith(_ =>
- {
- _updateCallback();
- });
+ _ = Exercute(); // manually use callback strategy
return defaultValue;
}
-
- if (!base.Value.IsCompleted || base.Value.IsFaulted)
+
+ if (!base.Value.IsCompletedSuccessfully)
return defaultValue;
return base.Value.Result;
+
+ // If none of the variables captured by the local function are captured by other lambdas,
+ // the compiler can avoid heap allocations.
+ async ValueTask Exercute()
+ {
+ await base.Value.ConfigureAwait(false);
+ _updateCallback();
+ }
+
}
}
- public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory)
+ public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory)
{
if (defaultValue != null)
{
@@ -55,13 +62,13 @@ namespace Flow.Launcher.ViewModel
Result = result;
Image = new LazyAsync(
- SetImage,
+ SetImage,
ImageLoader.DefaultImage,
() =>
{
OnPropertyChanged(nameof(Image));
});
- }
+ }
Settings = settings;
}
@@ -82,7 +89,7 @@ namespace Flow.Launcher.ViewModel
public LazyAsync Image { get; set; }
- private async Task SetImage()
+ private async ValueTask SetImage()
{
var imagePath = Result.IcoPath;
if (string.IsNullOrEmpty(imagePath) && Result.Icon != null)
@@ -94,7 +101,7 @@ namespace Flow.Launcher.ViewModel
catch (Exception e)
{
Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e);
- imagePath = Constant.MissingImgIcon;
+ return ImageLoader.DefaultImage;
}
}
diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index 4ebf898ea..3c90f8712 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -439,7 +439,7 @@ namespace Flow.Launcher.ViewModel
}
}
- public ImageSource ThemeImage => ImageLoader.Load(Constant.QueryTextBoxIconImagePath);
+ public string ThemeImage => Constant.QueryTextBoxIconImagePath;
#endregion
diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
index 06d8dea7d..1090926fc 100644
--- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj
@@ -11,6 +11,7 @@
true
false
false
+ en
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
index 9d9c09a93..9f0b46d93 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj
@@ -7,6 +7,7 @@
true
true
false
+ en
diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
index 0140444e1..cc280b9a9 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
+++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj
@@ -10,6 +10,7 @@
true
false
false
+ en
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 724ddf20d..68df5bc1f 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -127,7 +127,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
- await Http.Download(plugin.UrlDownload, filePath).ConfigureAwait(false);
+ await Http.DownloadAsync(plugin.UrlDownload, filePath).ConfigureAwait(false);
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
@@ -217,7 +217,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
- await Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false);
+ await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false);
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_download_success"));
diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1
index 836e27380..b08fac8f6 100644
--- a/Scripts/post_build.ps1
+++ b/Scripts/post_build.ps1
@@ -1,13 +1,13 @@
param(
[string]$config = "Release",
- [string]$solution,
- [string]$targetpath
+ [string]$solution = (Join-Path $PSScriptRoot ".." -Resolve)
)
Write-Host "Config: $config"
function Build-Version {
if ([string]::IsNullOrEmpty($env:flowVersion)) {
- $v = (Get-Command ${TargetPath}).FileVersionInfo.FileVersion
+ $targetPath = Join-Path $solution "Output/Release/Flow.Launcher.dll" -Resolve
+ $v = (Get-Command ${targetPath}).FileVersionInfo.FileVersion
} else {
$v = $env:flowVersion
}
@@ -31,13 +31,9 @@ function Build-Path {
return $p
}
-function Copy-Resources ($path, $config) {
- $project = "$path\Flow.Launcher"
- $output = "$path\Output"
- $target = "$output\$config"
- Copy-Item -Recurse -Force $project\Images\* $target\Images\
+function Copy-Resources ($path) {
# making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced.
- Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe $output\Update.exe
+ Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe $path\Output\Update.exe
}
function Delete-Unused ($path, $config) {
@@ -55,17 +51,6 @@ function Validate-Directory ($output) {
New-Item $output -ItemType Directory -Force
}
-function Zip-Release ($path, $version, $output) {
- Write-Host "Begin zip release"
-
- $content = "$path\Output\Release\*"
- $zipFile = "$output\Flow-Launcher-v$version.zip"
-
- Compress-Archive -Force -Path $content -DestinationPath $zipFile
-
- Write-Host "End zip release"
-}
-
function Pack-Squirrel-Installer ($path, $version, $output) {
# msbuild based installer generation is not working in appveyor, not sure why
Write-Host "Begin pack squirrel installer"
@@ -75,6 +60,8 @@ function Pack-Squirrel-Installer ($path, $version, $output) {
Write-Host "Packing: $spec"
Write-Host "Input path: $input"
+ # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced.
+ New-Alias Nuget $env:USERPROFILE\.nuget\packages\NuGet.CommandLine\5.4.0\tools\NuGet.exe -Force
# TODO: can we use dotnet pack here?
nuget pack $spec -Version $version -BasePath $input -OutputDirectory $output -Properties Configuration=Release
@@ -100,40 +87,30 @@ function Pack-Squirrel-Installer ($path, $version, $output) {
Write-Host "End pack squirrel installer"
}
-function IsDotNetCoreAppSelfContainedPublishEvent{
- return Test-Path $solution\Output\Release\coreclr.dll
-}
+function Publish-Self-Contained ($p) {
-function FixPublishLastWriteDateTimeError ($solutionPath) {
- #Fix error from publishing self contained app, when nuget tries to pack core dll references throws the error 'The DateTimeOffset specified cannot be converted into a Zip file timestamp'
- gci -path "$solutionPath\Output\Release" -rec -file *.dll | Where-Object {$_.LastWriteTime -lt (Get-Date).AddYears(-20)} | % { try { $_.LastWriteTime = '01/01/2000 00:00:00' } catch {} }
+ $csproj = Join-Path "$p" "Flow.Launcher/Flow.Launcher.csproj" -Resolve
+ $profile = Join-Path "$p" "Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml" -Resolve
+
+ # we call dotnet publish on the main project.
+ # The other projects should have been built in Release at this point.
+ dotnet publish -c Release $csproj /p:PublishProfile=$profile
}
function Main {
$p = Build-Path
$v = Build-Version
- Copy-Resources $p $config
+ Copy-Resources $p
if ($config -eq "Release"){
- if(IsDotNetCoreAppSelfContainedPublishEvent) {
- FixPublishLastWriteDateTimeError $p
- }
-
Delete-Unused $p $config
+
+ Publish-Self-Contained $p
+
$o = "$p\Output\Packages"
Validate-Directory $o
- # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced.
- New-Alias Nuget $env:USERPROFILE\.nuget\packages\NuGet.CommandLine\5.4.0\tools\NuGet.exe -Force
Pack-Squirrel-Installer $p $v $o
-
- $isInCI = $env:APPVEYOR
- if ($isInCI) {
- Zip-Release $p $v $o
- }
-
- Write-Host "List output directory"
- Get-ChildItem $o
}
}
diff --git a/appveyor.yml b/appveyor.yml
index 1f0937d6d..7d1da7f3f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -26,17 +26,42 @@ before_build:
build:
project: Flow.Launcher.sln
verbosity: minimal
+after_build:
+ - ps: .\Scripts\post_build.ps1
artifacts:
-- path: 'Output\Packages\Flow-Launcher-*.zip'
- name: Zip
- path: 'Output\Release\Flow.Launcher.Plugin.*.nupkg'
name: Plugin nupkg
+- path: 'Output\Packages\Flow-Launcher-*.exe'
+ name: Squirrel Installer
+- path: 'Output\Packages\FlowLauncher-*-full.nupkg'
+ name: Squirrel nupkg
+- path: 'Output\Packages\RELEASES'
+ name: Squirrel RELEASES
deploy:
- provider: NuGet
- artifact: /.*\.nupkg/
- api_key:
- secure: n80IeWR3pN81p0w4uXq4mO0TdTXoJSHHFL+yTB9YBJ0Wni2DjZGYwOFdaWzW4hRi
- on:
- branch: master
\ No newline at end of file
+ - provider: NuGet
+ artifact: Plugin nupkg
+ api_key:
+ secure: n80IeWR3pN81p0w4uXq4mO0TdTXoJSHHFL+yTB9YBJ0Wni2DjZGYwOFdaWzW4hRi
+ on:
+ branch: master
+
+ - provider: GitHub
+ release: v$(flowVersion)
+ auth_token:
+ secure: ij4UeXUYQBDJxn2YRAAhUOjklOGVKDB87Hn5J8tKIzj13yatoI7sLM666QDQFEgv
+ artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES
+ draft: true
+ force_update: true
+ on:
+ branch: master
+
+ - provider: GitHub
+ release: v$(flowVersion)
+ auth_token:
+ secure: ij4UeXUYQBDJxn2YRAAhUOjklOGVKDB87Hn5J8tKIzj13yatoI7sLM666QDQFEgv
+ artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES
+ force_update: true
+ on:
+ APPVEYOR_REPO_TAG: true
\ No newline at end of file