Merge branch 'dev' into filewatcher
|
|
@ -2,6 +2,8 @@
|
|||
using Flow.Launcher.Infrastructure.Logger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -10,43 +12,43 @@ namespace Flow.Launcher.Core.ExternalPlugins
|
|||
{
|
||||
public static class PluginsManifest
|
||||
{
|
||||
static PluginsManifest()
|
||||
{
|
||||
UpdateTask = UpdateManifestAsync();
|
||||
}
|
||||
|
||||
public static List<UserPlugin> UserPlugins { get; private set; } = new List<UserPlugin>();
|
||||
|
||||
public static Task UpdateTask { get; private set; }
|
||||
private const string manifestFileUrl = "https://cdn.jsdelivr.net/gh/Flow-Launcher/Flow.Launcher.PluginsManifest@plugin_api_v2/plugins.json";
|
||||
|
||||
private static readonly SemaphoreSlim manifestUpdateLock = new(1);
|
||||
|
||||
public static Task UpdateManifestAsync()
|
||||
{
|
||||
if (manifestUpdateLock.CurrentCount == 0)
|
||||
{
|
||||
return UpdateTask;
|
||||
}
|
||||
private static string latestEtag = "";
|
||||
|
||||
return UpdateTask = DownloadManifestAsync();
|
||||
}
|
||||
public static List<UserPlugin> UserPlugins { get; private set; } = new List<UserPlugin>();
|
||||
|
||||
private static async Task DownloadManifestAsync()
|
||||
public static async Task UpdateManifestAsync(CancellationToken token = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await manifestUpdateLock.WaitAsync().ConfigureAwait(false);
|
||||
await manifestUpdateLock.WaitAsync(token).ConfigureAwait(false);
|
||||
|
||||
await using var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json")
|
||||
.ConfigureAwait(false);
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl);
|
||||
request.Headers.Add("If-None-Match", latestEtag);
|
||||
|
||||
UserPlugins = await JsonSerializer.DeserializeAsync<List<UserPlugin>>(jsonStream).ConfigureAwait(false);
|
||||
var response = await Http.SendAsync(request, token).ConfigureAwait(false);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
Log.Info($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Fetched plugins from manifest repo");
|
||||
|
||||
var json = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false);
|
||||
|
||||
UserPlugins = await JsonSerializer.DeserializeAsync<List<UserPlugin>>(json, cancellationToken: token).ConfigureAwait(false);
|
||||
|
||||
latestEtag = response.Headers.ETag.Tag;
|
||||
}
|
||||
else if (response.StatusCode != HttpStatusCode.NotModified)
|
||||
{
|
||||
Log.Warn($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http response for manifest file was {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception("|PluginManagement.GetManifest|Encountered error trying to download plugins manifest", e);
|
||||
|
||||
UserPlugins = new List<UserPlugin>();
|
||||
Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -153,5 +153,13 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
|
||||
return await response.Content.ReadAsStreamAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchrously send an HTTP request.
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken token = default)
|
||||
{
|
||||
return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,13 @@ namespace Flow.Launcher.Plugin
|
|||
/// </summary>
|
||||
public string ActionKeywordAssigned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This holds the text which can be provided by plugin to be copied to the
|
||||
/// user's clipboard when Ctrl + C is pressed on a result. If the text is a file/directory path
|
||||
/// flow will copy the actual file/folder instead of just the path text.
|
||||
/// </summary>
|
||||
public string CopyText { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// This holds the text which can be provided by plugin to help Flow autocomplete text
|
||||
/// for user on the plugin result. If autocomplete action for example is tab, pressing tab will have
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ namespace Flow.Launcher
|
|||
DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// let exception throw as normal is better for Debug
|
||||
/// </summary>
|
||||
|
|
@ -179,4 +178,4 @@ namespace Flow.Launcher
|
|||
Current.MainWindow.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="InputSimulator" Version="1.0.4" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="ModernWpfUI" Version="0.9.4" />
|
||||
<PackageReference Include="NHotkey.Wpf" Version="2.1.0" />
|
||||
<PackageReference Include="NuGet.CommandLine" Version="5.4.0">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 506 B After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 674 B After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 792 B After Width: | Height: | Size: 752 B |
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 760 B After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 794 B After Width: | Height: | Size: 1.4 KiB |
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Opdater</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Annuler</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Denne opdatering vil genstarte Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Følgende filer bliver opdateret</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Følgende filer bliver opdateret</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Opdatereringsfiler</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Opdateringsbeskrivelse</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Opdateringsbeskrivelse</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Aktualisieren</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Abbrechen</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Diese Aktualisierung wird Flow Launcher neu starten</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Folgende Dateien werden aktualisiert</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Folgende Dateien werden aktualisiert</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Aktualisiere Dateien</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Aktualisierungbeschreibung</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Aktualisierungbeschreibung</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -18,6 +18,9 @@
|
|||
<system:String x:Key="copy">Copy</system:String>
|
||||
<system:String x:Key="cut">Cut</system:String>
|
||||
<system:String x:Key="paste">Paste</system:String>
|
||||
<system:String x:Key="fileTitle">File</system:String>
|
||||
<system:String x:Key="folderTitle">Folder</system:String>
|
||||
<system:String x:Key="textTitle">Text</system:String>
|
||||
<system:String x:Key="GameMode">Game Mode</system:String>
|
||||
<system:String x:Key="GameModeToolTip">Suspend the use of Hotkeys.</system:String>
|
||||
|
||||
|
|
@ -244,9 +247,9 @@
|
|||
<system:String x:Key="update_flowlauncher_fail">Update Failed</system:String>
|
||||
<system:String x:Key="update_flowlauncher_check_connection">Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">This upgrade will restart Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Following files will be updated</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Following files will be updated</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Update files</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Update description</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Update description</system:String>
|
||||
|
||||
<!-- Welcome Window -->
|
||||
<system:String x:Key="Skip">Skip</system:String>
|
||||
|
|
@ -281,7 +284,7 @@
|
|||
<system:String x:Key="RecommendShell">> ping 8.8.8.8</system:String>
|
||||
<system:String x:Key="RecommendShellDesc">Shell Command</system:String>
|
||||
<system:String x:Key="RecommendBluetooth">Bluetooth</system:String>
|
||||
<system:String x:Key="RecommendBluetoothDesc">Bluetooth in Windows Setting</system:String>
|
||||
<system:String x:Key="RecommendBluetoothDesc">Bluetooth in Windows Settings</system:String>
|
||||
<system:String x:Key="RecommendAcronyms">sn</system:String>
|
||||
<system:String x:Key="RecommendAcronymsDesc">Sticky Notes</system:String>
|
||||
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Mettre à jour</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Annuler</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Flow Launcher doit redémarrer pour installer cette mise à jour</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Les fichiers suivants seront mis à jour</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Les fichiers suivants seront mis à jour</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Fichiers mis à jour</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Description de la mise à jour</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Description de la mise à jour</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Aggiorna</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Annulla</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Questo aggiornamento riavvierà Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">I seguenti file saranno aggiornati</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">I seguenti file saranno aggiornati</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">File aggiornati</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Descrizione aggiornamento</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Descrizione aggiornamento</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -138,8 +138,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">アップデート</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">キャンセル</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">このアップデートでは、Flow Launcherの再起動が必要です</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">次のファイルがアップデートされます</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">次のファイルがアップデートされます</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">更新ファイル一覧</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">アップデートの詳細</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">アップデートの詳細</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -241,9 +241,9 @@
|
|||
<system:String x:Key="update_flowlauncher_fail">업데이트 실패</system:String>
|
||||
<system:String x:Key="update_flowlauncher_check_connection">Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">업데이트를 위해 Flow Launcher를 재시작합니다.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">아래 파일들이 업데이트됩니다.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">아래 파일들이 업데이트됩니다.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">업데이트 파일</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">업데이트 설명</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">업데이트 설명</system:String>
|
||||
|
||||
|
||||
<!-- Welcome Window -->
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Oppdater</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Avbryt</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Denne opgraderingen vil starte Flow Launcher på nytt</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Følgende filer vil bli oppdatert</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Følgende filer vil bli oppdatert</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Oppdateringsfiler</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Oppdateringsbeskrivelse</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Oppdateringsbeskrivelse</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Update</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Annuleer</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Deze upgrade zal Flow Launcher opnieuw opstarten</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Volgende bestanden zullen worden geüpdatet</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Volgende bestanden zullen worden geüpdatet</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Update bestanden</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Update beschrijving</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Update beschrijving</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Aktualizuj</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Anuluj</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Aby dokończyć proces aktualizacji Flow Launcher musi zostać zresetowany</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Następujące pliki zostaną zaktualizowane</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Następujące pliki zostaną zaktualizowane</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Aktualizuj pliki</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Opis aktualizacji</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Opis aktualizacji</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -135,8 +135,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Atualizar</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Cancelar</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Essa atualização reiniciará o Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Os seguintes arquivos serão atualizados</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Os seguintes arquivos serão atualizados</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Atualizar arquivos</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Atualizar descrição</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Atualizar descrição</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -244,9 +244,9 @@
|
|||
<system:String x:Key="update_flowlauncher_fail">Falha ao atualizar</system:String>
|
||||
<system:String x:Key="update_flowlauncher_check_connection">Verifique a sua ligação e as definições do proxy estabelecidas para github-cloud.s3.amazonaws.com</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Esta atualização irá reiniciar o Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Os seguintes ficheiros serão atualizados</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Os seguintes ficheiros serão atualizados</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Atualizar ficheiros</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Atualizar descrição</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Atualizar descrição</system:String>
|
||||
|
||||
<!-- Welcome Window -->
|
||||
<system:String x:Key="Skip">Ignorar</system:String>
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Обновить</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Отмена</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Это обновление перезапустит Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Следующие файлы будут обновлены</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Следующие файлы будут обновлены</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Обновить файлы</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Описание обновления</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Описание обновления</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -242,9 +242,9 @@
|
|||
<system:String x:Key="update_flowlauncher_fail">Aktualizácia zlyhala</system:String>
|
||||
<system:String x:Key="update_flowlauncher_check_connection">Skontrolujte pripojenie a skúste aktualizovať nastavenia servera proxy k github-cloud.s3.amazonaws.com.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Tento upgrade reštartuje Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Nasledujúce súbory budú aktualizované</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Nasledujúce súbory budú aktualizované</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Aktualizovať súbory</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Aktualizovať popis</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Aktualizovať popis</system:String>
|
||||
|
||||
<!-- Welcome Window -->
|
||||
<system:String x:Key="Skip">Preskočiť</system:String>
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Ažuriraj</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Otkaži</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Ova nadogradnja će ponovo pokrenuti Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Sledeće datoteke će biti ažurirane</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Sledeće datoteke će biti ažurirane</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Ažuriraj datoteke</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Opis ažuriranja</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Opis ažuriranja</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -139,8 +139,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Güncelle</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">İptal</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Bu güncelleme Flow Launcher'u yeniden başlatacaktır</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Aşağıdaki dosyalar güncelleştirilecektir</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Aşağıdaki dosyalar güncelleştirilecektir</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Güncellenecek dosyalar</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Güncelleme açıklaması</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Güncelleme açıklaması</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">Оновити</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">Скасувати</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">Це оновлення перезавантажить Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">Ці файли будуть оновлені</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">Ці файли будуть оновлені</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">Оновити файли</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">Опис оновлення</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">Опис оновлення</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -226,9 +226,9 @@
|
|||
<system:String x:Key="update_flowlauncher_fail">更新失败</system:String>
|
||||
<system:String x:Key="update_flowlauncher_check_connection">检查网络是否可以连接至github-cloud.s3.amazonaws.com.</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">此次更新需要重启Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">下列文件会被更新</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">下列文件会被更新</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">更新文件</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">更新日志</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">更新日志</system:String>
|
||||
|
||||
<!-- Welcome Window -->
|
||||
<system:String x:Key="Skip">跳过</system:String>
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@
|
|||
<system:String x:Key="update_flowlauncher_update">更新</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_cancel">取消</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_restart_flowlauncher_tip">此更新需要重新啟動 Flow Launcher</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_files">下列檔案會被更新</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_files">下列檔案會被更新</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_files">更新檔案</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_upadte_description">更新日誌</system:String>
|
||||
<system:String x:Key="update_flowlauncher_update_update_description">更新日誌</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@
|
|||
Style="{DynamicResource QueryBoxStyle}"
|
||||
Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Visibility="Visible">
|
||||
<TextBox.CommandBindings>
|
||||
<CommandBinding Command="ApplicationCommands.Copy" Executed="OnCopy" />
|
||||
</TextBox.CommandBindings>
|
||||
<TextBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Command="ApplicationCommands.Cut" Header="{DynamicResource cut}" />
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
|||
using NotifyIcon = System.Windows.Forms.NotifyIcon;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using System.Windows.Media;
|
||||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
|
|
@ -50,7 +52,18 @@ namespace Flow.Launcher
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
private void OnCopy(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
if (QueryTextBox.SelectionLength == 0)
|
||||
{
|
||||
_viewModel.ResultCopy(string.Empty);
|
||||
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(QueryTextBox.Text))
|
||||
{
|
||||
_viewModel.ResultCopy(QueryTextBox.SelectedText);
|
||||
}
|
||||
}
|
||||
private async void OnClosing(object sender, CancelEventArgs e)
|
||||
{
|
||||
_settings.WindowTop = Top;
|
||||
|
|
@ -59,6 +72,7 @@ namespace Flow.Launcher
|
|||
_viewModel.Save();
|
||||
e.Cancel = true;
|
||||
await PluginManager.DisposePluginsAsync();
|
||||
Notification.Uninstall();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -498,6 +512,24 @@ namespace Flow.Launcher
|
|||
e.Handled = true;
|
||||
}
|
||||
break;
|
||||
case Key.Back:
|
||||
var specialKeyState = GlobalHotkey.CheckModifiers();
|
||||
if (specialKeyState.CtrlPressed)
|
||||
{
|
||||
if (_viewModel.SelectedIsFromQueryResults()
|
||||
&& QueryTextBox.CaretIndex == QueryTextBox.Text.Length)
|
||||
{
|
||||
var queryWithoutActionKeyword =
|
||||
QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.NonGlobalPlugins).Search;
|
||||
|
||||
if (FilesFolders.IsLocationPathString(queryWithoutActionKeyword))
|
||||
{
|
||||
_viewModel.BackspaceCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Flow.Launcher.Infrastructure;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Windows.Data.Xml.Dom;
|
||||
|
|
@ -8,10 +9,17 @@ namespace Flow.Launcher
|
|||
{
|
||||
internal static class Notification
|
||||
{
|
||||
internal static bool legacy = Environment.OSVersion.Version.Build < 19041;
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
internal static void Uninstall()
|
||||
{
|
||||
if (!legacy)
|
||||
ToastNotificationManagerCompat.Uninstall();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public static void Show(string title, string subTitle, string iconPath)
|
||||
{
|
||||
var legacy = Environment.OSVersion.Version.Build < 19041;
|
||||
// Handle notification for win7/8/early win10
|
||||
if (legacy)
|
||||
{
|
||||
|
|
@ -24,13 +32,11 @@ namespace Flow.Launcher
|
|||
? Path.Combine(Constant.ProgramDirectory, "Images\\app.png")
|
||||
: iconPath;
|
||||
|
||||
var xml = $"<?xml version=\"1.0\"?><toast><visual><binding template=\"ToastImageAndText04\"><image id=\"1\" src=\"{Icon}\" alt=\"meziantou\"/><text id=\"1\">{title}</text>" +
|
||||
$"<text id=\"2\">{subTitle}</text></binding></visual></toast>";
|
||||
var toastXml = new XmlDocument();
|
||||
toastXml.LoadXml(xml);
|
||||
var toast = new ToastNotification(toastXml);
|
||||
ToastNotificationManager.CreateToastNotifier("Flow Launcher").Show(toast);
|
||||
|
||||
new ToastContentBuilder()
|
||||
.AddText(title, hintMaxLines: 1)
|
||||
.AddText(subTitle)
|
||||
.AddAppLogoOverride(new Uri(Icon))
|
||||
.Show();
|
||||
}
|
||||
|
||||
private static void LegacyShow(string title, string subTitle, string iconPath)
|
||||
|
|
|
|||
|
|
@ -2514,6 +2514,18 @@
|
|||
Margin="14,14,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Color15B}"
|
||||
TextWrapping="WrapWithOverflow">
|
||||
<Hyperlink NavigateUri="https://icons8.com" RequestNavigate="OnRequestNavigate">
|
||||
<Run Text="Icons by icons8.com" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Margin="14,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
DockPanel.Dock="Bottom"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Color15B}"
|
||||
|
|
|
|||
|
|
@ -13,12 +13,14 @@ using Flow.Launcher.Infrastructure.Hotkey;
|
|||
using Flow.Launcher.Infrastructure.Storage;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
using Flow.Launcher.Storage;
|
||||
using Flow.Launcher.Infrastructure.Logger;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using System.Threading.Channels;
|
||||
using ISavable = Flow.Launcher.Plugin.ISavable;
|
||||
|
||||
using System.IO;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
|
|
@ -229,7 +231,7 @@ namespace Flow.Launcher.ViewModel
|
|||
AutocompleteQueryCommand = new RelayCommand(_ =>
|
||||
{
|
||||
var result = SelectedResults.SelectedItem?.Result;
|
||||
if (result != null) // SelectedItem returns null if selection is empty.
|
||||
if (result != null && SelectedIsFromQueryResults()) // SelectedItem returns null if selection is empty.
|
||||
{
|
||||
var autoCompleteText = result.Title;
|
||||
|
||||
|
|
@ -252,6 +254,18 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
});
|
||||
|
||||
BackspaceCommand = new RelayCommand(index =>
|
||||
{
|
||||
var query = QueryBuilder.Build(QueryText.Trim(), PluginManager.NonGlobalPlugins);
|
||||
|
||||
// GetPreviousExistingDirectory does not require trailing '\', otherwise will return empty string
|
||||
var path = FilesFolders.GetPreviousExistingDirectory((_) => true, query.Search.TrimEnd('\\'));
|
||||
|
||||
var actionKeyword = string.IsNullOrEmpty(query.ActionKeyword) ? string.Empty : $"{query.ActionKeyword} ";
|
||||
|
||||
ChangeQueryText($"{actionKeyword}{path}");
|
||||
});
|
||||
|
||||
LoadContextMenuCommand = new RelayCommand(_ =>
|
||||
{
|
||||
if (SelectedIsFromQueryResults())
|
||||
|
|
@ -398,6 +412,7 @@ namespace Flow.Launcher.ViewModel
|
|||
public string PluginIconPath { get; set; } = null;
|
||||
|
||||
public ICommand EscCommand { get; set; }
|
||||
public ICommand BackspaceCommand { get; set; }
|
||||
public ICommand SelectNextItemCommand { get; set; }
|
||||
public ICommand SelectPrevItemCommand { get; set; }
|
||||
public ICommand SelectNextPageCommand { get; set; }
|
||||
|
|
@ -410,6 +425,9 @@ namespace Flow.Launcher.ViewModel
|
|||
public ICommand OpenSettingCommand { get; set; }
|
||||
public ICommand ReloadPluginDataCommand { get; set; }
|
||||
public ICommand ClearQueryCommand { get; private set; }
|
||||
|
||||
public ICommand CopyToClipboard { get; set; }
|
||||
|
||||
public ICommand AutocompleteQueryCommand { get; set; }
|
||||
|
||||
public string OpenResultCommandModifiers { get; private set; }
|
||||
|
|
@ -662,7 +680,7 @@ namespace Flow.Launcher.ViewModel
|
|||
Action = _ =>
|
||||
{
|
||||
_topMostRecord.Remove(result);
|
||||
App.API.ShowMsg("Success");
|
||||
App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success"));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
@ -706,7 +724,11 @@ namespace Flow.Launcher.ViewModel
|
|||
IcoPath = icon,
|
||||
SubTitle = subtitle,
|
||||
PluginDirectory = metadata.PluginDirectory,
|
||||
Action = _ => false
|
||||
Action = _ =>
|
||||
{
|
||||
App.API.OpenUrl(metadata.Website);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return menu;
|
||||
}
|
||||
|
|
@ -853,6 +875,52 @@ namespace Flow.Launcher.ViewModel
|
|||
Results.AddResults(resultsForUpdates, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the global copy method for an individual result. If no text is passed,
|
||||
/// the method will work out what is to be copied based on the result, so plugin can offer the text
|
||||
/// to be copied via the result model. If the text is a directory/file path,
|
||||
/// then actual file/folder will be copied instead.
|
||||
/// The result's subtitle text is the default text to be copied
|
||||
/// </summary>
|
||||
public void ResultCopy(string stringToCopy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stringToCopy))
|
||||
{
|
||||
var result = Results.SelectedItem?.Result;
|
||||
if (result != null)
|
||||
{
|
||||
string copyText = string.IsNullOrEmpty(result.CopyText) ? result.SubTitle : result.CopyText;
|
||||
var isFile = File.Exists(copyText);
|
||||
var isFolder = Directory.Exists(copyText);
|
||||
if (isFile || isFolder)
|
||||
{
|
||||
var paths = new StringCollection();
|
||||
paths.Add(copyText);
|
||||
|
||||
Clipboard.SetFileDropList(paths);
|
||||
App.API.ShowMsg(
|
||||
App.API.GetTranslation("copy")
|
||||
+" "
|
||||
+ (isFile? App.API.GetTranslation("fileTitle") : App.API.GetTranslation("folderTitle")),
|
||||
App.API.GetTranslation("completedSuccessfully"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Clipboard.SetDataObject(copyText.ToString());
|
||||
App.API.ShowMsg(
|
||||
App.API.GetTranslation("copy")
|
||||
+ " "
|
||||
+ App.API.GetTranslation("textTitle"),
|
||||
App.API.GetTranslation("completedSuccessfully"));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Clipboard.SetDataObject(stringToCopy);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,16 @@ using Flow.Launcher.Infrastructure.Logger;
|
|||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using System.IO;
|
||||
using System.Drawing.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
public class ResultViewModel : BaseModel
|
||||
{
|
||||
private static PrivateFontCollection fontCollection = new();
|
||||
private static Dictionary<string, string> fonts = new();
|
||||
|
||||
public ResultViewModel(Result result, Settings settings)
|
||||
{
|
||||
if (result != null)
|
||||
|
|
@ -23,13 +28,29 @@ namespace Flow.Launcher.ViewModel
|
|||
// Checks if it's a system installed font, which does not require path to be provided.
|
||||
if (glyph.FontFamily.EndsWith(".ttf") || glyph.FontFamily.EndsWith(".otf"))
|
||||
{
|
||||
var fontPath = Result.Glyph.FontFamily;
|
||||
Glyph = Path.IsPathRooted(fontPath)
|
||||
? Result.Glyph
|
||||
: Result.Glyph with
|
||||
string fontFamilyPath = glyph.FontFamily;
|
||||
|
||||
if (!Path.IsPathRooted(fontFamilyPath))
|
||||
{
|
||||
fontFamilyPath = Path.Combine(Result.PluginDirectory, fontFamilyPath);
|
||||
}
|
||||
|
||||
if (fonts.ContainsKey(fontFamilyPath))
|
||||
{
|
||||
Glyph = glyph with
|
||||
{
|
||||
FontFamily = Path.Combine(Result.PluginDirectory, fontPath)
|
||||
FontFamily = fonts[fontFamilyPath]
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fontCollection.AddFontFile(fontFamilyPath);
|
||||
fonts[fontFamilyPath] = $"{Path.GetDirectoryName(fontFamilyPath)}/#{fontCollection.Families[^1].Name}";
|
||||
Glyph = glyph with
|
||||
{
|
||||
FontFamily = fonts[fontFamilyPath]
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -310,4 +310,4 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 3.2 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "Browser Bookmarks",
|
||||
"Description": "Search your browser bookmarks",
|
||||
"Author": "qianlifeng, Ioannis G.",
|
||||
"Version": "1.6.2",
|
||||
"Version": "1.6.3",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.BrowserBookmark.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 3.2 KiB |
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">제어판</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">제어판 항목을 검색합니다.</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.3 KiB |
|
|
@ -10,7 +10,7 @@
|
|||
"Name": "Explorer",
|
||||
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
|
||||
"Author": "Jeremy Wu",
|
||||
"Version": "1.11.1",
|
||||
"Version": "1.11.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 2.7 KiB |
|
|
@ -25,6 +25,7 @@ namespace Flow.Launcher.Plugin.PluginIndicator
|
|||
SubTitle = $"Activate {metadata.Name} plugin",
|
||||
Score = 100,
|
||||
IcoPath = metadata.IcoPath,
|
||||
AutoCompleteText = $"{keyword}{Plugin.Query.TermSeparator}",
|
||||
Action = c =>
|
||||
{
|
||||
context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "Plugin Indicator",
|
||||
"Description": "Provide plugin actionword suggestion",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.1.3",
|
||||
"Version": "1.1.4",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.PluginIndicator.dll",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Flow.Launcher.Plugin.PluginsManager
|
||||
{
|
||||
|
|
@ -53,8 +53,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
{
|
||||
// standard UrlSourceCode format in PluginsManifest's plugins.json file: https://github.com/jjw24/Flow.Launcher.Plugin.Putty/tree/master
|
||||
var link = pluginManifestInfo.UrlSourceCode.StartsWith("https://github.com")
|
||||
? pluginManifestInfo.UrlSourceCode.Replace("/tree/master", "/issues/new/choose")
|
||||
: pluginManifestInfo.UrlSourceCode;
|
||||
? Regex.Replace(pluginManifestInfo.UrlSourceCode, @"\/tree\/\w+$", "") + "/issues/new/choose"
|
||||
: pluginManifestInfo.UrlSourceCode;
|
||||
|
||||
Context.API.OpenUrl(link);
|
||||
return true;
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 484 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 2.7 KiB |
|
|
@ -12,7 +12,7 @@ using System.Windows;
|
|||
|
||||
namespace Flow.Launcher.Plugin.PluginsManager
|
||||
{
|
||||
public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n, IAsyncReloadable
|
||||
public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n
|
||||
{
|
||||
internal PluginInitContext Context { get; set; }
|
||||
|
||||
|
|
@ -24,28 +24,20 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
|
||||
internal PluginsManager pluginManager;
|
||||
|
||||
private DateTime lastUpdateTime = DateTime.MinValue;
|
||||
|
||||
public Control CreateSettingPanel()
|
||||
{
|
||||
return new PluginsManagerSettings(viewModel);
|
||||
}
|
||||
|
||||
public Task InitAsync(PluginInitContext context)
|
||||
public async Task InitAsync(PluginInitContext context)
|
||||
{
|
||||
Context = context;
|
||||
Settings = context.API.LoadSettingJsonStorage<Settings>();
|
||||
viewModel = new SettingsViewModel(context, Settings);
|
||||
contextMenu = new ContextMenu(Context);
|
||||
pluginManager = new PluginsManager(Context, Settings);
|
||||
_manifestUpdateTask = pluginManager
|
||||
.UpdateManifestAsync(true)
|
||||
.ContinueWith(_ =>
|
||||
{
|
||||
lastUpdateTime = DateTime.Now;
|
||||
}, TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
|
||||
return Task.CompletedTask;
|
||||
await pluginManager.UpdateManifestAsync();
|
||||
}
|
||||
|
||||
public List<Result> LoadContextMenus(Result selectedResult)
|
||||
|
|
@ -53,35 +45,20 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
return contextMenu.LoadContextMenus(selectedResult);
|
||||
}
|
||||
|
||||
private Task _manifestUpdateTask = Task.CompletedTask;
|
||||
|
||||
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
|
||||
{
|
||||
var search = query.Search;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(search))
|
||||
if (string.IsNullOrWhiteSpace(query.Search))
|
||||
return pluginManager.GetDefaultHotKeys();
|
||||
|
||||
if ((DateTime.Now - lastUpdateTime).TotalHours > 12 && _manifestUpdateTask.IsCompleted) // 12 hours
|
||||
{
|
||||
_manifestUpdateTask = pluginManager.UpdateManifestAsync().ContinueWith(t =>
|
||||
{
|
||||
lastUpdateTime = DateTime.Now;
|
||||
}, TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
}
|
||||
|
||||
return search switch
|
||||
return query.FirstSearch.ToLower() switch
|
||||
{
|
||||
//search could be url, no need ToLower() when passed in
|
||||
var s when s.StartsWith(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase)
|
||||
=> await pluginManager.RequestInstallOrUpdate(search, token),
|
||||
var s when s.StartsWith(Settings.HotkeyUninstall, StringComparison.OrdinalIgnoreCase)
|
||||
=> pluginManager.RequestUninstall(search),
|
||||
var s when s.StartsWith(Settings.HotkeyUpdate, StringComparison.OrdinalIgnoreCase)
|
||||
=> await pluginManager.RequestUpdate(search, token),
|
||||
Settings.InstallCommand => await pluginManager.RequestInstallOrUpdate(query.SecondToEndSearch, token),
|
||||
Settings.UninstallCommand => pluginManager.RequestUninstall(query.SecondToEndSearch),
|
||||
Settings.UpdateCommand => await pluginManager.RequestUpdate(query.SecondToEndSearch, token),
|
||||
_ => pluginManager.GetDefaultHotKeys().Where(hotkey =>
|
||||
{
|
||||
hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score;
|
||||
hotkey.Score = StringMatcher.FuzzySearch(query.Search, hotkey.Title).Score;
|
||||
return hotkey.Score > 0;
|
||||
}).ToList()
|
||||
};
|
||||
|
|
@ -96,11 +73,5 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
{
|
||||
return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description");
|
||||
}
|
||||
|
||||
public async Task ReloadDataAsync()
|
||||
{
|
||||
await pluginManager.UpdateManifestAsync();
|
||||
lastUpdateTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
|
||||
private Task _downloadManifestTask = Task.CompletedTask;
|
||||
|
||||
internal Task UpdateManifestAsync(bool silent = false)
|
||||
internal Task UpdateManifestAsync(CancellationToken token = default, bool silent = false)
|
||||
{
|
||||
if (_downloadManifestTask.Status == TaskStatus.Running)
|
||||
{
|
||||
|
|
@ -59,7 +59,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
}
|
||||
else
|
||||
{
|
||||
_downloadManifestTask = PluginsManifest.UpdateTask;
|
||||
_downloadManifestTask = PluginsManifest.UpdateManifestAsync(token);
|
||||
if (!silent)
|
||||
_downloadManifestTask.ContinueWith(_ =>
|
||||
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_failed_title"),
|
||||
|
|
@ -75,31 +75,34 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
{
|
||||
new Result()
|
||||
{
|
||||
Title = Settings.HotKeyInstall,
|
||||
Title = Settings.InstallCommand,
|
||||
IcoPath = icoPath,
|
||||
AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} ",
|
||||
Action = _ =>
|
||||
{
|
||||
Context.API.ChangeQuery("pm install ");
|
||||
Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} ");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new Result()
|
||||
{
|
||||
Title = Settings.HotkeyUninstall,
|
||||
Title = Settings.UninstallCommand,
|
||||
IcoPath = icoPath,
|
||||
AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} ",
|
||||
Action = _ =>
|
||||
{
|
||||
Context.API.ChangeQuery("pm uninstall ");
|
||||
Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} ");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new Result()
|
||||
{
|
||||
Title = Settings.HotkeyUpdate,
|
||||
Title = Settings.UpdateCommand,
|
||||
IcoPath = icoPath,
|
||||
AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} ",
|
||||
Action = _ =>
|
||||
{
|
||||
Context.API.ChangeQuery("pm update ");
|
||||
Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -119,7 +122,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
Context
|
||||
.API
|
||||
.ChangeQuery(
|
||||
$"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}");
|
||||
$"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.UpdateCommand} {plugin.Name}");
|
||||
|
||||
var mainWindow = Application.Current.MainWindow;
|
||||
mainWindow.Show();
|
||||
|
|
@ -181,22 +184,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
|
||||
internal async ValueTask<List<Result>> RequestUpdate(string search, CancellationToken token)
|
||||
{
|
||||
if (!PluginsManifest.UserPlugins.Any())
|
||||
{
|
||||
await UpdateManifestAsync();
|
||||
}
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var autocompletedResults = AutoCompleteReturnAllResults(search,
|
||||
Settings.HotkeyUpdate,
|
||||
"Update",
|
||||
"Select a plugin to update");
|
||||
|
||||
if (autocompletedResults.Any())
|
||||
return autocompletedResults;
|
||||
|
||||
var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart();
|
||||
await UpdateManifestAsync(token);
|
||||
|
||||
var resultsForUpdate =
|
||||
from existingPlugin in Context.API.GetAllPlugins()
|
||||
|
|
@ -285,7 +273,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
}
|
||||
});
|
||||
|
||||
return Search(results, uninstallSearch);
|
||||
return Search(results, search);
|
||||
}
|
||||
|
||||
internal bool PluginExists(string id)
|
||||
|
|
@ -369,20 +357,13 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
return url.StartsWith(acceptedSource) && Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(contructedUrlPart));
|
||||
}
|
||||
|
||||
internal async ValueTask<List<Result>> RequestInstallOrUpdate(string searchName, CancellationToken token)
|
||||
internal async ValueTask<List<Result>> RequestInstallOrUpdate(string search, CancellationToken token)
|
||||
{
|
||||
if (!PluginsManifest.UserPlugins.Any())
|
||||
{
|
||||
await UpdateManifestAsync();
|
||||
}
|
||||
await UpdateManifestAsync(token);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty, StringComparison.OrdinalIgnoreCase).Trim();
|
||||
|
||||
if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute)
|
||||
&& searchNameWithoutKeyword.Split('.').Last() == zip)
|
||||
return InstallFromWeb(searchNameWithoutKeyword);
|
||||
if (Uri.IsWellFormedUriString(search, UriKind.Absolute)
|
||||
&& search.Split('.').Last() == zip)
|
||||
return InstallFromWeb(search);
|
||||
|
||||
var results =
|
||||
PluginsManifest
|
||||
|
|
@ -408,7 +389,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
ContextData = x
|
||||
});
|
||||
|
||||
return Search(results, searchNameWithoutKeyword);
|
||||
return Search(results, search);
|
||||
}
|
||||
|
||||
private void Install(UserPlugin plugin, string downloadedFilePath)
|
||||
|
|
@ -468,16 +449,6 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
|
||||
internal List<Result> RequestUninstall(string search)
|
||||
{
|
||||
var autocompletedResults = AutoCompleteReturnAllResults(search,
|
||||
Settings.HotkeyUninstall,
|
||||
"Uninstall",
|
||||
"Select a plugin to uninstall");
|
||||
|
||||
if (autocompletedResults.Any())
|
||||
return autocompletedResults;
|
||||
|
||||
var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart();
|
||||
|
||||
var results = Context.API
|
||||
.GetAllPlugins()
|
||||
.Select(x =>
|
||||
|
|
@ -508,7 +479,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
}
|
||||
});
|
||||
|
||||
return Search(results, uninstallSearch);
|
||||
return Search(results, search);
|
||||
}
|
||||
|
||||
private void Uninstall(PluginMetadata plugin, bool removedSetting = true)
|
||||
|
|
@ -523,36 +494,6 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt"));
|
||||
}
|
||||
|
||||
private List<Result> AutoCompleteReturnAllResults(string search, string hotkey, string title, string subtitle)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(search)
|
||||
&& hotkey.StartsWith(search)
|
||||
&& (hotkey != search || !search.StartsWith(hotkey)))
|
||||
{
|
||||
return
|
||||
new List<Result>
|
||||
{
|
||||
new Result
|
||||
{
|
||||
Title = title,
|
||||
IcoPath = icoPath,
|
||||
SubTitle = subtitle,
|
||||
Action = e =>
|
||||
{
|
||||
Context
|
||||
.API
|
||||
.ChangeQuery(
|
||||
$"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {hotkey} ");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new List<Result>();
|
||||
}
|
||||
|
||||
private bool SameOrLesserPluginVersionExists(string metadataPath)
|
||||
{
|
||||
var newMetadata = JsonSerializer.Deserialize<PluginMetadata>(File.ReadAllText(metadataPath));
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
{
|
||||
internal class Settings
|
||||
{
|
||||
internal string HotKeyInstall { get; set; } = "install";
|
||||
internal const string InstallCommand = "install";
|
||||
|
||||
internal string HotkeyUninstall { get; set; } = "uninstall";
|
||||
internal const string UninstallCommand = "uninstall";
|
||||
|
||||
internal string HotkeyUpdate { get; set; } = "update";
|
||||
internal const string UpdateCommand = "update";
|
||||
|
||||
public bool WarnFromUnknownSource { get; set; } = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"Name": "Plugins Manager",
|
||||
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
|
||||
"Author": "Jeremy Wu",
|
||||
"Version": "1.11.2",
|
||||
"Version": "1.12.1",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
|
@ -88,6 +88,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
TitleHighlightData = StringMatcher.FuzzySearch(termToSearch, p.ProcessName).MatchData,
|
||||
Score = pr.Score,
|
||||
ContextData = p.ProcessName,
|
||||
AutoCompleteText = $"{_context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}",
|
||||
Action = (c) =>
|
||||
{
|
||||
processHelper.TryKill(p);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Name":"Process Killer",
|
||||
"Description":"Kill running processes from Flow",
|
||||
"Author":"Flow-Launcher",
|
||||
"Version":"1.2.4",
|
||||
"Version":"1.2.6",
|
||||
"Language":"csharp",
|
||||
"Website":"https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller",
|
||||
"IcoPath":"Images\\app.png",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.3 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "Program",
|
||||
"Description": "Search programs in Flow.Launcher",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.8.1",
|
||||
"Version": "1.8.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Program.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 2.5 KiB |