Merge pull request #2563 from Flow-Launcher/dev

Release 1.17.2
This commit is contained in:
Jeremy Wu 2024-02-12 22:36:50 +11:00 committed by GitHub
commit 2f679e943c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 132 additions and 52 deletions

View file

@ -5,6 +5,8 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
@ -16,6 +18,11 @@ namespace Flow.Launcher.Core.ExternalPlugins
private List<UserPlugin> plugins = new();
private static JsonSerializerOptions PluginStoreItemSerializationOption = new JsonSerializerOptions()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
};
/// <summary>
/// Fetch and deserialize the contents of a plugins.json file found at <see cref="ManifestFileUrl"/>.
/// We use conditional http requests to keep repeat requests fast.
@ -32,12 +39,15 @@ namespace Flow.Launcher.Core.ExternalPlugins
request.Headers.Add("If-None-Match", latestEtag);
using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false);
using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token)
.ConfigureAwait(false);
if (response.StatusCode == HttpStatusCode.OK)
{
this.plugins = await response.Content.ReadFromJsonAsync<List<UserPlugin>>(cancellationToken: token).ConfigureAwait(false);
this.latestEtag = response.Headers.ETag.Tag;
this.plugins = await response.Content
.ReadFromJsonAsync<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
.ConfigureAwait(false);
this.latestEtag = response.Headers.ETag?.Tag;
Log.Info(nameof(CommunityPluginSource), $"Loaded {this.plugins.Count} plugins from {ManifestFileUrl}");
return this.plugins;
@ -49,7 +59,8 @@ namespace Flow.Launcher.Core.ExternalPlugins
}
else
{
Log.Warn(nameof(CommunityPluginSource), $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
Log.Warn(nameof(CommunityPluginSource),
$"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
throw new Exception($"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
}
}

View file

@ -14,8 +14,8 @@ namespace Flow.Launcher.Core.ExternalPlugins
public string UrlDownload { get; set; }
public string UrlSourceCode { get; set; }
public string IcoPath { get; set; }
public DateTime LatestReleaseDate { get; set; }
public DateTime DateAdded { get; set; }
public DateTime? LatestReleaseDate { get; set; }
public DateTime? DateAdded { get; set; }
}
}

View file

@ -55,6 +55,7 @@
<ItemGroup>
<PackageReference Include="Droplex" Version="1.7.0" />
<PackageReference Include="FSharp.Core" Version="7.0.401" />
<PackageReference Include="Meziantou.Framework.Win32.Jobs" Version="3.2.1" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageReference Include="squirrel.windows" Version="1.5.2" NoWarn="NU1701" />
<PackageReference Include="StreamJsonRpc" Version="2.17.8" />

View file

@ -37,7 +37,7 @@ namespace Flow.Launcher.Core.Plugin
_storage = new JsonStorage<ConcurrentDictionary<string, object>>(SettingPath);
Settings = await _storage.LoadAsync();
if (Settings != null || Configuration == null)
if (Configuration == null)
{
return;
}

View file

@ -28,20 +28,21 @@ namespace Flow.Launcher.Core.Plugin
protected override Task<Stream> RequestAsync(JsonRPCRequestModel request, CancellationToken token = default)
{
_startInfo.ArgumentList[1] = JsonSerializer.Serialize(request);
_startInfo.ArgumentList[1] = JsonSerializer.Serialize(request, RequestSerializeOption);
return ExecuteAsync(_startInfo, token);
}
protected override string Request(JsonRPCRequestModel rpcRequest, CancellationToken token = default)
{
// since this is not static, request strings will build up in ArgumentList if index is not specified
_startInfo.ArgumentList[1] = JsonSerializer.Serialize(rpcRequest);
_startInfo.ArgumentList[1] = JsonSerializer.Serialize(rpcRequest, RequestSerializeOption);
return Execute(_startInfo);
}
public override async Task InitAsync(PluginInitContext context)
{
_startInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
_startInfo.ArgumentList.Add(string.Empty);
_startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
await base.InitAsync(context);
}

View file

@ -5,12 +5,24 @@ using System.IO.Pipelines;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin;
using Meziantou.Framework.Win32;
using Nerdbank.Streams;
namespace Flow.Launcher.Core.Plugin
{
internal abstract class ProcessStreamPluginV2 : JsonRPCPluginV2
{
private static JobObject _jobObject = new JobObject();
static ProcessStreamPluginV2()
{
_jobObject.SetLimits(new JobObjectLimits()
{
Flags = JobObjectLimitFlags.KillOnJobClose | JobObjectLimitFlags.DieOnUnhandledException
});
_jobObject.AssignProcess(Process.GetCurrentProcess());
}
public override string SupportedLanguage { get; set; }
protected sealed override IDuplexPipe ClientPipe { get; set; }
@ -30,22 +42,22 @@ namespace Flow.Launcher.Core.Plugin
ClientProcess = Process.Start(StartInfo);
ArgumentNullException.ThrowIfNull(ClientProcess);
SetupPipe(ClientProcess);
ErrorStream = ClientProcess.StandardError;
await base.InitAsync(context);
}
private void SetupPipe(Process process)
{
var (reader, writer) = (PipeReader.Create(process.StandardOutput.BaseStream),
PipeWriter.Create(process.StandardInput.BaseStream));
ClientPipe = new DuplexPipe(reader, writer);
}
public override async Task ReloadDataAsync()
{
var oldProcess = ClientProcess;
@ -57,8 +69,8 @@ namespace Flow.Launcher.Core.Plugin
await oldProcess.WaitForExitAsync();
oldProcess.Dispose();
}
public override async ValueTask DisposeAsync()
{
ClientProcess.Kill(true);

View file

@ -5,57 +5,57 @@
<system:String x:Key="flowlauncher_plugin_sys_command">Befehl</system:String>
<system:String x:Key="flowlauncher_plugin_sys_desc">Beschreibung</system:String>
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer_cmd">Shutdown</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_computer_cmd">Restart</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_advanced_cmd">Restart With Advanced Boot Options</system:String>
<system:String x:Key="flowlauncher_plugin_sys_log_off_cmd">Log Off/Sign Out</system:String>
<system:String x:Key="flowlauncher_plugin_sys_lock_cmd">Lock</system:String>
<system:String x:Key="flowlauncher_plugin_sys_sleep_cmd">Sleep</system:String>
<system:String x:Key="flowlauncher_plugin_sys_hibernate_cmd">Hibernate</system:String>
<system:String x:Key="flowlauncher_plugin_sys_indexoption_cmd">Index Option</system:String>
<system:String x:Key="flowlauncher_plugin_sys_emptyrecyclebin_cmd">Empty Recycle Bin</system:String>
<system:String x:Key="flowlauncher_plugin_sys_openrecyclebin_cmd">Open Recycle Bin</system:String>
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer_cmd">Herunterfahren</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_computer_cmd">Neu starten</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_advanced_cmd">Neustart mit erweiterten Startoptionen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_log_off_cmd">Abmelden</system:String>
<system:String x:Key="flowlauncher_plugin_sys_lock_cmd">Sperren</system:String>
<system:String x:Key="flowlauncher_plugin_sys_sleep_cmd">Energie sparen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_hibernate_cmd">Ruhezustand</system:String>
<system:String x:Key="flowlauncher_plugin_sys_indexoption_cmd">Indizierungsoptionen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_emptyrecyclebin_cmd">Papierkorb leeren</system:String>
<system:String x:Key="flowlauncher_plugin_sys_openrecyclebin_cmd">Papierkorb öffnen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_exit_cmd">Schließen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_save_all_settings_cmd">Save Settings</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_cmd">Restart Flow Launcher&quot;</system:String>
<system:String x:Key="flowlauncher_plugin_sys_save_all_settings_cmd">Einstellungen speichern</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_cmd">Flow Launcher neu starten</system:String>
<system:String x:Key="flowlauncher_plugin_sys_setting_cmd">Einstellungen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_reload_plugin_data_cmd">Plugin-Daten neu laden</system:String>
<system:String x:Key="flowlauncher_plugin_sys_check_for_update_cmd">Check For Update</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_log_location_cmd">Open Log Location</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_docs_tips_cmd">Flow Launcher Tips</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_userdata_location_cmd">Flow Launcher UserData Folder</system:String>
<system:String x:Key="flowlauncher_plugin_sys_check_for_update_cmd">Auf Updates prüfen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_log_location_cmd">Log-Speicherort öffnen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_docs_tips_cmd">Flow Launcher Tipps</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_userdata_location_cmd">Flow Launcher Benutzerdaten-Ordner</system:String>
<system:String x:Key="flowlauncher_plugin_sys_toggle_game_mode_cmd">Gott Modus</system:String>
<!-- Command Descriptions -->
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer">Computer herunterfahren</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_computer">Computer neu starten</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_advanced">Restart the computer with Advanced Boot Options for Safe and Debugging modes, as well as other options</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart_advanced">Startet den Computer mit erweiterten Startoptionen für den abgesicherten Modus neu</system:String>
<system:String x:Key="flowlauncher_plugin_sys_log_off">Abmelden</system:String>
<system:String x:Key="flowlauncher_plugin_sys_lock">Computer sperren</system:String>
<system:String x:Key="flowlauncher_plugin_sys_exit">Flow Launcher schließen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_restart">Flow Launcher neu starten</system:String>
<system:String x:Key="flowlauncher_plugin_sys_setting">Tweak Flow Launcher's settings</system:String>
<system:String x:Key="flowlauncher_plugin_sys_setting">Einstellungen des Flow Launchers anpassen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_sleep">Computer in Schlafmodus versetzen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_emptyrecyclebin">Papierkorb leeren</system:String>
<system:String x:Key="flowlauncher_plugin_sys_openrecyclebin">Open recycle bin</system:String>
<system:String x:Key="flowlauncher_plugin_sys_indexoption">Indexierungsoptionen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_hibernate">Hibernate computer</system:String>
<system:String x:Key="flowlauncher_plugin_sys_save_all_settings">Save all Flow Launcher settings</system:String>
<system:String x:Key="flowlauncher_plugin_sys_reload_plugin_data">Refreshes plugin data with new content</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_log_location">Open Flow Launcher's log location</system:String>
<system:String x:Key="flowlauncher_plugin_sys_check_for_update">Check for new Flow Launcher update</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_docs_tips">Visit Flow Launcher's documentation for more help and how to use tips</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_userdata_location">Open the location where Flow Launcher's settings are stored</system:String>
<system:String x:Key="flowlauncher_plugin_sys_openrecyclebin">Papierkorb öffnen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_indexoption">Indizierungsoptionen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_hibernate">Computer in den Ruhezustand versetzen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_save_all_settings">Alle Flow Launcher Einstellungen speichern</system:String>
<system:String x:Key="flowlauncher_plugin_sys_reload_plugin_data">Aktualisiert Plugin-Daten mit neuen Inhalten</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_log_location">Öffnet den Speicherort der Flow Launcher Logs</system:String>
<system:String x:Key="flowlauncher_plugin_sys_check_for_update">Prüft auf neue Flow Launcher Updates</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_docs_tips">Öffnet die Dokumentation von Flow Launcher für Hilfe und Tipps</system:String>
<system:String x:Key="flowlauncher_plugin_sys_open_userdata_location">Öffnet den Ort an dem Flow Laucher Einstellungen speichert</system:String>
<system:String x:Key="flowlauncher_plugin_sys_toggle_game_mode">Gott Modus</system:String>
<!-- Dialogs -->
<system:String x:Key="flowlauncher_plugin_sys_dlgtitle_success">Erfolgreich</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_settings_saved">All Flow Launcher settings saved</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded">Reloaded all applicable plugin data</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_shutdown_computer">Are you sure you want to shut the computer down?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer">Are you sure you want to restart the computer?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer_advanced">Are you sure you want to restart the computer with Advanced Boot Options?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_logoff_computer">Are you sure you want to log off?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_settings_saved">Alle Flow Launcher Einstellungen wurden gespeichert</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded">Alle betroffenen Plugin-Daten wurden neu geladen</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_shutdown_computer">Soll der Computer wirklich heruntergefahren werden?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer">Soll der Computer wirklich neu gestartet werden?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer_advanced">Soll der Computer wirklich mit erweiterten Startoptionen neu gestartet werden?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_logoff_computer">Soll der aktuelle Benutzer wirklich abgemeldet werden?</system:String>
<system:String x:Key="flowlauncher_plugin_sys_plugin_name">Systembefehle</system:String>
<system:String x:Key="flowlauncher_plugin_sys_plugin_description">Stellt Systemrelevante Befehle bereit. z.B. herunterfahren, sperren, Einstellungen, usw.</system:String>

View file

@ -4,7 +4,7 @@
"Name": "System Commands",
"Description": "Provide System related commands. e.g. shutdown,lock, setting etc.",
"Author": "qianlifeng",
"Version": "3.1.0",
"Version": "3.1.1",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Sys.dll",

View file

@ -197,7 +197,8 @@ namespace Flow.Launcher.Plugin.WebSearch
public SuggestionSource[] Suggestions { get; set; } = {
new Google(),
new Baidu(),
new Bing()
new Bing(),
new DuckDuckGo()
};
[JsonIgnore]

View file

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Http;
using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
using System.Threading;
using System.Text.Json;
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
public class DuckDuckGo : SuggestionSource
{
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
{
// When the search query is empty, DuckDuckGo returns `[]`. When it's not empty, it returns data
// in the following format: `["query", ["suggestion1", "suggestion2", ...]]`.
if (string.IsNullOrEmpty(query))
{
return new List<string>();
}
try
{
const string api = "https://duckduckgo.com/ac/?type=list&q=";
await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false);
using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token);
var results = json.RootElement.EnumerateArray().ElementAt(1);
return results.EnumerateArray().Select(o => o.GetString()).ToList();
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
Log.Exception("|DuckDuckGo.Suggestions|Can't get suggestion from DuckDuckGo", e);
return null;
}
catch (JsonException e)
{
Log.Exception("|DuckDuckGo.Suggestions|can't parse suggestions", e);
return new List<string>();
}
}
public override string ToString()
{
return "DuckDuckGo";
}
}
}

View file

@ -26,7 +26,7 @@
"Name": "Web Searches",
"Description": "Provide the web search ability",
"Author": "qianlifeng",
"Version": "3.0.6",
"Version": "3.0.7",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll",

View file

@ -1,4 +1,4 @@
version: '1.17.1.{build}'
version: '1.17.2.{build}'
init:
- ps: |