diff --git a/.github/workflows/default_plugins.yml b/.github/workflows/default_plugins.yml
index a2283defe..2cb04fe0d 100644
--- a/.github/workflows/default_plugins.yml
+++ b/.github/workflows/default_plugins.yml
@@ -18,7 +18,7 @@ jobs:
dotnet-version: 7.0.x
- name: Determine New Plugin Updates
- uses: dorny/paths-filter@v2
+ uses: dorny/paths-filter@v3
id: changes
with:
filters: |
diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
index 68e7c115c..18101ccf0 100644
--- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj
+++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
@@ -56,9 +56,9 @@
-
+
-
+
diff --git a/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs b/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs
index 0bff23fe1..ffb7d65b8 100644
--- a/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs
+++ b/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs
@@ -9,18 +9,11 @@ namespace Flow.Launcher.Converters
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- if (value is bool v)
+ return value switch
{
- if (v)
- {
- return ImeConversionModeValues.Alphanumeric;
- }
- else
- {
- return ImeConversionModeValues.DoNotCare;
- }
- }
- return ImeConversionModeValues.DoNotCare;
+ true => ImeConversionModeValues.Alphanumeric,
+ _ => ImeConversionModeValues.DoNotCare
+ };
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
@@ -33,18 +26,11 @@ namespace Flow.Launcher.Converters
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- if (value is bool v)
+ return value switch
{
- if (v)
- {
- return InputMethodState.Off;
- }
- else
- {
- return InputMethodState.DoNotCare;
- }
- }
- return InputMethodState.DoNotCare;
+ true => InputMethodState.Off,
+ _ => InputMethodState.DoNotCare
+ };
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Flow.Launcher/Converters/BoolToVisibilityConverter.cs b/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
index 627937c7f..ac3b2cfd0 100644
--- a/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
+++ b/Flow.Launcher/Converters/BoolToVisibilityConverter.cs
@@ -8,28 +8,14 @@ namespace Flow.Launcher.Converters
{
public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
{
- if (parameter != null)
+ return (value, parameter) switch
{
- if (value is true)
- {
- return Visibility.Collapsed;
- }
+ (true, not null) => Visibility.Collapsed,
+ (_, not null) => Visibility.Visible,
- else
- {
- return Visibility.Visible;
- }
- }
- else {
- if (value is true)
- {
- return Visibility.Visible;
- }
-
- else {
- return Visibility.Collapsed;
- }
- }
+ (true, null) => Visibility.Visible,
+ (_, null) => Visibility.Collapsed
+ };
}
public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
@@ -40,30 +26,14 @@ namespace Flow.Launcher.Converters
{
public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
{
- if (parameter != null)
+ return (value, parameter) switch
{
- if (value is true)
- {
- return 0;
- }
+ (true, not null) => 0,
+ (_, not null) => 5,
- else
- {
- return 5;
- }
- }
- else
- {
- if (value is true)
- {
- return 5;
- }
-
- else
- {
- return 0;
- }
- }
+ (true, null) => 5,
+ (_, null) => 0
+ };
}
public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
diff --git a/Flow.Launcher/Converters/BorderClipConverter.cs b/Flow.Launcher/Converters/BorderClipConverter.cs
index c0bce2cd9..a8d9b34c6 100644
--- a/Flow.Launcher/Converters/BorderClipConverter.cs
+++ b/Flow.Launcher/Converters/BorderClipConverter.cs
@@ -13,34 +13,31 @@ namespace Flow.Launcher.Converters
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
- if (values.Length == 3 && values[0] is double && values[1] is double && values[2] is CornerRadius)
+ if (values is not [double width, double height, CornerRadius radius])
{
- var width = (double)values[0];
- var height = (double)values[1];
- Path myPath = new Path();
- if (width < Double.Epsilon || height < Double.Epsilon)
- {
- return Geometry.Empty;
- }
- var radius = (CornerRadius)values[2];
- var radiusHeight = radius.TopLeft;
-
- // Drawing Round box for bottom round, and rect for top area of listbox.
- var corner = new RectangleGeometry(new Rect(0, 0, width, height), radius.TopLeft, radius.TopLeft);
- var box = new RectangleGeometry(new Rect(0, 0, width, radiusHeight), 0, 0);
-
- GeometryGroup myGeometryGroup = new GeometryGroup();
- myGeometryGroup.Children.Add(corner);
- myGeometryGroup.Children.Add(box);
-
- CombinedGeometry c1 = new CombinedGeometry(GeometryCombineMode.Union, corner, box);
- myPath.Data = c1;
-
- myPath.Data.Freeze();
- return myPath.Data;
+ return DependencyProperty.UnsetValue;
}
- return DependencyProperty.UnsetValue;
+ Path myPath = new Path();
+ if (width < Double.Epsilon || height < Double.Epsilon)
+ {
+ return Geometry.Empty;
+ }
+ var radiusHeight = radius.TopLeft;
+
+ // Drawing Round box for bottom round, and rect for top area of listbox.
+ var corner = new RectangleGeometry(new Rect(0, 0, width, height), radius.TopLeft, radius.TopLeft);
+ var box = new RectangleGeometry(new Rect(0, 0, width, radiusHeight), 0, 0);
+
+ GeometryGroup myGeometryGroup = new GeometryGroup();
+ myGeometryGroup.Children.Add(corner);
+ myGeometryGroup.Children.Add(box);
+
+ CombinedGeometry c1 = new CombinedGeometry(GeometryCombineMode.Union, corner, box);
+ myPath.Data = c1;
+
+ myPath.Data.Freeze();
+ return myPath.Data;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
diff --git a/Flow.Launcher/Converters/HighlightTextConverter.cs b/Flow.Launcher/Converters/HighlightTextConverter.cs
index cb62c0d3d..3f02443e2 100644
--- a/Flow.Launcher/Converters/HighlightTextConverter.cs
+++ b/Flow.Launcher/Converters/HighlightTextConverter.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;
@@ -12,30 +11,27 @@ namespace Flow.Launcher.Converters
{
public object Convert(object[] value, Type targetType, object parameter, CultureInfo cultureInfo)
{
- var text = value[0] as string;
- var highlightData = value[1] as List;
-
- var textBlock = new Span();
-
- if (highlightData == null || !highlightData.Any())
- {
+ if (value.Length < 2)
+ return new Run(string.Empty);
+
+ if (value[0] is not string text)
+ return new Run(string.Empty);
+
+ if (value[1] is not List { Count: > 0 } highlightData)
// No highlight data, just return the text
return new Run(text);
- }
+
+ var highlightStyle = (Style)Application.Current.FindResource("HighlightStyle");
+ var textBlock = new Span();
for (var i = 0; i < text.Length; i++)
{
var currentCharacter = text.Substring(i, 1);
- if (this.ShouldHighlight(highlightData, i))
+ var run = new Run(currentCharacter)
{
-
- textBlock.Inlines.Add(new Run(currentCharacter) { Style = (Style)Application.Current.FindResource("HighlightStyle") });
-
- }
- else
- {
- textBlock.Inlines.Add(new Run(currentCharacter));
- }
+ Style = ShouldHighlight(highlightData, i) ? highlightStyle : null
+ };
+ textBlock.Inlines.Add(run);
}
return textBlock;
}
diff --git a/Flow.Launcher/Converters/IconRadiusConverter.cs b/Flow.Launcher/Converters/IconRadiusConverter.cs
index c73bef8b2..d0bdc9d1c 100644
--- a/Flow.Launcher/Converters/IconRadiusConverter.cs
+++ b/Flow.Launcher/Converters/IconRadiusConverter.cs
@@ -8,15 +8,10 @@ namespace Flow.Launcher.Converters
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
- if (values.Length != 2)
- throw new ArgumentException("IconRadiusConverter must have 2 parameters");
+ if (values is not [double size, bool isIconCircular])
+ throw new ArgumentException("IconRadiusConverter must have 2 parameters: [double, bool]");
- return values[1] switch
- {
- true => (double)values[0] / 2,
- false => (double)values[0],
- _ => throw new ArgumentException("The second argument should be boolean", nameof(values))
- };
+ return isIconCircular ? size / 2 : size;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
diff --git a/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs b/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs
index a44b07cab..7b7bd0906 100644
--- a/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs
+++ b/Flow.Launcher/Converters/OpenResultHotkeyVisibilityConverter.cs
@@ -22,6 +22,6 @@ namespace Flow.Launcher.Converters
return number <= MaxVisibleHotkeys ? Visibility.Visible : Visibility.Collapsed;
}
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new InvalidOperationException();
}
}
diff --git a/Flow.Launcher/Converters/OrdinalConverter.cs b/Flow.Launcher/Converters/OrdinalConverter.cs
index 02b9bdbde..438d4effa 100644
--- a/Flow.Launcher/Converters/OrdinalConverter.cs
+++ b/Flow.Launcher/Converters/OrdinalConverter.cs
@@ -1,3 +1,4 @@
+using System;
using System.Globalization;
using System.Windows.Controls;
using System.Windows.Data;
@@ -6,18 +7,19 @@ namespace Flow.Launcher.Converters
{
public class OrdinalConverter : IValueConverter
{
- public object Convert(object value, System.Type targetType, object parameter, CultureInfo culture)
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- if (value is ListBoxItem listBoxItem
- && ItemsControl.ItemsControlFromItemContainer(listBoxItem) is ListBox listBox)
+ if (value is not ListBoxItem listBoxItem
+ || ItemsControl.ItemsControlFromItemContainer(listBoxItem) is not ListBox listBox)
{
- var res = listBox.ItemContainerGenerator.IndexFromContainer(listBoxItem) + 1;
- return res == 10 ? 0 : res; // 10th item => HOTKEY+0
+ return 0;
}
- return 0;
+ var res = listBox.ItemContainerGenerator.IndexFromContainer(listBoxItem) + 1;
+ return res == 10 ? 0 : res; // 10th item => HOTKEY+0
+
}
- public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new InvalidOperationException();
}
}
diff --git a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs
index 1e39473e0..4a8c9e92b 100644
--- a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs
+++ b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs
@@ -12,32 +12,23 @@ namespace Flow.Launcher.Converters
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
- if (values.Length != 3)
- {
+ // values[0] is TextBox: The textbox displaying the autocomplete suggestion
+ // values[1] is ResultViewModel: Currently selected item in the list
+ // values[2] is string: Query text
+ if (
+ values.Length != 3 ||
+ values[0] is not TextBox queryTextBox ||
+ values[1] is null ||
+ values[2] is not string queryText ||
+ string.IsNullOrEmpty(queryText)
+ )
return string.Empty;
- }
- var QueryTextBox = values[0] as TextBox;
-
- var queryText = (string)values[2];
-
- if (string.IsNullOrEmpty(queryText))
- return string.Empty;
-
- // second prop is the current selected item result
- var val = values[1];
- if (val == null)
- {
- return string.Empty;
- }
- if (!(val is ResultViewModel))
- {
- return System.Windows.Data.Binding.DoNothing;
- }
+
+ if (values[1] is not ResultViewModel selectedItem)
+ return Binding.DoNothing;
try
{
- var selectedItem = (ResultViewModel)val;
-
var selectedResult = selectedItem.Result;
var selectedResultActionKeyword = string.IsNullOrEmpty(selectedResult.ActionKeywordAssigned) ? "" : selectedResult.ActionKeywordAssigned + " ";
var selectedResultPossibleSuggestion = selectedResultActionKeyword + selectedResult.Title;
@@ -50,17 +41,15 @@ namespace Flow.Launcher.Converters
// When user typed lower case and result title is uppercase, we still want to display suggestion
selectedItem.QuerySuggestionText = queryText + selectedResultPossibleSuggestion.Substring(queryText.Length);
- // Check if Text will be larger then our QueryTextBox
- System.Windows.Media.Typeface typeface = new Typeface(QueryTextBox.FontFamily, QueryTextBox.FontStyle, QueryTextBox.FontWeight, QueryTextBox.FontStretch);
+ // Check if Text will be larger than our QueryTextBox
+ Typeface typeface = new Typeface(queryTextBox.FontFamily, queryTextBox.FontStyle, queryTextBox.FontWeight, queryTextBox.FontStretch);
// TODO: Obsolete warning?
- System.Windows.Media.FormattedText ft = new FormattedText(QueryTextBox.Text, System.Globalization.CultureInfo.DefaultThreadCurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, QueryTextBox.FontSize, Brushes.Black);
+ var ft = new FormattedText(queryTextBox.Text, CultureInfo.DefaultThreadCurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, queryTextBox.FontSize, Brushes.Black);
- var offset = QueryTextBox.Padding.Right;
+ var offset = queryTextBox.Padding.Right;
- if ((ft.Width + offset) > QueryTextBox.ActualWidth || QueryTextBox.HorizontalOffset != 0)
- {
+ if (ft.Width + offset > queryTextBox.ActualWidth || queryTextBox.HorizontalOffset != 0)
return string.Empty;
- };
return selectedItem.QuerySuggestionText;
}
diff --git a/Flow.Launcher/Converters/StringToKeyBindingConverter.cs b/Flow.Launcher/Converters/StringToKeyBindingConverter.cs
index 3675f06fc..22526bd82 100644
--- a/Flow.Launcher/Converters/StringToKeyBindingConverter.cs
+++ b/Flow.Launcher/Converters/StringToKeyBindingConverter.cs
@@ -9,19 +9,17 @@ namespace Flow.Launcher.Converters
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- var mode = parameter as string;
- var hotkeyStr = value as string;
+ if (parameter is not string mode || value is not string hotkeyStr)
+ return null;
+
var converter = new KeyGestureConverter();
var key = (KeyGesture)converter.ConvertFromString(hotkeyStr);
- if (mode == "key")
+ return mode switch
{
- return key.Key;
- }
- else if (mode == "modifiers")
- {
- return key.Modifiers;
- }
- return null;
+ "key" => key?.Key,
+ "modifiers" => key?.Modifiers,
+ _ => null
+ };
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
diff --git a/Flow.Launcher/Converters/TextConverter.cs b/Flow.Launcher/Converters/TextConverter.cs
index 90d445776..c0b34d053 100644
--- a/Flow.Launcher/Converters/TextConverter.cs
+++ b/Flow.Launcher/Converters/TextConverter.cs
@@ -10,23 +10,22 @@ namespace Flow.Launcher.Converters
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
- var ID = value.ToString();
- switch(ID)
+ var id = value?.ToString();
+ var translationKey = id switch
{
- case PluginStoreItemViewModel.NewRelease:
- return InternationalizationManager.Instance.GetTranslation("pluginStore_NewRelease");
- case PluginStoreItemViewModel.RecentlyUpdated:
- return InternationalizationManager.Instance.GetTranslation("pluginStore_RecentlyUpdated");
- case PluginStoreItemViewModel.None:
- return InternationalizationManager.Instance.GetTranslation("pluginStore_None");
- case PluginStoreItemViewModel.Installed:
- return InternationalizationManager.Instance.GetTranslation("pluginStore_Installed");
- default:
- return ID;
- }
+ PluginStoreItemViewModel.NewRelease => "pluginStore_NewRelease",
+ PluginStoreItemViewModel.RecentlyUpdated => "pluginStore_RecentlyUpdated",
+ PluginStoreItemViewModel.None => "pluginStore_None",
+ PluginStoreItemViewModel.Installed => "pluginStore_Installed",
+ _ => null
+ };
+ if (translationKey is null)
+ return id;
+
+ return InternationalizationManager.Instance.GetTranslation(translationKey);
}
- public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException();
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new InvalidOperationException();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs
index 1e4f3f9ac..8ce597b30 100644
--- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs
+++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs
@@ -33,20 +33,32 @@ namespace Flow.Launcher.Plugin.BrowserBookmark
protected List LoadBookmarksFromFile(string path, string source)
{
- if (!File.Exists(path))
- return new List();
-
var bookmarks = new List();
+
+ if (!File.Exists(path))
+ return bookmarks;
+
using var jsonDocument = JsonDocument.Parse(File.ReadAllText(path));
if (!jsonDocument.RootElement.TryGetProperty("roots", out var rootElement))
- return new List();
+ return bookmarks;
+ EnumerateRoot(rootElement, bookmarks, source);
+ return bookmarks;
+ }
+
+ private void EnumerateRoot(JsonElement rootElement, ICollection bookmarks, string source)
+ {
foreach (var folder in rootElement.EnumerateObject())
{
- if (folder.Value.ValueKind == JsonValueKind.Object)
+ if (folder.Value.ValueKind != JsonValueKind.Object)
+ continue;
+
+ // Fix for Opera. It stores bookmarks slightly different than chrome. See PR and bug report for this change for details.
+ // If various exceptions start to build up here consider splitting this Loader into multiple separate ones.
+ if (folder.Name == "custom_root")
+ EnumerateRoot(folder.Value, bookmarks, source);
+ else
EnumerateFolderBookmark(folder.Value, bookmarks, source);
}
-
- return bookmarks;
}
private void EnumerateFolderBookmark(JsonElement folderElement, ICollection bookmarks,