mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Release 1.9.3 (#1052)
## Bug fixes - Addresses the issue where WindowsSettings plugin results appear higher than other results #1020 - Fixed an issue where full screen mode does not disable hotkey when enabled #1037 - Fixed some potential issues when loading plugins that use shared assembly #1036 - Sorted out a race condition issue causing image loading on some results to fail #1040 - Revised ttf/otf support #935 - Resolved the issue where WebSearch plugin would crash if not connected to internet #977 - Fixed incorrect text for "New Tab" and "New Window" buttons under Settings' default browser section #951 - Fixed typos in plugin title and WindowsSettings name inside the context menu #1056
This commit is contained in:
parent
68101e0bda
commit
84a806bf75
20 changed files with 92 additions and 90 deletions
|
|
@ -15,20 +15,6 @@ namespace Flow.Launcher.Core.Plugin
|
|||
|
||||
private readonly AssemblyName assemblyName;
|
||||
|
||||
private static readonly ConcurrentDictionary<string, byte> loadedAssembly;
|
||||
|
||||
static PluginAssemblyLoader()
|
||||
{
|
||||
var currentAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
loadedAssembly = new ConcurrentDictionary<string, byte>(
|
||||
currentAssemblies.Select(x => new KeyValuePair<string, byte>(x.FullName, default)));
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyLoad += (sender, args) =>
|
||||
{
|
||||
loadedAssembly[args.LoadedAssembly.FullName] = default;
|
||||
};
|
||||
}
|
||||
|
||||
internal PluginAssemblyLoader(string assemblyFilePath)
|
||||
{
|
||||
dependencyResolver = new AssemblyDependencyResolver(assemblyFilePath);
|
||||
|
|
@ -47,10 +33,9 @@ namespace Flow.Launcher.Core.Plugin
|
|||
// When resolving dependencies, ignore assembly depenedencies that already exits with Flow.Launcher
|
||||
// Otherwise duplicate assembly will be loaded and some weird behavior will occur, such as WinRT.Runtime.dll
|
||||
// will fail due to loading multiple versions in process, each with their own static instance of registration state
|
||||
if (assemblyPath == null || ExistsInReferencedPackage(assemblyName))
|
||||
return null;
|
||||
var existAssembly = Default.Assemblies.FirstOrDefault(x => x.FullName == assemblyName.FullName);
|
||||
|
||||
return LoadFromAssemblyPath(assemblyPath);
|
||||
return existAssembly ?? (assemblyPath == null ? null : LoadFromAssemblyPath(assemblyPath));
|
||||
}
|
||||
|
||||
internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type)
|
||||
|
|
@ -58,10 +43,5 @@ namespace Flow.Launcher.Core.Plugin
|
|||
var allTypes = assembly.ExportedTypes;
|
||||
return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Any(t => t == type));
|
||||
}
|
||||
|
||||
internal bool ExistsInReferencedPackage(AssemblyName assemblyName)
|
||||
{
|
||||
return loadedAssembly.ContainsKey(assemblyName.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary
|
||||
// Double Check to avoid concurrent remove
|
||||
if (Data.Count > permissibleFactor * MaxCached)
|
||||
foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key).ToArray())
|
||||
foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
|
||||
Data.TryRemove(key, out _);
|
||||
semaphore.Release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Flow.Launcher.Helper
|
|||
|
||||
internal static void OnToggleHotkey(object sender, HotkeyEventArgs args)
|
||||
{
|
||||
if (!mainViewModel.GameModeStatus)
|
||||
if (!mainViewModel.ShouldIgnoreHotkeys() && !mainViewModel.GameModeStatus)
|
||||
mainViewModel.ToggleFlowLauncher();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,8 +176,8 @@
|
|||
<system:String x:Key="defaultBrowser_name">Browser</system:String>
|
||||
<system:String x:Key="defaultBrowser_profile_name">Browser Name</system:String>
|
||||
<system:String x:Key="defaultBrowser_path">Browser Path</system:String>
|
||||
<system:String x:Key="defaultBrowser_newtab">New Window</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">New Tab</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">New Window</system:String>
|
||||
<system:String x:Key="defaultBrowser_newTab">New Tab</system:String>
|
||||
<system:String x:Key="defaultBrowser_parameter">Private Mode</system:String>
|
||||
|
||||
<!-- Priority Setting Dialog -->
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@
|
|||
<system:String x:Key="defaultBrowser_name">브라우저</system:String>
|
||||
<system:String x:Key="defaultBrowser_profile_name">브라우저 이름</system:String>
|
||||
<system:String x:Key="defaultBrowser_path">브라우저 경로</system:String>
|
||||
<system:String x:Key="defaultBrowser_newtab">새 창</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">새 탭</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">새 창</system:String>
|
||||
<system:String x:Key="defaultBrowser_newTab">새 탭</system:String>
|
||||
<system:String x:Key="defaultBrowser_parameter">프라이빗 모드</system:String>
|
||||
|
||||
<!-- Priority Setting Dialog -->
|
||||
|
|
|
|||
|
|
@ -176,8 +176,8 @@
|
|||
<system:String x:Key="defaultBrowser_name">Navegador</system:String>
|
||||
<system:String x:Key="defaultBrowser_profile_name">Nome do navegador</system:String>
|
||||
<system:String x:Key="defaultBrowser_path">Caminho do navegador</system:String>
|
||||
<system:String x:Key="defaultBrowser_newtab">Nova janela</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">Novo separador</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">Nova janela</system:String>
|
||||
<system:String x:Key="defaultBrowser_newTab">Novo separador</system:String>
|
||||
<system:String x:Key="defaultBrowser_parameter">Modo privado</system:String>
|
||||
|
||||
<!-- Priority Setting Dialog -->
|
||||
|
|
|
|||
|
|
@ -174,8 +174,8 @@
|
|||
<system:String x:Key="defaultBrowser_name">Prehliadač</system:String>
|
||||
<system:String x:Key="defaultBrowser_profile_name">Názov prehliadača</system:String>
|
||||
<system:String x:Key="defaultBrowser_path">Cesta k prehliadaču</system:String>
|
||||
<system:String x:Key="defaultBrowser_newtab">Nové okno</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">Nová karta</system:String>
|
||||
<system:String x:Key="defaultBrowser_newWindow">Nové okno</system:String>
|
||||
<system:String x:Key="defaultBrowser_newTab">Nová karta</system:String>
|
||||
<system:String x:Key="defaultBrowser_parameter">Privátny režim</system:String>
|
||||
|
||||
<!-- Priority Setting Dialog -->
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ namespace Flow.Launcher
|
|||
var link = new Hyperlink { IsEnabled = true };
|
||||
link.Inlines.Add(url);
|
||||
link.NavigateUri = new Uri(url);
|
||||
link.RequestNavigate += (s, e) => SearchWeb.NewTabInBrowser(e.Uri.ToString());
|
||||
link.Click += (s, e) => SearchWeb.NewTabInBrowser(url);
|
||||
link.RequestNavigate += (s, e) => SearchWeb.OpenInBrowserTab(e.Uri.ToString());
|
||||
link.Click += (s, e) => SearchWeb.OpenInBrowserTab(url);
|
||||
|
||||
paragraph.Inlines.Add(textBeforeUrl);
|
||||
paragraph.Inlines.Add(link);
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@
|
|||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<RadioButton IsChecked="{Binding OpenInTab}"
|
||||
Content="{DynamicResource defaultBrowser_newWindow}"></RadioButton>
|
||||
Content="{DynamicResource defaultBrowser_newTab}"></RadioButton>
|
||||
<RadioButton IsChecked="{Binding OpenInNewWindow, Mode=OneTime}"
|
||||
Content="{DynamicResource defaultBrowser_newWindow}"></RadioButton>
|
||||
</StackPanel>
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ namespace Flow.Launcher
|
|||
var uri = new Uri(website);
|
||||
if (Uri.CheckSchemeName(uri.Scheme))
|
||||
{
|
||||
website.NewTabInBrowser();
|
||||
website.OpenInBrowserTab();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
{
|
||||
if (e.SpecialKeyState.CtrlPressed)
|
||||
{
|
||||
SearchWeb.NewTabInBrowser(plugin.UrlDownload);
|
||||
SearchWeb.OpenInBrowserTab(plugin.UrlDownload);
|
||||
return ShouldHideWindow;
|
||||
}
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
{
|
||||
if (e.SpecialKeyState.CtrlPressed)
|
||||
{
|
||||
SearchWeb.NewTabInBrowser(x.Website);
|
||||
SearchWeb.OpenInBrowserTab(x.Website);
|
||||
return ShouldHideWindow;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
var results = new List<Result>();
|
||||
|
||||
foreach (SearchSource searchSource in _settings.SearchSources.Where(o => (o.ActionKeyword == query.ActionKeyword ||
|
||||
o.ActionKeyword == SearchSourceGlobalPluginWildCardSign)
|
||||
&& o.Enabled))
|
||||
o.ActionKeyword == SearchSourceGlobalPluginWildCardSign)
|
||||
&& o.Enabled))
|
||||
{
|
||||
string keyword = string.Empty;
|
||||
keyword = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? query.ToString() : query.Search;
|
||||
|
|
@ -105,11 +105,11 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
if (_settings.EnableSuggestion)
|
||||
{
|
||||
var suggestions = await SuggestionsAsync(keyword, subtitle, searchSource, token).ConfigureAwait(false);
|
||||
if (token.IsCancellationRequested || !suggestions.Any())
|
||||
var enumerable = suggestions?.ToList();
|
||||
if (token.IsCancellationRequested || enumerable is not { Count: > 0 })
|
||||
return;
|
||||
|
||||
|
||||
results.AddRange(suggestions);
|
||||
|
||||
results.AddRange(enumerable);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
|
@ -118,32 +118,32 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
private async Task<IEnumerable<Result>> SuggestionsAsync(string keyword, string subtitle, SearchSource searchSource, CancellationToken token)
|
||||
{
|
||||
var source = _settings.SelectedSuggestion;
|
||||
if (source != null)
|
||||
if (source == null)
|
||||
{
|
||||
//Suggestions appear below actual result, and appear above global action keyword match if non-global;
|
||||
var score = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? scoreSuggestions : scoreSuggestions + 1;
|
||||
|
||||
var suggestions = await source.Suggestions(keyword, token).ConfigureAwait(false);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var resultsFromSuggestion = suggestions?.Select(o => new Result
|
||||
{
|
||||
Title = o,
|
||||
SubTitle = subtitle,
|
||||
Score = score,
|
||||
IcoPath = searchSource.IconPath,
|
||||
ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword,
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return resultsFromSuggestion;
|
||||
return new List<Result>();
|
||||
}
|
||||
return new List<Result>();
|
||||
//Suggestions appear below actual result, and appear above global action keyword match if non-global;
|
||||
var score = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? scoreSuggestions : scoreSuggestions + 1;
|
||||
|
||||
var suggestions = await source.SuggestionsAsync(keyword, token).ConfigureAwait(false);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var resultsFromSuggestion = suggestions?.Select(o => new Result
|
||||
{
|
||||
Title = o,
|
||||
SubTitle = subtitle,
|
||||
Score = score,
|
||||
IcoPath = searchSource.IconPath,
|
||||
ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword,
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return resultsFromSuggestion;
|
||||
}
|
||||
|
||||
public Task InitAsync(PluginInitContext context)
|
||||
|
|
@ -191,4 +191,4 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
|
||||
public event ResultUpdatedEventHandler ResultsUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
private readonly Regex _reg = new Regex("window.baidu.sug\\((.*)\\)");
|
||||
|
||||
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
string result;
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
const string api = "http://suggestion.baidu.com/su?json=1&wd=";
|
||||
result = await Http.GetAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e.InnerException is TimeoutException)
|
||||
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
|
||||
{
|
||||
Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
class Bing : SuggestionSource
|
||||
{
|
||||
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
|
||||
try
|
||||
|
|
@ -40,7 +40,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
|
||||
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e.InnerException is TimeoutException)
|
||||
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
|
||||
{
|
||||
Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
public class Google : SuggestionSource
|
||||
{
|
||||
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -32,7 +32,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
return results.EnumerateArray().Select(o => o.GetString()).ToList();
|
||||
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e.InnerException is TimeoutException)
|
||||
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
|
||||
{
|
||||
Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
public abstract class SuggestionSource
|
||||
{
|
||||
public abstract Task<List<string>> Suggestions(string query, CancellationToken token);
|
||||
public abstract Task<List<string>> SuggestionsAsync(string query, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper
|
|||
var resultList = new List<Result>();
|
||||
foreach (var entry in list)
|
||||
{
|
||||
const int highScore = 20;
|
||||
const int midScore = 10;
|
||||
// Adjust the score to lower the order of many irrelevant matches from area strings
|
||||
// that may only be for description.
|
||||
const int nonNameMatchScoreAdj = 10;
|
||||
|
||||
Result? result;
|
||||
Debug.Assert(_api != null, nameof(_api) + " != null");
|
||||
|
|
@ -44,7 +45,7 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper
|
|||
|
||||
if (nameMatch.IsSearchPrecisionScoreMet())
|
||||
{
|
||||
var settingResult = NewSettingResult(nameMatch.Score + highScore, entry.Type);
|
||||
var settingResult = NewSettingResult(nameMatch.Score, entry.Type);
|
||||
settingResult.TitleHighlightData = nameMatch.MatchData;
|
||||
result = settingResult;
|
||||
}
|
||||
|
|
@ -53,7 +54,7 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper
|
|||
var areaMatch = _api.FuzzySearch(query.Search, entry.Area);
|
||||
if (areaMatch.IsSearchPrecisionScoreMet())
|
||||
{
|
||||
var settingResult = NewSettingResult(areaMatch.Score + midScore, entry.Type);
|
||||
var settingResult = NewSettingResult(areaMatch.Score - nonNameMatchScoreAdj, entry.Type);
|
||||
result = settingResult;
|
||||
}
|
||||
else
|
||||
|
|
@ -61,7 +62,7 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper
|
|||
result = entry.AltNames?
|
||||
.Select(altName => _api.FuzzySearch(query.Search, altName))
|
||||
.Where(match => match.IsSearchPrecisionScoreMet())
|
||||
.Select(altNameMatch => NewSettingResult(altNameMatch.Score + midScore, entry.Type))
|
||||
.Select(altNameMatch => NewSettingResult(altNameMatch.Score - nonNameMatchScoreAdj, entry.Type))
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper
|
|||
.SelectMany(x => x)
|
||||
.Contains(x, StringComparer.CurrentCultureIgnoreCase))
|
||||
)
|
||||
result = NewSettingResult(midScore, entry.Type);
|
||||
result = NewSettingResult(nonNameMatchScoreAdj, entry.Type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ namespace Flow.Launcher.Plugin.WindowsSettings.Helper
|
|||
private static void AddOptionalToolTip(WindowsSetting entry, Result result)
|
||||
{
|
||||
var toolTipText = new StringBuilder();
|
||||
|
||||
|
||||
var settingType = entry.Type == "AppSettingsApp" ? "System settings" : "Control Panel";
|
||||
|
||||
toolTipText.AppendLine($"{Resources.Application}: {settingType}");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Description": "Search settings inside Control Panel and Settings App",
|
||||
"Name": "Windows Settings",
|
||||
"Author": "TobiasSekan",
|
||||
"Version": "2.0.1",
|
||||
"Version": "2.0.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.WindowsSettings.dll",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version: '1.9.2.{build}'
|
||||
version: '1.9.3.{build}'
|
||||
|
||||
init:
|
||||
- ps: |
|
||||
|
|
|
|||
Loading…
Reference in a new issue