Skip to content

Commit 6a4fdcb

Browse files
authored
Merge branch 'dev' into empty_query
2 parents aa0f9b2 + 8bb96d7 commit 6a4fdcb

File tree

352 files changed

+8457
-3558
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

352 files changed

+8457
-3558
lines changed

.github/workflows/dotnet.yml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# This workflow will build a .NET project
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
3+
4+
name: Build
5+
6+
on:
7+
workflow_dispatch:
8+
push:
9+
branches:
10+
- dev
11+
- master
12+
pull_request:
13+
14+
jobs:
15+
build:
16+
17+
runs-on: windows-latest
18+
env:
19+
FlowVersion: 1.19.5
20+
NUGET_CERT_REVOCATION_MODE: offline
21+
BUILD_NUMBER: ${{ github.run_number }}
22+
steps:
23+
- uses: actions/checkout@v4
24+
- name: Set Flow.Launcher.csproj version
25+
id: update
26+
uses: vers-one/[email protected]
27+
with:
28+
file: |
29+
"**/SolutionAssemblyInfo.cs"
30+
version: ${{ env.FlowVersion }}.${{ env.BUILD_NUMBER }}
31+
- name: Setup .NET
32+
uses: actions/setup-dotnet@v4
33+
with:
34+
dotnet-version: 7.0.x
35+
# cache: true
36+
# cache-dependency-path: |
37+
# Flow.Launcher/packages.lock.json
38+
# Flow.Launcher.Core/packages.lock.json
39+
# Flow.Launcher.Infrastructure/packages.lock.json
40+
# Flow.Launcher.Plugin/packages.lock.json
41+
- name: Install vpk
42+
run: dotnet tool install -g vpk
43+
- name: Restore dependencies
44+
run: nuget restore
45+
- name: Build
46+
run: dotnet build --no-restore -c Release
47+
- name: Initialize Service
48+
run: |
49+
sc config WSearch start= auto # Starts Windows Search service- Needed for running ExplorerTest
50+
net start WSearch
51+
- name: Test
52+
run: dotnet test --no-build --verbosity normal -c Release
53+
- name: Perform post_build tasks
54+
shell: powershell
55+
run: .\Scripts\post_build.ps1
56+
- name: Upload Plugin Nupkg
57+
uses: actions/upload-artifact@v4
58+
with:
59+
name: Plugin nupkg
60+
path: |
61+
Output\Release\Flow.Launcher.Plugin.*.nupkg
62+
compression-level: 0
63+
- name: Upload Setup
64+
uses: actions/upload-artifact@v4
65+
with:
66+
name: Flow Installer
67+
path: |
68+
Output\Packages\Flow-Launcher-*.exe
69+
compression-level: 0
70+
- name: Upload Portable Version
71+
uses: actions/upload-artifact@v4
72+
with:
73+
name: Portable Version
74+
path: |
75+
Output\Packages\Flow-Launcher-Portable.zip
76+
compression-level: 0
77+
- name: Upload Full Nupkg
78+
uses: actions/upload-artifact@v4
79+
with:
80+
name: Full nupkg
81+
path: |
82+
Output\Packages\FlowLauncher-*-full.nupkg
83+
84+
compression-level: 0
85+
- name: Upload Release Information
86+
uses: actions/upload-artifact@v4
87+
with:
88+
name: RELEASES
89+
path: |
90+
Output\Packages\RELEASES
91+
compression-level: 0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
3+
name: Deploy Website On Release
4+
on:
5+
release:
6+
types: [published]
7+
workflow_dispatch:
8+
9+
jobs:
10+
dispatch:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Dispatch event
14+
run: |
15+
http_status=$(curl -L -f -s -o /dev/null -w "%{http_code}" \
16+
-X POST \
17+
-H "Accept: application/vnd.github+json" \
18+
-H "Authorization: Bearer ${{ secrets.DEPLOY_FLOW_WEBSITE }}" \
19+
https://api.github.com/repos/Flow-Launcher/flow-launcher.github.io/dispatches \
20+
-d '{"event_type":"deploy"}')
21+
if [ "$http_status" -ne 204 ]; then echo "Error: Deploy trigger failed, HTTP status code is $http_status"; exit 1; fi

Flow.Launcher.Core/Configuration/Portable.cs

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
1-
using Microsoft.Win32;
2-
using Squirrel;
3-
using System;
1+
using System;
42
using System.IO;
3+
using System.Linq;
54
using System.Reflection;
65
using System.Windows;
6+
using CommunityToolkit.Mvvm.DependencyInjection;
77
using Flow.Launcher.Infrastructure;
8-
using Flow.Launcher.Infrastructure.Logger;
98
using Flow.Launcher.Infrastructure.UserSettings;
10-
using Flow.Launcher.Plugin.SharedCommands;
11-
using System.Linq;
12-
using CommunityToolkit.Mvvm.DependencyInjection;
139
using Flow.Launcher.Plugin;
10+
using Flow.Launcher.Plugin.SharedCommands;
11+
using Microsoft.Win32;
12+
using Squirrel;
1413

1514
namespace Flow.Launcher.Core.Configuration
1615
{
1716
public class Portable : IPortable
1817
{
18+
private static readonly string ClassName = nameof(Portable);
19+
1920
private readonly IPublicAPI API = Ioc.Default.GetRequiredService<IPublicAPI>();
2021

2122
/// <summary>
2223
/// As at Squirrel.Windows version 1.5.2, UpdateManager needs to be disposed after finish
2324
/// </summary>
2425
/// <returns></returns>
25-
private UpdateManager NewUpdateManager()
26+
private static UpdateManager NewUpdateManager()
2627
{
2728
var applicationFolderName = Constant.ApplicationDirectory
2829
.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None)
@@ -51,7 +52,7 @@ public void DisablePortableMode()
5152
}
5253
catch (Exception e)
5354
{
54-
Log.Exception("|Portable.DisablePortableMode|Error occurred while disabling portable mode", e);
55+
API.LogException(ClassName, "Error occurred while disabling portable mode", e);
5556
}
5657
}
5758

@@ -75,26 +76,22 @@ public void EnablePortableMode()
7576
}
7677
catch (Exception e)
7778
{
78-
Log.Exception("|Portable.EnablePortableMode|Error occurred while enabling portable mode", e);
79+
API.LogException(ClassName, "Error occurred while enabling portable mode", e);
7980
}
8081
}
8182

8283
public void RemoveShortcuts()
8384
{
84-
using (var portabilityUpdater = NewUpdateManager())
85-
{
86-
portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu);
87-
portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop);
88-
portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup);
89-
}
85+
using var portabilityUpdater = NewUpdateManager();
86+
portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu);
87+
portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop);
88+
portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup);
9089
}
9190

9291
public void RemoveUninstallerEntry()
9392
{
94-
using (var portabilityUpdater = NewUpdateManager())
95-
{
96-
portabilityUpdater.RemoveUninstallerRegistryEntry();
97-
}
93+
using var portabilityUpdater = NewUpdateManager();
94+
portabilityUpdater.RemoveUninstallerRegistryEntry();
9895
}
9996

10097
public void MoveUserDataFolder(string fromLocation, string toLocation)
@@ -110,12 +107,10 @@ public void VerifyUserDataAfterMove(string fromLocation, string toLocation)
110107

111108
public void CreateShortcuts()
112109
{
113-
using (var portabilityUpdater = NewUpdateManager())
114-
{
115-
portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu, false);
116-
portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop, false);
117-
portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup, false);
118-
}
110+
using var portabilityUpdater = NewUpdateManager();
111+
portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu, false);
112+
portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop, false);
113+
portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup, false);
119114
}
120115

121116
public void CreateUninstallerEntry()
@@ -129,18 +124,14 @@ public void CreateUninstallerEntry()
129124
subKey2.SetValue("DisplayIcon", Path.Combine(Constant.ApplicationDirectory, "app.ico"), RegistryValueKind.String);
130125
}
131126

132-
using (var portabilityUpdater = NewUpdateManager())
133-
{
134-
_ = portabilityUpdater.CreateUninstallerRegistryEntry();
135-
}
127+
using var portabilityUpdater = NewUpdateManager();
128+
_ = portabilityUpdater.CreateUninstallerRegistryEntry();
136129
}
137130

138-
internal void IndicateDeletion(string filePathTodelete)
131+
private static void IndicateDeletion(string filePathTodelete)
139132
{
140133
var deleteFilePath = Path.Combine(filePathTodelete, DataLocation.DeletionIndicatorFile);
141-
using (var _ = File.CreateText(deleteFilePath))
142-
{
143-
}
134+
using var _ = File.CreateText(deleteFilePath);
144135
}
145136

146137
///<summary>

Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
1-
using Flow.Launcher.Infrastructure.Http;
2-
using Flow.Launcher.Infrastructure.Logger;
3-
using System;
1+
using System;
42
using System.Collections.Generic;
53
using System.Net;
64
using System.Net.Http;
75
using System.Net.Http.Json;
6+
using System.Net.Sockets;
87
using System.Text.Json;
98
using System.Text.Json.Serialization;
109
using System.Threading;
1110
using System.Threading.Tasks;
11+
using CommunityToolkit.Mvvm.DependencyInjection;
12+
using Flow.Launcher.Infrastructure.Http;
13+
using Flow.Launcher.Plugin;
1214

1315
namespace Flow.Launcher.Core.ExternalPlugins
1416
{
1517
public record CommunityPluginSource(string ManifestFileUrl)
1618
{
19+
private static readonly string ClassName = nameof(CommunityPluginSource);
20+
21+
// We should not initialize API in static constructor because it will create another API instance
22+
private static IPublicAPI api = null;
23+
private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService<IPublicAPI>();
24+
1725
private string latestEtag = "";
1826

1927
private List<UserPlugin> plugins = new();
2028

21-
private static JsonSerializerOptions PluginStoreItemSerializationOption = new JsonSerializerOptions()
29+
private static readonly JsonSerializerOptions PluginStoreItemSerializationOption = new()
2230
{
2331
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
2432
};
@@ -33,35 +41,49 @@ public record CommunityPluginSource(string ManifestFileUrl)
3341
/// </remarks>
3442
public async Task<List<UserPlugin>> FetchAsync(CancellationToken token)
3543
{
36-
Log.Info(nameof(CommunityPluginSource), $"Loading plugins from {ManifestFileUrl}");
44+
API.LogInfo(ClassName, $"Loading plugins from {ManifestFileUrl}");
3745

3846
var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl);
3947

4048
request.Headers.Add("If-None-Match", latestEtag);
4149

42-
using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token)
50+
try
51+
{
52+
using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token)
4353
.ConfigureAwait(false);
4454

45-
if (response.StatusCode == HttpStatusCode.OK)
46-
{
47-
this.plugins = await response.Content
48-
.ReadFromJsonAsync<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
49-
.ConfigureAwait(false);
50-
this.latestEtag = response.Headers.ETag?.Tag;
55+
if (response.StatusCode == HttpStatusCode.OK)
56+
{
57+
plugins = await response.Content
58+
.ReadFromJsonAsync<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
59+
.ConfigureAwait(false);
60+
latestEtag = response.Headers.ETag?.Tag;
5161

52-
Log.Info(nameof(CommunityPluginSource), $"Loaded {this.plugins.Count} plugins from {ManifestFileUrl}");
53-
return this.plugins;
54-
}
55-
else if (response.StatusCode == HttpStatusCode.NotModified)
56-
{
57-
Log.Info(nameof(CommunityPluginSource), $"Resource {ManifestFileUrl} has not been modified.");
58-
return this.plugins;
62+
API.LogInfo(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}");
63+
return plugins;
64+
}
65+
else if (response.StatusCode == HttpStatusCode.NotModified)
66+
{
67+
API.LogInfo(ClassName, $"Resource {ManifestFileUrl} has not been modified.");
68+
return plugins;
69+
}
70+
else
71+
{
72+
API.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
73+
return null;
74+
}
5975
}
60-
else
76+
catch (Exception e)
6177
{
62-
Log.Warn(nameof(CommunityPluginSource),
63-
$"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
64-
throw new Exception($"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
78+
if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
79+
{
80+
API.LogException(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e);
81+
}
82+
else
83+
{
84+
API.LogException(ClassName, "Error Occurred", e);
85+
}
86+
return null;
6587
}
6688
}
6789
}

Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Threading;
44
using System.Threading.Tasks;
5+
using Flow.Launcher.Plugin;
56

67
namespace Flow.Launcher.Core.ExternalPlugins
78
{
@@ -39,10 +40,14 @@ public async Task<List<UserPlugin>> FetchAsync(CancellationToken token, bool onl
3940
var completedTask = await Task.WhenAny(tasks);
4041
if (completedTask.IsCompletedSuccessfully)
4142
{
42-
// one of the requests completed successfully; keep its results
43-
// and cancel the remaining http requests.
44-
pluginResults = await completedTask;
45-
cts.Cancel();
43+
var result = await completedTask;
44+
if (result != null)
45+
{
46+
// one of the requests completed successfully; keep its results
47+
// and cancel the remaining http requests.
48+
pluginResults = result;
49+
cts.Cancel();
50+
}
4651
}
4752
tasks.Remove(completedTask);
4853
}

0 commit comments

Comments
 (0)