mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
feat(avalonia): add Avalonia settings views for 8 plugins
- Add i18n injection to Application.Resources for DynamicResource bindings - Create Avalonia settings views for plugins: - Explorer (ExplorerSettings + QuickAccessLinkSettings dialog) - BrowserBookmark (SettingsControl + CustomBrowserSettingWindow) - Calculator (CalculatorSettings) - ProcessKiller (SettingsControl) - PluginsManager (PluginsManagerSettings) - WebSearch (SettingsControl) - Shell (ShellSetting + converter) - Program (ProgramSetting) - Add IsAvalonia detection pattern for dual-framework dialog support - Update 11 plugin .csproj files with CopyToAvaloniaOutput targets - Add System.Threading.Tasks using for async RelayCommand support
This commit is contained in:
parent
0c2f026d01
commit
c0d17672af
41 changed files with 1810 additions and 29 deletions
|
|
@ -36,6 +36,10 @@ public partial class App : Application
|
|||
ConfigureDI();
|
||||
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
// Inject translations into Application.Resources for DynamicResource bindings in plugins
|
||||
var i18n = Ioc.Default.GetRequiredService<Internationalization>();
|
||||
i18n.InjectIntoApplicationResources();
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
|
|
|
|||
|
|
@ -201,6 +201,37 @@ public class Internationalization
|
|||
Log.Debug(ClassName, $"Parsed {count} strings from {filePath}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inject all translations into Avalonia's Application.Resources so {DynamicResource} works.
|
||||
/// This enables plugin settings to use {DynamicResource key} for localization.
|
||||
/// Must be called after Application is initialized.
|
||||
/// </summary>
|
||||
public void InjectIntoApplicationResources()
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app == null)
|
||||
{
|
||||
Log.Warn(ClassName, "Cannot inject resources: Application.Current is null");
|
||||
return;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (var kvp in _translations)
|
||||
{
|
||||
app.Resources[kvp.Key] = kvp.Value;
|
||||
count++;
|
||||
}
|
||||
|
||||
Log.Info(ClassName, $"Injected {count} translations into Application.Resources");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(ClassName, "Failed to inject translations into Application.Resources", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a translated string by key.
|
||||
/// </summary>
|
||||
|
|
@ -208,12 +239,10 @@ public class Internationalization
|
|||
{
|
||||
if (_translations.TryGetValue(key, out var translation))
|
||||
{
|
||||
Log.Debug(ClassName, $"Translation found for '{key}': '{translation}'");
|
||||
return translation;
|
||||
}
|
||||
|
||||
Log.Warn(ClassName, $"Translation not found for key: {key}");
|
||||
Log.Debug(ClassName, $"Available keys (first 20): {string.Join(", ", _translations.Keys.Take(20))}");
|
||||
return $"[{key}]";
|
||||
}
|
||||
|
||||
|
|
@ -260,6 +289,10 @@ public class Internationalization
|
|||
}
|
||||
|
||||
ChangeCultureInfo(languageCode);
|
||||
|
||||
// Re-inject into Application.Resources for DynamicResource bindings
|
||||
InjectIntoApplicationResources();
|
||||
|
||||
Log.Info(ClassName, $"Language changed to: {languageCode}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -108,6 +108,19 @@
|
|||
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.0" />
|
||||
<PackageReference Include="Svg.Skia" Version="3.2.1" />
|
||||
<PackageReference Include="SkiaSharp" Version="3.119.1" />
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -10,6 +10,7 @@ using Flow.Launcher.Plugin.BrowserBookmark.Commands;
|
|||
using Flow.Launcher.Plugin.BrowserBookmark.Models;
|
||||
using Flow.Launcher.Plugin.BrowserBookmark.Views;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
|
||||
namespace Flow.Launcher.Plugin.BrowserBookmark;
|
||||
|
||||
|
|
@ -225,6 +226,11 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex
|
|||
return new SettingsControl(_settings);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Views.Avalonia.SettingsControl(_settings);
|
||||
}
|
||||
|
||||
public List<Result> LoadContextMenus(Result selectedResult)
|
||||
{
|
||||
return new List<Result>()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:Flow.Launcher.Plugin.BrowserBookmark.Models"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="400"
|
||||
x:Class="Flow.Launcher.Plugin.BrowserBookmark.Views.Avalonia.CustomBrowserSettingWindow"
|
||||
Title="{DynamicResource flowlauncher_plugin_browserbookmark_bookmarkDataSetting}"
|
||||
Width="550" SizeToContent="Height" CanResize="False"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="*,Auto" Margin="20">
|
||||
<StackPanel Grid.Row="0" Spacing="15">
|
||||
<TextBlock Text="{DynamicResource flowlauncher_plugin_browserbookmark_bookmarkDataSetting}"
|
||||
FontSize="20" FontWeight="SemiBold" />
|
||||
|
||||
<TextBlock Text="{DynamicResource flowlauncher_plugin_browserbookmark_guideMessage01}" TextWrapping="Wrap" />
|
||||
<TextBlock Text="{DynamicResource flowlauncher_plugin_browserbookmark_guideMessage02}" TextWrapping="Wrap" />
|
||||
<TextBlock Text="{DynamicResource flowlauncher_plugin_browserbookmark_guideMessage03}" TextWrapping="Wrap" />
|
||||
|
||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto,Auto" Margin="0,10,0,0">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="{DynamicResource flowlauncher_plugin_browserbookmark_browserName}" VerticalAlignment="Center" Margin="0,0,10,10"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Name}" Margin="0,0,0,10"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="{DynamicResource flowlauncher_plugin_browserbookmark_browserEngine}" VerticalAlignment="Center" Margin="0,0,10,10"/>
|
||||
<ComboBox Grid.Row="1" Grid.Column="1"
|
||||
ItemsSource="{Binding AllBrowserTypes}"
|
||||
SelectedValue="{Binding BrowserType}"
|
||||
SelectedValueBinding="{Binding Value}"
|
||||
DisplayMemberBinding="{Binding Display}"
|
||||
HorizontalAlignment="Stretch" Margin="0,0,0,10"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="{DynamicResource flowlauncher_plugin_browserbookmark_browserBookmarkDataDirectory}" VerticalAlignment="Center" Margin="0,0,10,0"/>
|
||||
<Grid Grid.Row="2" Grid.Column="1" ColumnDefinitions="*,Auto">
|
||||
<TextBox Grid.Column="0" Text="{Binding DataDirectoryPath}" Margin="0,0,5,0"/>
|
||||
<Button Grid.Column="1" Content="{DynamicResource flowlauncher_plugin_browserbookmark_browseBrowserBookmark}" Click="OnBrowseClick"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10" Margin="0,20,0,0">
|
||||
<Button Content="{DynamicResource cancel}" Click="OnCancelClick"/>
|
||||
<Button Content="{DynamicResource done}" Click="OnDoneClick" Classes="accent"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Flow.Launcher.Plugin.BrowserBookmark.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Flow.Launcher.Plugin.BrowserBookmark.Views.Avalonia;
|
||||
|
||||
public partial class CustomBrowserSettingWindow : Window
|
||||
{
|
||||
public CustomBrowserSettingWindow(CustomBrowser browser)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = browser;
|
||||
}
|
||||
|
||||
public CustomBrowserSettingWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void OnCancelClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnDoneClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private async void OnBrowseClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null) return;
|
||||
|
||||
var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||
{
|
||||
Title = "Select Bookmark Data Directory",
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (folders.Count > 0)
|
||||
{
|
||||
if (DataContext is CustomBrowser browser)
|
||||
{
|
||||
browser.DataDirectoryPath = folders[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:local="using:Flow.Launcher.Plugin.BrowserBookmark.Views.Avalonia"
|
||||
xmlns:models="using:Flow.Launcher.Plugin.BrowserBookmark.Models"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
|
||||
x:Class="Flow.Launcher.Plugin.BrowserBookmark.Views.Avalonia.SettingsControl"
|
||||
x:DataType="local:SettingsViewModel">
|
||||
|
||||
<StackPanel Spacing="10" Margin="0,0,10,0">
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_browserbookmark_loadBrowserFrom}"
|
||||
IconSource="Globe"
|
||||
Description="Select which browsers to load bookmarks from"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="Chrome">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding LoadChromeBookmark}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem Content="Edge">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding LoadEdgeBookmark}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem Content="Firefox">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding LoadFirefoxBookmark}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_browserbookmark_others}"
|
||||
IconSource="Library"
|
||||
Description="Manage custom Chromium-based browsers">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem>
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<ListBox Grid.Row="0"
|
||||
ItemsSource="{Binding Settings.CustomChromiumBrowsers}"
|
||||
SelectedItem="{Binding SelectedCustomBrowser}"
|
||||
Height="200"
|
||||
Background="{DynamicResource CardBackgroundFillColorDefault}"
|
||||
BorderBrush="{DynamicResource ControlStrokeColorDefault}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:CustomBrowser">
|
||||
<Grid ColumnDefinitions="2*,*,3*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding Name}" VerticalAlignment="Center" Margin="10,5"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding BrowserType}" VerticalAlignment="Center" Margin="5" Foreground="{DynamicResource TextFillColorSecondaryBrush}"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding DataDirectoryPath}" VerticalAlignment="Center" Margin="5" Foreground="{DynamicResource TextFillColorSecondaryBrush}" TextTrimming="CharacterEllipsis"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" Spacing="10" Margin="0,10,0,0" HorizontalAlignment="Right">
|
||||
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_addBrowserBookmark}" Command="{Binding NewCustomBrowserCommand}" />
|
||||
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_editBrowserBookmark}" Command="{Binding EditCustomBrowserCommand}" />
|
||||
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_removeBrowserBookmark}" Command="{Binding DeleteCustomBrowserCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="Options" IconSource="Settings">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_browserbookmark_enable_favicons}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.EnableFavicons}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Flow.Launcher.Plugin.BrowserBookmark.Models;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Flow.Launcher.Plugin.BrowserBookmark.Views.Avalonia;
|
||||
|
||||
public partial class SettingsControl : UserControl
|
||||
{
|
||||
public SettingsControl(Settings settings)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new SettingsViewModel(settings, EditBrowser);
|
||||
}
|
||||
|
||||
public SettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private async Task EditBrowser(CustomBrowser browser)
|
||||
{
|
||||
var window = new CustomBrowserSettingWindow(browser);
|
||||
if (VisualRoot is Window parentWindow)
|
||||
{
|
||||
await window.ShowDialog(parentWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class SettingsViewModel : ObservableObject
|
||||
{
|
||||
private readonly Settings _settings;
|
||||
private readonly Func<CustomBrowser, Task> _editBrowserAction;
|
||||
|
||||
public SettingsViewModel(Settings settings, Func<CustomBrowser, Task> editBrowserAction)
|
||||
{
|
||||
_settings = settings;
|
||||
_editBrowserAction = editBrowserAction;
|
||||
}
|
||||
|
||||
public Settings Settings => _settings;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(EditCustomBrowserCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(DeleteCustomBrowserCommand))]
|
||||
private CustomBrowser _selectedCustomBrowser;
|
||||
|
||||
public bool LoadChromeBookmark
|
||||
{
|
||||
get => _settings.LoadChromeBookmark;
|
||||
set
|
||||
{
|
||||
if (_settings.LoadChromeBookmark != value)
|
||||
{
|
||||
_settings.LoadChromeBookmark = value;
|
||||
OnPropertyChanged();
|
||||
_ = Task.Run(() => Main.ReloadAllBookmarks());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool LoadFirefoxBookmark
|
||||
{
|
||||
get => _settings.LoadFirefoxBookmark;
|
||||
set
|
||||
{
|
||||
if (_settings.LoadFirefoxBookmark != value)
|
||||
{
|
||||
_settings.LoadFirefoxBookmark = value;
|
||||
OnPropertyChanged();
|
||||
_ = Task.Run(() => Main.ReloadAllBookmarks());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool LoadEdgeBookmark
|
||||
{
|
||||
get => _settings.LoadEdgeBookmark;
|
||||
set
|
||||
{
|
||||
if (_settings.LoadEdgeBookmark != value)
|
||||
{
|
||||
_settings.LoadEdgeBookmark = value;
|
||||
OnPropertyChanged();
|
||||
_ = Task.Run(() => Main.ReloadAllBookmarks());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task NewCustomBrowser()
|
||||
{
|
||||
var newBrowser = new CustomBrowser();
|
||||
await _editBrowserAction(newBrowser);
|
||||
|
||||
if (!string.IsNullOrEmpty(newBrowser.Name) && !string.IsNullOrEmpty(newBrowser.DataDirectoryPath))
|
||||
{
|
||||
_settings.CustomChromiumBrowsers.Add(newBrowser);
|
||||
_ = Task.Run(() => Main.ReloadAllBookmarks());
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanEditOrDelete))]
|
||||
private async Task EditCustomBrowser()
|
||||
{
|
||||
if (SelectedCustomBrowser is null) return;
|
||||
|
||||
await _editBrowserAction(SelectedCustomBrowser);
|
||||
_ = Task.Run(() => Main.ReloadAllBookmarks());
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanEditOrDelete))]
|
||||
private void DeleteCustomBrowser()
|
||||
{
|
||||
if (SelectedCustomBrowser is null) return;
|
||||
_settings.CustomChromiumBrowsers.Remove(SelectedCustomBrowser);
|
||||
_ = Task.Run(() => Main.ReloadAllBookmarks());
|
||||
}
|
||||
|
||||
private bool CanEditOrDelete() => SelectedCustomBrowser != null;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -65,6 +65,19 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.6" />
|
||||
<PackageReference Include="Mages" Version="3.0.0" />
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Controls;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
using Flow.Launcher.Plugin.Calculator.ViewModels;
|
||||
using Flow.Launcher.Plugin.Calculator.Views;
|
||||
using Mages.Core;
|
||||
|
|
@ -424,6 +425,11 @@ namespace Flow.Launcher.Plugin.Calculator
|
|||
return new CalculatorSettings(_settings);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Views.Avalonia.CalculatorSettings(_viewModel);
|
||||
}
|
||||
|
||||
public void OnCultureInfoChanged(CultureInfo newCulture)
|
||||
{
|
||||
DecimalSeparatorLocalized.UpdateLabels(_viewModel.AllDecimalSeparator);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:vm="using:Flow.Launcher.Plugin.Calculator.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Flow.Launcher.Plugin.Calculator.Views.Avalonia.CalculatorSettings"
|
||||
x:DataType="vm:SettingsViewModel">
|
||||
|
||||
<StackPanel Spacing="10" Margin="0,0,10,0">
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_calculator_plugin_name}"
|
||||
IconSource="Calculator"
|
||||
Description="{DynamicResource flowlauncher_plugin_calculator_plugin_description}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_calculator_output_decimal_separator}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding AllDecimalSeparator}"
|
||||
SelectedValue="{Binding SelectedDecimalSeparator, Mode=TwoWay}"
|
||||
DisplayMemberBinding="{Binding Display}"
|
||||
SelectedValueBinding="{Binding Value}"
|
||||
MinWidth="150" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_calculator_max_decimal_places}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding MaxDecimalPlacesRange}"
|
||||
SelectedItem="{Binding Settings.MaxDecimalPlaces}"
|
||||
MinWidth="150" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_calculator_show_error_message}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.ShowErrorMessage}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Flow.Launcher.Plugin.Calculator.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Calculator.Views.Avalonia;
|
||||
|
||||
public partial class CalculatorSettings : UserControl
|
||||
{
|
||||
public CalculatorSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public CalculatorSettings(SettingsViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -46,6 +46,8 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="Droplex" Version="1.7.0" />
|
||||
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.6" />
|
||||
|
|
@ -57,5 +59,16 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using Flow.Launcher.Plugin.Explorer.Helper;
|
||||
using Flow.Launcher.Plugin.Explorer.Helper;
|
||||
using Flow.Launcher.Plugin.Explorer.Search;
|
||||
using Flow.Launcher.Plugin.Explorer.Search.Everything;
|
||||
using Flow.Launcher.Plugin.Explorer.ViewModels;
|
||||
|
|
@ -12,6 +12,7 @@ using System.Windows.Controls;
|
|||
using Flow.Launcher.Plugin.Explorer.Exceptions;
|
||||
using System.Linq;
|
||||
using System.Globalization;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer
|
||||
{
|
||||
|
|
@ -34,6 +35,11 @@ namespace Flow.Launcher.Plugin.Explorer
|
|||
return new ExplorerSettings(viewModel);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Views.Avalonia.ExplorerSettings(viewModel);
|
||||
}
|
||||
|
||||
public Task InitAsync(PluginInitContext context)
|
||||
{
|
||||
Context = context;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#nullable enable
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -6,6 +6,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
|
@ -15,11 +16,18 @@ using Flow.Launcher.Plugin.Explorer.Search.Everything;
|
|||
using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions;
|
||||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||
using Flow.Launcher.Plugin.Explorer.Views;
|
||||
using AvaloniaApp = Avalonia.Application;
|
||||
using AvaloniaQuickAccessLinkSettings = Flow.Launcher.Plugin.Explorer.Views.Avalonia.QuickAccessLinkSettings;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||
{
|
||||
public partial class SettingsViewModel : BaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Detects if we're running in an Avalonia application context
|
||||
/// </summary>
|
||||
private static bool IsAvalonia => AvaloniaApp.Current != null;
|
||||
|
||||
public Settings Settings { get; set; }
|
||||
|
||||
internal PluginInitContext Context { get; set; }
|
||||
|
|
@ -394,7 +402,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void EditQuickAccessLink()
|
||||
private async Task EditQuickAccessLinkAsync()
|
||||
{
|
||||
var selectedLink = SelectedQuickAccessLink;
|
||||
var collection = Settings.QuickAccessLinks;
|
||||
|
|
@ -405,20 +413,50 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
return;
|
||||
}
|
||||
|
||||
var quickAccessLinkSettings = new QuickAccessLinkSettings(collection, SelectedQuickAccessLink);
|
||||
if (quickAccessLinkSettings.ShowDialog() == true)
|
||||
if (IsAvalonia)
|
||||
{
|
||||
Save();
|
||||
var dialog = new AvaloniaQuickAccessLinkSettings(collection, selectedLink);
|
||||
var mainWindow = AvaloniaApp.Current?.ApplicationLifetime is global::Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktop
|
||||
? desktop.MainWindow
|
||||
: null;
|
||||
var result = await dialog.ShowDialog<bool?>(mainWindow!);
|
||||
if (result == true)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var quickAccessLinkSettings = new QuickAccessLinkSettings(collection, SelectedQuickAccessLink);
|
||||
if (quickAccessLinkSettings.ShowDialog() == true)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void AddQuickAccessLink()
|
||||
private async Task AddQuickAccessLinkAsync()
|
||||
{
|
||||
var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings.QuickAccessLinks);
|
||||
if (quickAccessLinkSettings.ShowDialog() == true)
|
||||
if (IsAvalonia)
|
||||
{
|
||||
Save();
|
||||
var dialog = new AvaloniaQuickAccessLinkSettings(Settings.QuickAccessLinks);
|
||||
var mainWindow = AvaloniaApp.Current?.ApplicationLifetime is global::Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktop
|
||||
? desktop.MainWindow
|
||||
: null;
|
||||
var result = await dialog.ShowDialog<bool?>(mainWindow!);
|
||||
if (result == true)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings.QuickAccessLinks);
|
||||
if (quickAccessLinkSettings.ShowDialog() == true)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,320 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:vm="using:Flow.Launcher.Plugin.Explorer.ViewModels"
|
||||
xmlns:qa="using:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="1200"
|
||||
x:Class="Flow.Launcher.Plugin.Explorer.Views.Avalonia.ExplorerSettings"
|
||||
x:DataType="vm:SettingsViewModel">
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Spacing="10" Margin="10">
|
||||
|
||||
<!-- General Settings -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_generalsetting_header}"
|
||||
IconSource="Settings"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_use_location_as_working_dir}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.UseLocationAsWorkingDir}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_default_open_in_file_manager}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.DefaultOpenFolderInFileManager}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_display_more_info_in_tooltip}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.DisplayMoreInformationInToolTip}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_file_editor_path}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<TextBox Text="{Binding FileEditorPath}" Width="200" />
|
||||
<Button Content="{DynamicResource select}" Click="BtnOpenFileEditorPath_OnClick" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_folder_editor_path}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<TextBox Text="{Binding FolderEditorPath}" Width="200" />
|
||||
<Button Content="{DynamicResource select}" Click="BtnOpenFolderEditorPath_OnClick" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_shell_path}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<TextBox Text="{Binding ShellPath}" Width="200" />
|
||||
<Button Content="{DynamicResource select}" Click="BtnOpenShellPath_OnClick" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_Index_Search_Engine}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding IndexSearchEngines}"
|
||||
SelectedItem="{Binding SelectedIndexSearchEngine}"
|
||||
DisplayMemberBinding="{Binding Description}"
|
||||
MinWidth="150"/>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_Content_Search_Engine}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding ContentIndexSearchEngines}"
|
||||
SelectedItem="{Binding SelectedContentSearchEngine}"
|
||||
DisplayMemberBinding="{Binding Description}"
|
||||
MinWidth="150"/>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_Directory_Recursive_Search_Engine}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding PathEnumerationEngines}"
|
||||
SelectedItem="{Binding SelectedPathEnumerationEngine}"
|
||||
DisplayMemberBinding="{Binding Description}"
|
||||
MinWidth="150"/>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_Excluded_File_Types}"
|
||||
Description="{DynamicResource plugin_explorer_Excluded_File_Types_Tooltip}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<TextBox Text="{Binding ExcludedFileTypes}" Width="200" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_Maximum_Results}"
|
||||
Description="{DynamicResource plugin_explorer_Maximum_Results_Tooltip}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<TextBox Text="{Binding MaxResult}" Width="100" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem>
|
||||
<Button Content="{DynamicResource plugin_explorer_Open_Window_Index_Option}"
|
||||
Click="btnOpenIndexingOptions_Click" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<!-- Native Context Menu -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_native_context_menu_header}"
|
||||
IconSource="Menu"
|
||||
IsExpanded="False">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_native_context_menu_display_context_menu}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding ShowWindowsContextMenu}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_native_context_menu_include_patterns_guide}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<TextBox Text="{Binding WindowsContextMenuIncludedItems}"
|
||||
AcceptsReturn="True"
|
||||
Height="100"
|
||||
Width="300"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_native_context_menu_exclude_patterns_guide}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<TextBox Text="{Binding WindowsContextMenuExcludedItems}"
|
||||
AcceptsReturn="True"
|
||||
Height="100"
|
||||
Width="300"
|
||||
TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<!-- Preview Panel -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_previewpanel_setting_header}"
|
||||
IconSource="PreviewLink"
|
||||
IsExpanded="False">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_previewpanel_file_info_label}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<CheckBox Content="{DynamicResource plugin_explorer_previewpanel_display_file_size_checkbox}"
|
||||
IsChecked="{Binding ShowFileSizeInPreviewPanel}" />
|
||||
<CheckBox Content="{DynamicResource plugin_explorer_previewpanel_display_file_creation_checkbox}"
|
||||
IsChecked="{Binding ShowCreatedDateInPreviewPanel}" />
|
||||
<CheckBox Content="{DynamicResource plugin_explorer_previewpanel_display_file_modification_checkbox}"
|
||||
IsChecked="{Binding ShowModifiedDateInPreviewPanel}" />
|
||||
<CheckBox Content="{DynamicResource plugin_explorer_previewpanel_display_file_age_checkbox}"
|
||||
IsChecked="{Binding ShowFileAgeInPreviewPanel}" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_previewpanel_date_and_time_format_label}"
|
||||
IsVisible="{Binding ShowPreviewPanelDateTimeChoices}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<StackPanel Spacing="5">
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<ComboBox ItemsSource="{Binding DateFormatList}"
|
||||
SelectedItem="{Binding PreviewPanelDateFormat}"
|
||||
MinWidth="150"/>
|
||||
<TextBlock Text="{Binding PreviewPanelDateFormatDemo}" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<ComboBox ItemsSource="{Binding TimeFormatList}"
|
||||
SelectedItem="{Binding PreviewPanelTimeFormat}"
|
||||
MinWidth="150"/>
|
||||
<TextBlock Text="{Binding PreviewPanelTimeFormatDemo}" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<!-- Everything Settings -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_everything_setting_header}"
|
||||
IconSource="Find"
|
||||
IsExpanded="False">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_everything_search_fullpath}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.EverythingSearchFullPath}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_everything_enable_run_count}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.EverythingEnableRunCount}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_everything_sort_option}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding AllEverythingSortOptions}"
|
||||
SelectedValue="{Binding SelectedEverythingSortOption}"
|
||||
SelectedValueBinding="{Binding Value}"
|
||||
DisplayMemberBinding="{Binding Display}"
|
||||
MinWidth="150"/>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_explorer_everything_installed_path}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<TextBox Text="{Binding EverythingInstalledPath}" Width="200" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem IsVisible="{Binding FastSortWarningVisibility}">
|
||||
<TextBlock Text="{Binding SortOptionWarningMessage}" Foreground="Orange" TextWrapping="Wrap" />
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<!-- Manage Action Keywords -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_manageactionkeywords_header}"
|
||||
IconSource="Keyboard"
|
||||
IsExpanded="False">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem>
|
||||
<StackPanel Spacing="10">
|
||||
<ListBox ItemsSource="{Binding ActionKeywordsModels}"
|
||||
SelectedItem="{Binding SelectedActionKeyword}"
|
||||
Height="150">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid ColumnDefinitions="*,*,*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding LocalizedDescription}" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding Keyword}" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding Enabled}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<Button Content="{DynamicResource plugin_explorer_edit}"
|
||||
Command="{Binding EditActionKeywordCommand}"
|
||||
HorizontalAlignment="Right"/>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<!-- Quick Access Links -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_quickaccesslinks_header}"
|
||||
IconSource="Star"
|
||||
IsExpanded="False">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem>
|
||||
<StackPanel Spacing="10">
|
||||
<ListBox ItemsSource="{Binding Settings.QuickAccessLinks}"
|
||||
SelectedItem="{Binding SelectedQuickAccessLink}"
|
||||
Height="200">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="qa:AccessLink">
|
||||
<Grid ColumnDefinitions="*,2*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding Name}" FontWeight="Bold" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding Path}" TextTrimming="CharacterEllipsis" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
|
||||
<Button Content="{DynamicResource plugin_explorer_delete}"
|
||||
Command="{Binding RemoveLinkCommand}"
|
||||
CommandParameter="QuickAccessLink"/>
|
||||
<Button Content="{DynamicResource plugin_explorer_edit}"
|
||||
Command="{Binding EditQuickAccessLinkCommand}"/>
|
||||
<Button Content="{DynamicResource plugin_explorer_add}"
|
||||
Command="{Binding AddQuickAccessLinkCommand}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<!-- Index Search Excluded Paths -->
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_explorer_indexsearchexcludedpaths_header}"
|
||||
IconSource="Block"
|
||||
IsExpanded="False">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem>
|
||||
<StackPanel Spacing="10">
|
||||
<ListBox ItemsSource="{Binding Settings.IndexSearchExcludedSubdirectoryPaths}"
|
||||
SelectedItem="{Binding SelectedIndexSearchExcludedPath}"
|
||||
Height="200">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="qa:AccessLink">
|
||||
<TextBlock Text="{Binding Path}" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
|
||||
<Button Content="{DynamicResource plugin_explorer_delete}"
|
||||
Command="{Binding RemoveLinkCommand}"
|
||||
CommandParameter="IndexSearchExcludedPaths"/>
|
||||
<Button Content="{DynamicResource plugin_explorer_edit}"
|
||||
Command="{Binding EditIndexSearchExcludePathsCommand}"/>
|
||||
<Button Content="{DynamicResource plugin_explorer_add}"
|
||||
Command="{Binding AddIndexSearchExcludePathsCommand}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#nullable enable
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Flow.Launcher.Plugin.Explorer.ViewModels;
|
||||
using System;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer.Views.Avalonia
|
||||
{
|
||||
public partial class ExplorerSettings : UserControl
|
||||
{
|
||||
public ExplorerSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ExplorerSettings(SettingsViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = viewModel;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void btnOpenIndexingOptions_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SettingsViewModel.OpenWindowsIndexingOptions();
|
||||
}
|
||||
|
||||
private async void BtnOpenFileEditorPath_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not SettingsViewModel vm) return;
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null) return;
|
||||
|
||||
var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (files.Count > 0)
|
||||
{
|
||||
vm.FileEditorPath = files[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
|
||||
private async void BtnOpenFolderEditorPath_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not SettingsViewModel vm) return;
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null) return;
|
||||
|
||||
var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||
{
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (folders.Count > 0)
|
||||
{
|
||||
vm.FolderEditorPath = folders[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
|
||||
private async void BtnOpenShellPath_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not SettingsViewModel vm) return;
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null) return;
|
||||
|
||||
var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (files.Count > 0)
|
||||
{
|
||||
vm.ShellPath = files[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
x:Class="Flow.Launcher.Plugin.Explorer.Views.Avalonia.QuickAccessLinkSettings"
|
||||
Title="{DynamicResource plugin_explorer_manage_quick_access_links_header}"
|
||||
Width="450"
|
||||
Height="280"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
CanResize="False"
|
||||
ShowInTaskbar="False">
|
||||
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
<!-- Main Content -->
|
||||
<StackPanel Grid.Row="0" Margin="24,20,24,10" Spacing="16">
|
||||
<!-- Header -->
|
||||
<TextBlock Text="{DynamicResource plugin_explorer_manage_quick_access_links_header}"
|
||||
FontSize="20"
|
||||
FontWeight="SemiBold" />
|
||||
|
||||
<!-- Form Fields -->
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto,Auto,Auto">
|
||||
<!-- Name -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{DynamicResource plugin_explorer_name}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,10,0" />
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Text="{Binding SelectedName, Mode=TwoWay}"
|
||||
Margin="0,0,0,10" />
|
||||
|
||||
<!-- Type -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
Text="{DynamicResource plugin_explorer_type}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,10,0" />
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
|
||||
Orientation="Horizontal" Spacing="20"
|
||||
Margin="0,0,0,10">
|
||||
<RadioButton Content="{DynamicResource plugin_explorer_file}"
|
||||
GroupName="PathType"
|
||||
IsChecked="{Binding IsFileSelected, Mode=TwoWay}" />
|
||||
<RadioButton Content="{DynamicResource plugin_explorer_folder}"
|
||||
GroupName="PathType"
|
||||
IsChecked="{Binding IsFolderSelected, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Path -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
Text="{DynamicResource plugin_explorer_path}"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,10,0" />
|
||||
<TextBox Grid.Row="2" Grid.Column="1"
|
||||
Text="{Binding SelectedPath, Mode=TwoWay}"
|
||||
IsReadOnly="True"
|
||||
Margin="0,0,10,0" />
|
||||
<Button Grid.Row="2" Grid.Column="2"
|
||||
Content="{DynamicResource select}"
|
||||
Click="SelectPath_OnClick"
|
||||
MinWidth="80" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Button Area -->
|
||||
<Border Grid.Row="1"
|
||||
Background="{DynamicResource SystemControlBackgroundChromeMediumLowBrush}"
|
||||
BorderThickness="0,1,0,0"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseMediumLowBrush}"
|
||||
Padding="24,16">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="10">
|
||||
<Button Content="{DynamicResource cancel}"
|
||||
Click="BtnCancel_OnClick"
|
||||
Width="120"
|
||||
HorizontalContentAlignment="Center" />
|
||||
<Button Content="{DynamicResource done}"
|
||||
Click="OnDoneButtonClick"
|
||||
Width="120"
|
||||
HorizontalContentAlignment="Center"
|
||||
Classes="accent" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Flow.Launcher.Plugin.Explorer.Helper;
|
||||
using Flow.Launcher.Plugin.Explorer.Search;
|
||||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer.Views.Avalonia;
|
||||
|
||||
public partial class QuickAccessLinkSettings : Window, INotifyPropertyChanged
|
||||
{
|
||||
private static readonly string ClassName = nameof(QuickAccessLinkSettings);
|
||||
|
||||
private string _selectedPath = string.Empty;
|
||||
public string SelectedPath
|
||||
{
|
||||
get => _selectedPath;
|
||||
set
|
||||
{
|
||||
if (_selectedPath != value)
|
||||
{
|
||||
_selectedPath = value;
|
||||
OnPropertyChanged();
|
||||
if (string.IsNullOrEmpty(_selectedName))
|
||||
{
|
||||
SelectedName = _selectedPath.GetPathName();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(_selectedPath))
|
||||
{
|
||||
_accessLinkType = GetResultType(_selectedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _selectedName = string.Empty;
|
||||
public string SelectedName
|
||||
{
|
||||
get => string.IsNullOrEmpty(_selectedName) ? _selectedPath.GetPathName() : _selectedName;
|
||||
set
|
||||
{
|
||||
if (_selectedName != value)
|
||||
{
|
||||
_selectedName = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isFileSelected;
|
||||
public bool IsFileSelected
|
||||
{
|
||||
get => _isFileSelected;
|
||||
set
|
||||
{
|
||||
if (_isFileSelected != value)
|
||||
{
|
||||
_isFileSelected = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isFolderSelected = true;
|
||||
public bool IsFolderSelected
|
||||
{
|
||||
get => _isFolderSelected;
|
||||
set
|
||||
{
|
||||
if (_isFolderSelected != value)
|
||||
{
|
||||
_isFolderSelected = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsEdit { get; }
|
||||
private AccessLink? SelectedAccessLink { get; }
|
||||
public ObservableCollection<AccessLink> QuickAccessLinks { get; }
|
||||
private ResultType _accessLinkType = ResultType.Folder;
|
||||
|
||||
public QuickAccessLinkSettings()
|
||||
{
|
||||
QuickAccessLinks = new ObservableCollection<AccessLink>();
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
public QuickAccessLinkSettings(ObservableCollection<AccessLink> quickAccessLinks)
|
||||
{
|
||||
IsEdit = false;
|
||||
QuickAccessLinks = quickAccessLinks;
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
public QuickAccessLinkSettings(ObservableCollection<AccessLink> quickAccessLinks, AccessLink selectedAccessLink)
|
||||
{
|
||||
IsEdit = true;
|
||||
_selectedName = selectedAccessLink.Name;
|
||||
_selectedPath = selectedAccessLink.Path;
|
||||
_accessLinkType = GetResultType(_selectedPath);
|
||||
_isFileSelected = selectedAccessLink.Type == ResultType.File;
|
||||
_isFolderSelected = !_isFileSelected;
|
||||
SelectedAccessLink = selectedAccessLink;
|
||||
QuickAccessLinks = quickAccessLinks;
|
||||
InitializeComponent();
|
||||
DataContext = this;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void BtnCancel_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
Close(false);
|
||||
}
|
||||
|
||||
private void OnDoneButtonClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
// Validate the input before proceeding
|
||||
if (string.IsNullOrEmpty(SelectedName) || string.IsNullOrEmpty(SelectedPath))
|
||||
{
|
||||
var warning = Localize.plugin_explorer_quick_access_link_no_folder_selected();
|
||||
Main.Context.API.ShowMsgBox(warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the path already exists in the quick access links (when not editing)
|
||||
if (!IsEdit && QuickAccessLinks.Any(x =>
|
||||
x.Path.Equals(SelectedPath, StringComparison.OrdinalIgnoreCase) &&
|
||||
x.Name.Equals(SelectedName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var warning = Localize.plugin_explorer_quick_access_link_path_already_exists();
|
||||
Main.Context.API.ShowMsgBox(warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// If editing, update the existing link
|
||||
if (IsEdit && SelectedAccessLink != null)
|
||||
{
|
||||
var index = QuickAccessLinks.IndexOf(SelectedAccessLink);
|
||||
if (index >= 0)
|
||||
{
|
||||
var updatedLink = new AccessLink
|
||||
{
|
||||
Name = SelectedName,
|
||||
Type = _accessLinkType,
|
||||
Path = SelectedPath
|
||||
};
|
||||
QuickAccessLinks[index] = updatedLink;
|
||||
}
|
||||
Close(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add a new one
|
||||
var newAccessLink = new AccessLink
|
||||
{
|
||||
Name = SelectedName,
|
||||
Type = _accessLinkType,
|
||||
Path = SelectedPath
|
||||
};
|
||||
QuickAccessLinks.Add(newAccessLink);
|
||||
Close(true);
|
||||
}
|
||||
}
|
||||
|
||||
private async void SelectPath_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null) return;
|
||||
|
||||
if (IsFileSelected)
|
||||
{
|
||||
var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (files.Count > 0)
|
||||
{
|
||||
SelectedPath = files[0].Path.LocalPath;
|
||||
_accessLinkType = ResultType.File;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
||||
{
|
||||
AllowMultiple = false
|
||||
});
|
||||
|
||||
if (folders.Count > 0)
|
||||
{
|
||||
SelectedPath = folders[0].Path.LocalPath;
|
||||
_accessLinkType = GetResultType(SelectedPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ResultType GetResultType(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return ResultType.File;
|
||||
}
|
||||
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
if (string.Equals(Path.GetPathRoot(path), path, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ResultType.Volume;
|
||||
}
|
||||
return ResultType.Folder;
|
||||
}
|
||||
|
||||
Main.Context.API.LogError(ClassName, $"The path '{path}' does not exist or is invalid. Defaulting to Folder type.");
|
||||
return ResultType.Folder;
|
||||
}
|
||||
|
||||
public new event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -60,4 +60,15 @@
|
|||
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
|
|
@ -38,5 +38,18 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using Flow.Launcher.Plugin.PluginsManager.ViewModels;
|
||||
using Flow.Launcher.Plugin.PluginsManager.Views;
|
||||
using Flow.Launcher.Plugin.PluginsManager.Views.Avalonia;
|
||||
|
||||
namespace Flow.Launcher.Plugin.PluginsManager
|
||||
{
|
||||
|
|
@ -22,7 +24,12 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
|||
|
||||
public Control CreateSettingPanel()
|
||||
{
|
||||
return new PluginsManagerSettings(viewModel);
|
||||
return new Views.PluginsManagerSettings(viewModel);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Views.Avalonia.PluginsManagerSettings(viewModel);
|
||||
}
|
||||
|
||||
public async Task InitAsync(PluginInitContext context)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:vm="using:Flow.Launcher.Plugin.PluginsManager.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Flow.Launcher.Plugin.PluginsManager.Views.Avalonia.PluginsManagerSettings"
|
||||
x:DataType="vm:SettingsViewModel">
|
||||
<StackPanel Spacing="10" Margin="0,0,10,0">
|
||||
<ui:SettingsExpander Header="{DynamicResource plugin_pluginsmanager_plugin_name}"
|
||||
IconSource="Settings"
|
||||
Description="{DynamicResource plugin_pluginsmanager_plugin_description}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_pluginsmanager_plugin_settings_unknown_source}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding WarnFromUnknownSource}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource plugin_pluginsmanager_plugin_settings_auto_restart}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding AutoRestartAfterChanging}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Flow.Launcher.Plugin.PluginsManager.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.PluginsManager.Views.Avalonia;
|
||||
|
||||
public partial class PluginsManagerSettings : UserControl
|
||||
{
|
||||
public PluginsManagerSettings()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
internal PluginsManagerSettings(SettingsViewModel viewModel)
|
||||
{
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -16,6 +16,11 @@
|
|||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>portable</DebugType>
|
||||
|
|
@ -64,4 +69,15 @@
|
|||
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using Flow.Launcher.Plugin.ProcessKiller.ViewModels;
|
||||
using Flow.Launcher.Plugin.ProcessKiller.Views;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
|
||||
namespace Flow.Launcher.Plugin.ProcessKiller
|
||||
{
|
||||
|
|
@ -217,5 +218,11 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
{
|
||||
return new SettingsControl(_viewModel);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Views.Avalonia.SettingsControl(_viewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:vm="using:Flow.Launcher.Plugin.ProcessKiller.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Flow.Launcher.Plugin.ProcessKiller.Views.Avalonia.SettingsControl"
|
||||
x:DataType="vm:SettingsViewModel">
|
||||
<StackPanel Spacing="10" Margin="0,0,10,0">
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_processkiller_plugin_name}"
|
||||
IconSource="Settings"
|
||||
Description="{DynamicResource flowlauncher_plugin_processkiller_plugin_description}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_processkiller_show_window_title}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.ShowWindowTitle}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_processkiller_put_visible_window_process_top}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.PutVisibleWindowProcessesTop}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Flow.Launcher.Plugin.ProcessKiller.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.ProcessKiller.Views.Avalonia;
|
||||
|
||||
public partial class SettingsControl : UserControl
|
||||
{
|
||||
public SettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public SettingsControl(SettingsViewModel viewModel)
|
||||
{
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -75,4 +75,15 @@
|
|||
<PackageReference Include="NLog" Version="6.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Shell.Converters.Avalonia
|
||||
{
|
||||
public class LeaveShellOpenOrCloseShellAfterPressEnabledConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values == null || values.Count != 2)
|
||||
return false;
|
||||
|
||||
if (values[0] is not bool closeShellAfterPressOrLeaveShellOpen ||
|
||||
values[1] is not Shell shell)
|
||||
return false;
|
||||
|
||||
return (!closeShellAfterPressOrLeaveShellOpen) && shell != Shell.RunCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -61,6 +61,19 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.6" />
|
||||
<PackageReference Include="InputSimulator" Version="1.0.4" NoWarn="NU1701" />
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -10,6 +10,7 @@ using Flow.Launcher.Plugin.Shell.Views;
|
|||
using WindowsInput;
|
||||
using WindowsInput.Native;
|
||||
using Control = System.Windows.Controls.Control;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
using Keys = System.Windows.Forms.Keys;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Shell
|
||||
|
|
@ -434,6 +435,11 @@ namespace Flow.Launcher.Plugin.Shell
|
|||
return new CMDSetting(_settings);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Flow.Launcher.Plugin.Shell.Views.Avalonia.ShellSetting(_settings);
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
{
|
||||
return Localize.flowlauncher_plugin_cmd_plugin_name();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:vm="using:Flow.Launcher.Plugin.Shell.ViewModels"
|
||||
xmlns:converters="using:Flow.Launcher.Plugin.Shell.Converters.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
|
||||
x:Class="Flow.Launcher.Plugin.Shell.Views.Avalonia.ShellSetting"
|
||||
x:DataType="vm:ShellSettingViewModel">
|
||||
|
||||
<UserControl.Resources>
|
||||
<converters:LeaveShellOpenOrCloseShellAfterPressEnabledConverter x:Key="LeaveShellOpenOrCloseShellAfterPressEnabledConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<StackPanel Spacing="10" Margin="0,0,10,0">
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_cmd_plugin_name}"
|
||||
IconSource="Code"
|
||||
Description="{DynamicResource flowlauncher_plugin_cmd_plugin_description}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_cmd_relace_winr}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.ReplaceWinR}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_cmd_always_run_as_administrator}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.RunAsAdministrator}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_cmd_use_windows_terminal}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.UseWindowsTerminal}" OnContent="" OffContent="" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="Shell">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ComboBox ItemsSource="{Binding AllShells}"
|
||||
SelectedValue="{Binding SelectedShell}"
|
||||
DisplayMemberBinding="{Binding Display}"
|
||||
SelectedValueBinding="{Binding Value}"
|
||||
MinWidth="150" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_cmd_close_cmd_after_press}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding CloseShellAfterPress}" OnContent="" OffContent="">
|
||||
<ToggleSwitch.IsEnabled>
|
||||
<MultiBinding Converter="{StaticResource LeaveShellOpenOrCloseShellAfterPressEnabledConverter}">
|
||||
<Binding Path="LeaveShellOpen" />
|
||||
<Binding Path="SelectedShell" />
|
||||
</MultiBinding>
|
||||
</ToggleSwitch.IsEnabled>
|
||||
</ToggleSwitch>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_cmd_leave_cmd_open}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch IsChecked="{Binding LeaveShellOpen}" OnContent="" OffContent="">
|
||||
<ToggleSwitch.IsEnabled>
|
||||
<MultiBinding Converter="{StaticResource LeaveShellOpenOrCloseShellAfterPressEnabledConverter}">
|
||||
<Binding Path="CloseShellAfterPress" />
|
||||
<Binding Path="SelectedShell" />
|
||||
</MultiBinding>
|
||||
</ToggleSwitch.IsEnabled>
|
||||
</ToggleSwitch>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem Content="{DynamicResource flowlauncher_plugin_cmd_history}">
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<ComboBox ItemsSource="{Binding OnlyMostUsedCMDsNumbers}"
|
||||
SelectedItem="{Binding SelectedOnlyMostUsedCMDsNumber}"
|
||||
IsEnabled="{Binding Settings.ShowOnlyMostUsedCMDs}"
|
||||
MinWidth="60" />
|
||||
<ToggleSwitch IsChecked="{Binding Settings.ShowOnlyMostUsedCMDs}" OnContent="" OffContent="" />
|
||||
</StackPanel>
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Flow.Launcher.Plugin.Shell.ViewModels;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Shell.Views.Avalonia
|
||||
{
|
||||
public partial class ShellSetting : UserControl
|
||||
{
|
||||
public ShellSetting()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ShellSetting(Settings settings)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new ShellSettingViewModel(settings);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -65,4 +65,16 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -61,4 +61,15 @@
|
|||
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
|
|
@ -54,4 +54,20 @@
|
|||
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.3" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -6,6 +6,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
using AvaloniaControl = Avalonia.Controls.Control;
|
||||
|
||||
namespace Flow.Launcher.Plugin.WebSearch
|
||||
{
|
||||
|
|
@ -193,6 +194,11 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
return new SettingsControl(_context, _viewModel);
|
||||
}
|
||||
|
||||
public AvaloniaControl CreateSettingPanelAvalonia()
|
||||
{
|
||||
return new Views.Avalonia.SettingsControl(_context, _viewModel);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:vm="using:Flow.Launcher.Plugin.WebSearch"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
|
||||
x:Class="Flow.Launcher.Plugin.WebSearch.Views.Avalonia.SettingsControl"
|
||||
x:DataType="vm:SettingsViewModel">
|
||||
|
||||
<StackPanel Spacing="10" Margin="0,0,10,0">
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_websearch_plugin_name}"
|
||||
IconSource="Globe"
|
||||
Description="{DynamicResource flowlauncher_plugin_websearch_plugin_description}"
|
||||
IsExpanded="True">
|
||||
<ui:SettingsExpander.Items>
|
||||
<ui:SettingsExpanderItem>
|
||||
<Grid RowDefinitions="*,Auto" MinHeight="300">
|
||||
<ListBox Grid.Row="0"
|
||||
ItemsSource="{Binding Settings.SearchSources}"
|
||||
SelectedItem="{Binding Settings.SelectedSearchSource}"
|
||||
Background="{DynamicResource CardBackgroundFillColorDefault}"
|
||||
BorderBrush="{DynamicResource ControlStrokeColorDefault}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Margin="0,0,0,10">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SearchSource">
|
||||
<Grid ColumnDefinitions="Auto,120,*,80,80" Margin="0,5">
|
||||
<Image Grid.Column="0" Width="20" Height="20" Source="{Binding IconPath}" Margin="0,0,10,0"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding ActionKeyword}" VerticalAlignment="Center" FontWeight="SemiBold"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding Title}" VerticalAlignment="Center"/>
|
||||
<CheckBox Grid.Column="3" IsChecked="{Binding Enabled}" IsEnabled="False" HorizontalAlignment="Center"/>
|
||||
<CheckBox Grid.Column="4" IsChecked="{Binding IsPrivateMode}" IsEnabled="False" HorizontalAlignment="Center"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right">
|
||||
<Button Content="{DynamicResource flowlauncher_plugin_websearch_add}" Click="OnAddSearchSourceClick"/>
|
||||
<Button Content="{DynamicResource flowlauncher_plugin_websearch_edit}" Click="OnEditSearchSourceClick"/>
|
||||
<Button Content="{DynamicResource flowlauncher_plugin_websearch_delete}" Click="OnDeleteSearchSourceClick"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ui:SettingsExpanderItem>
|
||||
</ui:SettingsExpander.Items>
|
||||
</ui:SettingsExpander>
|
||||
|
||||
<ui:SettingsExpander Header="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion_provider}"
|
||||
IconSource="Lightbulb"
|
||||
Description="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion}">
|
||||
<ui:SettingsExpander.Footer>
|
||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||
<ComboBox ItemsSource="{Binding Settings.Suggestions}"
|
||||
SelectedItem="{Binding Settings.SelectedSuggestion}"
|
||||
IsEnabled="{Binding Settings.EnableSuggestion}"
|
||||
MinWidth="150"/>
|
||||
<ToggleSwitch IsChecked="{Binding Settings.EnableSuggestion}"
|
||||
OnContent="" OffContent=""/>
|
||||
</StackPanel>
|
||||
</ui:SettingsExpander.Footer>
|
||||
</ui:SettingsExpander>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using System;
|
||||
|
||||
namespace Flow.Launcher.Plugin.WebSearch.Views.Avalonia
|
||||
{
|
||||
public partial class SettingsControl : UserControl
|
||||
{
|
||||
private readonly PluginInitContext _context;
|
||||
private readonly SettingsViewModel _viewModel;
|
||||
|
||||
public SettingsControl(PluginInitContext context, SettingsViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
_context = context;
|
||||
_viewModel = viewModel;
|
||||
DataContext = viewModel;
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private async void OnAddSearchSourceClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new ContentDialog
|
||||
{
|
||||
Title = "Add Search Source",
|
||||
Content = "Adding search sources is not yet implemented in the Avalonia version.",
|
||||
CloseButtonText = "OK"
|
||||
};
|
||||
|
||||
if (VisualRoot is TopLevel topLevel)
|
||||
{
|
||||
await dialog.ShowAsync(topLevel);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnEditSearchSourceClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new ContentDialog
|
||||
{
|
||||
Title = "Edit Search Source",
|
||||
Content = "Editing search sources is not yet implemented in the Avalonia version.",
|
||||
CloseButtonText = "OK"
|
||||
};
|
||||
|
||||
if (VisualRoot is TopLevel topLevel)
|
||||
{
|
||||
await dialog.ShowAsync(topLevel);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnDeleteSearchSourceClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_viewModel.Settings.SelectedSearchSource != null)
|
||||
{
|
||||
var selected = _viewModel.Settings.SelectedSearchSource;
|
||||
var warning = _context.API.GetTranslation("flowlauncher_plugin_websearch_delete_warning");
|
||||
var formatted = string.Format(warning, selected.Title);
|
||||
|
||||
var dialog = new ContentDialog
|
||||
{
|
||||
Title = "Delete Search Source",
|
||||
Content = formatted,
|
||||
PrimaryButtonText = "Yes",
|
||||
CloseButtonText = "No"
|
||||
};
|
||||
|
||||
if (VisualRoot is TopLevel topLevel)
|
||||
{
|
||||
var result = await dialog.ShowAsync(topLevel);
|
||||
|
||||
if (result == ContentDialogResult.Primary)
|
||||
{
|
||||
var id = _context.CurrentPluginMetadata.ID;
|
||||
_context.API.RemoveActionKeyword(id, selected.ActionKeyword);
|
||||
_viewModel.Settings.SearchSources.Remove(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
|
|
@ -69,4 +69,15 @@
|
|||
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy plugin output to Avalonia build directory -->
|
||||
<Target Name="CopyToAvaloniaOutput" AfterTargets="Build">
|
||||
<PropertyGroup>
|
||||
<AvaloniaPluginDir>..\..\Output\$(Configuration)\Avalonia\Plugins\$(AssemblyName)\</AvaloniaPluginDir>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PluginFiles Include="$(OutputPath)**\*.*" />
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(PluginFiles)" DestinationFolder="$(AvaloniaPluginDir)%(RecursiveDir)" SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
Loading…
Reference in a new issue