Skip to content

Commit abc1b48

Browse files
authored
Merge branch 'dev' into ui_wpf_modern
2 parents 0053ada + d400cda commit abc1b48

File tree

22 files changed

+648
-133
lines changed

22 files changed

+648
-133
lines changed

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ ssh
44
ubuntu
55
runcount
66
Firefox
7-
Português
8-
Português (Brasil)
7+
workaround

.github/actions/spelling/expect.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,4 @@ Reloadable
103103
metadatas
104104
WMP
105105
VSTHRD
106+
CJK

.github/actions/spelling/patterns.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,12 @@
134134
\bčeština\b
135135
\bPortuguês\b
136136
\bIoc\b
137+
\bXiao\s*He\b
138+
\bZi\s*Ran\s*Ma\b
139+
\bWei\s*Ruan\b
140+
\bZhi\s*Neng\s*ABC\b
141+
\bZi\s*Guang\s*Pin\s*Yin\b
142+
\bPin\s*Yin\s*Jia\s*Jia\b
143+
\bXing\s*Kong\s*Jian\s*Dao\b
144+
\bDa\s*Niu\b
145+
\bXiao\s*Lang\b

.github/workflows/dotnet.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
runs-on: windows-latest
1818
env:
19-
FlowVersion: 1.19.5
19+
FlowVersion: 1.20.2
2020
NUGET_CERT_REVOCATION_MODE: offline
2121
BUILD_NUMBER: ${{ github.run_number }}
2222
steps:

.github/workflows/spelling.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
steps:
7373
- name: check-spelling
7474
id: spelling
75-
uses: check-spelling/check-spelling@prerelease
75+
uses: check-spelling/check-spelling@v0.0.25
7676
with:
7777
suppress_push_for_open_pull_request: 1
7878
checkout: true
@@ -128,7 +128,7 @@ jobs:
128128
if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request')
129129
steps:
130130
- name: comment
131-
uses: check-spelling/check-spelling@prerelease
131+
uses: check-spelling/check-spelling@v0.0.25
132132
with:
133133
checkout: true
134134
spell_check_this: check-spelling/spell-check-this@main

Flow.Launcher.Core/Flow.Launcher.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
<PackageReference Include="FSharp.Core" Version="9.0.201" />
5858
<PackageReference Include="Meziantou.Framework.Win32.Jobs" Version="3.4.0" />
5959
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
60+
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
6061
<PackageReference Include="squirrel.windows" Version="1.5.2" NoWarn="NU1701" />
6162
<PackageReference Include="StreamJsonRpc" Version="2.21.10" />
6263
</ItemGroup>

Flow.Launcher.Core/Plugin/PluginInstaller.cs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using System.IO.Compression;
45
using System.Linq;
@@ -277,6 +278,100 @@ await DownloadFileAsync(
277278
}
278279
}
279280

281+
/// <summary>
282+
/// Updates the plugin to the latest version available from its source.
283+
/// </summary>
284+
/// <param name="silentUpdate">If true, do not show any messages when there is no update available.</param>
285+
/// <param name="usePrimaryUrlOnly">If true, only use the primary URL for updates.</param>
286+
/// <param name="token">Cancellation token to cancel the update operation.</param>
287+
/// <returns></returns>
288+
public static async Task CheckForPluginUpdatesAsync(bool silentUpdate = true, bool usePrimaryUrlOnly = false, CancellationToken token = default)
289+
{
290+
// Update the plugin manifest
291+
await API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token);
292+
293+
// Get all plugins that can be updated
294+
var resultsForUpdate = (
295+
from existingPlugin in API.GetAllPlugins()
296+
join pluginUpdateSource in API.GetPluginManifest()
297+
on existingPlugin.Metadata.ID equals pluginUpdateSource.ID
298+
where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version,
299+
StringComparison.InvariantCulture) <
300+
0 // if current version precedes version of the plugin from update source (e.g. PluginsManifest)
301+
&& !API.PluginModified(existingPlugin.Metadata.ID)
302+
select
303+
new PluginUpdateInfo()
304+
{
305+
ID = existingPlugin.Metadata.ID,
306+
Name = existingPlugin.Metadata.Name,
307+
Author = existingPlugin.Metadata.Author,
308+
CurrentVersion = existingPlugin.Metadata.Version,
309+
NewVersion = pluginUpdateSource.Version,
310+
IcoPath = existingPlugin.Metadata.IcoPath,
311+
PluginExistingMetadata = existingPlugin.Metadata,
312+
PluginNewUserPlugin = pluginUpdateSource
313+
}).ToList();
314+
315+
// No updates
316+
if (!resultsForUpdate.Any())
317+
{
318+
if (!silentUpdate)
319+
{
320+
API.ShowMsg(API.GetTranslation("updateNoResultTitle"), API.GetTranslation("updateNoResultSubtitle"));
321+
}
322+
return;
323+
}
324+
325+
// If all plugins are modified, just return
326+
if (resultsForUpdate.All(x => API.PluginModified(x.ID)))
327+
{
328+
return;
329+
}
330+
331+
// Show message box with button to update all plugins
332+
API.ShowMsgWithButton(
333+
API.GetTranslation("updateAllPluginsTitle"),
334+
API.GetTranslation("updateAllPluginsButtonContent"),
335+
() =>
336+
{
337+
UpdateAllPlugins(resultsForUpdate);
338+
},
339+
string.Join(", ", resultsForUpdate.Select(x => x.PluginExistingMetadata.Name)));
340+
}
341+
342+
private static void UpdateAllPlugins(IEnumerable<PluginUpdateInfo> resultsForUpdate)
343+
{
344+
_ = Task.WhenAll(resultsForUpdate.Select(async plugin =>
345+
{
346+
var downloadToFilePath = Path.Combine(Path.GetTempPath(), $"{plugin.Name}-{plugin.NewVersion}.zip");
347+
348+
try
349+
{
350+
using var cts = new CancellationTokenSource();
351+
352+
await DownloadFileAsync(
353+
$"{API.GetTranslation("DownloadingPlugin")} {plugin.PluginNewUserPlugin.Name}",
354+
plugin.PluginNewUserPlugin.UrlDownload, downloadToFilePath, cts);
355+
356+
// check if user cancelled download before installing plugin
357+
if (cts.IsCancellationRequested)
358+
{
359+
return;
360+
}
361+
362+
if (!await API.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, downloadToFilePath))
363+
{
364+
return;
365+
}
366+
}
367+
catch (Exception e)
368+
{
369+
API.LogException(ClassName, "Failed to update plugin", e);
370+
API.ShowMsgError(API.GetTranslation("ErrorUpdatingPlugin"));
371+
}
372+
}));
373+
}
374+
280375
/// <summary>
281376
/// Downloads a file from a URL to a local path, optionally showing a progress box and handling cancellation.
282377
/// </summary>
@@ -350,4 +445,16 @@ private static bool InstallSourceKnown(string url)
350445
x.Metadata.Website.StartsWith(constructedUrlPart)
351446
);
352447
}
448+
449+
private record PluginUpdateInfo
450+
{
451+
public string ID { get; init; }
452+
public string Name { get; init; }
453+
public string Author { get; init; }
454+
public string CurrentVersion { get; init; }
455+
public string NewVersion { get; init; }
456+
public string IcoPath { get; init; }
457+
public PluginMetadata PluginExistingMetadata { get; init; }
458+
public UserPlugin PluginNewUserPlugin { get; init; }
459+
}
353460
}

Flow.Launcher.Core/Updater.cs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ public async Task UpdateAppAsync(bool silentUpdate = true)
4949
// UpdateApp CheckForUpdate will return value only if the app is squirrel installed
5050
var newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false);
5151

52-
var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString());
53-
var currentVersion = Version.Parse(Constant.Version);
52+
var newReleaseVersion =
53+
SemanticVersioning.Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString());
54+
var currentVersion = SemanticVersioning.Version.Parse(Constant.Version);
5455

5556
_api.LogInfo(ClassName, $"Future Release <{Formatted(newUpdateInfo.FutureReleaseEntry)}>");
5657

@@ -71,10 +72,13 @@ public async Task UpdateAppAsync(bool silentUpdate = true)
7172

7273
if (DataLocation.PortableDataLocationInUse())
7374
{
74-
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion}\\{DataLocation.PortableFolderName}";
75+
var targetDestination = updateManager.RootAppDirectory +
76+
$"\\app-{newReleaseVersion}\\{DataLocation.PortableFolderName}";
7577
FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => _api.ShowMsgBox(s));
76-
if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => _api.ShowMsgBox(s)))
77-
_api.ShowMsgBox(string.Format(_api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"),
78+
if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination,
79+
(s) => _api.ShowMsgBox(s)))
80+
_api.ShowMsgBox(string.Format(
81+
_api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"),
7882
DataLocation.PortableDataPath,
7983
targetDestination));
8084
}
@@ -87,22 +91,25 @@ public async Task UpdateAppAsync(bool silentUpdate = true)
8791

8892
_api.LogInfo(ClassName, $"Update success:{newVersionTips}");
8993

90-
if (_api.ShowMsgBox(newVersionTips, _api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes)
94+
if (_api.ShowMsgBox(newVersionTips, _api.GetTranslation("update_flowlauncher_new_update"),
95+
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
9196
{
9297
UpdateManager.RestartApp(Constant.ApplicationFileName);
9398
}
9499
}
95100
catch (Exception e)
96101
{
97-
if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
102+
if (e is HttpRequestException or WebException or SocketException ||
103+
e.InnerException is TimeoutException)
98104
{
99-
_api.LogException(ClassName, $"Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
105+
_api.LogException(ClassName,
106+
$"Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
100107
}
101108
else
102109
{
103110
_api.LogException(ClassName, $"Error Occurred", e);
104111
}
105-
112+
106113
if (!silentUpdate)
107114
_api.ShowMsg(_api.GetTranslation("update_flowlauncher_fail"),
108115
_api.GetTranslation("update_flowlauncher_check_connection"));
@@ -116,14 +123,11 @@ public async Task UpdateAppAsync(bool silentUpdate = true)
116123
[UsedImplicitly]
117124
private class GithubRelease
118125
{
119-
[JsonPropertyName("prerelease")]
120-
public bool Prerelease { get; [UsedImplicitly] set; }
126+
[JsonPropertyName("prerelease")] public bool Prerelease { get; [UsedImplicitly] set; }
121127

122-
[JsonPropertyName("published_at")]
123-
public DateTime PublishedAt { get; [UsedImplicitly] set; }
128+
[JsonPropertyName("published_at")] public DateTime PublishedAt { get; [UsedImplicitly] set; }
124129

125-
[JsonPropertyName("html_url")]
126-
public string HtmlUrl { get; [UsedImplicitly] set; }
130+
[JsonPropertyName("html_url")] public string HtmlUrl { get; [UsedImplicitly] set; }
127131
}
128132

129133
// https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/UpdateManager.Factory.cs
@@ -138,10 +142,7 @@ private static async Task<UpdateManager> GitHubUpdateManagerAsync(string reposit
138142
var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First();
139143
var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/");
140144

141-
var client = new WebClient
142-
{
143-
Proxy = Http.WebProxy
144-
};
145+
var client = new WebClient { Proxy = Http.WebProxy };
145146
var downloader = new FileDownloader(client);
146147

147148
var manager = new UpdateManager(latestUrl, urlDownloader: downloader);
@@ -158,10 +159,7 @@ private string NewVersionTips(string version)
158159

159160
private static string Formatted<T>(T t)
160161
{
161-
var formatted = JsonSerializer.Serialize(t, new JsonSerializerOptions
162-
{
163-
WriteIndented = true
164-
});
162+
var formatted = JsonSerializer.Serialize(t, new JsonSerializerOptions { WriteIndented = true });
165163

166164
return formatted;
167165
}

0 commit comments

Comments
 (0)