diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..454c4e976
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,17 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ - package-ecosystem: "nuget" # See documentation for possible values
+ directory: "/" # Location of package manifests
+ schedule:
+ interval: "weekly"
+ ignore:
+ - dependency-name: "squirrel-windows"
+ reviewers:
+ - "jjw24"
+ - "taooceros"
+ - "JohnTheGr8"
diff --git a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs
index f98815c1a..bb1279b2c 100644
--- a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs
@@ -1,4 +1,6 @@
-namespace Flow.Launcher.Core.ExternalPlugins
+using System;
+
+namespace Flow.Launcher.Core.ExternalPlugins
{
public record UserPlugin
{
@@ -12,5 +14,8 @@
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; }
+
}
}
diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
index 9f9fa8ff5..7d18c467b 100644
--- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj
+++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
@@ -54,7 +54,7 @@
-
+
diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs
index 976c4eec1..bad0344eb 100644
--- a/Flow.Launcher.Core/Updater.cs
+++ b/Flow.Launcher.Core/Updater.cs
@@ -141,6 +141,7 @@ namespace Flow.Launcher.Core
{
var translater = InternationalizationManager.Instance;
var tips = string.Format(translater.GetTranslation("newVersionTips"), version);
+
return tips;
}
diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
index 930cf0b91..4a7bc20e3 100644
--- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
+++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
@@ -53,7 +53,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index 8c1d7d74f..11f66c8af 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -252,6 +252,7 @@ namespace Flow.Launcher.Infrastructure.Image
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(path);
+ image.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;
image.EndInit();
return image;
}
diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs
index 3ffa9f7b1..46165a849 100644
--- a/Flow.Launcher.Infrastructure/StringMatcher.cs
+++ b/Flow.Launcher.Infrastructure/StringMatcher.cs
@@ -202,7 +202,11 @@ namespace Flow.Launcher.Infrastructure
if (allQuerySubstringsMatched)
{
var nearestSpaceIndex = CalculateClosestSpaceIndex(spaceIndices, firstMatchIndex);
- var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex - nearestSpaceIndex - 1,
+
+ // firstMatchIndex - nearestSpaceIndex - 1 is to set the firstIndex as the index of the first matched char
+ // preceded by a space e.g. 'world' matching 'hello world' firstIndex would be 0 not 6
+ // giving more weight than 'we or donald' by allowing the distance calculation to treat the starting position at after the space.
+ var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex - nearestSpaceIndex - 1, spaceIndices,
lastMatchIndex - firstMatchIndex, allSubstringsContainedInCompareString);
var resultList = indexList.Select(x => translationMapping?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
@@ -296,7 +300,7 @@ namespace Flow.Launcher.Infrastructure
return currentQuerySubstringIndex >= querySubstringsLength;
}
- private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
+ private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, List spaceIndices, int matchLen,
bool allSubstringsContainedInCompareString)
{
// A match found near the beginning of a string is scored more than a match found near the end
@@ -304,6 +308,14 @@ namespace Flow.Launcher.Infrastructure
// while the score is lower if they are more spread out
var score = 100 * (query.Length + 1) / ((1 + firstIndex) + (matchLen + 1));
+ // Give more weight to a match that is closer to the start of the string.
+ // if the first matched char is immediately before space and all strings are contained in the compare string e.g. 'world' matching 'hello world'
+ // and 'world hello', because both have 'world' immediately preceded by space, their firstIndex will be 0 when distance is calculated,
+ // to prevent them scoring the same, we adjust the score by deducting the number of spaces it has from the start of the string, so 'world hello'
+ // will score slightly higher than 'hello world' because 'hello world' has one additional space.
+ if (firstIndex == 0 && allSubstringsContainedInCompareString)
+ score -= spaceIndices.Count;
+
// A match with less characters assigning more weights
if (stringToCompare.Length - query.Length < 5)
{
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index 211bc1798..27afff5b6 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -41,6 +41,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool UseGlyphIcons { get; set; } = true;
public bool UseAnimation { get; set; } = true;
public bool UseSound { get; set; } = true;
+ public bool UseClock { get; set; } = true;
+ public bool UseDate { get; set; } = false;
+ public string TimeFormat { get; set; } = "hh:mm tt";
+ public string DateFormat { get; set; } = "MM'/'dd ddd";
public bool FirstLaunch { get; set; } = true;
public double SettingWindowWidth { get; set; } = 1000;
@@ -199,7 +203,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
}
public bool LeaveCmdOpen { get; set; }
public bool HideWhenDeactive { get; set; } = true;
- public bool RememberLastLaunchLocation { get; set; }
+ public SearchWindowPositions SearchWindowPosition { get; set; } = SearchWindowPositions.MouseScreenCenter;
public bool IgnoreHotkeysOnFullscreen { get; set; }
public HttpProxy Proxy { get; set; } = new HttpProxy();
@@ -225,4 +229,12 @@ namespace Flow.Launcher.Infrastructure.UserSettings
Light,
Dark
}
+ public enum SearchWindowPositions
+ {
+ RememberLastLaunchLocation,
+ MouseScreenCenter,
+ MouseScreenCenterTop,
+ MouseScreenLeftTop,
+ MouseScreenRightTop
+ }
}
diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj
index f429586ce..c4341288f 100644
--- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj
+++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj
@@ -50,7 +50,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher.Test/FuzzyMatcherTest.cs b/Flow.Launcher.Test/FuzzyMatcherTest.cs
index bbddcbd2a..46c848c7a 100644
--- a/Flow.Launcher.Test/FuzzyMatcherTest.cs
+++ b/Flow.Launcher.Test/FuzzyMatcherTest.cs
@@ -129,14 +129,20 @@ namespace Flow.Launcher.Test
}
}
+
+ ///
+ /// These are standard match scenarios
+ /// The intention of this test is provide a bench mark for how much the score has increased from a change.
+ /// Usually the increase in scoring should not be drastic, increase of less than 10 is acceptable.
+ ///
[TestCase(Chrome, Chrome, 157)]
- [TestCase(Chrome, LastIsChrome, 147)]
+ [TestCase(Chrome, LastIsChrome, 145)]
[TestCase("chro", HelpCureHopeRaiseOnMindEntityChrome, 50)]
[TestCase("chr", HelpCureHopeRaiseOnMindEntityChrome, 30)]
[TestCase(Chrome, UninstallOrChangeProgramsOnYourComputer, 21)]
[TestCase(Chrome, CandyCrushSagaFromKing, 0)]
- [TestCase("sql", MicrosoftSqlServerManagementStudio, 110)]
- [TestCase("sql manag", MicrosoftSqlServerManagementStudio, 121)] //double spacing intended
+ [TestCase("sql", MicrosoftSqlServerManagementStudio, 109)]
+ [TestCase("sql manag", MicrosoftSqlServerManagementStudio, 120)] //double spacing intended
public void WhenGivenQueryString_ThenShouldReturn_TheDesiredScoring(
string queryString, string compareString, int expectedScore)
{
@@ -275,7 +281,40 @@ namespace Flow.Launcher.Test
$"Query: \"{queryString}\"{Environment.NewLine} " +
$"CompareString1: \"{compareString1}\", Score: {compareString1Result.Score}{Environment.NewLine}" +
$"Should be greater than{Environment.NewLine}" +
- $"CompareString2: \"{compareString2}\", Score: {compareString1Result.Score}{Environment.NewLine}");
+ $"CompareString2: \"{compareString2}\", Score: {compareString2Result.Score}{Environment.NewLine}");
+ }
+
+ [TestCase("red", "red colour", "metro red")]
+ [TestCase("red", "this red colour", "this colour red")]
+ [TestCase("red", "this red colour", "this colour is very red")]
+ [TestCase("red", "this red colour", "this colour is surprisingly super awesome red and cool")]
+ [TestCase("red", "this colour is surprisingly super red very and cool", "this colour is surprisingly super very red and cool")]
+ public void WhenGivenTwoStrings_Scoring_ShouldGiveMoreWeightToTheStringCloserToIndexZero(
+ string queryString, string compareString1, string compareString2)
+ {
+ // When
+ var matcher = new StringMatcher { UserSettingSearchPrecision = SearchPrecisionScore.Regular };
+
+ // Given
+ var compareString1Result = matcher.FuzzyMatch(queryString, compareString1);
+ var compareString2Result = matcher.FuzzyMatch(queryString, compareString2);
+
+ Debug.WriteLine("");
+ Debug.WriteLine("###############################################");
+ Debug.WriteLine($"QueryString: \"{queryString}\"{Environment.NewLine}");
+ Debug.WriteLine(
+ $"CompareString1: \"{compareString1}\", Score: {compareString1Result.Score}{Environment.NewLine}");
+ Debug.WriteLine(
+ $"CompareString2: \"{compareString2}\", Score: {compareString2Result.Score}{Environment.NewLine}");
+ Debug.WriteLine("###############################################");
+ Debug.WriteLine("");
+
+ // Should
+ Assert.True(compareString1Result.Score > compareString2Result.Score,
+ $"Query: \"{queryString}\"{Environment.NewLine} " +
+ $"CompareString1: \"{compareString1}\", Score: {compareString1Result.Score}{Environment.NewLine}" +
+ $"Should be greater than{Environment.NewLine}" +
+ $"CompareString2: \"{compareString2}\", Score: {compareString2Result.Score}{Environment.NewLine}");
}
[TestCase("vim", "Vim", "ignoreDescription", "ignore.exe", "Vim Diff", "ignoreDescription", "ignore.exe")]
diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln
index ec4a29ee7..f59d3d26f 100644
--- a/Flow.Launcher.sln
+++ b/Flow.Launcher.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29806.167
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32901.215
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Test", "Flow.Launcher.Test\Flow.Launcher.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}"
ProjectSection(ProjectDependencies) = postProject
diff --git a/Flow.Launcher/Converters/BoolToVisibilityConverter.cs b/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
new file mode 100644
index 000000000..ad474d693
--- /dev/null
+++ b/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+
+namespace Flow.Launcher.Converters
+{
+ public class BoolToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter != null)
+ {
+ if (value is true)
+ {
+ return Visibility.Collapsed;
+ }
+
+ else
+ {
+ return Visibility.Visible;
+ }
+ }
+ else {
+ if (value is true)
+ {
+ return Visibility.Visible;
+ }
+
+ else {
+ return Visibility.Collapsed;
+ }
+ }
+ }
+
+ public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ }
+}
diff --git a/Flow.Launcher/Converters/TextConverter.cs b/Flow.Launcher/Converters/TextConverter.cs
new file mode 100644
index 000000000..90d445776
--- /dev/null
+++ b/Flow.Launcher/Converters/TextConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using Flow.Launcher.Core.Resource;
+using Flow.Launcher.ViewModel;
+
+namespace Flow.Launcher.Converters
+{
+ public class TextConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ var ID = value.ToString();
+ switch(ID)
+ {
+ case PluginStoreItemViewModel.NewRelease:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_NewRelease");
+ case PluginStoreItemViewModel.RecentlyUpdated:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_RecentlyUpdated");
+ case PluginStoreItemViewModel.None:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_None");
+ case PluginStoreItemViewModel.Installed:
+ return InternationalizationManager.Instance.GetTranslation("pluginStore_Installed");
+ default:
+ return ID;
+ }
+
+ }
+
+ public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ }
+}
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 66cc911ee..813a44527 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -83,6 +83,7 @@
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -114,4 +115,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs
index a3ad20f77..b9ac6afb3 100644
--- a/Flow.Launcher/Helper/HotKeyMapper.cs
+++ b/Flow.Launcher/Helper/HotKeyMapper.cs
@@ -17,7 +17,7 @@ namespace Flow.Launcher.Helper
internal static void Initialize(MainViewModel mainVM)
{
mainViewModel = mainVM;
- settings = mainViewModel._settings;
+ settings = mainViewModel.Settings;
SetHotkey(settings.Hotkey, OnToggleHotkey);
LoadCustomPluginHotkey();
diff --git a/Flow.Launcher/Images/app_missing_img.png b/Flow.Launcher/Images/app_missing_img.png
index b86c29ac9..27e366bbc 100644
Binary files a/Flow.Launcher/Images/app_missing_img.png and b/Flow.Launcher/Images/app_missing_img.png differ
diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml
index 7ec94fed1..25bd195dd 100644
--- a/Flow.Launcher/Languages/da.xaml
+++ b/Flow.Launcher/Languages/da.xaml
@@ -77,13 +77,13 @@
Søgetid:
| Version
Website
- Uninstall
+ Uninstall
Plugin Store
Refresh
- Install
+ Install
Tema
diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml
index a1b0b3b9b..ebd549adf 100644
--- a/Flow.Launcher/Languages/de.xaml
+++ b/Flow.Launcher/Languages/de.xaml
@@ -77,13 +77,13 @@
Abfragezeit:
Version
Webseite
- Deinstallieren
+ Deinstallieren
Erweiterungen laden
Aktualisieren
- Installieren
+ Installieren
Design
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 1ca2f0f7e..0eff97f4a 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -23,6 +23,8 @@
Text
Game Mode
Suspend the use of Hotkeys.
+ Position Reset
+ Reset search window position
Flow Launcher Settings
@@ -33,7 +35,13 @@
Error setting launch on startup
Hide Flow Launcher when focus is lost
Do not show new version notifications
+ Search Window Position
Remember last launch location
+ Remember Last Location
+ Mouse Focused Screen - Center
+ Mouse Focused Screen - Center Top
+ Mouse Focused Screen - Left Top
+ Mouse Focused Screen - Right Top
Language
Last Query Style
Show/Hide previous results when Flow Launcher is reactivated.
@@ -41,6 +49,7 @@
Select last Query
Empty last Query
Maximum results shown
+ You can also quickly adjust this by using CTRL+Plus and CTRL+Minus.
Ignore hotkeys in fullscreen mode
Disable Flow Launcher activation when a full screen application is active (Recommended for games).
Default File Manager
@@ -60,6 +69,10 @@
Shadow effect is not allowed while current theme has blur effect enabled
+ Search Plugin
+ Ctrl+F to search plugins
+ No results found
+ Please try a different search.
Plugin
Find more plugins
On
@@ -79,13 +92,24 @@
Query time:
| Version
Website
- Uninstall
Plugin Store
+ New Release
+ Recently Updated
+ Plugins
+ Installed
Refresh
- Install
+ Install
+ Uninstall
+ Update
+ Plug-in already installed
+ New Version
+ This plug-in has been updated within the last 7 days
+ New Update is Available
+
+
Theme
@@ -108,6 +132,8 @@
Play a small sound when the search window opens
Animation
Use Animation in UI
+ Clock
+ Date
Hotkey
@@ -127,6 +153,7 @@
Query window shadow effect
Shadow effect has a substantial usage of GPU. Not recommended if your computer performance is limited.
Window Width Size
+ You can also quickly adjust this by using Ctrl+[ and Ctrl+].
Use Segoe Fluent Icons
Use Segoe Fluent Icons for query results where supported
diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml
index 84a492d15..a410f4b32 100644
--- a/Flow.Launcher/Languages/es-419.xaml
+++ b/Flow.Launcher/Languages/es-419.xaml
@@ -77,13 +77,13 @@
Tiempo de consulta:
| Versión
Sitio web
- Uninstall
+ Uninstall
Tienda de Plugins
Recargar
- Instalar
+ Instalar
Tema
diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml
index 141d868a2..edc5e4f07 100644
--- a/Flow.Launcher/Languages/fr.xaml
+++ b/Flow.Launcher/Languages/fr.xaml
@@ -77,13 +77,13 @@
Utilisation :
| Version
Website
- Désinstaller
+ Désinstaller
Plugin Store
Refresh
- Install
+ Install
Thèmes
diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml
index 4304aead8..30a401875 100644
--- a/Flow.Launcher/Languages/it.xaml
+++ b/Flow.Launcher/Languages/it.xaml
@@ -77,13 +77,13 @@
Tempo ricerca:
| Versione
Sito Web
- Disinstalla
+ Disinstalla
Negozio dei Plugin
Aggiorna
- Installa
+ Installa
Tema
diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml
index 8c1386371..a2dcfb6a0 100644
--- a/Flow.Launcher/Languages/ja.xaml
+++ b/Flow.Launcher/Languages/ja.xaml
@@ -77,13 +77,13 @@
クエリ時間:
| バージョン
ウェブサイト
- アンインストール
+ アンインストール
プラグインストア
Refresh
- Install
+ Install
テーマ
diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml
index 809c5ccf8..acb68cb4f 100644
--- a/Flow.Launcher/Languages/ko.xaml
+++ b/Flow.Launcher/Languages/ko.xaml
@@ -77,13 +77,13 @@
쿼리 시간:
| 버전
웹사이트
- 제거
+ 제거
플러그인 스토어
새로고침
- 설치
+ 설치
테마
diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml
index e90a32347..0848e9d64 100644
--- a/Flow.Launcher/Languages/nb.xaml
+++ b/Flow.Launcher/Languages/nb.xaml
@@ -77,13 +77,13 @@
Query time:
| Version
Website
- Uninstall
+ Uninstall
Plugin Store
Refresh
- Install
+ Install
Theme
diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml
index 77a8e9e29..e398afa51 100644
--- a/Flow.Launcher/Languages/nl.xaml
+++ b/Flow.Launcher/Languages/nl.xaml
@@ -77,13 +77,13 @@
Query tijd:
| Versie
Website
- Uninstall
+ Uninstall
Plugin Winkel
Vernieuwen
- Installeren
+ Installeren
Thema
diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml
index bd7acd4e8..fc5badd69 100644
--- a/Flow.Launcher/Languages/pl.xaml
+++ b/Flow.Launcher/Languages/pl.xaml
@@ -77,13 +77,13 @@
Czas zapytania:
| Version
Website
- Odinstalowywanie
+ Odinstalowywanie
Plugin Store
Refresh
- Install
+ Install
Skórka
diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml
index 28ed30916..f6fc062c6 100644
--- a/Flow.Launcher/Languages/pt-br.xaml
+++ b/Flow.Launcher/Languages/pt-br.xaml
@@ -77,13 +77,13 @@
Tempo de consulta:
| Version
Website
- Desinstalar
+ Desinstalar
Plugin Store
Refresh
- Install
+ Install
Tema
diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml
index e7179e6e8..b19fc9924 100644
--- a/Flow.Launcher/Languages/pt-pt.xaml
+++ b/Flow.Launcher/Languages/pt-pt.xaml
@@ -77,13 +77,13 @@
Tempo de consulta:
| Versão
Site
- Desinstalar
+ Desinstalar
Loja de plugins
Recarregar
- Instalar
+ Instalar
Tema
diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml
index 2c8ca9fa3..87b3dd4ef 100644
--- a/Flow.Launcher/Languages/ru.xaml
+++ b/Flow.Launcher/Languages/ru.xaml
@@ -77,13 +77,13 @@
Запрос:
| Version
Website
- Удалить
+ Удалить
Plugin Store
Refresh
- Install
+ Install
Тема
diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml
index c4d5de6bf..ee703bcf8 100644
--- a/Flow.Launcher/Languages/sk.xaml
+++ b/Flow.Launcher/Languages/sk.xaml
@@ -77,13 +77,13 @@
Trvanie dopytu:
| Verzia
Webstránka
- Odinštalovať
+ Odinštalovať
Repozitár pluginov
Obnoviť
- Inštalovať
+ Inštalovať
Motív
diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml
index 61f619fd0..e805860dc 100644
--- a/Flow.Launcher/Languages/sr.xaml
+++ b/Flow.Launcher/Languages/sr.xaml
@@ -77,13 +77,13 @@
Vreme upita:
| Version
Website
- Uninstall
+ Uninstall
Plugin Store
Refresh
- Install
+ Install
Tema
diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml
index fb8e1d6f6..4a016ced8 100644
--- a/Flow.Launcher/Languages/tr.xaml
+++ b/Flow.Launcher/Languages/tr.xaml
@@ -77,13 +77,13 @@
Sorgu Süresi:
Sürüm
İnternet Sitesi
- Kaldır
+ Kaldır
Eklenti Mağazası
Yenile
- İndir
+ İndir
Temalar
diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml
index 8115a5dd1..a34ed4e8b 100644
--- a/Flow.Launcher/Languages/uk-UA.xaml
+++ b/Flow.Launcher/Languages/uk-UA.xaml
@@ -77,13 +77,13 @@
Запит:
| Версія
Сайт
- Uninstall
+ Uninstall
Магазин плагінів
Оновити
- Встановити
+ Встановити
Тема
diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml
index d80bfdaf6..b62736d16 100644
--- a/Flow.Launcher/Languages/zh-cn.xaml
+++ b/Flow.Launcher/Languages/zh-cn.xaml
@@ -77,13 +77,13 @@
查询耗时:
| 版本
官方网站
- 卸载
+ 卸载
插件商店
刷新
- 安装
+ 安装
主题
diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml
index 71cc887cf..69abbe401 100644
--- a/Flow.Launcher/Languages/zh-tw.xaml
+++ b/Flow.Launcher/Languages/zh-tw.xaml
@@ -77,13 +77,13 @@
查詢耗時:
| 版本
官方網站
- 解除安裝
+ 解除安裝
外掛商店
重新整理
- 安裝
+ 安裝
主題
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index 7d8c195f3..903f339c4 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -1,5 +1,4 @@
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
+
+
-
-
+
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs
index 1dd9fe34d..0b2918afe 100644
--- a/Flow.Launcher/MainWindow.xaml.cs
+++ b/Flow.Launcher/MainWindow.xaml.cs
@@ -20,8 +20,8 @@ using Flow.Launcher.Infrastructure;
using System.Windows.Media;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Plugin.SharedCommands;
+using System.Windows.Threading;
using System.Windows.Data;
-using System.Diagnostics;
namespace Flow.Launcher
{
@@ -42,6 +42,7 @@ namespace Flow.Launcher
DataContext = mainVM;
_viewModel = mainVM;
_settings = settings;
+
InitializeComponent();
InitializePosition();
animationSound.Open(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav"));
@@ -51,6 +52,7 @@ namespace Flow.Launcher
{
InitializeComponent();
}
+
private void OnCopy(object sender, ExecutedRoutedEventArgs e)
{
if (QueryTextBox.SelectionLength == 0)
@@ -88,6 +90,7 @@ namespace Flow.Launcher
InitializeColorScheme();
WindowsInteropHelper.DisableControlBox(this);
InitProgressbarAnimation();
+ InitializePosition();
// since the default main window visibility is visible
// so we need set focus during startup
QueryTextBox.Focus();
@@ -105,7 +108,6 @@ namespace Flow.Launcher
animationSound.Position = TimeSpan.Zero;
animationSound.Play();
}
-
UpdatePosition();
Activate();
QueryTextBox.Focus();
@@ -128,6 +130,7 @@ namespace Flow.Launcher
_viewModel.QueryTextCursorMovedToEnd = false;
}
break;
+
}
};
_settings.PropertyChanged += (o, e) =>
@@ -143,21 +146,40 @@ namespace Flow.Launcher
case nameof(Settings.Hotkey):
UpdateNotifyIconText();
break;
+ case nameof(Settings.WindowLeft):
+ Left = _settings.WindowLeft;
+ break;
+ case nameof(Settings.WindowTop):
+ Top = _settings.WindowTop;
+ break;
}
};
}
private void InitializePosition()
{
- if (_settings.RememberLastLaunchLocation)
+ switch (_settings.SearchWindowPosition)
{
- Top = _settings.WindowTop;
- Left = _settings.WindowLeft;
- }
- else
- {
- Left = WindowLeft();
- Top = WindowTop();
+ case SearchWindowPositions.RememberLastLaunchLocation:
+ Top = _settings.WindowTop;
+ Left = _settings.WindowLeft;
+ break;
+ case SearchWindowPositions.MouseScreenCenter:
+ Left = HorizonCenter();
+ Top = VerticalCenter();
+ break;
+ case SearchWindowPositions.MouseScreenCenterTop:
+ Left = HorizonCenter();
+ Top = 10;
+ break;
+ case SearchWindowPositions.MouseScreenLeftTop:
+ Left = 10;
+ Top = 10;
+ break;
+ case SearchWindowPositions.MouseScreenRightTop:
+ Left = HorizonRight();
+ Top = 10;
+ break;
}
}
@@ -166,8 +188,9 @@ namespace Flow.Launcher
var menu = contextMenu;
((MenuItem)menu.Items[1]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")";
((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("GameMode");
- ((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings");
- ((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit");
+ ((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("PositionReset");
+ ((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings");
+ ((MenuItem)menu.Items[5]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit");
}
private void InitializeNotifyIcon()
@@ -193,6 +216,10 @@ namespace Flow.Launcher
{
Header = InternationalizationManager.Instance.GetTranslation("GameMode")
};
+ var positionreset = new MenuItem
+ {
+ Header = InternationalizationManager.Instance.GetTranslation("PositionReset")
+ };
var settings = new MenuItem
{
Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings")
@@ -204,12 +231,15 @@ namespace Flow.Launcher
open.Click += (o, e) => _viewModel.ToggleFlowLauncher();
gamemode.Click += (o, e) => ToggleGameMode();
+ positionreset.Click += (o, e) => PositionReset();
settings.Click += (o, e) => App.API.OpenSettingDialog();
exit.Click += (o, e) => Close();
contextMenu.Items.Add(header);
contextMenu.Items.Add(open);
gamemode.ToolTip = InternationalizationManager.Instance.GetTranslation("GameModeToolTip");
+ positionreset.ToolTip = InternationalizationManager.Instance.GetTranslation("PositionResetToolTip");
contextMenu.Items.Add(gamemode);
+ contextMenu.Items.Add(positionreset);
contextMenu.Items.Add(settings);
contextMenu.Items.Add(exit);
@@ -256,6 +286,13 @@ namespace Flow.Launcher
_viewModel.GameModeStatus = true;
}
}
+ private async void PositionReset()
+ {
+ _viewModel.Show();
+ await Task.Delay(300); // If don't give a time, Positioning will be weird.
+ Left = HorizonCenter();
+ Top = VerticalCenter();
+ }
private void InitProgressbarAnimation()
{
var progressBarStoryBoard = new Storyboard();
@@ -378,6 +415,8 @@ namespace Flow.Launcher
private async void OnDeactivated(object sender, EventArgs e)
{
+ _settings.WindowLeft = Left;
+ _settings.WindowTop = Top;
//This condition stops extra hide call when animator is on,
// which causes the toggling to occasional hide instead of show.
if (_viewModel.MainWindowVisibilityStatus)
@@ -399,24 +438,14 @@ namespace Flow.Launcher
{
if (_animating)
return;
-
- if (_settings.RememberLastLaunchLocation)
- {
- Left = _settings.WindowLeft;
- Top = _settings.WindowTop;
- }
- else
- {
- Left = WindowLeft();
- Top = WindowTop();
- }
+ InitializePosition();
}
private void OnLocationChanged(object sender, EventArgs e)
{
if (_animating)
return;
- if (_settings.RememberLastLaunchLocation)
+ if (_settings.SearchWindowPosition == SearchWindowPositions.RememberLastLaunchLocation)
{
_settings.WindowLeft = Left;
_settings.WindowTop = Top;
@@ -435,8 +464,8 @@ namespace Flow.Launcher
_viewModel.Show();
}
}
-
- public double WindowLeft()
+
+ public double HorizonCenter()
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
@@ -445,7 +474,7 @@ namespace Flow.Launcher
return left;
}
- public double WindowTop()
+ public double VerticalCenter()
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
@@ -454,12 +483,22 @@ namespace Flow.Launcher
return top;
}
+ public double HorizonRight()
+ {
+ var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
+ var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
+ var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
+ var left = (dip2.X - ActualWidth) - 10;
+ return left;
+ }
+
///
/// Register up and down key
/// todo: any way to put this in xaml ?
///
private void OnKeyDown(object sender, KeyEventArgs e)
{
+ var specialKeyState = GlobalHotkey.CheckModifiers();
switch (e.Key)
{
case Key.Down:
@@ -494,8 +533,13 @@ namespace Flow.Launcher
e.Handled = true;
}
break;
+ case Key.F12:
+ if (specialKeyState.CtrlPressed)
+ {
+ ToggleGameMode();
+ }
+ break;
case Key.Back:
- var specialKeyState = GlobalHotkey.CheckModifiers();
if (specialKeyState.CtrlPressed)
{
if (_viewModel.SelectedIsFromQueryResults()
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index 9026f8f7c..808531765 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -7,7 +7,6 @@
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
- xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure"
@@ -40,6 +39,8 @@
+
+
@@ -323,8 +324,6 @@
-
-
@@ -388,6 +387,55 @@
+
+
+
+
+
+
+
+ SnapsToDevicePixels="True"
+ Style="{DynamicResource PluginListStyle}">
@@ -945,7 +1061,7 @@
Padding="0"
Background="Transparent"
FlowDirection="RightToLeft"
- IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
+ IsExpanded="{Binding Mode=TwoWay, Path=IsExpanded}"
Style="{StaticResource ExpanderStyle1}">
+ Content="{Binding SettingControl}" />
@@ -1216,7 +1331,7 @@
FontSize="11"
Foreground="{DynamicResource PluginInfoColor}"
MouseUp="OnExternalPluginUninstallClick"
- Text="{DynamicResource plugin_uninstall}"
+ Text="{DynamicResource uninstallbtn}"
TextDecorations="Underline" />
-
+
@@ -1285,19 +1400,66 @@
Text="{DynamicResource pluginStore}"
TextAlignment="left" />
-
+ Margin="5,24,0,0">
+
+
+
+
+
-
+
+ SelectionMode="Single"
+ Style="{DynamicResource StoreListStyle}">
+
+
+
+
+
+
+
@@ -1354,15 +1543,39 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ VerticalAlignment="Top">
+ Text="{Binding Description, Mode=OneWay}" />
@@ -1445,12 +1663,13 @@
-
+ VerticalAlignment="Top">
+
-
+
-
+
-
-
+ Orientation="Horizontal">
+
+
+
+
+
+
@@ -1497,7 +1738,6 @@
-
@@ -1569,8 +1809,11 @@
IsReadOnly="True"
Style="{DynamicResource QueryBoxStyle}"
Text="{DynamicResource hiThere}" />
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Images/deletefilefolder.png b/Plugins/Flow.Launcher.Plugin.Explorer/Images/deletefilefolder.png
index a8e27d342..745b34935 100644
Binary files a/Plugins/Flow.Launcher.Plugin.Explorer/Images/deletefilefolder.png and b/Plugins/Flow.Launcher.Plugin.Explorer/Images/deletefilefolder.png differ
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
index dddb7cf68..bf62caee8 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
@@ -37,7 +37,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
contextMenu = new ContextMenu(Context);
pluginManager = new PluginsManager(Context, Settings);
- await pluginManager.UpdateManifestAsync();
+ _ = pluginManager.UpdateManifestAsync();
}
public List LoadContextMenus(Result selectedResult)
@@ -74,4 +74,4 @@ namespace Flow.Launcher.Plugin.PluginsManager
return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description");
}
}
-}
\ No newline at end of file
+}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
index 2809e0b5c..83f9464c4 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
@@ -58,6 +58,7 @@
+
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
index 8d8cae02c..3132db36b 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/en.xaml
@@ -4,6 +4,7 @@
xmlns:system="clr-namespace:System;assembly=mscorlib">
+ Reset Default
Delete
Edit
Add
@@ -12,7 +13,7 @@
Disable
Location
All Programs
- File Suffixes
+ File Type
Reindex
Indexing
Index Start Menu
@@ -35,9 +36,24 @@
Are you sure you want to delete the selected program sources?
OK
- Flow Launcher will only index files that end with the following suffixes. (Each suffix should split by ';' )
+ Program Plugin will only index files with selected suffixes and .url files with selected protocols.
Successfully updated file suffixes
File suffixes can't be empty
+ Protocols can't be empty
+
+ File Suffixes
+ URL Protocols
+ Steam Games
+ Epic Games
+ Http/Https
+ Custom URL Protocols
+ Custom File Suffixes
+
+ Insert file suffixes you want to index. Suffixes should be separated by ';'. (ex>bat;py)
+
+
+ Insert protocols of .url files you want to index. Protocols should be separated by ';'. (ex>ftp;netflix)
+
Run As Different User
Run As Administrator
diff --git a/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml b/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml
index e5f404141..fbe538b7f 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml
@@ -4,10 +4,12 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{DynamicResource flowlauncher_plugin_program_suffixes}"
- Width="400"
+ Width="600"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
+ DataContext="{Binding RelativeSource={RelativeSource Self}}"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
@@ -15,9 +17,73 @@
-
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -55,7 +121,9 @@
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ appref-ms
+ exe
+ lnk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -90,7 +232,7 @@
MinWidth="140"
Margin="5,0,0,0"
HorizontalAlignment="Right"
- Click="ButtonBase_OnClick"
+ Click="BtnAdd_OnClick"
Content="{DynamicResource flowlauncher_plugin_program_update}"
Style="{DynamicResource AccentButtonStyle}" />
diff --git a/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml.cs
index 2a10928e6..31565c8b0 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/ProgramSuffixes.xaml.cs
@@ -1,44 +1,76 @@
using System;
+using System.Collections.Generic;
using System.Windows;
namespace Flow.Launcher.Plugin.Program
{
- ///
- /// ProgramSuffixes.xaml 的交互逻辑
- ///
public partial class ProgramSuffixes
{
private PluginInitContext context;
private Settings _settings;
+ public Dictionary SuffixesStatus { get; set; }
+ public Dictionary ProtocolsStatus { get; set; }
+ public bool UseCustomSuffixes { get; set; }
+ public bool UseCustomProtocols { get; set; }
public ProgramSuffixes(PluginInitContext context, Settings settings)
{
this.context = context;
- InitializeComponent();
_settings = settings;
- tbSuffixes.Text = string.Join(Settings.SuffixSeperator.ToString(), _settings.ProgramSuffixes);
+ SuffixesStatus = new Dictionary(_settings.BuiltinSuffixesStatus);
+ ProtocolsStatus = new Dictionary(_settings.BuiltinProtocolsStatus);
+ UseCustomSuffixes = _settings.UseCustomSuffixes;
+ UseCustomProtocols = _settings.UseCustomProtocols;
+ InitializeComponent();
+ tbSuffixes.Text = string.Join(Settings.SuffixSeparator, _settings.CustomSuffixes);
+ tbProtocols.Text = string.Join(Settings.SuffixSeparator, _settings.CustomProtocols);
}
+
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
{
Close();
}
- private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
- {
- var suffixes = tbSuffixes.Text.Split(Settings.SuffixSeperator, StringSplitOptions.RemoveEmptyEntries);
- if (suffixes.Length == 0)
+ private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
+ {
+ var suffixes = tbSuffixes.Text.Split(Settings.SuffixSeparator, StringSplitOptions.RemoveEmptyEntries);
+ var protocols = tbProtocols.Text.Split(Settings.SuffixSeparator, StringSplitOptions.RemoveEmptyEntries);
+
+ if (suffixes.Length == 0 && UseCustomSuffixes)
{
string warning = context.API.GetTranslation("flowlauncher_plugin_program_suffixes_cannot_empty");
MessageBox.Show(warning);
return;
}
- _settings.ProgramSuffixes = suffixes;
+ if (protocols.Length == 0 && UseCustomProtocols)
+ {
+ string warning = context.API.GetTranslation("flowlauncher_plugin_protocols_cannot_empty");
+ MessageBox.Show(warning);
+ return;
+ }
- string msg = context.API.GetTranslation("flowlauncher_plugin_program_update_file_suffixes");
- MessageBox.Show(msg);
+ _settings.CustomSuffixes = suffixes;
+ _settings.CustomProtocols = protocols;
+ _settings.BuiltinSuffixesStatus = new Dictionary(SuffixesStatus);
+ _settings.BuiltinProtocolsStatus = new Dictionary(ProtocolsStatus);
+ _settings.UseCustomSuffixes = UseCustomSuffixes;
+ _settings.UseCustomProtocols = UseCustomProtocols;
DialogResult = true;
}
+
+ private void BtnReset_OnClick(object sender, RoutedEventArgs e)
+ {
+ apprefMS.IsChecked = true;
+ exe.IsChecked = true;
+ lnk.IsChecked = true;
+ CustomFiles.IsChecked = false;
+
+ steam.IsChecked = true;
+ epic.IsChecked = true;
+ http.IsChecked = false;
+ CustomProtocol.IsChecked = false;
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
index 6a8b232e9..fbb3ea32c 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
@@ -16,7 +16,10 @@ using System.Collections;
using System.Diagnostics;
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
using System.Diagnostics.CodeAnalysis;
+using System.Text.RegularExpressions;
using System.Threading.Channels;
+using Flow.Launcher.Infrastructure.Image;
+using IniParser;
namespace Flow.Launcher.Plugin.Program.Programs
{
@@ -36,6 +39,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
public string Location => ParentDirectory;
private const string ShortcutExtension = "lnk";
+ private const string UrlExtension = "url";
private const string ExeExtension = "exe";
private static readonly Win32 Default = new Win32()
@@ -287,6 +291,45 @@ namespace Flow.Launcher.Plugin.Program.Programs
#endif
}
+ private static Win32 UrlProgram(string path)
+ {
+ var program = Win32Program(path);
+ program.Valid = false;
+
+ try
+ {
+ var parser = new FileIniDataParser();
+ var data = parser.ReadFile(path);
+ var urlSection = data["InternetShortcut"];
+ var url = urlSection?["URL"];
+ if (String.IsNullOrEmpty(url))
+ {
+ return program;
+ }
+ foreach(var protocol in Main._settings.GetProtocols())
+ {
+ if(url.StartsWith(protocol))
+ {
+ program.LnkResolvedPath = url;
+ program.Valid = true;
+ break;
+ }
+ }
+
+ var iconPath = urlSection?["IconFile"];
+ if (!String.IsNullOrEmpty(iconPath))
+ {
+ program.IcoPath = iconPath;
+ }
+ }
+ catch (Exception e)
+ {
+ // Many files do not have the required fields, so no logging is done.
+ }
+
+ return program;
+ }
+
private static Win32 ExeProgram(string path)
{
try
@@ -343,10 +386,10 @@ namespace Flow.Launcher.Plugin.Program.Programs
{
ExeExtension => ExeProgram(x),
ShortcutExtension => LnkProgram(x),
+ UrlExtension => UrlProgram(x),
_ => Win32Program(x)
});
-
return programs;
}
@@ -365,8 +408,9 @@ namespace Flow.Launcher.Plugin.Program.Programs
.Select(x => Extension(x) switch
{
ShortcutExtension => LnkProgram(x),
+ UrlExtension => UrlProgram(x),
_ => Win32Program(x)
- }).Where(x => x.Valid);
+ });
return programs;
}
@@ -504,7 +548,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
{
var programs = Enumerable.Empty();
- var unregistered = UnregisteredPrograms(settings.ProgramSources, settings.ProgramSuffixes);
+ var unregistered = UnregisteredPrograms(settings.ProgramSources, settings.GetSuffixes());
programs = programs.Concat(unregistered);
@@ -512,19 +556,19 @@ namespace Flow.Launcher.Plugin.Program.Programs
if (settings.EnableRegistrySource)
{
- var appPaths = AppPathsPrograms(settings.ProgramSuffixes);
+ var appPaths = AppPathsPrograms(settings.GetSuffixes());
autoIndexPrograms = autoIndexPrograms.Concat(appPaths);
}
if (settings.EnableStartMenuSource)
{
- var startMenu = StartMenuPrograms(settings.ProgramSuffixes);
+ var startMenu = StartMenuPrograms(settings.GetSuffixes());
autoIndexPrograms = autoIndexPrograms.Concat(startMenu);
}
autoIndexPrograms = ProgramsHasher(autoIndexPrograms);
- return programs.Concat(autoIndexPrograms).Distinct().ToArray();
+ return programs.Concat(autoIndexPrograms).Where(x => x.Valid).Distinct().ToArray();
}
#if DEBUG //This is to make developer aware of any unhandled exception and add in handling.
catch (Exception)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
index d97ddd993..96328ba62 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Settings.cs
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
+using System.Text.Json.Serialization;
+using Windows.Foundation.Metadata;
namespace Flow.Launcher.Plugin.Program
{
@@ -9,17 +12,109 @@ namespace Flow.Launcher.Plugin.Program
public DateTime LastIndexTime { get; set; }
public List ProgramSources { get; set; } = new List();
public List DisabledProgramSources { get; set; } = new List();
- public string[] ProgramSuffixes { get; set; } = {"appref-ms", "exe", "lnk"};
+
+ [Obsolete, JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string[] ProgramSuffixes { get; set; } = null;
+ public string[] CustomSuffixes { get; set; } = Array.Empty(); // Custom suffixes only
+ public string[] CustomProtocols { get; set; } = Array.Empty();
+
+ public Dictionary BuiltinSuffixesStatus { get; set; } = new Dictionary{
+ { "exe", true }, { "appref-ms", true }, { "lnk", true }
+ };
+
+ public Dictionary BuiltinProtocolsStatus { get; set; } = new Dictionary{
+ { "steam", true }, { "epic", true }, { "http", false }
+ };
+
+ [JsonIgnore]
+ public Dictionary BuiltinProtocols { get; set; } = new Dictionary{
+ { "steam", $"steam://run/{SuffixSeparator}steam://rungameid/" }, { "epic", "com.epicgames.launcher://apps/" }, { "http", $"http://{SuffixSeparator}https://"}
+ };
+
+ public bool UseCustomSuffixes { get; set; } = false;
+ public bool UseCustomProtocols { get; set; } = false;
+
+ public string[] GetSuffixes()
+ {
+ RemoveRedundantSuffixes();
+ List extensions = new List();
+ foreach (var item in BuiltinSuffixesStatus)
+ {
+ if (item.Value)
+ {
+ extensions.Add(item.Key);
+ }
+ }
+
+ if (BuiltinProtocolsStatus.Values.Any(x => x == true) || UseCustomProtocols)
+ {
+ extensions.Add("url");
+ }
+
+ if (UseCustomSuffixes)
+ {
+ return extensions.Concat(CustomSuffixes).DistinctBy(x => x.ToLower()).ToArray();
+ }
+ else
+ {
+ return extensions.DistinctBy(x => x.ToLower()).ToArray();
+ }
+ }
+
+ public string[] GetProtocols()
+ {
+ List protocols = new List();
+ foreach (var item in BuiltinProtocolsStatus)
+ {
+ if (item.Value)
+ {
+ if (BuiltinProtocols.TryGetValue(item.Key, out string ps))
+ {
+ var tmp = ps.Split(SuffixSeparator, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var protocol in tmp)
+ {
+ protocols.Add(protocol);
+ }
+ }
+ }
+ }
+
+ if (UseCustomProtocols)
+ {
+ return protocols.Concat(CustomProtocols).DistinctBy(x => x.ToLower()).ToArray();
+ }
+ else
+ {
+ return protocols.DistinctBy(x => x.ToLower()).ToArray();
+ }
+ }
+
+ private void RemoveRedundantSuffixes()
+ {
+ // Migrate to new settings
+ // CustomSuffixes no longer contains custom suffixes
+ // users has tweaked the settings
+ // or this function has been executed once
+ if (UseCustomSuffixes == true || ProgramSuffixes == null)
+ return;
+ var suffixes = ProgramSuffixes.ToList();
+ foreach(var item in BuiltinSuffixesStatus)
+ {
+ suffixes.Remove(item.Key);
+ }
+ CustomSuffixes = suffixes.ToArray(); // Custom suffixes
+ UseCustomSuffixes = CustomSuffixes.Length != 0; // Search custom suffixes or not
+ ProgramSuffixes = null;
+ }
public bool EnableStartMenuSource { get; set; } = true;
-
public bool EnableDescription { get; set; } = false;
public bool HideAppsPath { get; set; } = true;
public bool EnableRegistrySource { get; set; } = true;
public string CustomizedExplorer { get; set; } = Explorer;
public string CustomizedArgs { get; set; } = ExplorerArgs;
- internal const char SuffixSeperator = ';';
+ internal const char SuffixSeparator = ';';
internal const string Explorer = "explorer";
diff --git a/Plugins/Flow.Launcher.Plugin.Program/SuffixesConverter.cs b/Plugins/Flow.Launcher.Plugin.Program/SuffixesConverter.cs
index a5e9f75dc..ef93913a5 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/SuffixesConverter.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/SuffixesConverter.cs
@@ -12,7 +12,7 @@ namespace Flow.Launcher.Plugin.Program
var text = value as string[];
if (text != null)
{
- return string.Join(";", text);
+ return string.Join(Settings.SuffixSeparator, text);
}
else
{
diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Images/ControlPanel_Small.png b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Images/ControlPanel_Small.png
index 8a8a41aeb..0897fd788 100644
Binary files a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Images/ControlPanel_Small.png and b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Images/ControlPanel_Small.png differ
diff --git a/README.md b/README.md
index 58dbd0be9..1441c8b39 100644
--- a/README.md
+++ b/README.md
@@ -288,6 +288,12 @@ Yes please, let us know in the [Q&A](https://github.com/Flow-Launcher/Flow.Launc
## Development
+### New changes
+
+All changes to flow are captured via pull requests. Some new changes will have been merged but still pending release, this means whilst a change may not exist in the current latest release, it may very well have been accepted and merged into the dev branch and available as a pre-release download. It is therefore a good idea that before you start to make changes, search through the open and closed pull requests to make sure the change you intend to make is not already done.
+
+Each of the pull requests will be marked with a milestone indicating the planned release version for the change.
+
### Contributing
Contributions are very welcome, in addition to the main project(C#) there are also [documentation](https://github.com/Flow-Launcher/docs)(md), [website](https://github.com/Flow-Launcher/flow-launcher.github.io)(html/css) and [others](https://github.com/Flow-Launcher) that can be contributed to. If you are unsure of a change you want to make, let us know in the [Discussions](https://github.com/Flow-Launcher/Flow.Launcher/discussions/categories/ideas), otherwise feel free to put in a pull request.
diff --git a/global.json b/global.json
index 5e94f4b05..6ff5b35d3 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "6.0.100",
- "rollForward": "latestFeature"
+ "version": "6.0.*",
+ "rollForward": "latestPatch"
}
}
\ No newline at end of file