diff --git a/Flow.Launcher.Avalonia/ViewModel/SettingPages/PluginsSettingsViewModel.cs b/Flow.Launcher.Avalonia/ViewModel/SettingPages/PluginsSettingsViewModel.cs
index 08028a938..14a96cc83 100644
--- a/Flow.Launcher.Avalonia/ViewModel/SettingPages/PluginsSettingsViewModel.cs
+++ b/Flow.Launcher.Avalonia/ViewModel/SettingPages/PluginsSettingsViewModel.cs
@@ -7,7 +7,7 @@ using Flow.Launcher.Avalonia.Views.Controls;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-using System.Windows.Controls;
+using AvaloniaControl = Avalonia.Controls.Control;
namespace Flow.Launcher.Avalonia.ViewModel.SettingPages;
@@ -68,16 +68,47 @@ public partial class PluginItemViewModel : ObservableObject
HasSettings = true;
}
}
+
+ if (HasSettings && _settingProvider != null)
+ {
+ try
+ {
+ System.Console.WriteLine($"Checking Avalonia settings for {Name}");
+ AvaloniaSettingControl = _settingProvider.CreateSettingPanelAvalonia();
+ HasNativeAvaloniaSettings = AvaloniaSettingControl != null;
+ System.Console.WriteLine($"Avalonia settings for {Name}: {HasNativeAvaloniaSettings}");
+ }
+ catch (System.Exception ex)
+ {
+ System.Console.WriteLine($"Failed to create Avalonia settings for {Name}: {ex}");
+ Flow.Launcher.Infrastructure.Logger.Log.Exception(nameof(PluginItemViewModel), $"Failed to create Avalonia settings for {Name}", ex);
+ }
+ }
}
[ObservableProperty]
private bool _hasSettings;
+ [ObservableProperty]
+ private bool _hasNativeAvaloniaSettings;
+
+ [ObservableProperty]
+ private AvaloniaControl? _avaloniaSettingControl;
+
+ [ObservableProperty]
+ private bool _isExpanded;
+
[RelayCommand]
private void OpenSettings()
{
if (_settingProvider == null) return;
+ if (HasNativeAvaloniaSettings)
+ {
+ IsExpanded = !IsExpanded;
+ return;
+ }
+
try
{
// Create the WPF settings panel on demand
diff --git a/Flow.Launcher.Avalonia/Views/SettingPages/PluginsSettingsPage.axaml b/Flow.Launcher.Avalonia/Views/SettingPages/PluginsSettingsPage.axaml
index 181c1d4e4..6f0e2beec 100644
--- a/Flow.Launcher.Avalonia/Views/SettingPages/PluginsSettingsPage.axaml
+++ b/Flow.Launcher.Avalonia/Views/SettingPages/PluginsSettingsPage.axaml
@@ -17,37 +17,50 @@
Watermark="{i18n:Localize search}"
Margin="0,0,0,20" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
diff --git a/Flow.Launcher.Core/packages.lock.json b/Flow.Launcher.Core/packages.lock.json
index b499a5860..763ac07c2 100644
--- a/Flow.Launcher.Core/packages.lock.json
+++ b/Flow.Launcher.Core/packages.lock.json
@@ -61,6 +61,26 @@
"System.IO.Pipelines": "8.0.0"
}
},
+ "Avalonia": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "pD6woFAUfGcyEvMmrpctntU4jv4fT8752pfx1J5iRORVX3Ob0oQi8PWo0TXVaAJZiSfH0cdKTeKx0w0DzD0/mg==",
+ "dependencies": {
+ "Avalonia.BuildServices": "0.0.29",
+ "Avalonia.Remote.Protocol": "11.2.3",
+ "MicroCom.Runtime": "0.11.0"
+ }
+ },
+ "Avalonia.BuildServices": {
+ "type": "Transitive",
+ "resolved": "0.0.29",
+ "contentHash": "U4eJLQdoDNHXtEba7MZUCwrBErBTxFp6sUewXBOdAhU0Kwzwaa/EKFcYm8kpcysjzKtfB4S0S9n0uxKZFz/ikw=="
+ },
+ "Avalonia.Remote.Protocol": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "6V0aNtld48WmO8tAlWwlRlUmXYcOWv+1eJUSl1ETF+1blUe5yhcSmuWarPprO0hDk8Ta6wGfdfcrnVl2gITYcA=="
+ },
"Ben.Demystifier": {
"type": "Transitive",
"resolved": "0.4.1",
@@ -127,6 +147,11 @@
"resolved": "2.5.192",
"contentHash": "jaJuwcgovWIZ8Zysdyf3b7b34/BrADw4v82GaEZymUhDd3ScMPrYd/cttekeDteJJPXseJxp04yTIcxiVUjTWg=="
},
+ "MicroCom.Runtime": {
+ "type": "Transitive",
+ "resolved": "0.11.0",
+ "contentHash": "MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA=="
+ },
"Microsoft.NET.StringTools": {
"type": "Transitive",
"resolved": "17.6.3",
@@ -1161,7 +1186,7 @@
"Ben.Demystifier": "[0.4.1, )",
"BitFaster.Caching": "[2.5.4, )",
"CommunityToolkit.Mvvm": "[8.4.0, )",
- "Flow.Launcher.Plugin": "[5.0.0, )",
+ "Flow.Launcher.Plugin": "[5.1.0, )",
"InputSimulator": "[1.0.4, )",
"MemoryPack": "[1.21.4, )",
"Microsoft.VisualStudio.Threading": "[17.14.15, )",
@@ -1176,6 +1201,7 @@
"flow.launcher.plugin": {
"type": "Project",
"dependencies": {
+ "Avalonia": "[11.2.3, )",
"JetBrains.Annotations": "[2025.2.2, )"
}
}
diff --git a/Flow.Launcher.Infrastructure/packages.lock.json b/Flow.Launcher.Infrastructure/packages.lock.json
index 47c94d5f6..469d48ae3 100644
--- a/Flow.Launcher.Infrastructure/packages.lock.json
+++ b/Flow.Launcher.Infrastructure/packages.lock.json
@@ -121,6 +121,26 @@
"resolved": "3.1.0.3",
"contentHash": "VKcf8sUq/+LyY99WgLhOu7Q32ROEyR30/2xCCj9ADRi45wVC7kpXrYCf9vH1qirkmrIfpL8inoxAbrqAlfXxsQ=="
},
+ "Avalonia": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "pD6woFAUfGcyEvMmrpctntU4jv4fT8752pfx1J5iRORVX3Ob0oQi8PWo0TXVaAJZiSfH0cdKTeKx0w0DzD0/mg==",
+ "dependencies": {
+ "Avalonia.BuildServices": "0.0.29",
+ "Avalonia.Remote.Protocol": "11.2.3",
+ "MicroCom.Runtime": "0.11.0"
+ }
+ },
+ "Avalonia.BuildServices": {
+ "type": "Transitive",
+ "resolved": "0.0.29",
+ "contentHash": "U4eJLQdoDNHXtEba7MZUCwrBErBTxFp6sUewXBOdAhU0Kwzwaa/EKFcYm8kpcysjzKtfB4S0S9n0uxKZFz/ikw=="
+ },
+ "Avalonia.Remote.Protocol": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "6V0aNtld48WmO8tAlWwlRlUmXYcOWv+1eJUSl1ETF+1blUe5yhcSmuWarPprO0hDk8Ta6wGfdfcrnVl2gITYcA=="
+ },
"JetBrains.Annotations": {
"type": "Transitive",
"resolved": "2025.2.2",
@@ -136,6 +156,11 @@
"resolved": "1.21.4",
"contentHash": "g14EsSS85yn0lHTi0J9ivqlZMf09A2iI51fmI+0KkzIzyCbWOBWPi5mdaY7YWmXprk12aYh9u/qfWHQUYthlwg=="
},
+ "MicroCom.Runtime": {
+ "type": "Transitive",
+ "resolved": "0.11.0",
+ "contentHash": "MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA=="
+ },
"Microsoft.VisualStudio.Threading.Analyzers": {
"type": "Transitive",
"resolved": "17.14.15",
@@ -190,6 +215,7 @@
"flow.launcher.plugin": {
"type": "Project",
"dependencies": {
+ "Avalonia": "[11.2.3, )",
"JetBrains.Annotations": "[2025.2.2, )"
}
}
diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
index 649d59ad7..25135e649 100644
--- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
+++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj
@@ -1,4 +1,4 @@
-
+
net9.0-windows
@@ -68,6 +68,7 @@
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher.Plugin/Interfaces/ISettingProvider.cs b/Flow.Launcher.Plugin/Interfaces/ISettingProvider.cs
index f034243c3..5cab51c71 100644
--- a/Flow.Launcher.Plugin/Interfaces/ISettingProvider.cs
+++ b/Flow.Launcher.Plugin/Interfaces/ISettingProvider.cs
@@ -1,4 +1,5 @@
-using System.Windows.Controls;
+using System.Windows.Controls;
+using AvaloniaControl = Avalonia.Controls.Control;
namespace Flow.Launcher.Plugin
{
@@ -12,5 +13,12 @@ namespace Flow.Launcher.Plugin
///
///
Control CreateSettingPanel();
+
+ ///
+ /// Create settings panel control for Avalonia version
+ ///
+ ///
+ virtual AvaloniaControl CreateSettingPanelAvalonia() => null;
}
}
+
diff --git a/Flow.Launcher.Plugin/packages.lock.json b/Flow.Launcher.Plugin/packages.lock.json
index 70f71f20d..8e93f0fca 100644
--- a/Flow.Launcher.Plugin/packages.lock.json
+++ b/Flow.Launcher.Plugin/packages.lock.json
@@ -2,6 +2,17 @@
"version": 1,
"dependencies": {
"net9.0-windows7.0": {
+ "Avalonia": {
+ "type": "Direct",
+ "requested": "[11.2.3, )",
+ "resolved": "11.2.3",
+ "contentHash": "pD6woFAUfGcyEvMmrpctntU4jv4fT8752pfx1J5iRORVX3Ob0oQi8PWo0TXVaAJZiSfH0cdKTeKx0w0DzD0/mg==",
+ "dependencies": {
+ "Avalonia.BuildServices": "0.0.29",
+ "Avalonia.Remote.Protocol": "11.2.3",
+ "MicroCom.Runtime": "0.11.0"
+ }
+ },
"Fody": {
"type": "Direct",
"requested": "[6.9.3, )",
@@ -44,6 +55,21 @@
"Fody": "6.6.4"
}
},
+ "Avalonia.BuildServices": {
+ "type": "Transitive",
+ "resolved": "0.0.29",
+ "contentHash": "U4eJLQdoDNHXtEba7MZUCwrBErBTxFp6sUewXBOdAhU0Kwzwaa/EKFcYm8kpcysjzKtfB4S0S9n0uxKZFz/ikw=="
+ },
+ "Avalonia.Remote.Protocol": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "6V0aNtld48WmO8tAlWwlRlUmXYcOWv+1eJUSl1ETF+1blUe5yhcSmuWarPprO0hDk8Ta6wGfdfcrnVl2gITYcA=="
+ },
+ "MicroCom.Runtime": {
+ "type": "Transitive",
+ "resolved": "0.11.0",
+ "contentHash": "MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA=="
+ },
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "8.0.0",
diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json
index 2c685ea09..be2e9a195 100644
--- a/Flow.Launcher/packages.lock.json
+++ b/Flow.Launcher/packages.lock.json
@@ -163,6 +163,26 @@
"resolved": "6.3.0.90",
"contentHash": "WVTb5MxwGqKdeasd3nG5udlV4t6OpvkFanziwI133K0/QJ5FvZmfzRQgpAjGTJhQfIA8GP7AzKQ3sTY9JOFk8Q=="
},
+ "Avalonia": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "pD6woFAUfGcyEvMmrpctntU4jv4fT8752pfx1J5iRORVX3Ob0oQi8PWo0TXVaAJZiSfH0cdKTeKx0w0DzD0/mg==",
+ "dependencies": {
+ "Avalonia.BuildServices": "0.0.29",
+ "Avalonia.Remote.Protocol": "11.2.3",
+ "MicroCom.Runtime": "0.11.0"
+ }
+ },
+ "Avalonia.BuildServices": {
+ "type": "Transitive",
+ "resolved": "0.0.29",
+ "contentHash": "U4eJLQdoDNHXtEba7MZUCwrBErBTxFp6sUewXBOdAhU0Kwzwaa/EKFcYm8kpcysjzKtfB4S0S9n0uxKZFz/ikw=="
+ },
+ "Avalonia.Remote.Protocol": {
+ "type": "Transitive",
+ "resolved": "11.2.3",
+ "contentHash": "6V0aNtld48WmO8tAlWwlRlUmXYcOWv+1eJUSl1ETF+1blUe5yhcSmuWarPprO0hDk8Ta6wGfdfcrnVl2gITYcA=="
+ },
"Ben.Demystifier": {
"type": "Transitive",
"resolved": "0.4.1",
@@ -252,6 +272,11 @@
"resolved": "3.4.5",
"contentHash": "R/d2VSdbRQHDWfPf5sjvMOWrWvxh/CswdMDKODppHTjsDLIkLQbQrnjmtAaVqu0qgUf8KFlVzEfxy3GIVoCK9g=="
},
+ "MicroCom.Runtime": {
+ "type": "Transitive",
+ "resolved": "0.11.0",
+ "contentHash": "MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA=="
+ },
"Microsoft.Extensions.Configuration": {
"type": "Transitive",
"resolved": "9.0.9",
@@ -1599,7 +1624,7 @@
"Droplex": "[1.7.0, )",
"FSharp.Core": "[9.0.303, )",
"Flow.Launcher.Infrastructure": "[1.0.0, )",
- "Flow.Launcher.Plugin": "[5.0.0, )",
+ "Flow.Launcher.Plugin": "[5.1.0, )",
"Meziantou.Framework.Win32.Jobs": "[3.4.5, )",
"Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )",
"SemanticVersioning": "[3.0.0, )",
@@ -1613,7 +1638,7 @@
"Ben.Demystifier": "[0.4.1, )",
"BitFaster.Caching": "[2.5.4, )",
"CommunityToolkit.Mvvm": "[8.4.0, )",
- "Flow.Launcher.Plugin": "[5.0.0, )",
+ "Flow.Launcher.Plugin": "[5.1.0, )",
"InputSimulator": "[1.0.4, )",
"MemoryPack": "[1.21.4, )",
"Microsoft.VisualStudio.Threading": "[17.14.15, )",
@@ -1628,6 +1653,7 @@
"flow.launcher.plugin": {
"type": "Project",
"dependencies": {
+ "Avalonia": "[11.2.3, )",
"JetBrains.Annotations": "[2025.2.2, )"
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
index e9515fab4..6fb36fa1a 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
+++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj
@@ -1,4 +1,4 @@
-
+
Library
@@ -62,6 +62,9 @@
+
+
+
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 456085fca..9fa969237 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -12,11 +12,13 @@ using Flow.Launcher.Plugin.Program.Views.Models;
using Flow.Launcher.Plugin.SharedCommands;
using Microsoft.Extensions.Caching.Memory;
using Path = System.IO.Path;
+using AvaloniaControl = Avalonia.Controls.Control;
namespace Flow.Launcher.Plugin.Program
{
public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, IAsyncReloadable, IDisposable
{
+
private static readonly string ClassName = nameof(Main);
private const string Win32CacheName = "Win32";
@@ -417,6 +419,14 @@ namespace Flow.Launcher.Plugin.Program
return new ProgramSetting(Context, _settings);
}
+ public AvaloniaControl CreateSettingPanelAvalonia()
+ {
+ System.Console.WriteLine("Program plugin: CreateSettingPanelAvalonia called!");
+ Context.API.LogInfo(ClassName, "Creating Avalonia setting panel");
+ return new Views.Avalonia.ProgramSetting(Context, _settings);
+ }
+
+
public string GetTranslatedPluginTitle()
{
return Context.API.GetTranslation("flowlauncher_plugin_program_plugin_name");
diff --git a/Plugins/Flow.Launcher.Plugin.Program/ViewModels/ProgramSettingViewModel.cs b/Plugins/Flow.Launcher.Plugin.Program/ViewModels/ProgramSettingViewModel.cs
new file mode 100644
index 000000000..78197447d
--- /dev/null
+++ b/Plugins/Flow.Launcher.Plugin.Program/ViewModels/ProgramSettingViewModel.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Flow.Launcher.Plugin.Program.Views.Models;
+using Flow.Launcher.Plugin.Program.Views.Commands;
+using Flow.Launcher.Plugin.Program.Programs;
+using System.IO;
+using System.Windows;
+using Flow.Launcher.Plugin.Program.Views;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+using System.Globalization;
+
+namespace Flow.Launcher.Plugin.Program.ViewModels;
+
+public partial class ProgramSettingViewModel : ObservableObject
+{
+ public static IValueConverter EnabledToColorConverter { get; } = new FuncValueConverter(enabled =>
+ enabled ? Brushes.Green : Brushes.Red);
+
+ public static IValueConverter IsNotNullConverter { get; } = new FuncValueConverter