From fcbf97275406c9775149be25a8c68c606871f6e3 Mon Sep 17 00:00:00 2001
From: pc223 <10551242+pc223@users.noreply.github.com>
Date: Tue, 13 Jul 2021 03:44:28 +0700
Subject: [PATCH 01/97] Testing new search order: System.Search.Rank
---
.../Search/WindowsIndex/QueryConstructor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index 20e85bbb5..808f8e7e3 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -114,7 +114,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
///
public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'";
- public const string QueryOrderByFileNameRestriction = " ORDER BY System.FileName";
+ public const string QueryOrderByFileNameRestriction = " ORDER BY System.Search.Rank";
///
From 5d3b0ba2c06ceeea0f9f6cae668068bef0e7763a Mon Sep 17 00:00:00 2001
From: pc223 <10551242+pc223@users.noreply.github.com>
Date: Tue, 13 Jul 2021 04:12:09 +0700
Subject: [PATCH 02/97] Should be DESC
---
.../Search/WindowsIndex/QueryConstructor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index 808f8e7e3..c42a60193 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -114,7 +114,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
///
public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'";
- public const string QueryOrderByFileNameRestriction = " ORDER BY System.Search.Rank";
+ public const string QueryOrderByFileNameRestriction = " ORDER BY System.Search.Rank DESC";
///
From 9486355102c12e4c99d00b941eda0380ce8e8716 Mon Sep 17 00:00:00 2001
From: DB P
Date: Sat, 5 Apr 2025 20:14:31 +0900
Subject: [PATCH 03/97] Add check registry method
---
.../SettingsPaneGeneralViewModel.cs | 46 +++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index cec8c318c..a1b38a53c 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using CommunityToolkit.Mvvm.Input;
@@ -10,6 +11,8 @@ using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
+using Microsoft.Win32;
+using OpenFileDialog = System.Windows.Forms.OpenFileDialog;
namespace Flow.Launcher.SettingPages.ViewModels;
@@ -25,6 +28,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
_updater = updater;
_portable = portable;
UpdateEnumDropdownLocalizations();
+ IsLegacyKoreanIMEEnabled();
}
public class SearchWindowScreenData : DropdownDataGeneric { }
@@ -187,6 +191,48 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
}
+ bool IsLegacyKoreanIMEEnabled()
+ {
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath))
+ {
+ if (key != null)
+ {
+ object value = key.GetValue(valueName);
+ if (value != null)
+ {
+ Debug.WriteLine($"[IME DEBUG] '{valueName}' 값: {value} (타입: {value.GetType()})");
+
+ if (value is int intValue)
+ return intValue == 1;
+
+ if (int.TryParse(value.ToString(), out int parsed))
+ return parsed == 1;
+ }
+ else
+ {
+ Debug.WriteLine($"[IME DEBUG] '{valueName}' 값이 존재하지 않습니다.");
+ }
+ }
+ else
+ {
+ Debug.WriteLine($"[IME DEBUG] 레지스트리 키를 찾을 수 없습니다: {subKeyPath}");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"[IME DEBUG] 예외 발생: {ex.Message}");
+ }
+
+ return false; // 기본적으로 새 IME 사용 중으로 간주
+ }
+
+
public bool ShouldUsePinyin
{
get => Settings.ShouldUsePinyin;
From 43330db96925fd595823516079168caf442cbda1 Mon Sep 17 00:00:00 2001
From: DB p
Date: Sun, 6 Apr 2025 22:14:15 +0900
Subject: [PATCH 04/97] Add InfoBar Control
---
Flow.Launcher/Resources/Dark.xaml | 16 ++++++++---
Flow.Launcher/Resources/Light.xaml | 14 ++++++++--
.../Views/SettingsPaneGeneral.xaml | 27 +++++++++++++++++++
3 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/Flow.Launcher/Resources/Dark.xaml b/Flow.Launcher/Resources/Dark.xaml
index ec089b378..1daddbfa7 100644
--- a/Flow.Launcher/Resources/Dark.xaml
+++ b/Flow.Launcher/Resources/Dark.xaml
@@ -114,10 +114,20 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml
index aa6da9fb2..536099546 100644
--- a/Flow.Launcher/Resources/Light.xaml
+++ b/Flow.Launcher/Resources/Light.xaml
@@ -105,10 +105,20 @@
-
+
+
+
+
+
-
+
+
+
+
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 3f8272dda..c53edd07e 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -28,6 +28,33 @@
Style="{StaticResource PageTitle}"
Text="{DynamicResource general}"
TextAlignment="left" />
+
+
+
+
Date: Sun, 6 Apr 2025 23:17:56 +0900
Subject: [PATCH 05/97] Adjust Inforbar
---
Flow.Launcher/Resources/Controls/InfoBar.xaml | 78 +++++++
.../Resources/Controls/InfoBar.xaml.cs | 219 ++++++++++++++++++
.../Views/SettingsPaneGeneral.xaml | 13 +-
3 files changed, 307 insertions(+), 3 deletions(-)
create mode 100644 Flow.Launcher/Resources/Controls/InfoBar.xaml
create mode 100644 Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml b/Flow.Launcher/Resources/Controls/InfoBar.xaml
new file mode 100644
index 000000000..1713b3459
--- /dev/null
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
new file mode 100644
index 000000000..f50bc349e
--- /dev/null
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
@@ -0,0 +1,219 @@
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Flow.Launcher.Resources.Controls
+{
+ public partial class InfoBar : UserControl
+ {
+ public InfoBar()
+ {
+ InitializeComponent();
+ Loaded += InfoBar_Loaded;
+ }
+
+ private void InfoBar_Loaded(object sender, RoutedEventArgs e)
+ {
+ UpdateStyle();
+ UpdateTitleVisibility();
+ UpdateMessageVisibility();
+ UpdateOrientation();
+ UpdateIconAlignmentAndMargin();
+
+ // DataContext 설정 (예시)
+ this.DataContext = this; // InfoBar 자체를 DataContext로 사용
+ }
+
+ public static readonly DependencyProperty TypeProperty =
+ DependencyProperty.Register(nameof(Type), typeof(InfoBarType), typeof(InfoBar), new PropertyMetadata(InfoBarType.Info, OnTypeChanged));
+
+ public InfoBarType Type
+ {
+ get => (InfoBarType)GetValue(TypeProperty);
+ set => SetValue(TypeProperty, value);
+ }
+
+ private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is InfoBar infoBar)
+ {
+ infoBar.UpdateStyle();
+ }
+ }
+
+ public static readonly DependencyProperty MessageProperty =
+ DependencyProperty.Register(nameof(Message), typeof(string), typeof(InfoBar), new PropertyMetadata(string.Empty, OnMessageChanged));
+
+ public string Message
+ {
+ get => (string)GetValue(MessageProperty);
+ set
+ {
+ SetValue(MessageProperty, value);
+ UpdateMessageVisibility(); // Message 속성 변경 시 Visibility 업데이트
+ }
+ }
+
+ private static void OnMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is InfoBar infoBar)
+ {
+ infoBar.UpdateMessageVisibility();
+ }
+ }
+
+ private void UpdateMessageVisibility()
+ {
+ PART_Message.Visibility = string.IsNullOrEmpty(Message) ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public static readonly DependencyProperty TitleProperty =
+ DependencyProperty.Register(nameof(Title), typeof(string), typeof(InfoBar), new PropertyMetadata(string.Empty, OnTitleChanged));
+
+ public string Title
+ {
+ get => (string)GetValue(TitleProperty);
+ set
+ {
+ SetValue(TitleProperty, value);
+ UpdateTitleVisibility(); // Title 속성 변경 시 Visibility 업데이트
+ }
+ }
+
+ private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is InfoBar infoBar)
+ {
+ infoBar.UpdateTitleVisibility();
+ }
+ }
+
+ private void UpdateTitleVisibility()
+ {
+ PART_Title.Visibility = string.IsNullOrEmpty(Title) ? Visibility.Collapsed : Visibility.Visible;
+ }
+
+ public static readonly DependencyProperty IsIconVisibleProperty =
+ DependencyProperty.Register(nameof(IsIconVisible), typeof(bool), typeof(InfoBar), new PropertyMetadata(true, OnIsIconVisibleChanged));
+
+ public bool IsIconVisible
+ {
+ get => (bool)GetValue(IsIconVisibleProperty);
+ set => SetValue(IsIconVisibleProperty, value);
+ }
+
+ public static readonly DependencyProperty LengthProperty =
+ DependencyProperty.Register(nameof(Length), typeof(InfoBarLength), typeof(InfoBar), new PropertyMetadata(InfoBarLength.Short, OnLengthChanged));
+
+ public InfoBarLength Length
+ {
+ get { return (InfoBarLength)GetValue(LengthProperty); }
+ set { SetValue(LengthProperty, value); }
+ }
+
+ private static void OnLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is InfoBar infoBar)
+ {
+ infoBar.UpdateOrientation();
+ infoBar.UpdateIconAlignmentAndMargin();
+ }
+ }
+
+ private void UpdateOrientation()
+ {
+ PART_StackPanel.Orientation = Length == InfoBarLength.Long ? Orientation.Vertical : Orientation.Horizontal;
+ }
+
+ private void UpdateIconAlignmentAndMargin()
+ {
+ if (Length == InfoBarLength.Short)
+ {
+ Part_IconBorder.VerticalAlignment = VerticalAlignment.Center;
+ Part_IconBorder.Margin = new Thickness(0, 0, 12, 0);
+ }
+ else
+ {
+ Part_IconBorder.VerticalAlignment = VerticalAlignment.Top;
+ Part_IconBorder.Margin = new Thickness(0, 2, 12, 0);
+ }
+ }
+
+ public static readonly DependencyProperty ClosableProperty =
+ DependencyProperty.Register(nameof(Closable), typeof(bool), typeof(InfoBar), new PropertyMetadata(true, OnClosableChanged));
+
+ public bool Closable
+ {
+ get => (bool)GetValue(ClosableProperty);
+ set => SetValue(ClosableProperty, value);
+ }
+
+ private void PART_CloseButton_Click(object sender, RoutedEventArgs e)
+ {
+ Visibility = Visibility.Collapsed;
+ }
+
+ private void UpdateStyle()
+ {
+ switch (Type)
+ {
+ case InfoBarType.Info:
+ PART_Border.Background = (Brush)FindResource("InfoBarInfoBG");
+ Part_IconBorder.Background = (Brush)FindResource("InfoBarInfoIcon");
+ PART_Icon.Glyph = "\xF13F";
+ break;
+ case InfoBarType.Success:
+ PART_Border.Background = (Brush)FindResource("InfoBarSuccessBG");
+ Part_IconBorder.Background = (Brush)FindResource("InfoBarSuccessIcon");
+ PART_Icon.Glyph = "\xF13E";
+ break;
+ case InfoBarType.Warning:
+ PART_Border.Background = (Brush)FindResource("InfoBarWarningBG");
+ Part_IconBorder.Background = (Brush)FindResource("InfoBarWarningIcon");
+ PART_Icon.Glyph = "\xF13C";
+ break;
+ case InfoBarType.Error:
+ PART_Border.Background = (Brush)FindResource("InfoBarErrorBG");
+ Part_IconBorder.Background = (Brush)FindResource("InfoBarErrorIcon");
+ PART_Icon.Glyph = "\xF13D";
+ break;
+ }
+ }
+
+ private static void OnIsIconVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var infoBar = (InfoBar)d;
+ infoBar.UpdateIconVisibility();
+ }
+
+ private static void OnClosableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var infoBar = (InfoBar)d;
+ infoBar.UpdateCloseButtonVisibility();
+ }
+
+ private void UpdateIconVisibility()
+ {
+ Part_IconBorder.Visibility = IsIconVisible ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ private void UpdateCloseButtonVisibility()
+ {
+ PART_CloseButton.Visibility = Closable ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+
+ public enum InfoBarType
+ {
+ Info,
+ Success,
+ Warning,
+ Error
+ }
+
+ public enum InfoBarLength
+ {
+ Short,
+ Long
+ }
+}
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index c53edd07e..91f648586 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -32,13 +32,13 @@
Title="Test"
Closable="False"
IsIconVisible="True"
- Length="Long"
+ Length="Short"
Message="This is a success message."
Type="Info" />
+
Date: Mon, 7 Apr 2025 15:47:40 +0900
Subject: [PATCH 06/97] Add Infobar strings for korean
---
Flow.Launcher/Languages/en.xaml | 10 ++++++++++
.../SettingPages/Views/SettingsPaneGeneral.xaml | 10 +++++-----
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 24ab3cf94..3de278eca 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -116,6 +116,16 @@
Normal
Short
Very short
+ Information for Korean IME user
+
+ You're using the Korean language! The Korean input method used in Windows 11 may cause some issues in Flow Launcher.
+ If you experience any problems, you may need to enable compatibility mode for the Korean IME.
+ Open Setting in Windows 11 and go to:
+ Time & Language > Language & Region > Korean > Language Options > Keyboard - Microsoft IME > Compatibility,
+ and enable "Use previous version of Microsoft IME".
+ You can open the relevant menu using the option below, or change the setting directly without manually opening the settings page.
+
+ Very short
Search Plugin
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 91f648586..431293a50 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -56,12 +56,12 @@
Message="This is a success message."
Type="Error" />
+ IsIconVisible="True"
+ Length="Long"
+ Message="{DynamicResource KoreanImeGuide}"
+ Type="Warning" />
Date: Tue, 8 Apr 2025 15:23:23 +0900
Subject: [PATCH 07/97] Add function for switch and button
---
Flow.Launcher/Languages/en.xaml | 6 +-
.../SettingsPaneGeneralViewModel.cs | 122 ++++++++++++++----
.../Views/SettingsPaneGeneral.xaml | 62 ++++-----
3 files changed, 133 insertions(+), 57 deletions(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 3de278eca..c4c87dbc4 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -125,7 +125,11 @@
and enable "Use previous version of Microsoft IME".
You can open the relevant menu using the option below, or change the setting directly without manually opening the settings page.
- Very short
+ Open Language and Region System Settings
+ Opens the Korean IME setting locationKorean > Language Options > Keyboard - Microsoft IME > Compatibility
+ Open
+ Use Legacy Korean IME
+ You can change the IME settings directly from here without opening a separate settings window
Search Plugin
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index a1b38a53c..dcd17cf24 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -13,6 +13,8 @@ using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
using Microsoft.Win32;
using OpenFileDialog = System.Windows.Forms.OpenFileDialog;
+using System.Windows.Input;
+
namespace Flow.Launcher.SettingPages.ViewModels;
@@ -21,7 +23,8 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
public Settings Settings { get; }
private readonly Updater _updater;
private readonly IPortable _portable;
-
+ public ICommand OpenImeSettingsCommand { get; }
+
public SettingsPaneGeneralViewModel(Settings settings, Updater updater, IPortable portable)
{
Settings = settings;
@@ -29,6 +32,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
_portable = portable;
UpdateEnumDropdownLocalizations();
IsLegacyKoreanIMEEnabled();
+ OpenImeSettingsCommand = new RelayCommand(OpenImeSettings);
}
public class SearchWindowScreenData : DropdownDataGeneric { }
@@ -190,8 +194,89 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
UpdateEnumDropdownLocalizations();
}
}
+
+ public bool LegacyKoreanIMEEnabled
+ {
+ get => IsLegacyKoreanIMEEnabled();
+ set
+ {
+ SetLegacyKoreanIMEEnabled(value);
+ OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
+ OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
+ }
+ }
+
+ public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist();
+
+ public bool KoreanIMERegistryValueIsZero
+ {
+ get
+ {
+ object value = GetLegacyKoreanIMERegistryValue();
+ if (value is int intValue)
+ {
+ return intValue == 0;
+ }
+ else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
+ {
+ return parsedValue == 0;
+ }
+
+ return false;
+ }
+ }
+
+ bool IsKoreanIMEExist()
+ {
+ return GetLegacyKoreanIMERegistryValue() != null;
+ }
bool IsLegacyKoreanIMEEnabled()
+ {
+ object value = GetLegacyKoreanIMERegistryValue();
+
+ if (value is int intValue)
+ {
+ return intValue == 1;
+ }
+ else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
+ {
+ return parsedValue == 1;
+ }
+
+ return false;
+ }
+
+ bool SetLegacyKoreanIMEEnabled(bool enable)
+ {
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath))
+ {
+ if (key != null)
+ {
+ int value = enable ? 1 : 0;
+ key.SetValue(valueName, value, RegistryValueKind.DWord);
+ return true;
+ }
+ else
+ {
+ Debug.WriteLine($"[IME DEBUG] 레지스트리 키 생성 또는 열기 실패: {subKeyPath}");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"[IME DEBUG] 레지스트리 설정 중 예외 발생: {ex.Message}");
+ }
+
+ return false;
+ }
+
+ private object GetLegacyKoreanIMERegistryValue()
{
const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
const string valueName = "NoTsf3Override5";
@@ -202,25 +287,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
{
if (key != null)
{
- object value = key.GetValue(valueName);
- if (value != null)
- {
- Debug.WriteLine($"[IME DEBUG] '{valueName}' 값: {value} (타입: {value.GetType()})");
-
- if (value is int intValue)
- return intValue == 1;
-
- if (int.TryParse(value.ToString(), out int parsed))
- return parsed == 1;
- }
- else
- {
- Debug.WriteLine($"[IME DEBUG] '{valueName}' 값이 존재하지 않습니다.");
- }
- }
- else
- {
- Debug.WriteLine($"[IME DEBUG] 레지스트리 키를 찾을 수 없습니다: {subKeyPath}");
+ return key.GetValue(valueName);
}
}
}
@@ -229,10 +296,21 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
Debug.WriteLine($"[IME DEBUG] 예외 발생: {ex.Message}");
}
- return false; // 기본적으로 새 IME 사용 중으로 간주
+ return null;
+ }
+
+ private void OpenImeSettings()
+ {
+ try
+ {
+ Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine($"Error opening IME settings: {e.Message}");
+ }
}
-
public bool ShouldUsePinyin
{
get => Settings.ShouldUsePinyin;
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 431293a50..1d4dfd8ae 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -8,12 +8,16 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:settingsViewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels"
xmlns:ui="http://schemas.modernwpf.com/2019"
+ xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure"
Title="General"
d:DataContext="{d:DesignInstance settingsViewModels:SettingsPaneGeneralViewModel}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
From 5c55d29e1f8788a7f5cc62231fda7b9774e66342 Mon Sep 17 00:00:00 2001
From: DB p
Date: Wed, 9 Apr 2025 17:54:37 +0900
Subject: [PATCH 08/97] =?UTF-8?q?Handle=20it=20so=20that=20it=20doesn?=
=?UTF-8?q?=E2=80=99t=20show=20if=20the=20registry=20is=20missing.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Views/SettingsPaneGeneral.xaml | 33 +++++++++++--------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 1d4dfd8ae..d225b01a4 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -3,12 +3,12 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
+ xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ext="clr-namespace:Flow.Launcher.Resources.MarkupExtensions"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:settingsViewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels"
xmlns:ui="http://schemas.modernwpf.com/2019"
- xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure"
Title="General"
d:DataContext="{d:DesignInstance settingsViewModels:SettingsPaneGeneralViewModel}"
@@ -32,7 +32,7 @@
Style="{StaticResource PageTitle}"
Text="{DynamicResource general}"
TextAlignment="left" />
-
+
-
-
+
+
+
+
+ Icon=""
+ Sub="{DynamicResource KoreanImeRegistryTooltip}">
-
+ Icon=""
+ Sub="{DynamicResource KoreanImeOpenLinkTooltip}">
+
From 7fdc2161c43acb1196ea29ea1614934268f7f118 Mon Sep 17 00:00:00 2001
From: DB p
Date: Wed, 9 Apr 2025 23:36:51 +0900
Subject: [PATCH 09/97] Fix small things for merging dev
---
Flow.Launcher/Languages/en.xaml | 1 -
Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 8 ++++----
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index dc0799f90..1b0400d7b 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -130,7 +130,6 @@
Open
Use Legacy Korean IME
You can change the IME settings directly from here without opening a separate settings window
- Wait time before showing results after typing stops. Higher values wait longer. (ms)
Search Plugin
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index ca8d2fd6c..6b0f9d440 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -220,12 +220,12 @@
+ ValidationMode="InvalidInputOverwritten"
+ Value="{Binding SearchDelayTimeValue}" />
@@ -325,7 +325,7 @@
IsIconVisible="True"
Length="Long"
Message="{DynamicResource KoreanImeGuide}"
- Type="Info"
+ Type="Warning"
Visibility="{Binding LegacyKoreanIMEEnabled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Inverted, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
From 77ffafc582e34898e17167ac80830c6c8181ccb4 Mon Sep 17 00:00:00 2001
From: DB p
Date: Wed, 9 Apr 2025 23:43:36 +0900
Subject: [PATCH 10/97] Fix string
---
Flow.Launcher/Languages/en.xaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 1b0400d7b..9315f05c9 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -148,6 +148,10 @@
Change Action Keywords
Plugin seach delay time
Change Plugin Seach Delay Time
+ Advanced Settings:
+ Enabled
+ Priority
+ Search Delay
Current Priority
New Priority
Priority
From 3c49d8e7304a352a49b9f96541eab9e8141d7fe9 Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 00:38:35 +0900
Subject: [PATCH 11/97] Fix Binding error
---
Flow.Launcher/Resources/Controls/InfoBar.xaml | 36 ++++++++++---------
.../Resources/Controls/InfoBar.xaml.cs | 4 +--
.../SettingsPaneGeneralViewModel.cs | 16 ++++++---
.../Views/SettingsPaneGeneral.xaml | 1 +
4 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml b/Flow.Launcher/Resources/Controls/InfoBar.xaml
index 1713b3459..f82a32a8b 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml
@@ -2,6 +2,7 @@
x:Class="Flow.Launcher.Resources.Controls.InfoBar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -26,21 +27,22 @@
-
-
-
+
+
+
+ Text="{Binding RelativeSource={RelativeSource AncestorType=cc:InfoBar}, Path=Title}" />
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
index f50bc349e..8b82dc3b6 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
@@ -19,9 +19,7 @@ namespace Flow.Launcher.Resources.Controls
UpdateMessageVisibility();
UpdateOrientation();
UpdateIconAlignmentAndMargin();
-
- // DataContext 설정 (예시)
- this.DataContext = this; // InfoBar 자체를 DataContext로 사용
+ //this.DataContext = this;
}
public static readonly DependencyProperty TypeProperty =
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 9590f7283..b98d76000 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -188,15 +188,21 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
UpdateEnumDropdownLocalizations();
}
}
-
- public bool LegacyKoreanIMEEnabled
+ public bool LegacyKoreanIMEEnabled
{
get => IsLegacyKoreanIMEEnabled();
set
{
- SetLegacyKoreanIMEEnabled(value);
- OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
- OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
+ Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled 변경: {value}");
+ if (SetLegacyKoreanIMEEnabled(value))
+ {
+ OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
+ OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
+ }
+ else
+ {
+ Debug.WriteLine("[DEBUG] LegacyKoreanIMEEnabled 설정 실패");
+ }
}
}
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 6b0f9d440..16db1c676 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -322,6 +322,7 @@
Title="{DynamicResource KoreanImeTitle}"
Margin="0 12 0 0"
Closable="False"
+ DataContext="{Binding RelativeSource={RelativeSource AncestorType=Border}, Path=DataContext}"
IsIconVisible="True"
Length="Long"
Message="{DynamicResource KoreanImeGuide}"
From d9a353b4522b1471e18d684fe270256626094323 Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 00:52:34 +0900
Subject: [PATCH 12/97] - Fix String and adjust messages - Adjust Margin -
Cleanup comment
---
Flow.Launcher/Languages/en.xaml | 11 +-
.../SettingsPaneGeneralViewModel.cs | 175 +++++++++---------
.../Views/SettingsPaneGeneral.xaml | 6 +-
3 files changed, 96 insertions(+), 96 deletions(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 9315f05c9..bf430b6f5 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -118,18 +118,17 @@
Very short
Information for Korean IME user
- You're using the Korean language! The Korean input method used in Windows 11 may cause some issues in Flow Launcher.
- If you experience any problems, you may need to enable compatibility mode for the Korean IME.
+ The Korean input method used in Windows 11 may cause some issues in Flow Launcher.
+ If you experience any problems, you may need to enable "Use previous version of Korean IME".
Open Setting in Windows 11 and go to:
Time & Language > Language & Region > Korean > Language Options > Keyboard - Microsoft IME > Compatibility,
and enable "Use previous version of Microsoft IME".
- You can open the relevant menu using the option below, or change the setting directly without manually opening the settings page.
Open Language and Region System Settings
- Opens the Korean IME setting locationKorean > Language Options > Keyboard - Microsoft IME > Compatibility
+ Opens the Korean IME setting location. Go to Korean > Language Options > Keyboard - Microsoft IME > Compatibility
Open
- Use Legacy Korean IME
- You can change the IME settings directly from here without opening a separate settings window
+ Use Previous Korean IME
+ You can change the Previous Korean IME settings directly from here
Search Plugin
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index b98d76000..701de4361 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -189,128 +189,129 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
}
public bool LegacyKoreanIMEEnabled
+{
+ get => IsLegacyKoreanIMEEnabled();
+ set
{
- get => IsLegacyKoreanIMEEnabled();
- set
+ Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled changed: {value}");
+ if (SetLegacyKoreanIMEEnabled(value))
{
- Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled 변경: {value}");
- if (SetLegacyKoreanIMEEnabled(value))
- {
- OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
- OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
- }
- else
- {
- Debug.WriteLine("[DEBUG] LegacyKoreanIMEEnabled 설정 실패");
- }
+ OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
+ OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
+ }
+ else
+ {
+ Debug.WriteLine("[DEBUG] Failed to set LegacyKoreanIMEEnabled");
}
}
+}
- public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist();
+public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist();
- public bool KoreanIMERegistryValueIsZero
- {
- get
- {
- object value = GetLegacyKoreanIMERegistryValue();
- if (value is int intValue)
- {
- return intValue == 0;
- }
- else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
- {
- return parsedValue == 0;
- }
-
- return false;
- }
- }
-
- bool IsKoreanIMEExist()
- {
- return GetLegacyKoreanIMERegistryValue() != null;
- }
-
- bool IsLegacyKoreanIMEEnabled()
+public bool KoreanIMERegistryValueIsZero
+{
+ get
{
object value = GetLegacyKoreanIMERegistryValue();
-
if (value is int intValue)
{
- return intValue == 1;
+ return intValue == 0;
}
else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
{
- return parsedValue == 1;
+ return parsedValue == 0;
}
return false;
}
+}
- bool SetLegacyKoreanIMEEnabled(bool enable)
+bool IsKoreanIMEExist()
+{
+ return GetLegacyKoreanIMERegistryValue() != null;
+}
+
+bool IsLegacyKoreanIMEEnabled()
+{
+ object value = GetLegacyKoreanIMERegistryValue();
+
+ if (value is int intValue)
{
- const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
- const string valueName = "NoTsf3Override5";
+ return intValue == 1;
+ }
+ else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
+ {
+ return parsedValue == 1;
+ }
- try
+ return false;
+}
+
+bool SetLegacyKoreanIMEEnabled(bool enable)
+{
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath))
{
- using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath))
+ if (key != null)
{
- if (key != null)
- {
- int value = enable ? 1 : 0;
- key.SetValue(valueName, value, RegistryValueKind.DWord);
- return true;
- }
- else
- {
- Debug.WriteLine($"[IME DEBUG] 레지스트리 키 생성 또는 열기 실패: {subKeyPath}");
- }
+ int value = enable ? 1 : 0;
+ key.SetValue(valueName, value, RegistryValueKind.DWord);
+ return true;
+ }
+ else
+ {
+ Debug.WriteLine($"[IME DEBUG] Failed to create or open registry key: {subKeyPath}");
}
}
- catch (Exception ex)
- {
- Debug.WriteLine($"[IME DEBUG] 레지스트리 설정 중 예외 발생: {ex.Message}");
- }
-
- return false;
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"[IME DEBUG] Exception occurred while setting registry: {ex.Message}");
}
- private object GetLegacyKoreanIMERegistryValue()
- {
- const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
- const string valueName = "NoTsf3Override5";
+ return false;
+}
- try
+private object GetLegacyKoreanIMERegistryValue()
+{
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath))
{
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath))
+ if (key != null)
{
- if (key != null)
- {
- return key.GetValue(valueName);
- }
+ return key.GetValue(valueName);
}
}
- catch (Exception ex)
- {
- Debug.WriteLine($"[IME DEBUG] 예외 발생: {ex.Message}");
- }
-
- return null;
}
-
- private void OpenImeSettings()
+ catch (Exception ex)
{
- try
- {
- Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
- }
- catch (Exception e)
- {
- Debug.WriteLine($"Error opening IME settings: {e.Message}");
- }
+ Debug.WriteLine($"[IME DEBUG] Exception occurred: {ex.Message}");
}
+ return null;
+}
+
+private void OpenImeSettings()
+{
+ try
+ {
+ Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine($"Error opening IME settings: {e.Message}");
+ }
+}
+
+
public bool ShouldUsePinyin
{
get => Settings.ShouldUsePinyin;
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 16db1c676..5304824fe 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -320,7 +320,7 @@
-
+
+ Sub="{DynamicResource KoreanImeOpenLinkToolTip}">
From be0a9b7eadbee301e8441319f67ec714070383dc Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 01:11:36 +0900
Subject: [PATCH 13/97] clean up comment
---
Flow.Launcher/Resources/Controls/InfoBar.xaml.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
index 8b82dc3b6..d447192cf 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
@@ -19,7 +19,6 @@ namespace Flow.Launcher.Resources.Controls
UpdateMessageVisibility();
UpdateOrientation();
UpdateIconAlignmentAndMargin();
- //this.DataContext = this;
}
public static readonly DependencyProperty TypeProperty =
@@ -48,7 +47,7 @@ namespace Flow.Launcher.Resources.Controls
set
{
SetValue(MessageProperty, value);
- UpdateMessageVisibility(); // Message 속성 변경 시 Visibility 업데이트
+ UpdateMessageVisibility(); // Visibility update when change Message
}
}
@@ -74,7 +73,7 @@ namespace Flow.Launcher.Resources.Controls
set
{
SetValue(TitleProperty, value);
- UpdateTitleVisibility(); // Title 속성 변경 시 Visibility 업데이트
+ UpdateTitleVisibility(); // Visibility update when change Title
}
}
From 317f241c26feea8c970ce5cc36bf0d4422b46300 Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 01:25:12 +0900
Subject: [PATCH 14/97] - Add Comment - Applied changes from CodeRabbit
---
.../Resources/Controls/InfoBar.xaml.cs | 2 +
.../SettingsPaneGeneralViewModel.cs | 187 +++++++++---------
2 files changed, 99 insertions(+), 90 deletions(-)
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
index d447192cf..f4e26ea7c 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
@@ -19,6 +19,8 @@ namespace Flow.Launcher.Resources.Controls
UpdateMessageVisibility();
UpdateOrientation();
UpdateIconAlignmentAndMargin();
+ UpdateIconVisibility();
+ UpdateCloseButtonVisibility();
}
public static readonly DependencyProperty TypeProperty =
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 701de4361..432ac998c 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -34,6 +34,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
_portable = portable;
_translater = translater;
UpdateEnumDropdownLocalizations();
+ // Initialize the Korean IME status by checking registry
IsLegacyKoreanIMEEnabled();
OpenImeSettingsCommand = new RelayCommand(OpenImeSettings);
}
@@ -188,129 +189,135 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
UpdateEnumDropdownLocalizations();
}
}
+
+ // The new Korean IME used in Windows 11 has compatibility issues with WPF. This issue is difficult to resolve within
+ // WPF itself, but it can be avoided by having the user switch to the legacy IME at the system level. Therefore,
+ // we provide guidance and a direct button for users to make this change themselves. If the relevant registry key does
+ // not exist (i.e., the Korean IME is not installed), this setting will not be shown at all.
+ #region Korean IME
public bool LegacyKoreanIMEEnabled
-{
- get => IsLegacyKoreanIMEEnabled();
- set
{
- Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled changed: {value}");
- if (SetLegacyKoreanIMEEnabled(value))
+ get => IsLegacyKoreanIMEEnabled();
+ set
{
- OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
- OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
- }
- else
- {
- Debug.WriteLine("[DEBUG] Failed to set LegacyKoreanIMEEnabled");
+ Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled changed: {value}");
+ if (SetLegacyKoreanIMEEnabled(value))
+ {
+ OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
+ OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
+ }
+ else
+ {
+ Debug.WriteLine("[DEBUG] Failed to set LegacyKoreanIMEEnabled");
+ }
}
}
-}
-public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist();
+ public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist();
-public bool KoreanIMERegistryValueIsZero
-{
- get
+ public bool KoreanIMERegistryValueIsZero
+ {
+ get
+ {
+ object value = GetLegacyKoreanIMERegistryValue();
+ if (value is int intValue)
+ {
+ return intValue == 0;
+ }
+ else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
+ {
+ return parsedValue == 0;
+ }
+
+ return false;
+ }
+ }
+
+ bool IsKoreanIMEExist()
+ {
+ return GetLegacyKoreanIMERegistryValue() != null;
+ }
+
+ bool IsLegacyKoreanIMEEnabled()
{
object value = GetLegacyKoreanIMERegistryValue();
+
if (value is int intValue)
{
- return intValue == 0;
+ return intValue == 1;
}
else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
{
- return parsedValue == 0;
+ return parsedValue == 1;
}
return false;
}
-}
-bool IsKoreanIMEExist()
-{
- return GetLegacyKoreanIMERegistryValue() != null;
-}
-
-bool IsLegacyKoreanIMEEnabled()
-{
- object value = GetLegacyKoreanIMERegistryValue();
-
- if (value is int intValue)
+ bool SetLegacyKoreanIMEEnabled(bool enable)
{
- return intValue == 1;
- }
- else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
- {
- return parsedValue == 1;
- }
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
- return false;
-}
-
-bool SetLegacyKoreanIMEEnabled(bool enable)
-{
- const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
- const string valueName = "NoTsf3Override5";
-
- try
- {
- using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath))
+ try
{
- if (key != null)
+ using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath))
{
- int value = enable ? 1 : 0;
- key.SetValue(valueName, value, RegistryValueKind.DWord);
- return true;
- }
- else
- {
- Debug.WriteLine($"[IME DEBUG] Failed to create or open registry key: {subKeyPath}");
+ if (key != null)
+ {
+ int value = enable ? 1 : 0;
+ key.SetValue(valueName, value, RegistryValueKind.DWord);
+ return true;
+ }
+ else
+ {
+ Debug.WriteLine($"[IME DEBUG] Failed to create or open registry key: {subKeyPath}");
+ }
}
}
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"[IME DEBUG] Exception occurred while setting registry: {ex.Message}");
- }
-
- return false;
-}
-
-private object GetLegacyKoreanIMERegistryValue()
-{
- const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
- const string valueName = "NoTsf3Override5";
-
- try
- {
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath))
+ catch (Exception ex)
{
- if (key != null)
+ Debug.WriteLine($"[IME DEBUG] Exception occurred while setting registry: {ex.Message}");
+ }
+
+ return false;
+ }
+
+ private object GetLegacyKoreanIMERegistryValue()
+ {
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath))
{
- return key.GetValue(valueName);
+ if (key != null)
+ {
+ return key.GetValue(valueName);
+ }
}
}
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"[IME DEBUG] Exception occurred: {ex.Message}");
+ catch (Exception ex)
+ {
+ Debug.WriteLine($"[IME DEBUG] Exception occurred: {ex.Message}");
+ }
+
+ return null;
}
- return null;
-}
-
-private void OpenImeSettings()
-{
- try
+ private void OpenImeSettings()
{
- Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
+ try
+ {
+ Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
+ }
+ catch (Exception e)
+ {
+ Debug.WriteLine($"Error opening IME settings: {e.Message}");
+ }
}
- catch (Exception e)
- {
- Debug.WriteLine($"Error opening IME settings: {e.Message}");
- }
-}
-
+ #endregion
public bool ShouldUsePinyin
{
From 1c1bad087ce11066e315e5ea9efd1de4fcae76cb Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 01:37:06 +0900
Subject: [PATCH 15/97] Cleanup Code
---
Flow.Launcher/Resources/Controls/InfoBar.xaml | 2 +-
.../Resources/Controls/InfoBar.xaml.cs | 19 +++++++++----------
.../SettingsPaneGeneralViewModel.cs | 2 --
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml b/Flow.Launcher/Resources/Controls/InfoBar.xaml
index f82a32a8b..3c6780690 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml
@@ -28,7 +28,7 @@
Date: Thu, 10 Apr 2025 01:42:35 +0900
Subject: [PATCH 16/97] Remove namespace Add Default Case
---
Flow.Launcher/Resources/Controls/InfoBar.xaml | 3 ++-
Flow.Launcher/Resources/Controls/InfoBar.xaml.cs | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml b/Flow.Launcher/Resources/Controls/InfoBar.xaml
index 3c6780690..2ddcbdd0c 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml
@@ -3,7 +3,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
- xmlns:converters="clr-namespace:Flow.Launcher.Converters"
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"
@@ -69,10 +68,12 @@
Width="32"
Height="32"
VerticalAlignment="Center"
+ AutomationProperties.Name="Close InfoBar"
Click="PART_CloseButton_Click"
Content=""
FontFamily="Segoe MDL2 Assets"
FontSize="12"
+ ToolTip="Close"
Visibility="Visible" />
diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
index 77470dbc2..ebf763e22 100644
--- a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
+++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs
@@ -175,6 +175,11 @@ namespace Flow.Launcher.Resources.Controls
PART_IconBorder.Background = (Brush)FindResource("InfoBarErrorIcon");
PART_Icon.Glyph = "\xF13D";
break;
+ default:
+ PART_Border.Background = (Brush)FindResource("InfoBarInfoBG");
+ PART_IconBorder.Background = (Brush)FindResource("InfoBarInfoIcon");
+ PART_Icon.Glyph = "\xF13F";
+ break;
}
}
From ebff80caea3dd3d7e0cf05ee95ef6b3515b6aa23 Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 01:46:29 +0900
Subject: [PATCH 17/97] Add Error Message
---
.../SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 3a20f81d5..33a7428db 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -206,7 +206,8 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
else
{
- Debug.WriteLine("[DEBUG] Failed to set LegacyKoreanIMEEnabled");
+ //Since this is rarely seen text, language support is not provided.
+ App.API.ShowMsg("Failed to change Korean IME setting", "Please check your system registry access or contact support.");
}
}
}
From 22c0f59f202e993878ab2a0f884bb78b9a5ee75d Mon Sep 17 00:00:00 2001
From: DB p
Date: Thu, 10 Apr 2025 22:06:44 +0900
Subject: [PATCH 18/97] Add badge area in xaml
---
Flow.Launcher/ResultListBox.xaml | 95 +++++++++++++++++---------------
1 file changed, 51 insertions(+), 44 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 4c3bd1d12..59a16e10c 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -90,62 +90,69 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Date: Fri, 11 Apr 2025 10:37:49 +0800
Subject: [PATCH 19/97] Remove blank lines
---
Flow.Launcher/ResultListBox.xaml | 2 --
Flow.Launcher/ViewModel/ResultViewModel.cs | 1 -
2 files changed, 3 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 59a16e10c..b57cb0d40 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -151,8 +151,6 @@
-
-
Date: Fri, 11 Apr 2025 11:08:28 +0800
Subject: [PATCH 20/97] Remove debug codes & Improve code quality
---
Flow.Launcher.Infrastructure/Win32Helper.cs | 82 +++++++++++++
.../SettingsPaneGeneralViewModel.cs | 110 +++---------------
2 files changed, 95 insertions(+), 97 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs
index f9c548de8..815f31280 100644
--- a/Flow.Launcher.Infrastructure/Win32Helper.cs
+++ b/Flow.Launcher.Infrastructure/Win32Helper.cs
@@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
+using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows;
@@ -517,5 +518,86 @@ namespace Flow.Launcher.Infrastructure
}
#endregion
+
+ #region Korean IME
+
+ public static bool IsKoreanIMEExist()
+ {
+ return GetLegacyKoreanIMERegistryValue() != null;
+ }
+
+ public static bool IsLegacyKoreanIMEEnabled()
+ {
+ object value = GetLegacyKoreanIMERegistryValue();
+
+ if (value is int intValue)
+ {
+ return intValue == 1;
+ }
+ else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
+ {
+ return parsedValue == 1;
+ }
+
+ return false;
+ }
+
+ public static bool SetLegacyKoreanIMEEnabled(bool enable)
+ {
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath);
+ if (key != null)
+ {
+ int value = enable ? 1 : 0;
+ key.SetValue(valueName, value, RegistryValueKind.DWord);
+ return true;
+ }
+ }
+ catch (System.Exception)
+ {
+ // Ignored
+ }
+
+ return false;
+ }
+
+ public static object GetLegacyKoreanIMERegistryValue()
+ {
+ const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
+ const string valueName = "NoTsf3Override5";
+
+ try
+ {
+ using RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath);
+ if (key != null)
+ {
+ return key.GetValue(valueName);
+ }
+ }
+ catch (System.Exception)
+ {
+ // Ignored
+ }
+
+ return null;
+ }
+
+ public static void OpenImeSettings()
+ {
+ try
+ {
+ Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
+ }
+ catch (System.Exception)
+ {
+ // Ignored
+ }
+ }
+
+ #endregion
}
}
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 33a7428db..7eba1602f 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -1,20 +1,16 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
using System.Windows.Forms;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Configuration;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
+using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
-using Microsoft.Win32;
using OpenFileDialog = System.Windows.Forms.OpenFileDialog;
-using System.Windows.Input;
-
namespace Flow.Launcher.SettingPages.ViewModels;
@@ -25,8 +21,6 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
private readonly IPortable _portable;
private readonly Internationalization _translater;
- public ICommand OpenImeSettingsCommand { get; }
-
public SettingsPaneGeneralViewModel(Settings settings, Updater updater, IPortable portable, Internationalization translater)
{
Settings = settings;
@@ -34,7 +28,6 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
_portable = portable;
_translater = translater;
UpdateEnumDropdownLocalizations();
- OpenImeSettingsCommand = new RelayCommand(OpenImeSettings);
}
public class SearchWindowScreenData : DropdownDataGeneric { }
@@ -187,21 +180,22 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
UpdateEnumDropdownLocalizations();
}
}
-
+
+ #region Korean IME
+
// The new Korean IME used in Windows 11 has compatibility issues with WPF. This issue is difficult to resolve within
// WPF itself, but it can be avoided by having the user switch to the legacy IME at the system level. Therefore,
// we provide guidance and a direct button for users to make this change themselves. If the relevant registry key does
// not exist (i.e., the Korean IME is not installed), this setting will not be shown at all.
- #region Korean IME
+
public bool LegacyKoreanIMEEnabled
{
- get => IsLegacyKoreanIMEEnabled();
+ get => Win32Helper.IsLegacyKoreanIMEEnabled();
set
{
- Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled changed: {value}");
- if (SetLegacyKoreanIMEEnabled(value))
+ if (Win32Helper.SetLegacyKoreanIMEEnabled(value))
{
- OnPropertyChanged(nameof(LegacyKoreanIMEEnabled));
+ OnPropertyChanged();
OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero));
}
else
@@ -212,13 +206,13 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
}
- public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist();
+ public bool KoreanIMERegistryKeyExists => Win32Helper.IsKoreanIMEExist();
public bool KoreanIMERegistryValueIsZero
{
get
{
- object value = GetLegacyKoreanIMERegistryValue();
+ object value = Win32Helper.GetLegacyKoreanIMERegistryValue();
if (value is int intValue)
{
return intValue == 0;
@@ -232,90 +226,12 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
}
- bool IsKoreanIMEExist()
- {
- return GetLegacyKoreanIMERegistryValue() != null;
- }
-
- bool IsLegacyKoreanIMEEnabled()
- {
- object value = GetLegacyKoreanIMERegistryValue();
-
- if (value is int intValue)
- {
- return intValue == 1;
- }
- else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
- {
- return parsedValue == 1;
- }
-
- return false;
- }
-
- bool SetLegacyKoreanIMEEnabled(bool enable)
- {
- const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
- const string valueName = "NoTsf3Override5";
-
- try
- {
- using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath))
- {
- if (key != null)
- {
- int value = enable ? 1 : 0;
- key.SetValue(valueName, value, RegistryValueKind.DWord);
- return true;
- }
- else
- {
- Debug.WriteLine($"[IME DEBUG] Failed to create or open registry key: {subKeyPath}");
- }
- }
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"[IME DEBUG] Exception occurred while setting registry: {ex.Message}");
- }
-
- return false;
- }
-
- private object GetLegacyKoreanIMERegistryValue()
- {
- const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}";
- const string valueName = "NoTsf3Override5";
-
- try
- {
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath))
- {
- if (key != null)
- {
- return key.GetValue(valueName);
- }
- }
- }
- catch (Exception ex)
- {
- Debug.WriteLine($"[IME DEBUG] Exception occurred: {ex.Message}");
- }
-
- return null;
- }
-
+ [RelayCommand]
private void OpenImeSettings()
{
- try
- {
- Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true });
- }
- catch (Exception e)
- {
- Debug.WriteLine($"Error opening IME settings: {e.Message}");
- }
+ Win32Helper.OpenImeSettings();
}
+
#endregion
public bool ShouldUsePinyin
From b14cf89d6878ee42cab2d5ef08249c6d186c8bb9 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 11:11:58 +0800
Subject: [PATCH 21/97] Remove useless using
---
.../SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 7eba1602f..2697a508e 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -10,7 +10,6 @@ using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
-using OpenFileDialog = System.Windows.Forms.OpenFileDialog;
namespace Flow.Launcher.SettingPages.ViewModels;
@@ -20,7 +19,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
private readonly Updater _updater;
private readonly IPortable _portable;
private readonly Internationalization _translater;
-
+
public SettingsPaneGeneralViewModel(Settings settings, Updater updater, IPortable portable, Internationalization translater)
{
Settings = settings;
From 1517db8326c3e42d876e78aa12aa2f5daf0f7cab Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 11:21:22 +0800
Subject: [PATCH 22/97] Revert wrong changes on en.xaml
---
Flow.Launcher/Languages/en.xaml | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index bf430b6f5..0df77b127 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -110,12 +110,7 @@
Search Delay
Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average.
Default Search Delay Time
- Plugin default delay time after which search results appear when typing is stopped.
- Very long
- Long
- Normal
- Short
- Very short
+ Wait time before showing results after typing stops. Higher values wait longer. (ms)
Information for Korean IME user
The Korean input method used in Windows 11 may cause some issues in Flow Launcher.
@@ -393,9 +388,7 @@
Search Delay Time Setting
- Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time.
- Current search delay time
- New search delay time
+ Input the search delay time in ms you like to use for the plugin. Input empty if you don't want to specify any, and the plugin will use default search delay time.
Custom Query Hotkey
From c5f2fcaddf11858b9c1ba111375cc0ec9ec63141 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 11:22:27 +0800
Subject: [PATCH 23/97] Revert wrong changes on en.xaml
---
Flow.Launcher/Languages/en.xaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 0df77b127..f1c0a67cb 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -161,7 +161,6 @@
Plugins: {0} - Fail to remove plugin settings files, please remove them manually
Fail to remove plugin cache
Plugins: {0} - Fail to remove plugin cache files, please remove them manually
- Default
Plugin Store
From 218635a035558b0562b009ae9cbd7605d27e823a Mon Sep 17 00:00:00 2001
From: DB p
Date: Fri, 11 Apr 2025 12:56:31 +0900
Subject: [PATCH 24/97] Add logic to check whether the Korean IME is in use
---
Flow.Launcher.Infrastructure/Win32Helper.cs | 4 ++++
.../ViewModels/SettingsPaneGeneralViewModel.cs | 14 +++++++++++++-
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs
index 815f31280..2df632545 100644
--- a/Flow.Launcher.Infrastructure/Win32Helper.cs
+++ b/Flow.Launcher.Infrastructure/Win32Helper.cs
@@ -21,6 +21,10 @@ namespace Flow.Launcher.Infrastructure
{
#region Blur Handling
+ public static bool IsWindows11()
+ {
+ return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000;
+ }
public static bool IsBackdropSupported()
{
// Mica and Acrylic only supported Windows 11 22000+
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 2697a508e..13ae65894 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Windows.Forms;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core;
@@ -205,7 +206,18 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
}
}
- public bool KoreanIMERegistryKeyExists => Win32Helper.IsKoreanIMEExist();
+ public bool KoreanIMERegistryKeyExists
+ {
+ get
+ {
+ bool registryKeyExists = Win32Helper.IsKoreanIMEExist();
+ bool koreanLanguageInstalled = InputLanguage.InstalledInputLanguages.Cast().Any(lang => lang.Culture.Name.StartsWith("ko"));
+ bool isWindows11 = Win32Helper.IsWindows11();
+
+ // Return true if Windows 11 with Korean IME installed, or if the registry key exists
+ return (isWindows11 && koreanLanguageInstalled) || registryKeyExists;
+ }
+ }
public bool KoreanIMERegistryValueIsZero
{
From a6c7430094f86dd369971adade4fc7afbf383358 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 12:36:19 +0800
Subject: [PATCH 25/97] Code quality
---
Flow.Launcher.Infrastructure/Win32Helper.cs | 10 ++++++----
.../ViewModels/SettingsPaneGeneralViewModel.cs | 10 +++++-----
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs
index 2df632545..54604a271 100644
--- a/Flow.Launcher.Infrastructure/Win32Helper.cs
+++ b/Flow.Launcher.Infrastructure/Win32Helper.cs
@@ -21,10 +21,6 @@ namespace Flow.Launcher.Infrastructure
{
#region Blur Handling
- public static bool IsWindows11()
- {
- return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000;
- }
public static bool IsBackdropSupported()
{
// Mica and Acrylic only supported Windows 11 22000+
@@ -525,6 +521,12 @@ namespace Flow.Launcher.Infrastructure
#region Korean IME
+ public static bool IsWindows11()
+ {
+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
+ Environment.OSVersion.Version.Build >= 22000;
+ }
+
public static bool IsKoreanIMEExist()
{
return GetLegacyKoreanIMERegistryValue() != null;
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
index 13ae65894..021c9d7fe 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs
@@ -210,9 +210,9 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
{
get
{
- bool registryKeyExists = Win32Helper.IsKoreanIMEExist();
- bool koreanLanguageInstalled = InputLanguage.InstalledInputLanguages.Cast().Any(lang => lang.Culture.Name.StartsWith("ko"));
- bool isWindows11 = Win32Helper.IsWindows11();
+ var registryKeyExists = Win32Helper.IsKoreanIMEExist();
+ var koreanLanguageInstalled = InputLanguage.InstalledInputLanguages.Cast().Any(lang => lang.Culture.Name.StartsWith("ko"));
+ var isWindows11 = Win32Helper.IsWindows11();
// Return true if Windows 11 with Korean IME installed, or if the registry key exists
return (isWindows11 && koreanLanguageInstalled) || registryKeyExists;
@@ -223,12 +223,12 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
{
get
{
- object value = Win32Helper.GetLegacyKoreanIMERegistryValue();
+ var value = Win32Helper.GetLegacyKoreanIMERegistryValue();
if (value is int intValue)
{
return intValue == 0;
}
- else if (value != null && int.TryParse(value.ToString(), out int parsedValue))
+ else if (value != null && int.TryParse(value.ToString(), out var parsedValue))
{
return parsedValue == 0;
}
From 71923194b61abd1aaec2df4b8e1275581078096f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 12:38:48 +0800
Subject: [PATCH 26/97] Change IME settings icon
---
Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
index 5304824fe..4782d356e 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml
@@ -341,7 +341,7 @@
From e29bf745149d7dc9178562fdec8e222cc9271b46 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 12:50:00 +0800
Subject: [PATCH 27/97] Fix explorer settings panel margin
---
.../Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml
index 1bdb9d36a..6ca7be84d 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml
@@ -598,7 +598,7 @@
From 3e20c518a0d6c45af027f8387dcb21c782466bdf Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 14:51:25 +0800
Subject: [PATCH 28/97] Code quality
---
Flow.Launcher/ViewModel/ResultsViewModel.cs | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs
index 61566b415..02fb379fa 100644
--- a/Flow.Launcher/ViewModel/ResultsViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs
@@ -19,7 +19,7 @@ namespace Flow.Launcher.ViewModel
public ResultCollection Results { get; }
- private readonly object _collectionLock = new object();
+ private readonly object _collectionLock = new();
private readonly Settings _settings;
private int MaxResults => _settings?.MaxResultsToShow ?? 6;
@@ -89,7 +89,7 @@ namespace Flow.Launcher.ViewModel
#region Private Methods
- private int InsertIndexOf(int newScore, IList list)
+ private static int InsertIndexOf(int newScore, IList list)
{
int index = 0;
for (; index < list.Count; index++)
@@ -118,7 +118,6 @@ namespace Flow.Launcher.ViewModel
}
}
-
#endregion
#region Public Methods
@@ -190,10 +189,10 @@ namespace Flow.Launcher.ViewModel
if (token.IsCancellationRequested)
return;
- UpdateResults(newResults, token, reselect);
+ UpdateResults(newResults, reselect, token);
}
- private void UpdateResults(List newResults, CancellationToken token = default, bool reselect = true)
+ private void UpdateResults(List newResults, bool reselect = true, CancellationToken token = default)
{
lock (_collectionLock)
{
From 47398f104f316675f4193af1ff6df1865f587047 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 14:58:47 +0800
Subject: [PATCH 29/97] Add ShowPluginBadges settings
---
Flow.Launcher.Infrastructure/UserSettings/Settings.cs | 1 +
Flow.Launcher/ResultListBox.xaml | 2 +-
Flow.Launcher/ViewModel/ResultViewModel.cs | 5 +++++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index e304a1b50..b48f047c5 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -101,6 +101,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool UseAnimation { get; set; } = true;
public bool UseSound { get; set; } = true;
public double SoundVolume { get; set; } = 50;
+ public bool ShowPluginBadges { get; set; } = false;
public bool UseClock { get; set; } = true;
public bool UseDate { get; set; } = false;
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index b57cb0d40..03bff03eb 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -146,7 +146,7 @@
VerticalAlignment="Bottom"
RenderOptions.BitmapScalingMode="Fant"
Source="{Binding Image, TargetNullValue={x:Null}}"
- Visibility="{Binding ShowBadge, Converter={StaticResource BoolToVisibilityConverter}}" />
+ Visibility="{Binding ShowBadge}" />
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 0975398dc..41e5dd12e 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -123,6 +123,11 @@ namespace Flow.Launcher.ViewModel
}
}
+ public Visibility ShowBadge
+ {
+ get => Settings.ShowPluginBadges ? Visibility.Visible : Visibility.Collapsed;
+ }
+
private bool GlyphAvailable => Glyph is not null;
private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPath) || Result.Icon is not null;
From 579dc061718ac2b151d8b9cf1523fd4c93e0b03f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:00:46 +0800
Subject: [PATCH 30/97] Code quality
---
Flow.Launcher.Plugin/Result.cs | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs
index 910485438..2e4befdc2 100644
--- a/Flow.Launcher.Plugin/Result.cs
+++ b/Flow.Launcher.Plugin/Result.cs
@@ -60,7 +60,7 @@ namespace Flow.Launcher.Plugin
/// GlyphInfo is prioritized if not null
public string IcoPath
{
- get { return _icoPath; }
+ get => _icoPath;
set
{
// As a standard this property will handle prepping and converting to absolute local path for icon image processing
@@ -101,7 +101,6 @@ namespace Flow.Launcher.Plugin
///
public GlyphInfo Glyph { get; init; }
-
///
/// An action to take in the form of a function call when the result has been selected.
///
@@ -143,7 +142,7 @@ namespace Flow.Launcher.Plugin
///
public string PluginDirectory
{
- get { return _pluginDirectory; }
+ get => _pluginDirectory;
set
{
_pluginDirectory = value;
From 471c3edc6fc679ebfb5b72f5be9ed418c3575bba Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:21:11 +0800
Subject: [PATCH 31/97] Add BadgePath & BadgeIcon property
---
Flow.Launcher.Plugin/Result.cs | 150 ++++++++++++++---------
Flow.Launcher/ViewModel/MainViewModel.cs | 11 +-
2 files changed, 102 insertions(+), 59 deletions(-)
diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs
index 2e4befdc2..7e520175e 100644
--- a/Flow.Launcher.Plugin/Result.cs
+++ b/Flow.Launcher.Plugin/Result.cs
@@ -12,12 +12,19 @@ namespace Flow.Launcher.Plugin
///
public class Result
{
+ ///
+ /// Maximum score. This can be useful when set one result to the top by default. This is the score for the results set to the topmost by users.
+ ///
+ public const int MaxScore = int.MaxValue;
+
private string _pluginDirectory;
private string _icoPath;
private string _copyText = string.Empty;
+ private string _badgePath;
+
///
/// The title of the result. This is always required.
///
@@ -80,6 +87,33 @@ namespace Flow.Launcher.Plugin
}
}
+ ///
+ /// The image to be displayed for the badge of the result.
+ ///
+ /// Can be a local file path or a URL.
+ /// If null or empty, will use plugin icon
+ public string BadgePath
+ {
+ get => _badgePath;
+ set
+ {
+ // As a standard this property will handle prepping and converting to absolute local path for icon image processing
+ if (!string.IsNullOrEmpty(value)
+ && !string.IsNullOrEmpty(PluginDirectory)
+ && !Path.IsPathRooted(value)
+ && !value.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
+ && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
+ && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase))
+ {
+ _badgePath = Path.Combine(PluginDirectory, value);
+ }
+ else
+ {
+ _badgePath = value;
+ }
+ }
+ }
+
///
/// Determines if Icon has a border radius
///
@@ -94,7 +128,12 @@ namespace Flow.Launcher.Plugin
///
/// Delegate to load an icon for this result.
///
- public IconDelegate Icon;
+ public IconDelegate Icon { get; set; }
+
+ ///
+ /// Delegate to load an icon for the badge of this result.
+ ///
+ public IconDelegate BadgeIcon { get; set; }
///
/// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons)
@@ -154,47 +193,6 @@ namespace Flow.Launcher.Plugin
}
}
- ///
- public override string ToString()
- {
- return Title + SubTitle + Score;
- }
-
- ///
- /// Clones the current result
- ///
- public Result Clone()
- {
- return new Result
- {
- Title = Title,
- SubTitle = SubTitle,
- ActionKeywordAssigned = ActionKeywordAssigned,
- CopyText = CopyText,
- AutoCompleteText = AutoCompleteText,
- IcoPath = IcoPath,
- RoundedIcon = RoundedIcon,
- Icon = Icon,
- Glyph = Glyph,
- Action = Action,
- AsyncAction = AsyncAction,
- Score = Score,
- TitleHighlightData = TitleHighlightData,
- OriginQuery = OriginQuery,
- PluginDirectory = PluginDirectory,
- ContextData = ContextData,
- PluginID = PluginID,
- TitleToolTip = TitleToolTip,
- SubTitleToolTip = SubTitleToolTip,
- PreviewPanel = PreviewPanel,
- ProgressBar = ProgressBar,
- ProgressBarColor = ProgressBarColor,
- Preview = Preview,
- AddSelectedCount = AddSelectedCount,
- RecordKey = RecordKey
- };
- }
-
///
/// Additional data associated with this result
///
@@ -223,16 +221,6 @@ namespace Flow.Launcher.Plugin
///
public Lazy PreviewPanel { get; set; }
- ///
- /// Run this result, asynchronously
- ///
- ///
- ///
- public ValueTask ExecuteAsync(ActionContext context)
- {
- return AsyncAction?.Invoke(context) ?? ValueTask.FromResult(Action?.Invoke(context) ?? false);
- }
-
///
/// Progress bar display. Providing an int value between 0-100 will trigger the progress bar to be displayed on the result
///
@@ -254,11 +242,6 @@ namespace Flow.Launcher.Plugin
///
public bool AddSelectedCount { get; set; } = true;
- ///
- /// Maximum score. This can be useful when set one result to the top by default. This is the score for the results set to the topmost by users.
- ///
- public const int MaxScore = int.MaxValue;
-
///
/// The key to identify the record. This is used when FL checks whether the result is the topmost record. Or FL calculates the hashcode of the result for user selected records.
/// This can be useful when your plugin will change the Title or SubTitle of the result dynamically.
@@ -267,6 +250,59 @@ namespace Flow.Launcher.Plugin
///
public string RecordKey { get; set; } = null;
+ ///
+ /// Run this result, asynchronously
+ ///
+ ///
+ ///
+ public ValueTask ExecuteAsync(ActionContext context)
+ {
+ return AsyncAction?.Invoke(context) ?? ValueTask.FromResult(Action?.Invoke(context) ?? false);
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Title + SubTitle + Score;
+ }
+
+ ///
+ /// Clones the current result
+ ///
+ public Result Clone()
+ {
+ return new Result
+ {
+ Title = Title,
+ SubTitle = SubTitle,
+ ActionKeywordAssigned = ActionKeywordAssigned,
+ CopyText = CopyText,
+ AutoCompleteText = AutoCompleteText,
+ IcoPath = IcoPath,
+ BadgePath = BadgePath,
+ RoundedIcon = RoundedIcon,
+ Icon = Icon,
+ BadgeIcon = BadgeIcon,
+ Glyph = Glyph,
+ Action = Action,
+ AsyncAction = AsyncAction,
+ Score = Score,
+ TitleHighlightData = TitleHighlightData,
+ OriginQuery = OriginQuery,
+ PluginDirectory = PluginDirectory,
+ ContextData = ContextData,
+ PluginID = PluginID,
+ TitleToolTip = TitleToolTip,
+ SubTitleToolTip = SubTitleToolTip,
+ PreviewPanel = PreviewPanel,
+ ProgressBar = ProgressBar,
+ ProgressBarColor = ProgressBarColor,
+ Preview = Preview,
+ AddSelectedCount = AddSelectedCount,
+ RecordKey = RecordKey
+ };
+ }
+
///
/// Info of the preview section of a
///
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 4a6c1d639..38efca72b 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -1268,8 +1268,7 @@ namespace Flow.Launcher.ViewModel
// Task.Yield will force it to run in ThreadPool
await Task.Yield();
- IReadOnlyList results =
- await PluginManager.QueryForPluginAsync(plugin, query, token);
+ var results = await PluginManager.QueryForPluginAsync(plugin, query, token);
if (token.IsCancellationRequested)
return;
@@ -1285,6 +1284,14 @@ namespace Flow.Launcher.ViewModel
resultsCopy = DeepCloneResults(results, token);
}
+ foreach (var result in results)
+ {
+ if (string.IsNullOrEmpty(result.BadgePath))
+ {
+ result.BadgePath = plugin.Metadata.IcoPath;
+ }
+ }
+
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, plugin.Metadata, query,
token, reSelect)))
{
From b85c2f48f9a3233991671971b9207996582b177d Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:35:36 +0800
Subject: [PATCH 32/97] Add related settings in appreance page
---
.../UserSettings/Settings.cs | 2 +-
Flow.Launcher/Languages/en.xaml | 2 ++
.../SettingPages/Views/SettingsPaneTheme.xaml | 16 ++++++++++++++--
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
4 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index b48f047c5..d97a9ed1a 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -101,7 +101,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool UseAnimation { get; set; } = true;
public bool UseSound { get; set; } = true;
public double SoundVolume { get; set; } = 50;
- public bool ShowPluginBadges { get; set; } = false;
+ public bool ShowBadges { get; set; } = false;
public bool UseClock { get; set; } = true;
public bool UseDate { get; set; } = false;
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 609859d0d..66721d828 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -283,6 +283,8 @@
Use Segoe Fluent Icons
Use Segoe Fluent Icons for query results where supported
Press Key
+ Show Result Badges
+ Show badges for query results where supported
HTTP Proxy
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml
index 49306cd2d..574002a05 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml
@@ -698,11 +698,10 @@
-
+
+
+
+
+
+
Settings.ShowPluginBadges ? Visibility.Visible : Visibility.Collapsed;
+ get => Settings.ShowBadges ? Visibility.Visible : Visibility.Collapsed;
}
private bool GlyphAvailable => Glyph is not null;
From 9e3e0f6e3c561b1106e63e0439162ec3df33a60f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:38:00 +0800
Subject: [PATCH 33/97] Change name to BadgeIcoPath
---
Flow.Launcher.Plugin/Result.cs | 12 ++++++------
Flow.Launcher/ViewModel/MainViewModel.cs | 4 ++--
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs
index 7e520175e..70d11dadd 100644
--- a/Flow.Launcher.Plugin/Result.cs
+++ b/Flow.Launcher.Plugin/Result.cs
@@ -23,7 +23,7 @@ namespace Flow.Launcher.Plugin
private string _copyText = string.Empty;
- private string _badgePath;
+ private string _badgeIcoPath;
///
/// The title of the result. This is always required.
@@ -92,9 +92,9 @@ namespace Flow.Launcher.Plugin
///
/// Can be a local file path or a URL.
/// If null or empty, will use plugin icon
- public string BadgePath
+ public string BadgeIcoPath
{
- get => _badgePath;
+ get => _badgeIcoPath;
set
{
// As a standard this property will handle prepping and converting to absolute local path for icon image processing
@@ -105,11 +105,11 @@ namespace Flow.Launcher.Plugin
&& !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
&& !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase))
{
- _badgePath = Path.Combine(PluginDirectory, value);
+ _badgeIcoPath = Path.Combine(PluginDirectory, value);
}
else
{
- _badgePath = value;
+ _badgeIcoPath = value;
}
}
}
@@ -279,7 +279,7 @@ namespace Flow.Launcher.Plugin
CopyText = CopyText,
AutoCompleteText = AutoCompleteText,
IcoPath = IcoPath,
- BadgePath = BadgePath,
+ BadgeIcoPath = BadgeIcoPath,
RoundedIcon = RoundedIcon,
Icon = Icon,
BadgeIcon = BadgeIcon,
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 38efca72b..0abd14ec5 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -1286,9 +1286,9 @@ namespace Flow.Launcher.ViewModel
foreach (var result in results)
{
- if (string.IsNullOrEmpty(result.BadgePath))
+ if (string.IsNullOrEmpty(result.BadgeIcoPath))
{
- result.BadgePath = plugin.Metadata.IcoPath;
+ result.BadgeIcoPath = plugin.Metadata.IcoPath;
}
}
From d338c5551d9cf136fffcf74e269f3446215a09e4 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:47:41 +0800
Subject: [PATCH 34/97] Fix badge icon url issue
---
Flow.Launcher.Plugin/Result.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs
index 70d11dadd..ac00d5af5 100644
--- a/Flow.Launcher.Plugin/Result.cs
+++ b/Flow.Launcher.Plugin/Result.cs
@@ -188,8 +188,9 @@ namespace Flow.Launcher.Plugin
// When the Result object is returned from the query call, PluginDirectory is not provided until
// UpdatePluginMetadata call is made at PluginManager.cs L196. Once the PluginDirectory becomes available
- // we need to update (only if not Uri path) the IcoPath with the full absolute path so the image can be loaded.
+ // we need to update (only if not Uri path) the IcoPath and BadgeIcoPath with the full absolute path so the image can be loaded.
IcoPath = _icoPath;
+ BadgeIcoPath = _badgeIcoPath;
}
}
From a1ce6b348dbc679bed986de05447e8fb86d7e21b Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:48:49 +0800
Subject: [PATCH 35/97] Fix result badge ico path update issue
---
Flow.Launcher/ViewModel/MainViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 0abd14ec5..c1a237c6a 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -1284,7 +1284,7 @@ namespace Flow.Launcher.ViewModel
resultsCopy = DeepCloneResults(results, token);
}
- foreach (var result in results)
+ foreach (var result in resultsCopy)
{
if (string.IsNullOrEmpty(result.BadgeIcoPath))
{
From ec99a365b9d27a708464b4506a41d55259c15961 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:49:39 +0800
Subject: [PATCH 36/97] Support badge path for result update interface
---
Flow.Launcher/ViewModel/MainViewModel.cs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index c1a237c6a..2155f7bf8 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -245,6 +245,14 @@ namespace Flow.Launcher.ViewModel
// make a clone to avoid possible issue that plugin will also change the list and items when updating view model
var resultsCopy = DeepCloneResults(e.Results, token);
+ foreach (var result in resultsCopy)
+ {
+ if (string.IsNullOrEmpty(result.BadgeIcoPath))
+ {
+ result.BadgeIcoPath = pair.Metadata.IcoPath;
+ }
+ }
+
PluginManager.UpdatePluginMetadata(resultsCopy, pair.Metadata, e.Query);
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query,
token)))
From 2eda64aa7af74dad5f3cf21fda8e8a8e6230fe64 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 15:51:26 +0800
Subject: [PATCH 37/97] Support badge icon loading
---
Flow.Launcher/ResultListBox.xaml | 2 +-
Flow.Launcher/ViewModel/ResultViewModel.cs | 46 ++++++++++++++++++++--
2 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 03bff03eb..63c461c43 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -145,7 +145,7 @@
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
RenderOptions.BitmapScalingMode="Fant"
- Source="{Binding Image, TargetNullValue={x:Null}}"
+ Source="{Binding BadgeImage, TargetNullValue={x:Null}}"
Visibility="{Binding ShowBadge}" />
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 61e228de1..4137d5f58 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -125,13 +125,21 @@ namespace Flow.Launcher.ViewModel
public Visibility ShowBadge
{
- get => Settings.ShowBadges ? Visibility.Visible : Visibility.Collapsed;
+ get
+ {
+ if (Settings.ShowBadges && BadgeIconAvailable)
+ return Visibility.Visible;
+
+ return Visibility.Collapsed;
+ }
}
private bool GlyphAvailable => Glyph is not null;
private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPath) || Result.Icon is not null;
+ private bool BadgeIconAvailable => !string.IsNullOrEmpty(Result.BadgeIcoPath) || Result.BadgeIcon is not null;
+
private bool PreviewImageAvailable => !string.IsNullOrEmpty(Result.Preview.PreviewImagePath) || Result.Preview.PreviewDelegate != null;
public string OpenResultModifiers => Settings.OpenResultModifiers;
@@ -145,9 +153,11 @@ namespace Flow.Launcher.ViewModel
: Result.SubTitleToolTip;
private volatile bool _imageLoaded;
+ private volatile bool _badgeImageLoaded;
private volatile bool _previewImageLoaded;
private ImageSource _image = ImageLoader.LoadingImage;
+ private ImageSource _badgeImage = ImageLoader.LoadingImage;
private ImageSource _previewImage = ImageLoader.LoadingImage;
public ImageSource Image
@@ -165,6 +175,21 @@ namespace Flow.Launcher.ViewModel
private set => _image = value;
}
+ public ImageSource BadgeImage
+ {
+ get
+ {
+ if (!_badgeImageLoaded)
+ {
+ _badgeImageLoaded = true;
+ _ = LoadBadgeImageAsync();
+ }
+
+ return _badgeImage;
+ }
+ private set => _badgeImage = value;
+ }
+
public ImageSource PreviewImage
{
get
@@ -210,7 +235,7 @@ namespace Flow.Launcher.ViewModel
{
var imagePath = Result.IcoPath;
var iconDelegate = Result.Icon;
- if (ImageLoader.TryGetValue(imagePath, false, out ImageSource img))
+ if (ImageLoader.TryGetValue(imagePath, false, out var img))
{
_image = img;
}
@@ -221,11 +246,26 @@ namespace Flow.Launcher.ViewModel
}
}
+ private async Task LoadBadgeImageAsync()
+ {
+ var badgeImagePath = Result.BadgeIcoPath;
+ var badgeIconDelegate = Result.BadgeIcon;
+ if (ImageLoader.TryGetValue(badgeImagePath, false, out var img))
+ {
+ _badgeImage = img;
+ }
+ else
+ {
+ // We need to modify the property not field here to trigger the OnPropertyChanged event
+ BadgeImage = await LoadImageInternalAsync(badgeImagePath, badgeIconDelegate, false).ConfigureAwait(false);
+ }
+ }
+
private async Task LoadPreviewImageAsync()
{
var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoPath;
var iconDelegate = Result.Preview.PreviewDelegate ?? Result.Icon;
- if (ImageLoader.TryGetValue(imagePath, true, out ImageSource img))
+ if (ImageLoader.TryGetValue(imagePath, true, out var img))
{
_previewImage = img;
}
From 01f896a57844184fb24e883fe5939c9689d96403 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 16:11:39 +0800
Subject: [PATCH 38/97] Support global query only
---
.../UserSettings/Settings.cs | 1 +
Flow.Launcher/Languages/en.xaml | 2 ++
.../SettingPages/Views/SettingsPaneTheme.xaml | 23 ++++++++++++++-----
Flow.Launcher/ViewModel/ResultViewModel.cs | 11 ++++++---
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index d97a9ed1a..7c2457a72 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -102,6 +102,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool UseSound { get; set; } = true;
public double SoundVolume { get; set; } = 50;
public bool ShowBadges { get; set; } = false;
+ public bool ShowBadgesGlobalOnly { get; set; } = false;
public bool UseClock { get; set; } = true;
public bool UseDate { get; set; } = false;
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 66721d828..87db45fbe 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -285,6 +285,8 @@
Press Key
Show Result Badges
Show badges for query results where supported
+ Show Result Badges Only for Global Query
+ Show badges only for global query results
HTTP Proxy
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml
index 574002a05..57c9a5b70 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml
@@ -711,16 +711,27 @@
-
-
-
+
+
+
+
+
+
+
Result.OriginQuery.ActionKeyword == Query.GlobalPluginWildcardSign;
+
private bool GlyphAvailable => Glyph is not null;
private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPath) || Result.Icon is not null;
From e6477e886b3e3589727fa8481dd92a98a6206df4 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 16:13:55 +0800
Subject: [PATCH 39/97] Fix global query determination issue
---
Flow.Launcher/ViewModel/MainViewModel.cs | 6 +++---
Flow.Launcher/ViewModel/ResultViewModel.cs | 3 ++-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 2155f7bf8..f6b9aa67c 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -1208,11 +1208,11 @@ namespace Flow.Launcher.ViewModel
_lastQuery = query;
- if (query.ActionKeyword == Plugin.Query.GlobalPluginWildcardSign)
+ if (string.IsNullOrEmpty(query.ActionKeyword))
{
- // Wait 45 millisecond for query change in global query
+ // Wait 15 millisecond for query change in global query
// if query changes, return so that it won't be calculated
- await Task.Delay(45, _updateSource.Token);
+ await Task.Delay(15, _updateSource.Token);
if (_updateSource.Token.IsCancellationRequested)
return;
}
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 27b385805..68c794aec 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections;
using System.Collections.Generic;
using System.Drawing.Text;
using System.IO;
@@ -137,7 +138,7 @@ namespace Flow.Launcher.ViewModel
}
}
- public bool IsGlobalQuery => Result.OriginQuery.ActionKeyword == Query.GlobalPluginWildcardSign;
+ public bool IsGlobalQuery => string.IsNullOrEmpty(Result.OriginQuery.ActionKeyword);
private bool GlyphAvailable => Glyph is not null;
From 8aff3c9f2ae49358d59760675c4ab552da865ad4 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 16:14:23 +0800
Subject: [PATCH 40/97] Improve strings
---
Flow.Launcher/Languages/en.xaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 87db45fbe..024258f1b 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -285,8 +285,8 @@
Press Key
Show Result Badges
Show badges for query results where supported
- Show Result Badges Only for Global Query
- Show badges only for global query results
+ Show Result Badges for Global Query Only
+ Show badges for global query results only
HTTP Proxy
From c1893366982d2f7d729a0cbdca6363c1d5b1218c Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 16:46:45 +0800
Subject: [PATCH 41/97] Fix possible directory not found issue when saving
storage
---
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 3 ++-
Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 8 +++++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 43bb8dade..414743d22 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -82,8 +82,8 @@ namespace Flow.Launcher.Infrastructure.Storage
public void Save()
{
+ FilesFolders.ValidateDirectory(DirectoryPath); // User may delete the directory, so we need to check it
var serialized = MemoryPackSerializer.Serialize(Data);
-
File.WriteAllBytes(FilePath, serialized);
}
@@ -103,6 +103,7 @@ namespace Flow.Launcher.Infrastructure.Storage
// so we need to pass it to SaveAsync
public async ValueTask SaveAsync(T data)
{
+ FilesFolders.ValidateDirectory(DirectoryPath); // User may delete the directory, so we need to check it
await using var stream = new FileStream(FilePath, FileMode.Create);
await MemoryPackSerializer.SerializeAsync(stream, data);
}
diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
index cdf3ae909..f283be59e 100644
--- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
@@ -183,7 +183,10 @@ namespace Flow.Launcher.Infrastructure.Storage
public void Save()
{
- string serialized = JsonSerializer.Serialize(Data,
+ // User may delete the directory, so we need to check it
+ FilesFolders.ValidateDirectory(DirectoryPath);
+
+ var serialized = JsonSerializer.Serialize(Data,
new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(TempFilePath, serialized);
@@ -193,6 +196,9 @@ namespace Flow.Launcher.Infrastructure.Storage
public async Task SaveAsync()
{
+ // User may delete the directory, so we need to check it
+ FilesFolders.ValidateDirectory(DirectoryPath);
+
await using var tempOutput = File.OpenWrite(TempFilePath);
await JsonSerializer.SerializeAsync(tempOutput, Data,
new JsonSerializerOptions { WriteIndented = true });
From 5c43dd45b236c6074f63dc314f0d3668c1653e09 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 16:48:02 +0800
Subject: [PATCH 42/97] Code quality
---
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 414743d22..b85111756 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -82,7 +82,9 @@ namespace Flow.Launcher.Infrastructure.Storage
public void Save()
{
- FilesFolders.ValidateDirectory(DirectoryPath); // User may delete the directory, so we need to check it
+ // User may delete the directory, so we need to check it
+ FilesFolders.ValidateDirectory(DirectoryPath);
+
var serialized = MemoryPackSerializer.Serialize(Data);
File.WriteAllBytes(FilePath, serialized);
}
@@ -103,7 +105,9 @@ namespace Flow.Launcher.Infrastructure.Storage
// so we need to pass it to SaveAsync
public async ValueTask SaveAsync(T data)
{
- FilesFolders.ValidateDirectory(DirectoryPath); // User may delete the directory, so we need to check it
+ // User may delete the directory, so we need to check it
+ FilesFolders.ValidateDirectory(DirectoryPath);
+
await using var stream = new FileStream(FilePath, FileMode.Create);
await MemoryPackSerializer.SerializeAsync(stream, data);
}
From e6377d046348058c1b32cb2905960747468a5101 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 18:40:03 +0800
Subject: [PATCH 43/97] Fix old Program plugin constructor issue
---
.../Storage/BinaryStorage.cs | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index b85111756..64f809181 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
@@ -40,6 +41,16 @@ namespace Flow.Launcher.Infrastructure.Storage
FilePath = Path.Combine(DirectoryPath, $"{filename}{FileSuffix}");
}
+ // Let the old Program plugin get this constructor
+ [Obsolete("This constructor is obsolete. Use BinaryStorage(string filename) instead.")]
+ public BinaryStorage(string filename, string directoryPath = null!)
+ {
+ directoryPath ??= DataLocation.CacheDirectory;
+ FilesFolders.ValidateDirectory(directoryPath);
+
+ FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}");
+ }
+
public async ValueTask TryLoadAsync(T defaultData)
{
if (Data != null) return Data;
From 3aa324d1201a79f7bdb05e21b22775fa85195b6f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 21:52:51 +0800
Subject: [PATCH 44/97] Throw plugin exception for plugin save interface
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 29d91dc8d..94519bf6f 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -64,7 +64,14 @@ namespace Flow.Launcher.Core.Plugin
foreach (var plugin in AllPlugins)
{
var savable = plugin.Plugin as ISavable;
- savable?.Save();
+ try
+ {
+ savable?.Save();
+ }
+ catch (Exception e)
+ {
+ throw new FlowPluginException(plugin.Metadata, e);
+ }
}
API.SavePluginSettings();
From bae0fa5c0e128538caf71943407088125289085b Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 22:00:36 +0800
Subject: [PATCH 45/97] Improve code quality
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 8 ++++----
.../Resource/Internationalization.cs | 17 ++++++++---------
Flow.Launcher/PublicAPIInstance.cs | 14 ++++++++------
3 files changed, 20 insertions(+), 19 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 94519bf6f..1d13dcfd3 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -37,7 +37,7 @@ namespace Flow.Launcher.Core.Plugin
private static PluginsSettings Settings;
private static List _metadatas;
- private static List _modifiedPlugins = new();
+ private static readonly List _modifiedPlugins = new();
///
/// Directories that will hold Flow Launcher plugin directory
@@ -299,7 +299,7 @@ namespace Flow.Launcher.Core.Plugin
{
Title = $"{metadata.Name}: Failed to respond!",
SubTitle = "Select this result for more info",
- IcoPath = Flow.Launcher.Infrastructure.Constant.ErrorIcon,
+ IcoPath = Constant.ErrorIcon,
PluginDirectory = metadata.PluginDirectory,
ActionKeywordAssigned = query.ActionKeyword,
PluginID = metadata.ID,
@@ -376,8 +376,8 @@ namespace Flow.Launcher.Core.Plugin
{
// this method is only checking for action keywords (defined as not '*') registration
// hence the actionKeyword != Query.GlobalPluginWildcardSign logic
- return actionKeyword != Query.GlobalPluginWildcardSign
- && NonGlobalPlugins.ContainsKey(actionKeyword);
+ return actionKeyword != Query.GlobalPluginWildcardSign
+ && NonGlobalPlugins.ContainsKey(actionKeyword);
}
///
diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs
index ffa17ab4d..df841dbbe 100644
--- a/Flow.Launcher.Core/Resource/Internationalization.cs
+++ b/Flow.Launcher.Core/Resource/Internationalization.cs
@@ -22,8 +22,8 @@ namespace Flow.Launcher.Core.Resource
private const string DefaultFile = "en.xaml";
private const string Extension = ".xaml";
private readonly Settings _settings;
- private readonly List _languageDirectories = new List();
- private readonly List _oldResources = new List();
+ private readonly List _languageDirectories = new();
+ private readonly List _oldResources = new();
private readonly string SystemLanguageCode;
public Internationalization(Settings settings)
@@ -144,7 +144,7 @@ namespace Flow.Launcher.Core.Resource
_settings.Language = isSystem ? Constant.SystemLanguageCode : language.LanguageCode;
}
- private Language GetLanguageByLanguageCode(string languageCode)
+ private static Language GetLanguageByLanguageCode(string languageCode)
{
var lowercase = languageCode.ToLower();
var language = AvailableLanguages.GetAvailableLanguages().FirstOrDefault(o => o.LanguageCode.ToLower() == lowercase);
@@ -239,7 +239,7 @@ namespace Flow.Launcher.Core.Resource
return list;
}
- public string GetTranslation(string key)
+ public static string GetTranslation(string key)
{
var translation = Application.Current.TryFindResource(key);
if (translation is string)
@@ -257,8 +257,7 @@ namespace Flow.Launcher.Core.Resource
{
foreach (var p in PluginManager.GetPluginsForInterface())
{
- var pluginI18N = p.Plugin as IPluginI18n;
- if (pluginI18N == null) return;
+ if (p.Plugin is not IPluginI18n pluginI18N) return;
try
{
p.Metadata.Name = pluginI18N.GetTranslatedPluginTitle();
@@ -272,11 +271,11 @@ namespace Flow.Launcher.Core.Resource
}
}
- public string LanguageFile(string folder, string language)
+ private static string LanguageFile(string folder, string language)
{
if (Directory.Exists(folder))
{
- string path = Path.Combine(folder, language);
+ var path = Path.Combine(folder, language);
if (File.Exists(path))
{
return path;
@@ -284,7 +283,7 @@ namespace Flow.Launcher.Core.Resource
else
{
Log.Error($"|Internationalization.LanguageFile|Language path can't be found <{path}>");
- string english = Path.Combine(folder, DefaultFile);
+ var english = Path.Combine(folder, DefaultFile);
if (File.Exists(english))
{
return english;
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 95ef6c9f3..5438eac7d 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -38,20 +38,23 @@ namespace Flow.Launcher
public class PublicAPIInstance : IPublicAPI, IRemovable
{
private readonly Settings _settings;
- private readonly Internationalization _translater;
private readonly MainViewModel _mainVM;
+ // Must use getter to access Application.Current.Resources.MergedDictionaries so earlier
private Theme _theme;
private Theme Theme => _theme ??= Ioc.Default.GetRequiredService();
+ // Must use getter to avoid circular dependency
+ private Updater _updater;
+ private Updater Updater => _updater ??= Ioc.Default.GetRequiredService();
+
private readonly object _saveSettingsLock = new();
#region Constructor
- public PublicAPIInstance(Settings settings, Internationalization translater, MainViewModel mainVM)
+ public PublicAPIInstance(Settings settings, MainViewModel mainVM)
{
_settings = settings;
- _translater = translater;
_mainVM = mainVM;
GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback;
WebRequest.RegisterPrefix("data", new DataWebRequestFactory());
@@ -100,8 +103,7 @@ namespace Flow.Launcher
remove => _mainVM.VisibilityChanged -= value;
}
- // Must use Ioc.Default.GetRequiredService() to avoid circular dependency
- public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService().UpdateAppAsync(false);
+ public void CheckForNewUpdate() => _ = Updater.UpdateAppAsync(false);
public void SaveAppAllSettings()
{
@@ -178,7 +180,7 @@ namespace Flow.Launcher
public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed;
- public string GetTranslation(string key) => _translater.GetTranslation(key);
+ public string GetTranslation(string key) => Internationalization.GetTranslation(key);
public List GetAllPlugins() => PluginManager.AllPlugins.ToList();
From 526f00261d2ccf9a148aec46d92708affef2e4d4 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 22:02:03 +0800
Subject: [PATCH 46/97] Throw plugin exception for plugin dispose interface
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 1d13dcfd3..f8a094575 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -88,14 +88,21 @@ namespace Flow.Launcher.Core.Plugin
private static async Task DisposePluginAsync(PluginPair pluginPair)
{
- switch (pluginPair.Plugin)
+ try
{
- case IDisposable disposable:
- disposable.Dispose();
- break;
- case IAsyncDisposable asyncDisposable:
- await asyncDisposable.DisposeAsync();
- break;
+ switch (pluginPair.Plugin)
+ {
+ case IDisposable disposable:
+ disposable.Dispose();
+ break;
+ case IAsyncDisposable asyncDisposable:
+ await asyncDisposable.DisposeAsync();
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new FlowPluginException(pluginPair.Metadata, e);
}
}
From deb22ad0fe02820dcdfe6431793e7ee9ecdf1d75 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 22:05:04 +0800
Subject: [PATCH 47/97] Set CanClose earlier
---
Flow.Launcher/MainWindow.xaml.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs
index 30afe67a1..bf7a45b1d 100644
--- a/Flow.Launcher/MainWindow.xaml.cs
+++ b/Flow.Launcher/MainWindow.xaml.cs
@@ -291,15 +291,15 @@ namespace Flow.Launcher
{
if (!CanClose)
{
+ CanClose = true;
_notifyIcon.Visible = false;
App.API.SaveAppAllSettings();
e.Cancel = true;
await ImageLoader.WaitSaveAsync();
await PluginManager.DisposePluginsAsync();
Notification.Uninstall();
- // After plugins are all disposed, we can close the main window
- CanClose = true;
- // Use this instead of Close() to avoid InvalidOperationException when calling Close() in OnClosing event
+ // After plugins are all disposed, we shutdown application to close app
+ // We use this instead of Close() to avoid InvalidOperationException when calling Close() in OnClosing event
Application.Current.Shutdown();
}
}
From 58c3b73ff7d65078185e7072fbac379fc823021a Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 22:13:58 +0800
Subject: [PATCH 48/97] Fix directory path issue
---
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 6 +++---
.../Storage/FlowLauncherJsonStorage.cs | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 64f809181..8ff10816c 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -45,10 +45,10 @@ namespace Flow.Launcher.Infrastructure.Storage
[Obsolete("This constructor is obsolete. Use BinaryStorage(string filename) instead.")]
public BinaryStorage(string filename, string directoryPath = null!)
{
- directoryPath ??= DataLocation.CacheDirectory;
- FilesFolders.ValidateDirectory(directoryPath);
+ DirectoryPath = directoryPath ?? DataLocation.CacheDirectory;
+ FilesFolders.ValidateDirectory(DirectoryPath);
- FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}");
+ FilePath = Path.Combine(DirectoryPath, $"{filename}{FileSuffix}");
}
public async ValueTask TryLoadAsync(T defaultData)
diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs
index 8b4062b6b..ca78b2f20 100644
--- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs
@@ -17,11 +17,11 @@ namespace Flow.Launcher.Infrastructure.Storage
public FlowLauncherJsonStorage()
{
- var directoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName);
- FilesFolders.ValidateDirectory(directoryPath);
+ DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName);
+ FilesFolders.ValidateDirectory(DirectoryPath);
var filename = typeof(T).Name;
- FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}");
+ FilePath = Path.Combine(DirectoryPath, $"{filename}{FileSuffix}");
}
public new void Save()
From 4527b334331a64b8ede630e84447de438f83cf5d Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 11 Apr 2025 22:16:04 +0800
Subject: [PATCH 49/97] Code quality
---
Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
index 1de5841a5..6c506cfc0 100644
--- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
+++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
@@ -264,12 +264,12 @@ namespace Flow.Launcher.Plugin.SharedCommands
var index = path.LastIndexOf('\\');
if (index > 0 && index < (path.Length - 1))
{
- string previousDirectoryPath = path.Substring(0, index + 1);
- return locationExists(previousDirectoryPath) ? previousDirectoryPath : "";
+ string previousDirectoryPath = path[..(index + 1)];
+ return locationExists(previousDirectoryPath) ? previousDirectoryPath : string.Empty;
}
else
{
- return "";
+ return string.Empty;
}
}
@@ -285,7 +285,7 @@ namespace Flow.Launcher.Plugin.SharedCommands
// not full path, get previous level directory string
var indexOfSeparator = path.LastIndexOf('\\');
- return path.Substring(0, indexOfSeparator + 1);
+ return path[..(indexOfSeparator + 1)];
}
return path;
From c66cbae78bfa96ecbec3a627ac40bed4d2b442ca Mon Sep 17 00:00:00 2001
From: DB p
Date: Sat, 12 Apr 2025 00:56:07 +0900
Subject: [PATCH 50/97] - Adjust Badge layout - Fix glyph margin in win11light
---
Flow.Launcher/ResultListBox.xaml | 15 +++++----------
Flow.Launcher/Themes/Win11Light.xaml | 4 ++--
2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 63c461c43..8231027f4 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -102,8 +102,6 @@
+
+
-
+
-
+
From 6b9c9e9eb7451dd195f7d519126b528740474161 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 08:08:26 +0800
Subject: [PATCH 51/97] Log exception instead of throw exception
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index f8a094575..52d6fd736 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -61,16 +61,16 @@ namespace Flow.Launcher.Core.Plugin
///
public static void Save()
{
- foreach (var plugin in AllPlugins)
+ foreach (var pluginPair in AllPlugins)
{
- var savable = plugin.Plugin as ISavable;
+ var savable = pluginPair.Plugin as ISavable;
try
{
savable?.Save();
}
catch (Exception e)
{
- throw new FlowPluginException(plugin.Metadata, e);
+ API.LogException(ClassName, $"Failed to save plugin {pluginPair.Metadata.Name}", e);
}
}
@@ -102,7 +102,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- throw new FlowPluginException(pluginPair.Metadata, e);
+ API.LogException(ClassName, $"Failed to dispose plugin {pluginPair.Metadata.Name}", e);
}
}
From eaac72b6969f59e975a571ea1c00ccf7945c577b Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 10:52:59 +0800
Subject: [PATCH 52/97] Handle TaskSchedulerUnhandledException
---
Flow.Launcher/App.xaml.cs | 10 ++++++++++
Flow.Launcher/Helper/ErrorReporting.cs | 9 +++++++++
2 files changed, 19 insertions(+)
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index 89faa105e..a9cd1a8b9 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -153,6 +153,7 @@ namespace Flow.Launcher
RegisterAppDomainExceptions();
RegisterDispatcherUnhandledException();
+ RegisterTaskSchedulerUnhandledException();
var imageLoadertask = ImageLoader.InitializeAsync();
@@ -284,6 +285,15 @@ namespace Flow.Launcher
AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle;
}
+ ///
+ /// let exception throw as normal is better for Debug
+ ///
+ [Conditional("RELEASE")]
+ private static void RegisterTaskSchedulerUnhandledException()
+ {
+ TaskScheduler.UnobservedTaskException += ErrorReporting.TaskSchedulerUnobservedTaskException;
+ }
+
#endregion
#region IDisposable
diff --git a/Flow.Launcher/Helper/ErrorReporting.cs b/Flow.Launcher/Helper/ErrorReporting.cs
index 5b79c520d..1787b1d91 100644
--- a/Flow.Launcher/Helper/ErrorReporting.cs
+++ b/Flow.Launcher/Helper/ErrorReporting.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading.Tasks;
using System.Windows.Threading;
using NLog;
using Flow.Launcher.Infrastructure;
@@ -30,6 +31,14 @@ public static class ErrorReporting
e.Handled = true;
}
+ public static void TaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
+ {
+ //handle unobserved task exceptions
+ Report(e.Exception);
+ //prevent application exist, so the user can copy prompted error info
+ e.SetObserved();
+ }
+
public static string RuntimeInfo()
{
var info =
From 5045f19ebe106c0d5d38546a728fd1a2c84217bf Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 14:29:40 +0800
Subject: [PATCH 53/97] Fix task scheduler unobserved task exception window
issue
---
Flow.Launcher/Helper/ErrorReporting.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/Helper/ErrorReporting.cs b/Flow.Launcher/Helper/ErrorReporting.cs
index 1787b1d91..34b776e71 100644
--- a/Flow.Launcher/Helper/ErrorReporting.cs
+++ b/Flow.Launcher/Helper/ErrorReporting.cs
@@ -1,9 +1,10 @@
using System;
using System.Threading.Tasks;
+using System.Windows;
using System.Windows.Threading;
-using NLog;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Exception;
+using NLog;
namespace Flow.Launcher.Helper;
@@ -34,7 +35,7 @@ public static class ErrorReporting
public static void TaskSchedulerUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
//handle unobserved task exceptions
- Report(e.Exception);
+ Application.Current.Dispatcher.Invoke(() => Report(e.Exception));
//prevent application exist, so the user can copy prompted error info
e.SetObserved();
}
From 5bafe23971c55f1505bd030cf721f426c23bb77d Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Sat, 12 Apr 2025 14:36:43 +0800
Subject: [PATCH 54/97] Improve code comments
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Flow.Launcher/Helper/ErrorReporting.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Flow.Launcher/Helper/ErrorReporting.cs b/Flow.Launcher/Helper/ErrorReporting.cs
index 34b776e71..b1ddba717 100644
--- a/Flow.Launcher/Helper/ErrorReporting.cs
+++ b/Flow.Launcher/Helper/ErrorReporting.cs
@@ -36,8 +36,7 @@ public static class ErrorReporting
{
//handle unobserved task exceptions
Application.Current.Dispatcher.Invoke(() => Report(e.Exception));
- //prevent application exist, so the user can copy prompted error info
- e.SetObserved();
+ //prevent application exit, so the user can copy the prompted error info
}
public static string RuntimeInfo()
From 5d39501707df1cfbf2b4b33e847e875e5698c61f Mon Sep 17 00:00:00 2001
From: DB p
Date: Sat, 12 Apr 2025 17:55:38 +0900
Subject: [PATCH 55/97] Change badge position logic
---
.../Converters/BadgePositionConverter.cs | 32 +++++++++++++++++++
.../Converters/SizeRatioConverter.cs | 27 ++++++++++++++++
Flow.Launcher/ResultListBox.xaml | 12 +++++--
3 files changed, 68 insertions(+), 3 deletions(-)
create mode 100644 Flow.Launcher/Converters/BadgePositionConverter.cs
create mode 100644 Flow.Launcher/Converters/SizeRatioConverter.cs
diff --git a/Flow.Launcher/Converters/BadgePositionConverter.cs b/Flow.Launcher/Converters/BadgePositionConverter.cs
new file mode 100644
index 000000000..66a7446f2
--- /dev/null
+++ b/Flow.Launcher/Converters/BadgePositionConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Flow.Launcher.Converters;
+
+public class BadgePositionConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double actualWidth && parameter is string param)
+ {
+ double offset = actualWidth / 2 - 8;
+
+ if (param == "1") // X-Offset
+ {
+ return offset + 2;
+ }
+ else if (param == "2") // Y-Offset
+ {
+ return offset + 2;
+ }
+ }
+
+ return 0.0;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+}
diff --git a/Flow.Launcher/Converters/SizeRatioConverter.cs b/Flow.Launcher/Converters/SizeRatioConverter.cs
new file mode 100644
index 000000000..e61eeaf9b
--- /dev/null
+++ b/Flow.Launcher/Converters/SizeRatioConverter.cs
@@ -0,0 +1,27 @@
+using System.Windows.Data;
+using System;
+using System.Globalization;
+using System.Windows;
+
+namespace Flow.Launcher.Converters;
+
+public class SizeRatioConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double size && parameter is string ratioString)
+ {
+ if (double.TryParse(ratioString, NumberStyles.Any, CultureInfo.InvariantCulture, out double ratio))
+ {
+ return size * ratio;
+ }
+ }
+
+ return 0.0;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+}
diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml
index 8231027f4..4141d9e2f 100644
--- a/Flow.Launcher/ResultListBox.xaml
+++ b/Flow.Launcher/ResultListBox.xaml
@@ -32,6 +32,8 @@
+
+
@@ -136,11 +138,15 @@
+ Visibility="{Binding ShowBadge}">
+
+
+
+
From d8f4eac0d2c1dc094802c41e307fab53c9f17643 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 20:10:24 +0800
Subject: [PATCH 56/97] Add ShowBadge property
---
Flow.Launcher.Plugin/Result.cs | 6 ++++++
Flow.Launcher/ViewModel/ResultViewModel.cs | 6 +++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs
index ac00d5af5..059f5c3f6 100644
--- a/Flow.Launcher.Plugin/Result.cs
+++ b/Flow.Launcher.Plugin/Result.cs
@@ -251,6 +251,12 @@ namespace Flow.Launcher.Plugin
///
public string RecordKey { get; set; } = null;
+ ///
+ /// Determines if the badge icon should be shown.
+ /// If users want to show the result badges and here you set this to true, the results will show the badge icon.
+ ///
+ public bool ShowBadge { get; set; } = false;
+
///
/// Run this result, asynchronously
///
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 68c794aec..8d7569dc1 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -128,9 +128,13 @@ namespace Flow.Launcher.ViewModel
{
get
{
- if (!Settings.ShowBadges || !BadgeIconAvailable)
+ // If results do not allow badges, or user has disabled badges in settings,
+ // or badge icon is not available, then do not show badge
+ if (!Result.ShowBadge || !Settings.ShowBadges || !BadgeIconAvailable)
return Visibility.Collapsed;
+ // If user has set to show badges only for global results, and this is not a global result,
+ // then do not show badge
if (Settings.ShowBadgesGlobalOnly && !IsGlobalQuery)
return Visibility.Collapsed;
From 03d7dccbb658a4650c0f3dfcb9c6b90e5189caad Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 20:22:15 +0800
Subject: [PATCH 57/97] Fix Results clone issue
---
Flow.Launcher.Plugin/Result.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs
index 059f5c3f6..f561fcb1d 100644
--- a/Flow.Launcher.Plugin/Result.cs
+++ b/Flow.Launcher.Plugin/Result.cs
@@ -306,7 +306,8 @@ namespace Flow.Launcher.Plugin
ProgressBarColor = ProgressBarColor,
Preview = Preview,
AddSelectedCount = AddSelectedCount,
- RecordKey = RecordKey
+ RecordKey = RecordKey,
+ ShowBadge = ShowBadge,
};
}
From 136a4aa1dd8c58174c6ebb03e493a9196ad1beae Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 20:47:43 +0800
Subject: [PATCH 58/97] Code quality
---
.../Search/WindowsIndex/QueryConstructor.cs | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index 22ac33f60..eed27ae71 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -60,13 +60,13 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
///
public string Directory(ReadOnlySpan path, ReadOnlySpan searchString = default, bool recursive = false)
{
- var queryConstraint = searchString.IsWhiteSpace() ? "" : $"AND ({FileName} LIKE '{searchString}%' OR CONTAINS({FileName},'\"{searchString}*\"'))";
+ var queryConstraint = searchString.IsWhiteSpace() ? "" : $"AND ({OrderIdentifier} LIKE '{searchString}%' OR CONTAINS({OrderIdentifier},'\"{searchString}*\"'))";
var scopeConstraint = recursive
? RecursiveDirectoryConstraint(path)
: TopLevelDirectoryConstraint(path);
- var query = $"SELECT TOP {settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {scopeConstraint} {queryConstraint} ORDER BY {FileName}";
+ var query = $"SELECT TOP {settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {scopeConstraint} {queryConstraint} ORDER BY {OrderIdentifier}";
return query;
}
@@ -83,7 +83,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
var replacedSearchString = ReplaceSpecialCharacterWithTwoSideWhiteSpace(userSearchString);
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
- return $"{CreateBaseQuery().GenerateSQLFromUserQuery(replacedSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {FileName}";
+ return $"{CreateBaseQuery().GenerateSQLFromUserQuery(replacedSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {OrderIdentifier}";
}
///
@@ -120,9 +120,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
public const string RestrictionsForAllFilesAndFoldersSearch = "scope='file:'";
///
- /// Order identifier: file name
+ /// Order identifier: System.Search.Rank DESC
///
- public const string FileName = "System.Search.Rank DESC";
+ ///
+ ///
+ ///
+ public const string OrderIdentifier = "System.Search.Rank DESC";
///
/// Search will be performed on all indexed file contents for the specified search keywords.
@@ -130,7 +133,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
public string FileContent(ReadOnlySpan userSearchString)
{
string query =
- $"SELECT TOP {settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {RestrictionsForFileContentSearch(userSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {FileName}";
+ $"SELECT TOP {settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {RestrictionsForFileContentSearch(userSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {OrderIdentifier}";
return query;
}
From dd9dc82ecf9f8d545a9822b415a0fb079ed712d9 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 21:06:52 +0800
Subject: [PATCH 59/97] Fix Logical error in query constraint using
System.Search.Rank
---
.../Search/WindowsIndex/QueryConstructor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index eed27ae71..b4b1bc540 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -60,7 +60,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
///
public string Directory(ReadOnlySpan path, ReadOnlySpan searchString = default, bool recursive = false)
{
- var queryConstraint = searchString.IsWhiteSpace() ? "" : $"AND ({OrderIdentifier} LIKE '{searchString}%' OR CONTAINS({OrderIdentifier},'\"{searchString}*\"'))";
+ var queryConstraint = searchString.IsWhiteSpace() ? "" : $"AND (System.FileName LIKE '{searchString}%' OR CONTAINS(System.FileName,'\"{searchString}*\"'))";
var scopeConstraint = recursive
? RecursiveDirectoryConstraint(path)
From 8b44b0818b1da1eb67bfccb4c8a61a156040148c Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 21:07:39 +0800
Subject: [PATCH 60/97] Fix explorer test issue
---
Flow.Launcher.Test/Plugins/ExplorerTest.cs | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
index 420da266d..9ec952155 100644
--- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs
+++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs
@@ -39,8 +39,8 @@ namespace Flow.Launcher.Test.Plugins
}
[SupportedOSPlatform("windows7.0")]
- [TestCase("C:\\", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\' ORDER BY System.FileName")]
- [TestCase("C:\\SomeFolder\\", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\SomeFolder\\' ORDER BY System.FileName")]
+ [TestCase("C:\\", $"SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\' ORDER BY {QueryConstructor.OrderIdentifier}")]
+ [TestCase("C:\\SomeFolder\\", $"SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\SomeFolder\\' ORDER BY {QueryConstructor.OrderIdentifier}")]
public void GivenWindowsIndexSearch_WhenSearchTypeIsTopLevelDirectorySearch_ThenQueryShouldUseExpectedString(string folderPath, string expectedString)
{
// Given
@@ -59,7 +59,7 @@ namespace Flow.Launcher.Test.Plugins
[TestCase("C:\\SomeFolder", "flow.launcher.sln", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType" +
" FROM SystemIndex WHERE directory='file:C:\\SomeFolder'" +
" AND (System.FileName LIKE 'flow.launcher.sln%' OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"'))" +
- " ORDER BY System.FileName")]
+ $" ORDER BY {QueryConstructor.OrderIdentifier}")]
public void GivenWindowsIndexSearchTopLevelDirectory_WhenSearchingForSpecificItem_ThenQueryShouldUseExpectedString(
string folderPath, string userSearchString, string expectedString)
{
@@ -87,8 +87,8 @@ namespace Flow.Launcher.Test.Plugins
[SupportedOSPlatform("windows7.0")]
[TestCase("flow.launcher.sln", "SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" " +
"FROM \"SystemIndex\" WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
- "OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:' ORDER BY System.FileName")]
- [TestCase("", "SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" FROM \"SystemIndex\" WHERE WorkId IS NOT NULL AND scope='file:' ORDER BY System.FileName")]
+ $"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:' ORDER BY {QueryConstructor.OrderIdentifier}")]
+ [TestCase("", $"SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" FROM \"SystemIndex\" WHERE WorkId IS NOT NULL AND scope='file:' ORDER BY {QueryConstructor.OrderIdentifier}")]
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShouldUseExpectedString(
string userSearchString, string expectedString)
{
@@ -107,7 +107,6 @@ namespace Flow.Launcher.Test.Plugins
ClassicAssert.AreEqual(expectedString, resultString);
}
-
[SupportedOSPlatform("windows7.0")]
[TestCase(@"some words", @"FREETEXT('some words')")]
public void GivenWindowsIndexSearch_WhenQueryWhereRestrictionsIsForFileContentSearch_ThenShouldReturnFreeTextString(
@@ -127,7 +126,7 @@ namespace Flow.Launcher.Test.Plugins
[SupportedOSPlatform("windows7.0")]
[TestCase("some words", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
- "FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:' ORDER BY System.FileName")]
+ $"FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:' ORDER BY {QueryConstructor.OrderIdentifier}")]
public void GivenWindowsIndexSearch_WhenSearchForFileContent_ThenQueryShouldUseExpectedString(
string userSearchString, string expectedString)
{
From 625ddbc0e11f8865f2fd02633c383b190e463e95 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 21:10:26 +0800
Subject: [PATCH 61/97] Code quality
---
.../Search/WindowsIndex/QueryConstructor.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index b4b1bc540..82b146de6 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -9,13 +9,13 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
private static Regex _specialCharacterMatcher = new(@"[\@\@\#\#\&\&*_;,\%\|\!\(\)\{\}\[\]\^\~\?\\""\/\:\=\-]+", RegexOptions.Compiled);
private static Regex _multiWhiteSpacesMatcher = new(@"\s+", RegexOptions.Compiled);
- private Settings settings { get; }
+ private Settings Settings { get; }
private const string SystemIndex = "SystemIndex";
public QueryConstructor(Settings settings)
{
- this.settings = settings;
+ Settings = settings;
}
public CSearchQueryHelper CreateBaseQuery()
@@ -23,7 +23,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
var baseQuery = CreateQueryHelper();
// Set the number of results we want. Don't set this property if all results are needed.
- baseQuery.QueryMaxResults = settings.MaxResult;
+ baseQuery.QueryMaxResults = Settings.MaxResult;
// Set list of columns we want to display, getting the path presently
baseQuery.QuerySelectColumns = "System.FileName, System.ItemUrl, System.ItemType";
@@ -37,7 +37,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
return baseQuery;
}
- internal CSearchQueryHelper CreateQueryHelper()
+ internal static CSearchQueryHelper CreateQueryHelper()
{
// This uses the Microsoft.Search.Interop assembly
// Throws COMException if Windows Search service is not running/disabled, this needs to be caught
@@ -66,7 +66,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
? RecursiveDirectoryConstraint(path)
: TopLevelDirectoryConstraint(path);
- var query = $"SELECT TOP {settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {scopeConstraint} {queryConstraint} ORDER BY {OrderIdentifier}";
+ var query = $"SELECT TOP {Settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {scopeConstraint} {queryConstraint} ORDER BY {OrderIdentifier}";
return query;
}
@@ -133,7 +133,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
public string FileContent(ReadOnlySpan userSearchString)
{
string query =
- $"SELECT TOP {settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {RestrictionsForFileContentSearch(userSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {OrderIdentifier}";
+ $"SELECT TOP {Settings.MaxResult} {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE {RestrictionsForFileContentSearch(userSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {OrderIdentifier}";
return query;
}
From 022b345a4d7933ed4aae2b77de9e4ffd43920f93 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 21:10:39 +0800
Subject: [PATCH 62/97] Add readonly
---
.../Search/WindowsIndex/QueryConstructor.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index 82b146de6..1d160983a 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -6,8 +6,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
public class QueryConstructor
{
- private static Regex _specialCharacterMatcher = new(@"[\@\@\#\#\&\&*_;,\%\|\!\(\)\{\}\[\]\^\~\?\\""\/\:\=\-]+", RegexOptions.Compiled);
- private static Regex _multiWhiteSpacesMatcher = new(@"\s+", RegexOptions.Compiled);
+ private static readonly Regex _specialCharacterMatcher = new(@"[\@\@\#\#\&\&*_;,\%\|\!\(\)\{\}\[\]\^\~\?\\""\/\:\=\-]+", RegexOptions.Compiled);
+ private static readonly Regex _multiWhiteSpacesMatcher = new(@"\s+", RegexOptions.Compiled);
private Settings Settings { get; }
From a9748acd22c3d5da098a3a6d8938d60962459348 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 12 Apr 2025 21:11:22 +0800
Subject: [PATCH 63/97] Code quality
---
.../Search/WindowsIndex/WindowsIndexSearchManager.cs | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
index c3a7d9e91..3d69a1ee6 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
@@ -82,14 +82,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
return HandledEngineNotAvailableExceptionAsync();
}
}
+
public IAsyncEnumerable SearchAsync(string search, CancellationToken token)
{
return WindowsIndexFilesAndFoldersSearchAsync(search, token: token);
}
+
public IAsyncEnumerable ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token)
{
return WindowsIndexFileContentSearchAsync(contentSearch, token);
}
+
public IAsyncEnumerable EnumerateAsync(string path, string search, bool recursive, CancellationToken token)
{
return WindowsIndexTopLevelFolderSearchAsync(search, path, recursive, token);
@@ -100,19 +103,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
if (!Settings.WarnWindowsSearchServiceOff)
return AsyncEnumerable.Empty();
- var api = Main.Context.API;
-
throw new EngineNotAvailableException(
"Windows Index",
- api.GetTranslation("plugin_explorer_windowsSearchServiceFix"),
- api.GetTranslation("plugin_explorer_windowsSearchServiceNotRunning"),
+ Main.Context.API.GetTranslation("plugin_explorer_windowsSearchServiceFix"),
+ Main.Context.API.GetTranslation("plugin_explorer_windowsSearchServiceNotRunning"),
Constants.WindowsIndexErrorImagePath,
c =>
{
Settings.WarnWindowsSearchServiceOff = false;
// Clears the warning message so user is not mistaken that it has not worked
- api.ChangeQuery(string.Empty);
+ Main.Context.API.ChangeQuery(string.Empty);
return ValueTask.FromResult(false);
});
From 0d9ec48e589f629541e81de131a69a19bbf078ea Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 16:36:34 +0800
Subject: [PATCH 64/97] Code quality
---
.../ExternalPlugins/CommunityPluginSource.cs | 12 ++++++------
Flow.Launcher.Infrastructure/Http/Http.cs | 7 +++----
2 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
index e9713564e..27891a2d4 100644
--- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
@@ -19,7 +19,7 @@ namespace Flow.Launcher.Core.ExternalPlugins
private List plugins = new();
- private static JsonSerializerOptions PluginStoreItemSerializationOption = new JsonSerializerOptions()
+ private static readonly JsonSerializerOptions PluginStoreItemSerializationOption = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
};
@@ -45,18 +45,18 @@ namespace Flow.Launcher.Core.ExternalPlugins
if (response.StatusCode == HttpStatusCode.OK)
{
- this.plugins = await response.Content
+ plugins = await response.Content
.ReadFromJsonAsync>(PluginStoreItemSerializationOption, cancellationToken: token)
.ConfigureAwait(false);
- this.latestEtag = response.Headers.ETag?.Tag;
+ latestEtag = response.Headers.ETag?.Tag;
- Log.Info(nameof(CommunityPluginSource), $"Loaded {this.plugins.Count} plugins from {ManifestFileUrl}");
- return this.plugins;
+ Log.Info(nameof(CommunityPluginSource), $"Loaded {plugins.Count} plugins from {ManifestFileUrl}");
+ return plugins;
}
else if (response.StatusCode == HttpStatusCode.NotModified)
{
Log.Info(nameof(CommunityPluginSource), $"Resource {ManifestFileUrl} has not been modified.");
- return this.plugins;
+ return plugins;
}
else
{
diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs
index 030aff7cf..0f2f302f1 100644
--- a/Flow.Launcher.Infrastructure/Http/Http.cs
+++ b/Flow.Launcher.Infrastructure/Http/Http.cs
@@ -16,15 +16,14 @@ namespace Flow.Launcher.Infrastructure.Http
{
private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko";
- private static HttpClient client = new HttpClient();
+ private static readonly HttpClient client = new();
static Http()
{
// need to be added so it would work on a win10 machine
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls
- | SecurityProtocolType.Tls11
- | SecurityProtocolType.Tls12;
+ | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
client.DefaultRequestHeaders.Add("User-Agent", UserAgent);
HttpClient.DefaultProxy = WebProxy;
@@ -72,7 +71,7 @@ namespace Flow.Launcher.Infrastructure.Http
ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials),
ProxyProperty.UserName => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)),
ProxyProperty.Password => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)),
- _ => throw new ArgumentOutOfRangeException()
+ _ => throw new ArgumentOutOfRangeException(null)
};
}
catch (UriFormatException e)
From 230df80b877549ac72ef93f76b88f495fcd0d83f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 16:44:14 +0800
Subject: [PATCH 65/97] Improve CommunityPluginSource http exception handler
---
.../ExternalPlugins/CommunityPluginSource.cs | 54 ++++++++++++-------
Flow.Launcher.Core/Updater.cs | 6 ++-
2 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
index 27891a2d4..dd79fbc7a 100644
--- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
+using System.Net.Sockets;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
@@ -15,6 +16,8 @@ namespace Flow.Launcher.Core.ExternalPlugins
{
public record CommunityPluginSource(string ManifestFileUrl)
{
+ private static readonly string ClassName = nameof(CommunityPluginSource);
+
private string latestEtag = "";
private List plugins = new();
@@ -34,36 +37,51 @@ namespace Flow.Launcher.Core.ExternalPlugins
///
public async Task> FetchAsync(CancellationToken token)
{
- Log.Info(nameof(CommunityPluginSource), $"Loading plugins from {ManifestFileUrl}");
+ Log.Info(ClassName, $"Loading plugins from {ManifestFileUrl}");
var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl);
request.Headers.Add("If-None-Match", latestEtag);
- using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token)
+ try
+ {
+ using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token)
.ConfigureAwait(false);
- if (response.StatusCode == HttpStatusCode.OK)
- {
- plugins = await response.Content
- .ReadFromJsonAsync>(PluginStoreItemSerializationOption, cancellationToken: token)
- .ConfigureAwait(false);
- latestEtag = response.Headers.ETag?.Tag;
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ plugins = await response.Content
+ .ReadFromJsonAsync>(PluginStoreItemSerializationOption, cancellationToken: token)
+ .ConfigureAwait(false);
+ latestEtag = response.Headers.ETag?.Tag;
- Log.Info(nameof(CommunityPluginSource), $"Loaded {plugins.Count} plugins from {ManifestFileUrl}");
- return plugins;
+ Log.Info(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}");
+ return plugins;
+ }
+ else if (response.StatusCode == HttpStatusCode.NotModified)
+ {
+ Log.Info(ClassName, $"Resource {ManifestFileUrl} has not been modified.");
+ return plugins;
+ }
+ else
+ {
+ Log.Warn(ClassName,
+ $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
+ return plugins;
+ }
}
- else if (response.StatusCode == HttpStatusCode.NotModified)
+ catch (Exception e)
{
- Log.Info(nameof(CommunityPluginSource), $"Resource {ManifestFileUrl} has not been modified.");
+ if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
+ {
+ Log.Exception(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e);
+ }
+ else
+ {
+ Log.Exception(ClassName, "Error Occurred", e);
+ }
return plugins;
}
- else
- {
- Log.Warn(nameof(CommunityPluginSource),
- $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
- throw new Exception($"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
- }
}
}
}
diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs
index 83d4fd9e0..f018bdfc7 100644
--- a/Flow.Launcher.Core/Updater.cs
+++ b/Flow.Launcher.Core/Updater.cs
@@ -93,10 +93,14 @@ namespace Flow.Launcher.Core
}
catch (Exception e)
{
- if ((e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException))
+ if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
+ {
Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
+ }
else
+ {
Log.Exception($"|Updater.UpdateApp|Error Occurred", e);
+ }
if (!silentUpdate)
_api.ShowMsg(_api.GetTranslation("update_flowlauncher_fail"),
From e31f14e60d94ab655513d9b7d962d6b9570b0f69 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 17:11:36 +0800
Subject: [PATCH 66/97] Use local reference instead
---
Flow.Launcher.Infrastructure/Http/Http.cs | 26 ++++++++++---------
.../Image/ImageLoader.cs | 21 ++++++---------
Flow.Launcher.Infrastructure/Logger/Log.cs | 6 -----
Flow.Launcher.Infrastructure/Stopwatch.cs | 21 +++++++--------
.../Storage/BinaryStorage.cs | 6 +++--
.../Storage/FlowLauncherJsonStorage.cs | 11 +++-----
.../Storage/JsonStorage.cs | 4 ++-
.../Storage/PluginBinaryStorage.cs | 11 +++-----
.../Storage/PluginJsonStorage.cs | 11 +++-----
9 files changed, 47 insertions(+), 70 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs
index 0f2f302f1..12edf34a4 100644
--- a/Flow.Launcher.Infrastructure/Http/Http.cs
+++ b/Flow.Launcher.Infrastructure/Http/Http.cs
@@ -1,19 +1,21 @@
-using System.IO;
+using System;
+using System.IO;
using System.Net;
using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
-using JetBrains.Annotations;
+using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
-using System;
-using System.Threading;
using Flow.Launcher.Plugin;
-using CommunityToolkit.Mvvm.DependencyInjection;
+using JetBrains.Annotations;
namespace Flow.Launcher.Infrastructure.Http
{
public static class Http
{
+ private static readonly string ClassName = nameof(Http);
+
private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko";
private static readonly HttpClient client = new();
@@ -33,7 +35,7 @@ namespace Flow.Launcher.Infrastructure.Http
public static HttpProxy Proxy
{
- private get { return proxy; }
+ private get => proxy;
set
{
proxy = value;
@@ -77,7 +79,7 @@ namespace Flow.Launcher.Infrastructure.Http
catch (UriFormatException e)
{
Ioc.Default.GetRequiredService().ShowMsg("Please try again", "Unable to parse Http Proxy");
- Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e);
+ Log.Exception(ClassName, "Unable to parse Uri", e);
}
}
@@ -133,7 +135,7 @@ namespace Flow.Launcher.Infrastructure.Http
}
catch (HttpRequestException e)
{
- Log.Exception("Infrastructure.Http", "Http Request Error", e, "DownloadAsync");
+ Log.Exception(ClassName, "Http Request Error", e, "DownloadAsync");
throw;
}
}
@@ -146,7 +148,7 @@ namespace Flow.Launcher.Infrastructure.Http
/// The Http result as string. Null if cancellation requested
public static Task GetAsync([NotNull] string url, CancellationToken token = default)
{
- Log.Debug($"|Http.Get|Url <{url}>");
+ Log.Debug(ClassName, $"Url <{url}>");
return GetAsync(new Uri(url), token);
}
@@ -158,7 +160,7 @@ namespace Flow.Launcher.Infrastructure.Http
/// The Http result as string. Null if cancellation requested
public static async Task GetAsync([NotNull] Uri url, CancellationToken token = default)
{
- Log.Debug($"|Http.Get|Url <{url}>");
+ Log.Debug(ClassName, $"Url <{url}>");
using var response = await client.GetAsync(url, token);
var content = await response.Content.ReadAsStringAsync(token);
if (response.StatusCode != HttpStatusCode.OK)
@@ -190,7 +192,7 @@ namespace Flow.Launcher.Infrastructure.Http
public static async Task GetStreamAsync([NotNull] Uri url,
CancellationToken token = default)
{
- Log.Debug($"|Http.Get|Url <{url}>");
+ Log.Debug(ClassName, $"Url <{url}>");
return await client.GetStreamAsync(url, token);
}
@@ -201,7 +203,7 @@ namespace Flow.Launcher.Infrastructure.Http
public static async Task GetResponseAsync([NotNull] Uri url, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead,
CancellationToken token = default)
{
- Log.Debug($"|Http.Get|Url <{url}>");
+ Log.Debug(ClassName, $"Url <{url}>");
return await client.GetAsync(url, completionOption, token);
}
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index 9e31d2b4e..a49385a02 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -7,9 +7,8 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
-using CommunityToolkit.Mvvm.DependencyInjection;
+using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.Storage;
-using Flow.Launcher.Plugin;
using SharpVectors.Converters;
using SharpVectors.Renderers.Wpf;
@@ -17,10 +16,6 @@ namespace Flow.Launcher.Infrastructure.Image
{
public static class ImageLoader
{
- // We should not initialize API in static constructor because it will create another API instance
- private static IPublicAPI api = null;
- private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
-
private static readonly string ClassName = nameof(ImageLoader);
private static readonly ImageCache ImageCache = new();
@@ -58,14 +53,14 @@ namespace Flow.Launcher.Infrastructure.Image
_ = Task.Run(async () =>
{
- await API.StopwatchLogInfoAsync(ClassName, "Preload images cost", async () =>
+ await Stopwatch.InfoAsync(ClassName, "Preload images cost", async () =>
{
foreach (var (path, isFullImage) in usage)
{
await LoadAsync(path, isFullImage);
}
});
- API.LogInfo(ClassName, $"Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
+ Log.Info(ClassName, $"Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
});
}
@@ -81,7 +76,7 @@ namespace Flow.Launcher.Infrastructure.Image
}
catch (System.Exception e)
{
- API.LogException(ClassName, "Failed to save image cache to file", e);
+ Log.Exception(ClassName, "Failed to save image cache to file", e);
}
finally
{
@@ -176,8 +171,8 @@ namespace Flow.Launcher.Infrastructure.Image
}
catch (System.Exception e2)
{
- API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e);
- API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2);
+ Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e);
+ Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2);
ImageSource image = ImageCache[Constant.MissingImgIcon, false];
ImageCache[path, false] = image;
@@ -243,7 +238,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
image = Image;
type = ImageType.Error;
- API.LogException(ClassName, $"Failed to load image file from path {path}: {ex.Message}", ex);
+ Log.Exception(ClassName, $"Failed to load image file from path {path}: {ex.Message}", ex);
}
}
else
@@ -267,7 +262,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
image = Image;
type = ImageType.Error;
- API.LogException(ClassName, $"Failed to load SVG image from path {path}: {ex.Message}", ex);
+ Log.Exception(ClassName, $"Failed to load SVG image from path {path}: {ex.Message}", ex);
}
}
else
diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs
index 807d631c7..25cfbbd3d 100644
--- a/Flow.Launcher.Infrastructure/Logger/Log.cs
+++ b/Flow.Launcher.Infrastructure/Logger/Log.cs
@@ -227,12 +227,6 @@ namespace Flow.Launcher.Infrastructure.Logger
{
LogInternal(LogLevel.Warn, className, message, methodName);
}
-
- /// Example: "|ClassName.MethodName|Message"
- public static void Warn(string message)
- {
- LogInternal(message, LogLevel.Warn);
- }
}
public enum LOGLEVEL
diff --git a/Flow.Launcher.Infrastructure/Stopwatch.cs b/Flow.Launcher.Infrastructure/Stopwatch.cs
index 784d323fe..870e0fe26 100644
--- a/Flow.Launcher.Infrastructure/Stopwatch.cs
+++ b/Flow.Launcher.Infrastructure/Stopwatch.cs
@@ -1,4 +1,5 @@
using System;
+using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
@@ -9,54 +10,50 @@ namespace Flow.Launcher.Infrastructure
///
/// This stopwatch will appear only in Debug mode
///
- public static long Debug(string message, Action action)
+ public static long Debug(string className, string message, Action action, [CallerMemberName] string methodName = "")
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
action();
stopWatch.Stop();
var milliseconds = stopWatch.ElapsedMilliseconds;
- string info = $"{message} <{milliseconds}ms>";
- Log.Debug(info);
+ Log.Debug(className, $"{message} <{milliseconds}ms>", methodName);
return milliseconds;
}
///
/// This stopwatch will appear only in Debug mode
///
- public static async Task DebugAsync(string message, Func action)
+ public static async Task DebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "")
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
await action();
stopWatch.Stop();
var milliseconds = stopWatch.ElapsedMilliseconds;
- string info = $"{message} <{milliseconds}ms>";
- Log.Debug(info);
+ Log.Debug(className, $"{message} <{milliseconds}ms>", methodName);
return milliseconds;
}
- public static long Normal(string message, Action action)
+ public static long Info(string className, string message, Action action, [CallerMemberName] string methodName = "")
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
action();
stopWatch.Stop();
var milliseconds = stopWatch.ElapsedMilliseconds;
- string info = $"{message} <{milliseconds}ms>";
- Log.Info(info);
+ Log.Info(className, $"{message} <{milliseconds}ms>", methodName);
return milliseconds;
}
- public static async Task NormalAsync(string message, Func action)
+ public static async Task InfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "")
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
await action();
stopWatch.Stop();
var milliseconds = stopWatch.ElapsedMilliseconds;
- string info = $"{message} <{milliseconds}ms>";
- Log.Info(info);
+ Log.Info(className, $"{message} <{milliseconds}ms>", methodName);
return milliseconds;
}
}
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 8ff10816c..48e6b5523 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -20,6 +20,8 @@ namespace Flow.Launcher.Infrastructure.Storage
///
public class BinaryStorage : ISavable
{
+ private static readonly string ClassName = "BinaryStorage";
+
protected T? Data;
public const string FileSuffix = ".cache";
@@ -59,7 +61,7 @@ namespace Flow.Launcher.Infrastructure.Storage
{
if (new FileInfo(FilePath).Length == 0)
{
- Log.Error($"|BinaryStorage.TryLoad|Zero length cache file <{FilePath}>");
+ Log.Error(ClassName, $"Zero length cache file <{FilePath}>");
Data = defaultData;
await SaveAsync();
}
@@ -69,7 +71,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
else
{
- Log.Info("|BinaryStorage.TryLoad|Cache file not exist, load default data");
+ Log.Info(ClassName, "Cache file not exist, load default data");
Data = defaultData;
await SaveAsync();
}
diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs
index ca78b2f20..158e0cdf5 100644
--- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs
@@ -1,8 +1,7 @@
using System.IO;
using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.DependencyInjection;
+using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
-using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Infrastructure.Storage
@@ -11,10 +10,6 @@ namespace Flow.Launcher.Infrastructure.Storage
{
private static readonly string ClassName = "FlowLauncherJsonStorage";
- // We should not initialize API in static constructor because it will create another API instance
- private static IPublicAPI api = null;
- private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
-
public FlowLauncherJsonStorage()
{
DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName);
@@ -32,7 +27,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e);
+ Log.Exception(ClassName, $"Failed to save FL settings to path: {FilePath}", e);
}
}
@@ -44,7 +39,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e);
+ Log.Exception(ClassName, $"Failed to save FL settings to path: {FilePath}", e);
}
}
}
diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
index f283be59e..0b10382ee 100644
--- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
@@ -16,6 +16,8 @@ namespace Flow.Launcher.Infrastructure.Storage
///
public class JsonStorage : ISavable where T : new()
{
+ private static readonly string ClassName = "JsonStorage";
+
protected T? Data;
// need a new directory name
@@ -104,7 +106,7 @@ namespace Flow.Launcher.Infrastructure.Storage
private void RestoreBackup()
{
- Log.Info($"|JsonStorage.Load|Failed to load settings.json, {BackupFilePath} restored successfully");
+ Log.Info(ClassName, $"Failed to load settings.json, {BackupFilePath} restored successfully");
if (File.Exists(FilePath))
File.Replace(BackupFilePath, FilePath, null);
diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
index d18060e3d..01da96d62 100644
--- a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
@@ -1,7 +1,6 @@
using System.IO;
using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.DependencyInjection;
-using Flow.Launcher.Plugin;
+using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Infrastructure.Storage
@@ -10,10 +9,6 @@ namespace Flow.Launcher.Infrastructure.Storage
{
private static readonly string ClassName = "PluginBinaryStorage";
- // We should not initialize API in static constructor because it will create another API instance
- private static IPublicAPI api = null;
- private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
-
public PluginBinaryStorage(string cacheName, string cacheDirectory)
{
DirectoryPath = cacheDirectory;
@@ -30,7 +25,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e);
+ Log.Exception(ClassName, $"Failed to save plugin caches to path: {FilePath}", e);
}
}
@@ -42,7 +37,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e);
+ Log.Exception(ClassName, $"Failed to save plugin caches to path: {FilePath}", e);
}
}
}
diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
index e8cbd70fb..147152949 100644
--- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
@@ -1,8 +1,7 @@
using System.IO;
using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.DependencyInjection;
+using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
-using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Infrastructure.Storage
@@ -14,10 +13,6 @@ namespace Flow.Launcher.Infrastructure.Storage
private static readonly string ClassName = "PluginJsonStorage";
- // We should not initialize API in static constructor because it will create another API instance
- private static IPublicAPI api = null;
- private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
-
public PluginJsonStorage()
{
// C# related, add python related below
@@ -42,7 +37,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e);
+ Log.Exception(ClassName, $"Failed to save plugin settings to path: {FilePath}", e);
}
}
@@ -54,7 +49,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e);
+ Log.Exception(ClassName, $"Failed to save plugin settings to path: {FilePath}", e);
}
}
}
From dde933a96b8372ab4d5bea0658c27e44172e7e0c Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 17:26:21 +0800
Subject: [PATCH 67/97] Use api functions instead
---
Flow.Launcher.Core/Configuration/Portable.cs | 21 +++++++-------
.../ExternalPlugins/CommunityPluginSource.cs | 25 +++++++++--------
.../Environments/AbstractPluginEnvironment.cs | 5 ++--
Flow.Launcher.Core/Plugin/PluginConfig.cs | 28 +++++++++++--------
Flow.Launcher.Core/Plugin/PluginManager.cs | 17 ++++++-----
.../Resource/Internationalization.cs | 23 ++++++++-------
Flow.Launcher.Core/Resource/Theme.cs | 15 +++++-----
Flow.Launcher.Core/Updater.cs | 11 ++++----
8 files changed, 80 insertions(+), 65 deletions(-)
diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs
index 2b570d2c0..7f02cef09 100644
--- a/Flow.Launcher.Core/Configuration/Portable.cs
+++ b/Flow.Launcher.Core/Configuration/Portable.cs
@@ -1,21 +1,22 @@
-using Microsoft.Win32;
-using Squirrel;
-using System;
+using System;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Windows;
-using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
-using Flow.Launcher.Infrastructure.UserSettings;
-using Flow.Launcher.Plugin.SharedCommands;
-using System.Linq;
using CommunityToolkit.Mvvm.DependencyInjection;
+using Flow.Launcher.Infrastructure;
+using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
+using Flow.Launcher.Plugin.SharedCommands;
+using Microsoft.Win32;
+using Squirrel;
namespace Flow.Launcher.Core.Configuration
{
public class Portable : IPortable
{
+ private static readonly string ClassName = nameof(Portable);
+
private readonly IPublicAPI API = Ioc.Default.GetRequiredService();
///
@@ -51,7 +52,7 @@ namespace Flow.Launcher.Core.Configuration
}
catch (Exception e)
{
- Log.Exception("|Portable.DisablePortableMode|Error occurred while disabling portable mode", e);
+ API.LogException(ClassName, "Error occurred while disabling portable mode", e);
}
}
@@ -75,7 +76,7 @@ namespace Flow.Launcher.Core.Configuration
}
catch (Exception e)
{
- Log.Exception("|Portable.EnablePortableMode|Error occurred while enabling portable mode", e);
+ API.LogException(ClassName, "Error occurred while enabling portable mode", e);
}
}
diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
index dd79fbc7a..ac27c523c 100644
--- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs
@@ -1,7 +1,4 @@
-using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Logger;
-using Flow.Launcher.Plugin;
-using System;
+using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
@@ -11,11 +8,18 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.DependencyInjection;
+using Flow.Launcher.Infrastructure.Http;
+using Flow.Launcher.Plugin;
namespace Flow.Launcher.Core.ExternalPlugins
{
public record CommunityPluginSource(string ManifestFileUrl)
{
+ // We should not initialize API in static constructor because it will create another API instance
+ private static IPublicAPI api = null;
+ private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
+
private static readonly string ClassName = nameof(CommunityPluginSource);
private string latestEtag = "";
@@ -37,7 +41,7 @@ namespace Flow.Launcher.Core.ExternalPlugins
///
public async Task> FetchAsync(CancellationToken token)
{
- Log.Info(ClassName, $"Loading plugins from {ManifestFileUrl}");
+ API.LogInfo(ClassName, $"Loading plugins from {ManifestFileUrl}");
var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl);
@@ -55,18 +59,17 @@ namespace Flow.Launcher.Core.ExternalPlugins
.ConfigureAwait(false);
latestEtag = response.Headers.ETag?.Tag;
- Log.Info(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}");
+ API.LogInfo(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}");
return plugins;
}
else if (response.StatusCode == HttpStatusCode.NotModified)
{
- Log.Info(ClassName, $"Resource {ManifestFileUrl} has not been modified.");
+ API.LogInfo(ClassName, $"Resource {ManifestFileUrl} has not been modified.");
return plugins;
}
else
{
- Log.Warn(ClassName,
- $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
+ API.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}");
return plugins;
}
}
@@ -74,11 +77,11 @@ namespace Flow.Launcher.Core.ExternalPlugins
{
if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
{
- Log.Exception(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e);
+ API.LogException(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e);
}
else
{
- Log.Exception(ClassName, "Error Occurred", e);
+ API.LogException(ClassName, "Error Occurred", e);
}
return plugins;
}
diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
index bbb6cf638..14796a87a 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs
@@ -5,7 +5,6 @@ using System.Linq;
using System.Windows;
using System.Windows.Forms;
using CommunityToolkit.Mvvm.DependencyInjection;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
@@ -14,6 +13,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
public abstract class AbstractPluginEnvironment
{
+ private static readonly string ClassName = nameof(AbstractPluginEnvironment);
+
protected readonly IPublicAPI API = Ioc.Default.GetRequiredService();
internal abstract string Language { get; }
@@ -120,7 +121,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
else
{
API.ShowMsgBox(string.Format(API.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language));
- Log.Error("PluginsLoader",
+ API.LogError(ClassName,
$"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.",
$"{Language}Environment");
diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs
index 163f97046..f7457b4e1 100644
--- a/Flow.Launcher.Core/Plugin/PluginConfig.cs
+++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs
@@ -3,14 +3,20 @@ using System.Collections.Generic;
using System.Linq;
using System.IO;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin;
using System.Text.Json;
+using CommunityToolkit.Mvvm.DependencyInjection;
namespace Flow.Launcher.Core.Plugin
{
internal abstract class PluginConfig
{
+ private static readonly string ClassName = nameof(PluginConfig);
+
+ // We should not initialize API in static constructor because it will create another API instance
+ private static IPublicAPI api = null;
+ private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
+
///
/// Parse plugin metadata in the given directories
///
@@ -32,7 +38,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginConfig.ParsePLuginConfigs|Can't delete <{directory}>", e);
+ API.LogException(ClassName, $"Can't delete <{directory}>", e);
}
}
else
@@ -49,11 +55,11 @@ namespace Flow.Launcher.Core.Plugin
duplicateList
.ForEach(
- x => Log.Warn("PluginConfig",
- string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " +
- "not loaded due to version not the highest of the duplicates",
- x.Name, x.ID, x.Version),
- "GetUniqueLatestPluginMetadata"));
+ x => API.LogWarn(ClassName,
+ string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " +
+ "not loaded due to version not the highest of the duplicates",
+ x.Name, x.ID, x.Version),
+ "GetUniqueLatestPluginMetadata"));
return uniqueList;
}
@@ -101,7 +107,7 @@ namespace Flow.Launcher.Core.Plugin
string configPath = Path.Combine(pluginDirectory, Constant.PluginMetadataFileName);
if (!File.Exists(configPath))
{
- Log.Error($"|PluginConfig.GetPluginMetadata|Didn't find config file <{configPath}>");
+ API.LogError(ClassName, $"Didn't find config file <{configPath}>");
return null;
}
@@ -117,19 +123,19 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginConfig.GetPluginMetadata|invalid json for config <{configPath}>", e);
+ API.LogException(ClassName, $"Invalid json for config <{configPath}>", e);
return null;
}
if (!AllowedLanguage.IsAllowed(metadata.Language))
{
- Log.Error($"|PluginConfig.GetPluginMetadata|Invalid language <{metadata.Language}> for config <{configPath}>");
+ API.LogError(ClassName, $"Invalid language <{metadata.Language}> for config <{configPath}>");
return null;
}
if (!File.Exists(metadata.ExecuteFilePath))
{
- Log.Error($"|PluginConfig.GetPluginMetadata|execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}");
+ API.LogError(ClassName, $"Execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}");
return null;
}
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 52d6fd736..72303c8b7 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -9,7 +9,6 @@ using System.Threading.Tasks;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core.ExternalPlugins;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
@@ -214,12 +213,12 @@ namespace Flow.Launcher.Core.Plugin
() => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API)));
pair.Metadata.InitTime += milliseconds;
- Log.Info(
- $"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
+ API.LogInfo(ClassName,
+ $"Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
}
catch (Exception e)
{
- Log.Exception(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e);
+ API.LogException(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e);
pair.Metadata.Disabled = true;
failedPlugins.Enqueue(pair);
}
@@ -370,8 +369,8 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception(
- $"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>",
+ API.LogException(ClassName,
+ $"Can't load context menus for plugin <{pluginPair.Metadata.Name}>",
e);
}
}
@@ -563,7 +562,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginManager.InstallPlugin|Failed to delete temp folder {tempFolderPluginPath}", e);
+ API.LogException(ClassName, $"Failed to delete temp folder {tempFolderPluginPath}", e);
}
if (checkModified)
@@ -608,7 +607,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin settings folder for {plugin.Name}", e);
+ API.LogException(ClassName, $"Failed to delete plugin settings folder for {plugin.Name}", e);
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
}
@@ -624,7 +623,7 @@ namespace Flow.Launcher.Core.Plugin
}
catch (Exception e)
{
- Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin cache folder for {plugin.Name}", e);
+ API.LogException(ClassName, $"Failed to delete plugin cache folder for {plugin.Name}", e);
API.ShowMsg(API.GetTranslation("failedToRemovePluginCacheTitle"),
string.Format(API.GetTranslation("failedToRemovePluginCacheMessage"), plugin.Name));
}
diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs
index df841dbbe..1dfc6d4ed 100644
--- a/Flow.Launcher.Core/Resource/Internationalization.cs
+++ b/Flow.Launcher.Core/Resource/Internationalization.cs
@@ -6,7 +6,6 @@ using System.Reflection;
using System.Windows;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using System.Globalization;
@@ -17,11 +16,14 @@ namespace Flow.Launcher.Core.Resource
{
public class Internationalization
{
+ private static readonly string ClassName = nameof(Internationalization);
+
private const string Folder = "Languages";
private const string DefaultLanguageCode = "en";
private const string DefaultFile = "en.xaml";
private const string Extension = ".xaml";
private readonly Settings _settings;
+ private readonly IPublicAPI _api;
private readonly List _languageDirectories = new();
private readonly List _oldResources = new();
private readonly string SystemLanguageCode;
@@ -29,6 +31,7 @@ namespace Flow.Launcher.Core.Resource
public Internationalization(Settings settings)
{
_settings = settings;
+ _api = Ioc.Default.GetRequiredService();
AddFlowLauncherLanguageDirectory();
SystemLanguageCode = GetSystemLanguageCodeAtStartup();
}
@@ -80,7 +83,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- Log.Error($"|Internationalization.AddPluginLanguageDirectories|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
+ _api.LogError(ClassName, $"Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
}
}
@@ -144,13 +147,13 @@ namespace Flow.Launcher.Core.Resource
_settings.Language = isSystem ? Constant.SystemLanguageCode : language.LanguageCode;
}
- private static Language GetLanguageByLanguageCode(string languageCode)
+ private Language GetLanguageByLanguageCode(string languageCode)
{
var lowercase = languageCode.ToLower();
var language = AvailableLanguages.GetAvailableLanguages().FirstOrDefault(o => o.LanguageCode.ToLower() == lowercase);
if (language == null)
{
- Log.Error($"|Internationalization.GetLanguageByLanguageCode|Language code can't be found <{languageCode}>");
+ _api.LogError(ClassName, $"Language code can't be found <{languageCode}>");
return AvailableLanguages.English;
}
else
@@ -239,7 +242,7 @@ namespace Flow.Launcher.Core.Resource
return list;
}
- public static string GetTranslation(string key)
+ public string GetTranslation(string key)
{
var translation = Application.Current.TryFindResource(key);
if (translation is string)
@@ -248,7 +251,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- Log.Error($"|Internationalization.GetTranslation|No Translation for key {key}");
+ _api.LogError(ClassName, $"No Translation for key {key}");
return $"No Translation for key {key}";
}
}
@@ -266,12 +269,12 @@ namespace Flow.Launcher.Core.Resource
}
catch (Exception e)
{
- Log.Exception($"|Internationalization.UpdatePluginMetadataTranslations|Failed for <{p.Metadata.Name}>", e);
+ _api.LogException(ClassName, $"Failed for <{p.Metadata.Name}>", e);
}
}
}
- private static string LanguageFile(string folder, string language)
+ private string LanguageFile(string folder, string language)
{
if (Directory.Exists(folder))
{
@@ -282,7 +285,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- Log.Error($"|Internationalization.LanguageFile|Language path can't be found <{path}>");
+ _api.LogError(ClassName, $"Language path can't be found <{path}>");
var english = Path.Combine(folder, DefaultFile);
if (File.Exists(english))
{
@@ -290,7 +293,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- Log.Error($"|Internationalization.LanguageFile|Default English Language path can't be found <{path}>");
+ _api.LogError(ClassName, $"Default English Language path can't be found <{path}>");
return string.Empty;
}
}
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index 59e76e2d2..64ffec907 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -13,7 +13,6 @@ using System.Windows.Media.Effects;
using System.Windows.Shell;
using System.Windows.Threading;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedModels;
@@ -25,6 +24,8 @@ namespace Flow.Launcher.Core.Resource
{
#region Properties & Fields
+ private readonly string ClassName = nameof(Theme);
+
public bool BlurEnabled { get; private set; }
private const string ThemeMetadataNamePrefix = "Name:";
@@ -73,7 +74,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- Log.Error("Current theme resource not found. Initializing with default theme.");
+ _api.LogError(ClassName, "Current theme resource not found. Initializing with default theme.");
_oldTheme = Constant.DefaultTheme;
};
}
@@ -92,7 +93,7 @@ namespace Flow.Launcher.Core.Resource
}
catch (Exception e)
{
- Log.Exception($"|Theme.MakesureThemeDirectoriesExist|Exception when create directory <{dir}>", e);
+ _api.LogException(ClassName, $"Exception when create directory <{dir}>", e);
}
}
}
@@ -135,7 +136,7 @@ namespace Flow.Launcher.Core.Resource
}
catch (Exception e)
{
- Log.Exception("Error occurred while updating theme fonts", e);
+ _api.LogException(ClassName, "Error occurred while updating theme fonts", e);
}
}
@@ -387,7 +388,7 @@ namespace Flow.Launcher.Core.Resource
var matchingTheme = themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme);
if (matchingTheme == null)
{
- Log.Warn($"No matching theme found for '{_settings.Theme}'. Falling back to the first available theme.");
+ _api.LogWarn(ClassName, $"No matching theme found for '{_settings.Theme}'. Falling back to the first available theme.");
}
return matchingTheme ?? themes.FirstOrDefault();
}
@@ -440,7 +441,7 @@ namespace Flow.Launcher.Core.Resource
}
catch (DirectoryNotFoundException)
{
- Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found");
+ _api.LogError(ClassName, $"Theme <{theme}> path can't be found");
if (theme != Constant.DefaultTheme)
{
_api.ShowMsgBox(string.Format(_api.GetTranslation("theme_load_failure_path_not_exists"), theme));
@@ -450,7 +451,7 @@ namespace Flow.Launcher.Core.Resource
}
catch (XamlParseException)
{
- Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse");
+ _api.LogError(ClassName, $"Theme <{theme}> fail to parse");
if (theme != Constant.DefaultTheme)
{
_api.ShowMsgBox(string.Format(_api.GetTranslation("theme_load_failure_parse_error"), theme));
diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs
index f018bdfc7..bc3655f69 100644
--- a/Flow.Launcher.Core/Updater.cs
+++ b/Flow.Launcher.Core/Updater.cs
@@ -12,7 +12,6 @@ using System.Windows;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using JetBrains.Annotations;
@@ -24,6 +23,8 @@ namespace Flow.Launcher.Core
{
public string GitHubRepository { get; init; }
+ private static readonly string ClassName = nameof(Updater);
+
private readonly IPublicAPI _api;
public Updater(IPublicAPI publicAPI, string gitHubRepository)
@@ -51,7 +52,7 @@ namespace Flow.Launcher.Core
var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString());
var currentVersion = Version.Parse(Constant.Version);
- Log.Info($"|Updater.UpdateApp|Future Release <{Formatted(newUpdateInfo.FutureReleaseEntry)}>");
+ _api.LogInfo(ClassName, $"Future Release <{Formatted(newUpdateInfo.FutureReleaseEntry)}>");
if (newReleaseVersion <= currentVersion)
{
@@ -84,7 +85,7 @@ namespace Flow.Launcher.Core
var newVersionTips = NewVersionTips(newReleaseVersion.ToString());
- Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
+ _api.LogInfo(ClassName, $"Update success:{newVersionTips}");
if (_api.ShowMsgBox(newVersionTips, _api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
@@ -95,11 +96,11 @@ namespace Flow.Launcher.Core
{
if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)
{
- Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
+ _api.LogException(ClassName, $"Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
}
else
{
- Log.Exception($"|Updater.UpdateApp|Error Occurred", e);
+ _api.LogException(ClassName, $"Error Occurred", e);
}
if (!silentUpdate)
From b13ab3b893baefecdb788ab605e6e5d03bf504f3 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 17:27:17 +0800
Subject: [PATCH 68/97] Remove useless DI
---
Flow.Launcher/SettingWindow.xaml.cs | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs
index 28140f024..b4a3ae47a 100644
--- a/Flow.Launcher/SettingWindow.xaml.cs
+++ b/Flow.Launcher/SettingWindow.xaml.cs
@@ -6,7 +6,6 @@ using System.Windows.Interop;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
-using Flow.Launcher.Plugin;
using Flow.Launcher.SettingPages.Views;
using Flow.Launcher.ViewModel;
using ModernWpf.Controls;
@@ -16,7 +15,6 @@ namespace Flow.Launcher;
public partial class SettingWindow
{
- private readonly IPublicAPI _api;
private readonly Settings _settings;
private readonly SettingWindowViewModel _viewModel;
@@ -26,7 +24,6 @@ public partial class SettingWindow
_settings = Ioc.Default.GetRequiredService();
DataContext = viewModel;
_viewModel = viewModel;
- _api = Ioc.Default.GetRequiredService();
InitializePosition();
InitializeComponent();
}
@@ -49,7 +46,7 @@ public partial class SettingWindow
_settings.SettingWindowTop = Top;
_settings.SettingWindowLeft = Left;
_viewModel.Save();
- _api.SavePluginSettings();
+ App.API.SavePluginSettings();
}
private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e)
From 4a7915b9ffde654751bc3dbd3451cd070c1da018 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 17:50:44 +0800
Subject: [PATCH 69/97] Use api fuctions forr main project
---
.../Resource/Internationalization.cs | 24 ++++++++++---------
Flow.Launcher/App.xaml.cs | 18 +++++++-------
.../Converters/QuerySuggestionBoxConverter.cs | 5 ++--
Flow.Launcher/Helper/AutoStartup.cs | 14 ++++++-----
Flow.Launcher/Helper/HotKeyMapper.cs | 8 ++++---
Flow.Launcher/MessageBoxEx.xaml.cs | 6 ++---
Flow.Launcher/Msg.xaml.cs | 1 -
Flow.Launcher/Notification.cs | 7 +++---
Flow.Launcher/ProgressBoxEx.xaml.cs | 5 ++--
Flow.Launcher/PublicAPIInstance.cs | 8 +++----
Flow.Launcher/ReportWindow.xaml.cs | 6 +++--
Flow.Launcher/ViewModel/MainViewModel.cs | 13 +++++-----
Flow.Launcher/ViewModel/ResultViewModel.cs | 8 +++----
13 files changed, 67 insertions(+), 56 deletions(-)
diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs
index 1dfc6d4ed..b32b09e8f 100644
--- a/Flow.Launcher.Core/Resource/Internationalization.cs
+++ b/Flow.Launcher.Core/Resource/Internationalization.cs
@@ -18,12 +18,15 @@ namespace Flow.Launcher.Core.Resource
{
private static readonly string ClassName = nameof(Internationalization);
+ // We should not initialize API in static constructor because it will create another API instance
+ private static IPublicAPI api = null;
+ private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService();
+
private const string Folder = "Languages";
private const string DefaultLanguageCode = "en";
private const string DefaultFile = "en.xaml";
private const string Extension = ".xaml";
private readonly Settings _settings;
- private readonly IPublicAPI _api;
private readonly List _languageDirectories = new();
private readonly List _oldResources = new();
private readonly string SystemLanguageCode;
@@ -31,7 +34,6 @@ namespace Flow.Launcher.Core.Resource
public Internationalization(Settings settings)
{
_settings = settings;
- _api = Ioc.Default.GetRequiredService();
AddFlowLauncherLanguageDirectory();
SystemLanguageCode = GetSystemLanguageCodeAtStartup();
}
@@ -83,7 +85,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- _api.LogError(ClassName, $"Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
+ API.LogError(ClassName, $"Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
}
}
@@ -147,13 +149,13 @@ namespace Flow.Launcher.Core.Resource
_settings.Language = isSystem ? Constant.SystemLanguageCode : language.LanguageCode;
}
- private Language GetLanguageByLanguageCode(string languageCode)
+ private static Language GetLanguageByLanguageCode(string languageCode)
{
var lowercase = languageCode.ToLower();
var language = AvailableLanguages.GetAvailableLanguages().FirstOrDefault(o => o.LanguageCode.ToLower() == lowercase);
if (language == null)
{
- _api.LogError(ClassName, $"Language code can't be found <{languageCode}>");
+ API.LogError(ClassName, $"Language code can't be found <{languageCode}>");
return AvailableLanguages.English;
}
else
@@ -242,7 +244,7 @@ namespace Flow.Launcher.Core.Resource
return list;
}
- public string GetTranslation(string key)
+ public static string GetTranslation(string key)
{
var translation = Application.Current.TryFindResource(key);
if (translation is string)
@@ -251,7 +253,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- _api.LogError(ClassName, $"No Translation for key {key}");
+ API.LogError(ClassName, $"No Translation for key {key}");
return $"No Translation for key {key}";
}
}
@@ -269,12 +271,12 @@ namespace Flow.Launcher.Core.Resource
}
catch (Exception e)
{
- _api.LogException(ClassName, $"Failed for <{p.Metadata.Name}>", e);
+ API.LogException(ClassName, $"Failed for <{p.Metadata.Name}>", e);
}
}
}
- private string LanguageFile(string folder, string language)
+ private static string LanguageFile(string folder, string language)
{
if (Directory.Exists(folder))
{
@@ -285,7 +287,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- _api.LogError(ClassName, $"Language path can't be found <{path}>");
+ API.LogError(ClassName, $"Language path can't be found <{path}>");
var english = Path.Combine(folder, DefaultFile);
if (File.Exists(english))
{
@@ -293,7 +295,7 @@ namespace Flow.Launcher.Core.Resource
}
else
{
- _api.LogError(ClassName, $"Default English Language path can't be found <{path}>");
+ API.LogError(ClassName, $"Default English Language path can't be found <{path}>");
return string.Empty;
}
}
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index a9cd1a8b9..87677f58a 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -148,8 +148,8 @@ namespace Flow.Launcher
Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate();
- Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
- Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}");
+ API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------");
+ API.LogInfo(ClassName, "Runtime info:{ErrorReporting.RuntimeInfo()}");
RegisterAppDomainExceptions();
RegisterDispatcherUnhandledException();
@@ -176,7 +176,7 @@ namespace Flow.Launcher
_mainWindow = new MainWindow();
- Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
+ API.LogInfo(ClassName, "Dependencies Info:{ErrorReporting.DependenciesInfo()}");
Current.MainWindow = _mainWindow;
Current.MainWindow.Title = Constant.FlowLauncher;
@@ -192,7 +192,7 @@ namespace Flow.Launcher
AutoUpdates();
API.SaveAppAllSettings();
- Log.Info("|App.OnStartup|End Flow Launcher startup ----------------------------------------------------");
+ API.LogInfo(ClassName, "End Flow Launcher startup ----------------------------------------------------");
});
}
@@ -250,19 +250,19 @@ namespace Flow.Launcher
{
AppDomain.CurrentDomain.ProcessExit += (s, e) =>
{
- Log.Info("|App.RegisterExitEvents|Process Exit");
+ API.LogInfo(ClassName, "Process Exit");
Dispose();
};
Current.Exit += (s, e) =>
{
- Log.Info("|App.RegisterExitEvents|Application Exit");
+ API.LogInfo(ClassName, "Application Exit");
Dispose();
};
Current.SessionEnding += (s, e) =>
{
- Log.Info("|App.RegisterExitEvents|Session Ending");
+ API.LogInfo(ClassName, "Session Ending");
Dispose();
};
}
@@ -326,7 +326,7 @@ namespace Flow.Launcher
API.StopwatchLogInfo(ClassName, "Dispose cost", () =>
{
- Log.Info("|App.Dispose|Begin Flow Launcher dispose ----------------------------------------------------");
+ API.LogInfo(ClassName, "Begin Flow Launcher dispose ----------------------------------------------------");
if (disposing)
{
@@ -336,7 +336,7 @@ namespace Flow.Launcher
_mainVM?.Dispose();
}
- Log.Info("|App.Dispose|End Flow Launcher dispose ----------------------------------------------------");
+ API.LogInfo(ClassName, "End Flow Launcher dispose ----------------------------------------------------");
});
}
diff --git a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs
index 0d6f2e469..eb492e334 100644
--- a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs
+++ b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs
@@ -4,13 +4,14 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher.Converters;
public class QuerySuggestionBoxConverter : IMultiValueConverter
{
+ private static readonly string ClassName = nameof(QuerySuggestionBoxConverter);
+
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
// values[0] is TextBox: The textbox displaying the autocomplete suggestion
@@ -64,7 +65,7 @@ public class QuerySuggestionBoxConverter : IMultiValueConverter
}
catch (Exception e)
{
- Log.Exception(nameof(QuerySuggestionBoxConverter), "fail to convert text for suggestion box", e);
+ App.API.LogException(ClassName, "fail to convert text for suggestion box", e);
return string.Empty;
}
}
diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs
index c5e20504b..568ea7944 100644
--- a/Flow.Launcher/Helper/AutoStartup.cs
+++ b/Flow.Launcher/Helper/AutoStartup.cs
@@ -11,6 +11,8 @@ namespace Flow.Launcher.Helper;
public class AutoStartup
{
+ private static readonly string ClassName = nameof(AutoStartup);
+
private const string StartupPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
private const string LogonTaskName = $"{Constant.FlowLauncher} Startup";
private const string LogonTaskDesc = $"{Constant.FlowLauncher} Auto Startup";
@@ -34,7 +36,7 @@ public class AutoStartup
}
catch (Exception e)
{
- Log.Error("AutoStartup", $"Ignoring non-critical registry error (querying if enabled): {e}");
+ App.API.LogError(ClassName, $"Ignoring non-critical registry error (querying if enabled): {e}");
}
return false;
@@ -61,7 +63,7 @@ public class AutoStartup
}
catch (Exception e)
{
- Log.Error("AutoStartup", $"Failed to check logon task: {e}");
+ App.API.LogError(ClassName, $"Failed to check logon task: {e}");
}
}
@@ -112,7 +114,7 @@ public class AutoStartup
}
catch (Exception e)
{
- Log.Error("AutoStartup", $"Failed to disable auto-startup: {e}");
+ App.API.LogError(ClassName, $"Failed to disable auto-startup: {e}");
throw;
}
}
@@ -133,7 +135,7 @@ public class AutoStartup
}
catch (Exception e)
{
- Log.Error("AutoStartup", $"Failed to enable auto-startup: {e}");
+ App.API.LogError(ClassName, $"Failed to enable auto-startup: {e}");
throw;
}
}
@@ -161,7 +163,7 @@ public class AutoStartup
}
catch (Exception e)
{
- Log.Error("AutoStartup", $"Failed to schedule logon task: {e}");
+ App.API.LogError(ClassName, $"Failed to schedule logon task: {e}");
return false;
}
}
@@ -176,7 +178,7 @@ public class AutoStartup
}
catch (Exception e)
{
- Log.Error("AutoStartup", $"Failed to unschedule logon task: {e}");
+ App.API.LogError(ClassName, $"Failed to unschedule logon task: {e}");
return false;
}
}
diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs
index 0771a6074..1e83415cc 100644
--- a/Flow.Launcher/Helper/HotKeyMapper.cs
+++ b/Flow.Launcher/Helper/HotKeyMapper.cs
@@ -12,6 +12,8 @@ namespace Flow.Launcher.Helper;
internal static class HotKeyMapper
{
+ private static readonly string ClassName = nameof(HotKeyMapper);
+
private static Settings _settings;
private static MainViewModel _mainViewModel;
@@ -51,7 +53,7 @@ internal static class HotKeyMapper
}
catch (Exception e)
{
- Log.Error(
+ App.API.LogError(ClassName,
string.Format("|HotkeyMapper.SetWithChefKeys|Error registering hotkey: {0} \nStackTrace:{1}",
e.Message,
e.StackTrace));
@@ -76,7 +78,7 @@ internal static class HotKeyMapper
}
catch (Exception e)
{
- Log.Error(
+ App.API.LogError(ClassName,
string.Format("|HotkeyMapper.SetHotkey|Error registering hotkey {2}: {0} \nStackTrace:{1}",
e.Message,
e.StackTrace,
@@ -102,7 +104,7 @@ internal static class HotKeyMapper
}
catch (Exception e)
{
- Log.Error(
+ App.API.LogError(ClassName,
string.Format("|HotkeyMapper.RemoveHotkey|Error removing hotkey: {0} \nStackTrace:{1}",
e.Message,
e.StackTrace));
diff --git a/Flow.Launcher/MessageBoxEx.xaml.cs b/Flow.Launcher/MessageBoxEx.xaml.cs
index 3d94769d0..a55aeb811 100644
--- a/Flow.Launcher/MessageBoxEx.xaml.cs
+++ b/Flow.Launcher/MessageBoxEx.xaml.cs
@@ -4,13 +4,13 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Image;
-using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher
{
public partial class MessageBoxEx : Window
{
+ private static readonly string ClassName = nameof(MessageBoxEx);
+
private static MessageBoxEx msgBox;
private static MessageBoxResult _result = MessageBoxResult.None;
@@ -59,7 +59,7 @@ namespace Flow.Launcher
}
catch (Exception e)
{
- Log.Error($"|MessageBoxEx.Show|An error occurred: {e.Message}");
+ App.API.LogError(ClassName, $"An error occurred: {e.Message}");
msgBox = null;
return MessageBoxResult.None;
}
diff --git a/Flow.Launcher/Msg.xaml.cs b/Flow.Launcher/Msg.xaml.cs
index ff9accd62..110235cb5 100644
--- a/Flow.Launcher/Msg.xaml.cs
+++ b/Flow.Launcher/Msg.xaml.cs
@@ -5,7 +5,6 @@ using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media.Animation;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Image;
namespace Flow.Launcher
{
diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs
index 30b3a0673..be81e6ec6 100644
--- a/Flow.Launcher/Notification.cs
+++ b/Flow.Launcher/Notification.cs
@@ -1,5 +1,4 @@
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
using Microsoft.Toolkit.Uwp.Notifications;
using System;
using System.IO;
@@ -9,6 +8,8 @@ namespace Flow.Launcher
{
internal static class Notification
{
+ private static readonly string ClassName = nameof(Notification);
+
internal static bool legacy = !Win32Helper.IsNotificationSupported();
internal static void Uninstall()
@@ -51,12 +52,12 @@ namespace Flow.Launcher
{
// Temporary fix for the Windows 11 notification issue
// Possibly from 22621.1413 or 22621.1485, judging by post time of #2024
- Log.Exception("Flow.Launcher.Notification|Notification InvalidOperationException Error", e);
+ App.API.LogException(ClassName, "Notification InvalidOperationException Error", e);
LegacyShow(title, subTitle, iconPath);
}
catch (Exception e)
{
- Log.Exception("Flow.Launcher.Notification|Notification Error", e);
+ App.API.LogException(ClassName, "Notification Error", e);
LegacyShow(title, subTitle, iconPath);
}
}
diff --git a/Flow.Launcher/ProgressBoxEx.xaml.cs b/Flow.Launcher/ProgressBoxEx.xaml.cs
index 2395bdf34..840c8bade 100644
--- a/Flow.Launcher/ProgressBoxEx.xaml.cs
+++ b/Flow.Launcher/ProgressBoxEx.xaml.cs
@@ -2,12 +2,13 @@
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
-using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher
{
public partial class ProgressBoxEx : Window
{
+ private static readonly string ClassName = nameof(ProgressBoxEx);
+
private readonly Action _cancelProgress;
private ProgressBoxEx(Action cancelProgress)
@@ -47,7 +48,7 @@ namespace Flow.Launcher
}
catch (Exception e)
{
- Log.Error($"|ProgressBoxEx.Show|An error occurred: {e.Message}");
+ App.API.LogError(ClassName, $"An error occurred: {e.Message}");
await reportProgressAsync(null).ConfigureAwait(false);
}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 5438eac7d..3abc57b8a 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -435,16 +435,16 @@ namespace Flow.Launcher
PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings);
public long StopwatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") =>
- Stopwatch.Debug($"|{className}.{methodName}|{message}", action);
+ Stopwatch.Debug(className, message, action, methodName);
public Task StopwatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") =>
- Stopwatch.DebugAsync($"|{className}.{methodName}|{message}", action);
+ Stopwatch.DebugAsync(className, message, action, methodName);
public long StopwatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") =>
- Stopwatch.Normal($"|{className}.{methodName}|{message}", action);
+ Stopwatch.Info(className, message, action, methodName);
public Task StopwatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") =>
- Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action);
+ Stopwatch.InfoAsync(className, message, action, methodName);
#endregion
diff --git a/Flow.Launcher/ReportWindow.xaml.cs b/Flow.Launcher/ReportWindow.xaml.cs
index 6fe90783e..0ab785a17 100644
--- a/Flow.Launcher/ReportWindow.xaml.cs
+++ b/Flow.Launcher/ReportWindow.xaml.cs
@@ -8,13 +8,15 @@ using System.Windows;
using System.Windows.Documents;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin.SharedCommands;
+using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher
{
internal partial class ReportWindow
{
+ private static readonly string ClassName = nameof(ReportWindow);
+
public ReportWindow(Exception exception)
{
InitializeComponent();
@@ -38,7 +40,7 @@ namespace Flow.Launcher
private void SetException(Exception exception)
{
- string path = Log.CurrentLogDirectory;
+ var path = DataLocation.VersionLogDirectory;
var directory = new DirectoryInfo(path);
var log = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First();
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index f6b9aa67c..998fdb906 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -16,7 +16,6 @@ using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Hotkey;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
@@ -30,6 +29,8 @@ namespace Flow.Launcher.ViewModel
{
#region Private Fields
+ private static readonly string ClassName = nameof(MainViewModel);
+
private bool _isQueryRunning;
private Query _lastQuery;
private string _queryTextBeforeLeaveResults;
@@ -213,7 +214,7 @@ namespace Flow.Launcher.ViewModel
}
if (!_disposed)
- Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends");
+ App.API.LogError(ClassName, "Unexpected ResultViewUpdate ends");
}
void continueAction(Task t)
@@ -257,7 +258,7 @@ namespace Flow.Launcher.ViewModel
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query,
token)))
{
- Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
+ App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
}
};
}
@@ -1303,7 +1304,7 @@ namespace Flow.Launcher.ViewModel
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, plugin.Metadata, query,
token, reSelect)))
{
- Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
+ App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
}
}
}
@@ -1347,8 +1348,8 @@ namespace Flow.Launcher.ViewModel
}
catch (Exception e)
{
- Log.Exception(
- $"{nameof(MainViewModel)}.{nameof(ConstructQuery)}|Error when expanding shortcut {shortcut.Key}",
+ App.API.LogException(ClassName,
+ $"Error when expanding shortcut {shortcut.Key}",
e);
}
}
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index 8d7569dc1..ef7e24c3b 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Drawing.Text;
using System.IO;
@@ -7,7 +6,6 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using Flow.Launcher.Infrastructure.Image;
-using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
@@ -15,6 +13,8 @@ namespace Flow.Launcher.ViewModel
{
public class ResultViewModel : BaseModel
{
+ private static readonly string ClassName = nameof(ResultsViewModel);
+
private static readonly PrivateFontCollection FontCollection = new();
private static readonly Dictionary Fonts = new();
@@ -232,8 +232,8 @@ namespace Flow.Launcher.ViewModel
}
catch (Exception e)
{
- Log.Exception(
- $"|ResultViewModel.LoadImageInternalAsync|IcoPath is empty and exception when calling IconDelegate for result <{Result.Title}> of plugin <{Result.PluginDirectory}>",
+ App.API.LogException(ClassName,
+ $"IcoPath is empty and exception when calling IconDelegate for result <{Result.Title}> of plugin <{Result.PluginDirectory}>",
e);
}
}
From 3f57f944f620e3198a8a590bfeb9ecf4b30e62b7 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 17:52:42 +0800
Subject: [PATCH 70/97] Remove useless debug
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 16b6bcab2..d28845994 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -109,7 +109,6 @@ namespace Flow.Launcher.Plugin.Program
}
catch (OperationCanceledException)
{
- Context.API.LogDebug(ClassName, "Query operation cancelled");
return emptyResults;
}
finally
From 50130e4b009ae5a808b7b65d3238d0785c60b0df Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 17:59:39 +0800
Subject: [PATCH 71/97] Use class name instead
---
Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs | 4 +++-
Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 10 ++++++----
Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 4 +++-
Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs | 4 +++-
.../Search/DirectoryInfo/DirectoryInfoSearch.cs | 4 +++-
.../ProcessHelper.cs | 4 +++-
.../SuggestionSources/Baidu.cs | 6 ++++--
.../SuggestionSources/Bing.cs | 6 ++++--
.../SuggestionSources/DuckDuckGo.cs | 6 ++++--
.../SuggestionSources/Google.cs | 6 ++++--
Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs | 2 ++
11 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
index 44d3ef0ff..7ca91eaec 100644
--- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs
@@ -9,6 +9,8 @@ namespace Flow.Launcher.Core.ExternalPlugins
{
public static class PluginsManifest
{
+ private static readonly string ClassName = nameof(PluginsManifest);
+
private static readonly CommunityPluginStore mainPluginStore =
new("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json",
"https://fastly.jsdelivr.net/gh/Flow-Launcher/Flow.Launcher.PluginsManifest@plugin_api_v2/plugins.json",
@@ -44,7 +46,7 @@ namespace Flow.Launcher.Core.ExternalPlugins
}
catch (Exception e)
{
- Ioc.Default.GetRequiredService().LogException(nameof(PluginsManifest), "Http request failed", e);
+ Ioc.Default.GetRequiredService().LogException(ClassName, "Http request failed", e);
}
finally
{
diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs
index 77bebe2d3..93b9a8aaa 100644
--- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs
+++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs
@@ -12,6 +12,8 @@ namespace Flow.Launcher.Helper;
public static class WallpaperPathRetrieval
{
+ private static readonly string ClassName = nameof(WallpaperPathRetrieval);
+
private const int MaxCacheSize = 3;
private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new();
private static readonly object CacheLock = new();
@@ -29,7 +31,7 @@ public static class WallpaperPathRetrieval
var wallpaperPath = Win32Helper.GetWallpaperPath();
if (string.IsNullOrEmpty(wallpaperPath) || !File.Exists(wallpaperPath))
{
- App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Wallpaper path is invalid: {wallpaperPath}");
+ App.API.LogInfo(ClassName, $"Wallpaper path is invalid: {wallpaperPath}");
var wallpaperColor = GetWallpaperColor();
return new SolidColorBrush(wallpaperColor);
}
@@ -54,7 +56,7 @@ public static class WallpaperPathRetrieval
if (originalWidth == 0 || originalHeight == 0)
{
- App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}");
+ App.API.LogInfo(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}");
return new SolidColorBrush(Colors.Transparent);
}
@@ -95,7 +97,7 @@ public static class WallpaperPathRetrieval
}
catch (Exception ex)
{
- App.API.LogException(nameof(WallpaperPathRetrieval), "Error retrieving wallpaper", ex);
+ App.API.LogException(ClassName, "Error retrieving wallpaper", ex);
return new SolidColorBrush(Colors.Transparent);
}
}
@@ -113,7 +115,7 @@ public static class WallpaperPathRetrieval
}
catch (Exception ex)
{
- App.API.LogException(nameof(WallpaperPathRetrieval), "Error parsing wallpaper color", ex);
+ App.API.LogException(ClassName, "Error parsing wallpaper color", ex);
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs
index 3bee49bf2..9ad31ad14 100644
--- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs
@@ -15,6 +15,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark;
public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContextMenu, IDisposable
{
+ private static readonly string ClassName = nameof(Main);
+
internal static string _faviconCacheDir;
internal static PluginInitContext _context;
@@ -221,7 +223,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex
catch (Exception e)
{
var message = "Failed to set url in clipboard";
- _context.API.LogException(nameof(Main), message, e);
+ _context.API.LogException(ClassName, message, e);
_context.API.ShowMsg(message);
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
index f47907824..633af7b6b 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs
@@ -15,6 +15,8 @@ namespace Flow.Launcher.Plugin.Explorer
{
internal class ContextMenu : IContextMenu
{
+ private static readonly string ClassName = nameof(ContextMenu);
+
private PluginInitContext Context { get; set; }
private Settings Settings { get; set; }
@@ -469,7 +471,7 @@ namespace Flow.Launcher.Plugin.Explorer
private void LogException(string message, Exception e)
{
- Context.API.LogException(nameof(ContextMenu), message, e);
+ Context.API.LogException(ClassName, message, e);
}
private static bool CanRunAsDifferentUser(string path)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs
index 1a0d3bd15..631744252 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs
@@ -9,6 +9,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
{
public static class DirectoryInfoSearch
{
+ private static readonly string ClassName = nameof(DirectoryInfoSearch);
+
internal static IEnumerable TopLevelDirectorySearch(Query query, string search, CancellationToken token)
{
var criteria = ConstructSearchCriteria(search);
@@ -75,7 +77,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
}
catch (Exception e)
{
- Main.Context.API.LogException(nameof(DirectoryInfoSearch), "Error occurred while searching path", e);
+ Main.Context.API.LogException(ClassName, "Error occurred while searching path", e);
throw;
}
diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs
index 4c07341ec..d7f44ccce 100644
--- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs
+++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs
@@ -12,6 +12,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller
{
internal class ProcessHelper
{
+ private static readonly string ClassName = nameof(ProcessHelper);
+
private readonly HashSet _systemProcessList = new()
{
"conhost",
@@ -131,7 +133,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller
}
catch (Exception e)
{
- context.API.LogException($"{nameof(ProcessHelper)}", $"Failed to kill process {p.ProcessName}", e);
+ context.API.LogException(ClassName, $"Failed to kill process {p.ProcessName}", e);
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
index 65be06b53..681c8b649 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
@@ -11,6 +11,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
public class Baidu : SuggestionSource
{
+ private static readonly string ClassName = nameof(Baidu);
+
private readonly Regex _reg = new Regex("window.baidu.sug\\((.*)\\)");
public override async Task> SuggestionsAsync(string query, CancellationToken token)
@@ -24,7 +26,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from Baidu", e);
+ Main._context.API.LogException(ClassName, "Can't get suggestion from Baidu", e);
return null;
}
@@ -39,7 +41,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (JsonException e)
{
- Main._context.API.LogException(nameof(Baidu), "Can't parse suggestions", e);
+ Main._context.API.LogException(ClassName, "Can't parse suggestions", e);
return new List();
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
index 9efc36263..ccfa5dcc8 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
@@ -10,6 +10,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
public class Bing : SuggestionSource
{
+ private static readonly string ClassName = nameof(Bing);
+
public override async Task> SuggestionsAsync(string query, CancellationToken token)
{
try
@@ -33,12 +35,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException })
{
- Main._context.API.LogException(nameof(Bing), "Can't get suggestion from Bing", e);
+ Main._context.API.LogException(ClassName, "Can't get suggestion from Bing", e);
return null;
}
catch (JsonException e)
{
- Main._context.API.LogException(nameof(Bing), "Can't parse suggestions", e);
+ Main._context.API.LogException(ClassName, "Can't parse suggestions", e);
return new List();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs
index 1d248caf3..0627f7220 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs
@@ -10,6 +10,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
public class DuckDuckGo : SuggestionSource
{
+ private static readonly string ClassName = nameof(DuckDuckGo);
+
public override async Task> SuggestionsAsync(string query, CancellationToken token)
{
// When the search query is empty, DuckDuckGo returns `[]`. When it's not empty, it returns data
@@ -34,12 +36,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Main._context.API.LogException(nameof(DuckDuckGo), "Can't get suggestion from DuckDuckGo", e);
+ Main._context.API.LogException(ClassName, "Can't get suggestion from DuckDuckGo", e);
return null;
}
catch (JsonException e)
{
- Main._context.API.LogException(nameof(DuckDuckGo), "Can't parse suggestions", e);
+ Main._context.API.LogException(ClassName, "Can't parse suggestions", e);
return new List();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
index ad8fb508f..f28212524 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
@@ -10,6 +10,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
public class Google : SuggestionSource
{
+ private static readonly string ClassName = nameof(Google);
+
public override async Task> SuggestionsAsync(string query, CancellationToken token)
{
try
@@ -27,12 +29,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Main._context.API.LogException(nameof(Google), "Can't get suggestion from Google", e);
+ Main._context.API.LogException(ClassName, "Can't get suggestion from Google", e);
return null;
}
catch (JsonException e)
{
- Main._context.API.LogException(nameof(Google), "Can't parse suggestions", e);
+ Main._context.API.LogException(ClassName, "Can't parse suggestions", e);
return new List();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs
index 257b0fa8b..c72230f2b 100644
--- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs
+++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs
@@ -11,10 +11,12 @@ namespace Flow.Launcher.Plugin.WindowsSettings
{
_api = api;
}
+
public static void Exception(string message, Exception exception, Type type, [CallerMemberName] string methodName = "")
{
_api?.LogException(type.FullName, message, exception, methodName);
}
+
public static void Warn(string message, Type type, [CallerMemberName] string methodName = "")
{
_api?.LogWarn(type.FullName, message, methodName);
From 20d266138047225f5bf02d1d4041955422789789 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 18:04:50 +0800
Subject: [PATCH 72/97] Code quality
---
.../Environments/JavaScriptEnvironment.cs | 1 -
.../Environments/JavaScriptV2Environment.cs | 1 -
.../Environments/PythonEnvironment.cs | 5 ++++-
.../Environments/TypeScriptEnvironment.cs | 5 ++++-
.../Environments/TypeScriptV2Environment.cs | 5 ++++-
Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs | 14 +++++---------
6 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs
index b67059b1b..62d2d3e91 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs
@@ -4,7 +4,6 @@ using Flow.Launcher.Plugin;
namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
-
internal class JavaScriptEnvironment : TypeScriptEnvironment
{
internal override string Language => AllowedLanguage.JavaScript;
diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs
index 6c8c5aa57..726bc4cd4 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs
@@ -4,7 +4,6 @@ using Flow.Launcher.Plugin;
namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
-
internal class JavaScriptV2Environment : TypeScriptV2Environment
{
internal override string Language => AllowedLanguage.JavaScriptV2;
diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs
index fab5738de..455ee096d 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs
@@ -5,6 +5,7 @@ using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
+using Microsoft.VisualStudio.Threading;
namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
@@ -30,13 +31,15 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal PythonEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { }
+ private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext());
+
internal override void InstallEnvironment()
{
FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s));
// Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and
// uses Python plugin they need to custom install and use v3.8.9
- DroplexPackage.Drop(App.python_3_11_4_embeddable, InstallPath).Wait();
+ JTF.Run(() => DroplexPackage.Drop(App.python_3_11_4_embeddable, InstallPath));
PluginsSettingsFilePath = ExecutablePath;
}
diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs
index 8a4f527ba..12965286f 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs
@@ -5,6 +5,7 @@ using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
+using Microsoft.VisualStudio.Threading;
namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
@@ -27,11 +28,13 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal TypeScriptEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { }
+ private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext());
+
internal override void InstallEnvironment()
{
FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s));
- DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait();
+ JTF.Run(() => DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath));
PluginsSettingsFilePath = ExecutablePath;
}
diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs
index 61fd28376..6960b79c9 100644
--- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs
+++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs
@@ -5,6 +5,7 @@ using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
+using Microsoft.VisualStudio.Threading;
namespace Flow.Launcher.Core.ExternalPlugins.Environments
{
@@ -27,11 +28,13 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
internal TypeScriptV2Environment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { }
+ private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext());
+
internal override void InstallEnvironment()
{
FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s));
- DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait();
+ JTF.Run(() => DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath));
PluginsSettingsFilePath = ExecutablePath;
}
diff --git a/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs b/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs
index bae263157..7a6bf07e2 100644
--- a/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs
+++ b/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs
@@ -1,21 +1,19 @@
-#nullable enable
-
-using System;
-using System.Collections.Generic;
+using System;
using System.Diagnostics;
using System.IO.Pipelines;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin;
using Meziantou.Framework.Win32;
-using Microsoft.VisualBasic.ApplicationServices;
using Nerdbank.Streams;
+#nullable enable
+
namespace Flow.Launcher.Core.Plugin
{
internal abstract class ProcessStreamPluginV2 : JsonRPCPluginV2
{
- private static JobObject _jobObject = new JobObject();
+ private static readonly JobObject _jobObject = new();
static ProcessStreamPluginV2()
{
@@ -66,11 +64,10 @@ namespace Flow.Launcher.Core.Plugin
ClientPipe = new DuplexPipe(reader, writer);
}
-
public override async Task ReloadDataAsync()
{
var oldProcess = ClientProcess;
- ClientProcess = Process.Start(StartInfo);
+ ClientProcess = Process.Start(StartInfo)!;
ArgumentNullException.ThrowIfNull(ClientProcess);
SetupPipe(ClientProcess);
await base.ReloadDataAsync();
@@ -79,7 +76,6 @@ namespace Flow.Launcher.Core.Plugin
oldProcess.Dispose();
}
-
public override async ValueTask DisposeAsync()
{
await base.DisposeAsync();
From 43dbf1a0ee013bcfda2bd9d43a1c22863a72e9b9 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 18:13:55 +0800
Subject: [PATCH 73/97] Remove useless functions & Fix debug issue
---
Flow.Launcher.Core/Plugin/PluginsLoader.cs | 8 +--
Flow.Launcher.Infrastructure/Logger/Log.cs | 64 +---------------------
Flow.Launcher/ViewModel/MainViewModel.cs | 4 +-
3 files changed, 7 insertions(+), 69 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
index 1010d9f08..256c36065 100644
--- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs
+++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs
@@ -89,19 +89,19 @@ namespace Flow.Launcher.Core.Plugin
#else
catch (Exception e) when (assembly == null)
{
- Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
+ Log.Exception(ClassName, $"Couldn't load assembly for the plugin: {metadata.Name}", e);
}
catch (InvalidOperationException e)
{
- Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
+ Log.Exception(ClassName, $"Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
}
catch (ReflectionTypeLoadException e)
{
- Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
+ Log.Exception(ClassName, $"The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
}
catch (Exception e)
{
- Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
+ Log.Exception(ClassName, $"The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
}
#endif
diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs
index 25cfbbd3d..09eb98f46 100644
--- a/Flow.Launcher.Infrastructure/Logger/Log.cs
+++ b/Flow.Launcher.Infrastructure/Logger/Log.cs
@@ -94,13 +94,6 @@ namespace Flow.Launcher.Infrastructure.Logger
logger.Fatal(message);
}
- private static bool FormatValid(string message)
- {
- var parts = message.Split('|');
- var valid = parts.Length == 3 && !string.IsNullOrWhiteSpace(parts[1]) && !string.IsNullOrWhiteSpace(parts[2]);
- return valid;
- }
-
public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
{
exception = exception.Demystify();
@@ -135,57 +128,14 @@ namespace Flow.Launcher.Infrastructure.Logger
return className;
}
+#if !DEBUG
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
{
var logger = LogManager.GetLogger(classAndMethod);
logger.Error(e, message);
}
-
- private static void LogInternal(string message, LogLevel level)
- {
- if (FormatValid(message))
- {
- var parts = message.Split('|');
- var prefix = parts[1];
- var unprefixed = parts[2];
- var logger = LogManager.GetLogger(prefix);
- logger.Log(level, unprefixed);
- }
- else
- {
- LogFaultyFormat(message);
- }
- }
-
- /// Example: "|ClassName.MethodName|Message"
- /// Example: "|ClassName.MethodName|Message"
- /// Exception
- public static void Exception(string message, System.Exception e)
- {
- e = e.Demystify();
-#if DEBUG
- ExceptionDispatchInfo.Capture(e).Throw();
-#else
- if (FormatValid(message))
- {
- var parts = message.Split('|');
- var prefix = parts[1];
- var unprefixed = parts[2];
- ExceptionInternal(prefix, unprefixed, e);
- }
- else
- {
- LogFaultyFormat(message);
- }
#endif
- }
-
- /// Example: "|ClassName.MethodName|Message"
- public static void Error(string message)
- {
- LogInternal(message, LogLevel.Error);
- }
public static void Error(string className, string message, [CallerMemberName] string methodName = "")
{
@@ -206,23 +156,11 @@ namespace Flow.Launcher.Infrastructure.Logger
LogInternal(LogLevel.Debug, className, message, methodName);
}
- /// Example: "|ClassName.MethodName|Message""
- public static void Debug(string message)
- {
- LogInternal(message, LogLevel.Debug);
- }
-
public static void Info(string className, string message, [CallerMemberName] string methodName = "")
{
LogInternal(LogLevel.Info, className, message, methodName);
}
- /// Example: "|ClassName.MethodName|Message"
- public static void Info(string message)
- {
- LogInternal(message, LogLevel.Info);
- }
-
public static void Warn(string className, string message, [CallerMemberName] string methodName = "")
{
LogInternal(LogLevel.Warn, className, message, methodName);
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 998fdb906..00675149b 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -222,7 +222,7 @@ namespace Flow.Launcher.ViewModel
#if DEBUG
throw t.Exception;
#else
- Log.Error($"Error happen in task dealing with viewupdate for results. {t.Exception}");
+ App.API.LogError(ClassName, $"Error happen in task dealing with viewupdate for results. {t.Exception}");
_resultsViewUpdateTask =
Task.Run(UpdateActionAsync).ContinueWith(continueAction, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default);
#endif
@@ -892,7 +892,7 @@ namespace Flow.Launcher.ViewModel
#if DEBUG
throw new NotImplementedException("ResultAreaColumn should match ResultAreaColumnPreviewShown/ResultAreaColumnPreviewHidden value");
#else
- Log.Error("MainViewModel", "ResultAreaColumnPreviewHidden/ResultAreaColumnPreviewShown int value not implemented", "InternalPreviewVisible");
+ App.API.LogError(ClassName, "ResultAreaColumnPreviewHidden/ResultAreaColumnPreviewShown int value not implemented", "InternalPreviewVisible");
return false;
#endif
}
From 3fab9da633f5d7a13b28b379f43ac93bf170858a Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Sun, 13 Apr 2025 18:14:39 +0800
Subject: [PATCH 74/97] Fix incorrect class name reference
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index ef7e24c3b..648ac49bb 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -13,7 +13,7 @@ namespace Flow.Launcher.ViewModel
{
public class ResultViewModel : BaseModel
{
- private static readonly string ClassName = nameof(ResultsViewModel);
+ private static readonly string ClassName = nameof(ResultViewModel);
private static readonly PrivateFontCollection FontCollection = new();
private static readonly Dictionary Fonts = new();
From eec6145e1aca49f36be49a8b36099e8865ab97cf Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sun, 13 Apr 2025 20:35:27 +0800
Subject: [PATCH 75/97] Fix possible win32 exception
---
Flow.Launcher.Infrastructure/Win32Helper.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs
index 54604a271..6be024389 100644
--- a/Flow.Launcher.Infrastructure/Win32Helper.cs
+++ b/Flow.Launcher.Infrastructure/Win32Helper.cs
@@ -376,7 +376,8 @@ namespace Flow.Launcher.Infrastructure
if (!IsForegroundWindow(hwnd))
{
var result = PInvoke.SetForegroundWindow(hwnd);
- if (!result) throw new Win32Exception(Marshal.GetLastWin32Error());
+ // If we cannot set the foreground window, we can use the foreground window and switch the layout
+ if (!result) hwnd = PInvoke.GetForegroundWindow();
}
// Get the current foreground window thread ID
From 0bdfaac6a9d2c73bce84ec9b4c5b2715da4c9a3f Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 14 Apr 2025 21:37:15 +1000
Subject: [PATCH 76/97] Add sponsor
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index cbb553bd1..d8ecfa671 100644
--- a/README.md
+++ b/README.md
@@ -351,6 +351,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea
+
From f8396892940ca99bb1e2c471408b1b4f18277969 Mon Sep 17 00:00:00 2001
From: DB p
Date: Tue, 15 Apr 2025 05:54:46 +0900
Subject: [PATCH 77/97] Add Content Dialog owner
---
Flow.Launcher/HotkeyControl.xaml.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs
index 8762a934b..9af3b71aa 100644
--- a/Flow.Launcher/HotkeyControl.xaml.cs
+++ b/Flow.Launcher/HotkeyControl.xaml.cs
@@ -243,6 +243,9 @@ namespace Flow.Launcher
}
var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle);
+
+ dialog.Owner = Window.GetWindow(this);
+
await dialog.ShowAsync();
switch (dialog.ResultType)
{
From 9035aa6fab026722ef5ca71ebc3d55b0cfcfea69 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 08:41:20 +0800
Subject: [PATCH 78/97] Fix dialog owner for all content dialog
---
Flow.Launcher/HotkeyControl.xaml.cs | 13 +++++++------
.../ViewModels/SettingsPanePluginsViewModel.cs | 3 +--
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs
index 9af3b71aa..262727127 100644
--- a/Flow.Launcher/HotkeyControl.xaml.cs
+++ b/Flow.Launcher/HotkeyControl.xaml.cs
@@ -1,6 +1,4 @@
-#nullable enable
-
-using System.Collections.ObjectModel;
+using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
@@ -9,6 +7,8 @@ using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
+#nullable enable
+
namespace Flow.Launcher
{
public partial class HotkeyControl
@@ -242,9 +242,10 @@ namespace Flow.Launcher
HotKeyMapper.RemoveHotkey(Hotkey);
}
- var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle);
-
- dialog.Owner = Window.GetWindow(this);
+ var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle)
+ {
+ Owner = Window.GetWindow(this)
+ };
await dialog.ShowAsync();
switch (dialog.ResultType)
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
index b89e970e9..916fd1ece 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
@@ -5,7 +5,6 @@ using System.Windows.Controls;
using System.Windows;
using CommunityToolkit.Mvvm.Input;
using Flow.Launcher.Core.Plugin;
-using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel;
@@ -116,6 +115,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel
{
var helpDialog = new ContentDialog()
{
+ Owner = Application.Current.MainWindow,
Content = new StackPanel
{
Children =
@@ -146,7 +146,6 @@ public partial class SettingsPanePluginsViewModel : BaseModel
}
}
},
-
PrimaryButtonText = (string)Application.Current.Resources["commonOK"],
CornerRadius = new CornerRadius(8),
Style = (Style)Application.Current.Resources["ContentDialog"]
From 28c7538fc3b00bc88a62336bba79d04a0b841fc3 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 09:06:31 +0800
Subject: [PATCH 79/97] Fix possible Win32Exception
---
Flow.Launcher.Infrastructure/Win32Helper.cs | 15 ++-------------
1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs
index 6be024389..798501ae3 100644
--- a/Flow.Launcher.Infrastructure/Win32Helper.cs
+++ b/Flow.Launcher.Infrastructure/Win32Helper.cs
@@ -365,21 +365,10 @@ namespace Flow.Launcher.Infrastructure
// No installed English layout found
if (enHKL == HKL.Null) return;
- // When application is exiting, the Application.Current will be null
- if (Application.Current == null) return;
-
- // Get the FL main window
- var hwnd = GetWindowHandle(Application.Current.MainWindow, true);
+ // Get the foreground window
+ var hwnd = PInvoke.GetForegroundWindow();
if (hwnd == HWND.Null) return;
- // Check if the FL main window is the current foreground window
- if (!IsForegroundWindow(hwnd))
- {
- var result = PInvoke.SetForegroundWindow(hwnd);
- // If we cannot set the foreground window, we can use the foreground window and switch the layout
- if (!result) hwnd = PInvoke.GetForegroundWindow();
- }
-
// Get the current foreground window thread ID
var threadId = PInvoke.GetWindowThreadProcessId(hwnd);
if (threadId == 0) throw new Win32Exception(Marshal.GetLastWin32Error());
From d21ffce47af56b25bbf14e36d7b475ce3e7f4689 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 12:21:56 +0800
Subject: [PATCH 80/97] Use get window to get owner
---
.../SettingPages/ViewModels/SettingsPanePluginsViewModel.cs | 4 ++--
Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
index 916fd1ece..de7cf15c3 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs
@@ -111,11 +111,11 @@ public partial class SettingsPanePluginsViewModel : BaseModel
.ToList();
[RelayCommand]
- private async Task OpenHelperAsync()
+ private async Task OpenHelperAsync(Button button)
{
var helpDialog = new ContentDialog()
{
- Owner = Application.Current.MainWindow,
+ Owner = Window.GetWindow(button),
Content = new StackPanel
{
Children =
diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml
index f9f708314..f3d630306 100644
--- a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml
+++ b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml
@@ -57,6 +57,7 @@
Height="34"
Margin="0 0 20 0"
Command="{Binding OpenHelperCommand}"
+ CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
Content=""
FontFamily="{DynamicResource SymbolThemeFontFamily}"
FontSize="14" />
From c382732f974d99211b4d739340f6fcd7fa3cedc9 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 12:49:09 +0800
Subject: [PATCH 81/97] Improve windows exiting
---
Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
index 043eb7a19..39bf49654 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs
@@ -362,6 +362,7 @@ namespace Flow.Launcher.Plugin.Sys
Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xe89f"),
Action = c =>
{
+ _context.API.HideMainWindow();
Application.Current.MainWindow.Close();
return true;
}
From 8e51096ba9ded910e3c2c2906404e5bc5f247701 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 12:51:38 +0800
Subject: [PATCH 82/97] Improve log messages
---
Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index a49385a02..86df01a30 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -171,8 +171,8 @@ namespace Flow.Launcher.Infrastructure.Image
}
catch (System.Exception e2)
{
- Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e);
- Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2);
+ Log.Exception(ClassName, $"Failed to get thumbnail for {path} on first try", e);
+ Log.Exception(ClassName, $"Failed to get thumbnail for {path} on second try", e2);
ImageSource image = ImageCache[Constant.MissingImgIcon, false];
ImageCache[path, false] = image;
From a1b5941039da7370ee3c69d2c90ec61d7859ce35 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 12:52:09 +0800
Subject: [PATCH 83/97] Improve WindowsThumbnailProvider
---
.../Image/ThumbnailReader.cs | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs
index b98ea50fe..fe389a331 100644
--- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs
@@ -12,7 +12,7 @@ using Windows.Win32.Graphics.Gdi;
namespace Flow.Launcher.Infrastructure.Image
{
///
- /// Subclass of
+ /// Subclass of
///
[Flags]
public enum ThumbnailOptions
@@ -33,6 +33,8 @@ namespace Flow.Launcher.Infrastructure.Image
private static readonly HRESULT S_ExtractionFailed = (HRESULT)0x8004B200;
+ private static readonly HRESULT S_PATHNOTFOUND = (HRESULT)0x8004B205;
+
public static BitmapSource GetThumbnail(string fileName, int width, int height, ThumbnailOptions options)
{
HBITMAP hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options);
@@ -79,9 +81,10 @@ namespace Flow.Launcher.Infrastructure.Image
{
imageFactory.GetImage(size, (SIIGBF)options, &hBitmap);
}
- catch (COMException ex) when (ex.HResult == S_ExtractionFailed && options == ThumbnailOptions.ThumbnailOnly)
+ catch (COMException ex) when (options == ThumbnailOptions.ThumbnailOnly &&
+ (ex.HResult == S_PATHNOTFOUND || ex.HResult == S_ExtractionFailed))
{
- // Fallback to IconOnly if ThumbnailOnly fails
+ // Fallback to IconOnly if extraction fails or files cannot be found
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
}
catch (FileNotFoundException) when (options == ThumbnailOptions.ThumbnailOnly)
@@ -89,6 +92,11 @@ namespace Flow.Launcher.Infrastructure.Image
// Fallback to IconOnly if files cannot be found
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
}
+ catch (System.Exception ex)
+ {
+ // Handle other exceptions
+ throw new InvalidOperationException("Failed to get thumbnail", ex);
+ }
}
finally
{
From 83fa654e2733ef28af1bef3d4f85ac607b1000b9 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 12:59:58 +0800
Subject: [PATCH 84/97] Improve constant name
---
Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs
index fe389a331..4ce0df026 100644
--- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs
@@ -31,7 +31,7 @@ namespace Flow.Launcher.Infrastructure.Image
private static readonly Guid GUID_IShellItem = typeof(IShellItem).GUID;
- private static readonly HRESULT S_ExtractionFailed = (HRESULT)0x8004B200;
+ private static readonly HRESULT S_EXTRACTIONFAILED = (HRESULT)0x8004B200;
private static readonly HRESULT S_PATHNOTFOUND = (HRESULT)0x8004B205;
@@ -82,7 +82,7 @@ namespace Flow.Launcher.Infrastructure.Image
imageFactory.GetImage(size, (SIIGBF)options, &hBitmap);
}
catch (COMException ex) when (options == ThumbnailOptions.ThumbnailOnly &&
- (ex.HResult == S_PATHNOTFOUND || ex.HResult == S_ExtractionFailed))
+ (ex.HResult == S_PATHNOTFOUND || ex.HResult == S_EXTRACTIONFAILED))
{
// Fallback to IconOnly if extraction fails or files cannot be found
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
From 81007f79aee6ca7671880afaa8e329e99bacb9f4 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 15 Apr 2025 13:18:06 +0800
Subject: [PATCH 85/97] Remove mvvm command for code quality
---
Flow.Launcher/ViewModel/RelayCommand.cs | 29 ----------
.../Flow.Launcher.Plugin.Explorer.csproj | 1 +
.../ViewModels/RelayCommand.cs | 27 ---------
.../ViewModels/SettingsViewModel.cs | 55 +++++++------------
.../Views/ExplorerSettings.xaml | 6 +-
5 files changed, 24 insertions(+), 94 deletions(-)
delete mode 100644 Flow.Launcher/ViewModel/RelayCommand.cs
delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/RelayCommand.cs
diff --git a/Flow.Launcher/ViewModel/RelayCommand.cs b/Flow.Launcher/ViewModel/RelayCommand.cs
deleted file mode 100644
index e8d4af8b5..000000000
--- a/Flow.Launcher/ViewModel/RelayCommand.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using System.Windows.Input;
-
-namespace Flow.Launcher.ViewModel
-{
- public class RelayCommand : ICommand
- {
- private readonly Action