mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into 250412-ImportThemePreset
This commit is contained in:
commit
9981fab885
31 changed files with 158 additions and 163 deletions
|
|
@ -171,8 +171,8 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
catch (System.Exception e2)
|
||||
{
|
||||
Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e);
|
||||
Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2);
|
||||
Log.Exception(ClassName, $"Failed to get thumbnail for {path} on first try", e);
|
||||
Log.Exception(ClassName, $"Failed to get thumbnail for {path} on second try", e2);
|
||||
|
||||
ImageSource image = ImageCache[Constant.MissingImgIcon, false];
|
||||
ImageCache[path, false] = image;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ using Windows.Win32.Graphics.Gdi;
|
|||
namespace Flow.Launcher.Infrastructure.Image
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclass of <see cref="Windows.Win32.UI.Shell.SIIGBF"/>
|
||||
/// Subclass of <see cref="SIIGBF"/>
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ThumbnailOptions
|
||||
|
|
@ -31,7 +31,9 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
|
||||
private static readonly Guid GUID_IShellItem = typeof(IShellItem).GUID;
|
||||
|
||||
private static readonly HRESULT S_ExtractionFailed = (HRESULT)0x8004B200;
|
||||
private static readonly HRESULT S_EXTRACTIONFAILED = (HRESULT)0x8004B200;
|
||||
|
||||
private static readonly HRESULT S_PATHNOTFOUND = (HRESULT)0x8004B205;
|
||||
|
||||
public static BitmapSource GetThumbnail(string fileName, int width, int height, ThumbnailOptions options)
|
||||
{
|
||||
|
|
@ -79,9 +81,10 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
imageFactory.GetImage(size, (SIIGBF)options, &hBitmap);
|
||||
}
|
||||
catch (COMException ex) when (ex.HResult == S_ExtractionFailed && options == ThumbnailOptions.ThumbnailOnly)
|
||||
catch (COMException ex) when (options == ThumbnailOptions.ThumbnailOnly &&
|
||||
(ex.HResult == S_PATHNOTFOUND || ex.HResult == S_EXTRACTIONFAILED))
|
||||
{
|
||||
// Fallback to IconOnly if ThumbnailOnly fails
|
||||
// Fallback to IconOnly if extraction fails or files cannot be found
|
||||
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
|
||||
}
|
||||
catch (FileNotFoundException) when (options == ThumbnailOptions.ThumbnailOnly)
|
||||
|
|
@ -89,6 +92,11 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
// Fallback to IconOnly if files cannot be found
|
||||
imageFactory.GetImage(size, (SIIGBF)ThumbnailOptions.IconOnly, &hBitmap);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
// Handle other exceptions
|
||||
throw new InvalidOperationException("Failed to get thumbnail", ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -365,21 +365,10 @@ namespace Flow.Launcher.Infrastructure
|
|||
// No installed English layout found
|
||||
if (enHKL == HKL.Null) return;
|
||||
|
||||
// When application is exiting, the Application.Current will be null
|
||||
if (Application.Current == null) return;
|
||||
|
||||
// Get the FL main window
|
||||
var hwnd = GetWindowHandle(Application.Current.MainWindow, true);
|
||||
// Get the foreground window
|
||||
var hwnd = PInvoke.GetForegroundWindow();
|
||||
if (hwnd == HWND.Null) return;
|
||||
|
||||
// Check if the FL main window is the current foreground window
|
||||
if (!IsForegroundWindow(hwnd))
|
||||
{
|
||||
var result = PInvoke.SetForegroundWindow(hwnd);
|
||||
// If we cannot set the foreground window, we can use the foreground window and switch the layout
|
||||
if (!result) hwnd = PInvoke.GetForegroundWindow();
|
||||
}
|
||||
|
||||
// Get the current foreground window thread ID
|
||||
var threadId = PInvoke.GetWindowThreadProcessId(hwnd);
|
||||
if (threadId == 0) throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
|
|
|
|||
|
|
@ -128,12 +128,12 @@ namespace Flow.Launcher.Plugin
|
|||
/// <summary>
|
||||
/// Delegate to load an icon for this result.
|
||||
/// </summary>
|
||||
public IconDelegate Icon { get; set; }
|
||||
public IconDelegate Icon = null;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to load an icon for the badge of this result.
|
||||
/// </summary>
|
||||
public IconDelegate BadgeIcon { get; set; }
|
||||
public IconDelegate BadgeIcon = null;
|
||||
|
||||
/// <summary>
|
||||
/// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
#nullable enable
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
|
@ -9,6 +7,8 @@ using Flow.Launcher.Helper;
|
|||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
public partial class HotkeyControl
|
||||
|
|
@ -242,7 +242,11 @@ namespace Flow.Launcher
|
|||
HotKeyMapper.RemoveHotkey(Hotkey);
|
||||
}
|
||||
|
||||
var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle);
|
||||
var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle)
|
||||
{
|
||||
Owner = Window.GetWindow(this)
|
||||
};
|
||||
|
||||
await dialog.ShowAsync();
|
||||
switch (dialog.ResultType)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ namespace Flow.Launcher
|
|||
Close();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
public async void Show(string title, string subTitle, string iconPath)
|
||||
{
|
||||
tbTitle.Text = title;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ namespace Flow.Launcher
|
|||
{
|
||||
internal partial class ReportWindow
|
||||
{
|
||||
private static readonly string ClassName = nameof(ReportWindow);
|
||||
|
||||
public ReportWindow(Exception exception)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Windows.Controls;
|
|||
using System.Windows;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Flow.Launcher.Core.Plugin;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using Flow.Launcher.ViewModel;
|
||||
|
|
@ -112,10 +111,11 @@ public partial class SettingsPanePluginsViewModel : BaseModel
|
|||
.ToList();
|
||||
|
||||
[RelayCommand]
|
||||
private async Task OpenHelperAsync()
|
||||
private async Task OpenHelperAsync(Button button)
|
||||
{
|
||||
var helpDialog = new ContentDialog()
|
||||
{
|
||||
Owner = Window.GetWindow(button),
|
||||
Content = new StackPanel
|
||||
{
|
||||
Children =
|
||||
|
|
@ -146,7 +146,6 @@ public partial class SettingsPanePluginsViewModel : BaseModel
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
PrimaryButtonText = (string)Application.Current.Resources["commonOK"],
|
||||
CornerRadius = new CornerRadius(8),
|
||||
Style = (Style)Application.Current.Resources["ContentDialog"]
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
Height="34"
|
||||
Margin="0 0 20 0"
|
||||
Command="{Binding OpenHelperCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
|
||||
Content=""
|
||||
FontFamily="{DynamicResource SymbolThemeFontFamily}"
|
||||
FontSize="14" />
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using System.Windows.Navigation;
|
||||
using System.Windows.Navigation;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using Flow.Launcher.SettingPages.ViewModels;
|
||||
using Page = ModernWpf.Controls.Page;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Page = ModernWpf.Controls.Page;
|
||||
|
||||
namespace Flow.Launcher.SettingPages.Views;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
public class RelayCommand : ICommand
|
||||
{
|
||||
private readonly Action<object> _action;
|
||||
|
||||
public RelayCommand(Action<object> action)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public virtual bool CanExecute(object parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning disable CS0067 // the event is never used
|
||||
public event EventHandler CanExecuteChanged;
|
||||
#pragma warning restore CS0067
|
||||
|
||||
public virtual void Execute(object parameter)
|
||||
{
|
||||
_action?.Invoke(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<!-- Do not upgrade System.Data.OleDb since we are .Net7.0 -->
|
||||
<PackageReference Include="System.Data.OleDb" Version="8.0.1" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Drawing;
|
||||
|
|
@ -341,7 +341,7 @@ namespace Peter
|
|||
return null;
|
||||
}
|
||||
|
||||
IShellFolder oParentFolder = GetParentFolder(arrFI[0].Parent.FullName);
|
||||
IShellFolder oParentFolder = GetParentFolder(arrFI[0].Parent!.FullName);
|
||||
if (null == oParentFolder)
|
||||
{
|
||||
return null;
|
||||
|
|
@ -1535,7 +1535,7 @@ namespace Peter
|
|||
m_hookType,
|
||||
m_filterFunc,
|
||||
IntPtr.Zero,
|
||||
(int)AppDomain.GetCurrentThreadId());
|
||||
Environment.CurrentManagedThreadId);
|
||||
}
|
||||
// ************************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public static class SortOptionTranslationHelper
|
|||
ArgumentNullException.ThrowIfNull(API);
|
||||
|
||||
var enumName = Enum.GetName(sortOption);
|
||||
var splited = enumName.Split('_');
|
||||
var splited = enumName!.Split('_');
|
||||
var name = string.Join('_', splited[..^1]);
|
||||
var direction = splited[^1];
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
|
|||
|
||||
foreach (DictionaryEntry special in Environment.GetEnvironmentVariables())
|
||||
{
|
||||
var path = special.Value.ToString();
|
||||
var path = special.Value!.ToString();
|
||||
// we add a trailing slash to the path to make sure drive paths become valid absolute paths.
|
||||
// for example, if %systemdrive% is C: we turn it to C:\
|
||||
path = path.EnsureTrailingSlash();
|
||||
|
|
@ -61,7 +61,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
|
|||
{
|
||||
// Variables are returned with a mixture of all upper/lower case.
|
||||
// Call ToUpper() to make the results look consistent
|
||||
_envStringPaths.Add(special.Key.ToString().ToUpper(), path);
|
||||
_envStringPaths.Add(special.Key.ToString()!.ToUpper(), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer.Views
|
||||
{
|
||||
public class ActionKeywordModel : INotifyPropertyChanged
|
||||
{
|
||||
private static Settings _settings;
|
||||
private static Settings _settings = null!;
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
public static void Init(Settings settings)
|
||||
{
|
||||
|
|
@ -54,4 +56,4 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||
{
|
||||
internal class RelayCommand : ICommand
|
||||
{
|
||||
private Action<object> _action;
|
||||
|
||||
public RelayCommand(Action<object> action)
|
||||
{
|
||||
_action = action;
|
||||
}
|
||||
|
||||
public virtual bool CanExecute(object parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public virtual void Execute(object parameter)
|
||||
{
|
||||
_action?.Invoke(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,4 @@
|
|||
#nullable enable
|
||||
using Flow.Launcher.Plugin.Explorer.Search;
|
||||
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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
|
@ -13,11 +8,16 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Flow.Launcher.Plugin.Explorer.Search;
|
||||
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;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
||||
{
|
||||
public class SettingsViewModel : BaseModel
|
||||
public partial class SettingsViewModel : BaseModel
|
||||
{
|
||||
public Settings Settings { get; set; }
|
||||
|
||||
|
|
@ -36,7 +36,6 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
InitializeActionKeywordModels();
|
||||
}
|
||||
|
||||
|
||||
public void Save()
|
||||
{
|
||||
Context.API.SaveSettingJsonStorage<Settings>();
|
||||
|
|
@ -48,7 +47,6 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
private EnumBindingModel<Settings.ContentIndexSearchEngineOption> _selectedContentSearchEngine;
|
||||
private EnumBindingModel<Settings.PathEnumerationEngineOption> _selectedPathEnumerationEngine;
|
||||
|
||||
|
||||
public EnumBindingModel<Settings.IndexSearchEngineOption> SelectedIndexSearchEngine
|
||||
{
|
||||
get => _selectedIndexSearchEngine;
|
||||
|
|
@ -261,8 +259,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
|
||||
public ActionKeywordModel? SelectedActionKeyword { get; set; }
|
||||
|
||||
public ICommand EditActionKeywordCommand => new RelayCommand(EditActionKeyword);
|
||||
|
||||
[RelayCommand]
|
||||
private void EditActionKeyword(object obj)
|
||||
{
|
||||
if (SelectedActionKeyword is not { } actionKeyword)
|
||||
|
|
@ -307,12 +304,6 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
public AccessLink? SelectedQuickAccessLink { get; set; }
|
||||
public AccessLink? SelectedIndexSearchExcludedPath { get; set; }
|
||||
|
||||
|
||||
|
||||
public ICommand RemoveLinkCommand => new RelayCommand(RemoveLink);
|
||||
public ICommand EditLinkCommand => new RelayCommand(EditLink);
|
||||
public ICommand AddLinkCommand => new RelayCommand(AddLink);
|
||||
|
||||
public void AppendLink(string containerName, AccessLink link)
|
||||
{
|
||||
var container = containerName switch
|
||||
|
|
@ -324,6 +315,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
container.Add(link);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void EditLink(object commandParameter)
|
||||
{
|
||||
var (selectedLink, collection) = commandParameter switch
|
||||
|
|
@ -360,7 +352,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
Context.API.ShowMsgBox(warning);
|
||||
}
|
||||
|
||||
|
||||
[RelayCommand]
|
||||
private void AddLink(object commandParameter)
|
||||
{
|
||||
var container = commandParameter switch
|
||||
|
|
@ -385,6 +377,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
container.Add(newAccessLink);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void RemoveLink(object obj)
|
||||
{
|
||||
if (obj is not string container) return;
|
||||
|
|
@ -435,7 +428,6 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
return path;
|
||||
}
|
||||
|
||||
|
||||
internal static void OpenWindowsIndexingOptions()
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
|
|
@ -448,39 +440,35 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
Process.Start(psi);
|
||||
}
|
||||
|
||||
private ICommand? _openFileEditorPathCommand;
|
||||
|
||||
public ICommand OpenFileEditorPath => _openFileEditorPathCommand ??= new RelayCommand(_ =>
|
||||
[RelayCommand]
|
||||
private void OpenFileEditorPath()
|
||||
{
|
||||
var path = PromptUserSelectPath(ResultType.File, Settings.EditorPath != null ? Path.GetDirectoryName(Settings.EditorPath) : null);
|
||||
if (path is null)
|
||||
return;
|
||||
|
||||
FileEditorPath = path;
|
||||
});
|
||||
}
|
||||
|
||||
private ICommand? _openFolderEditorPathCommand;
|
||||
|
||||
public ICommand OpenFolderEditorPath => _openFolderEditorPathCommand ??= new RelayCommand(_ =>
|
||||
[RelayCommand]
|
||||
private void OpenFolderEditorPath()
|
||||
{
|
||||
var path = PromptUserSelectPath(ResultType.File, Settings.FolderEditorPath != null ? Path.GetDirectoryName(Settings.FolderEditorPath) : null);
|
||||
if (path is null)
|
||||
return;
|
||||
|
||||
FolderEditorPath = path;
|
||||
});
|
||||
}
|
||||
|
||||
private ICommand? _openShellPathCommand;
|
||||
|
||||
public ICommand OpenShellPath => _openShellPathCommand ??= new RelayCommand(_ =>
|
||||
[RelayCommand]
|
||||
private void OpenShellPath()
|
||||
{
|
||||
var path = PromptUserSelectPath(ResultType.File, Settings.EditorPath != null ? Path.GetDirectoryName(Settings.EditorPath) : null);
|
||||
if (path is null)
|
||||
return;
|
||||
|
||||
ShellPath = path;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public string FileEditorPath
|
||||
{
|
||||
|
|
@ -537,7 +525,6 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#region Everything FastSortWarning
|
||||
|
||||
public Visibility FastSortWarningVisibility
|
||||
|
|
@ -593,7 +580,5 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
|||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void TxtCurrentActionKeyword_OnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
|
|
@ -94,11 +95,13 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
private bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value))
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@
|
|||
Margin="{StaticResource SettingPanelItemLeftMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenFileEditorPath}"
|
||||
Command="{Binding OpenFileEditorPathCommand}"
|
||||
Content="{DynamicResource select}" />
|
||||
</StackPanel>
|
||||
|
||||
|
|
@ -272,7 +272,7 @@
|
|||
Margin="{StaticResource SettingPanelItemLeftMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenFolderEditorPath}"
|
||||
Command="{Binding OpenFolderEditorPathCommand}"
|
||||
Content="{DynamicResource select}" />
|
||||
</StackPanel>
|
||||
|
||||
|
|
@ -299,7 +299,7 @@
|
|||
Margin="{StaticResource SettingPanelItemLeftMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Command="{Binding OpenShellPath}"
|
||||
Command="{Binding OpenShellPathCommand}"
|
||||
Content="{DynamicResource select}" />
|
||||
</StackPanel>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||
using Flow.Launcher.Plugin.Explorer.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
|
||||
using Flow.Launcher.Plugin.Explorer.ViewModels;
|
||||
using DataFormats = System.Windows.DataFormats;
|
||||
using DragDropEffects = System.Windows.DragDropEffects;
|
||||
using DragEventArgs = System.Windows.DragEventArgs;
|
||||
|
|
@ -19,9 +18,6 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
|||
{
|
||||
private readonly SettingsViewModel viewModel;
|
||||
|
||||
private List<ActionKeywordModel> actionKeywordsListView;
|
||||
|
||||
|
||||
public ExplorerSettings(SettingsViewModel viewModel)
|
||||
{
|
||||
DataContext = viewModel;
|
||||
|
|
@ -39,8 +35,6 @@ namespace Flow.Launcher.Plugin.Explorer.Views
|
|||
lbxExcludedPaths.Items.SortDescriptions.Add(new SortDescription("Path", ListSortDirection.Ascending));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void AccessLinkDragDrop(string containerName, DragEventArgs e)
|
||||
{
|
||||
var files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
<system:String x:Key="flowlauncher_plugin_processkiller_kill_all_count">kill {0} processes</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_processkiller_kill_instances">kill all instances</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_processkiller_show_window_title">Show title for processes with visible windows</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_processkiller_put_visible_window_process_top">Put processes with visible windows on the top</system:String>
|
||||
|
||||
</ResourceDictionary>
|
||||
|
|
@ -81,7 +81,10 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
// Filter processes based on search term
|
||||
var searchTerm = query.Search;
|
||||
var processlist = new List<ProcessResult>();
|
||||
var processWindowTitle = ProcessHelper.GetProcessesWithNonEmptyWindowTitle();
|
||||
var processWindowTitle =
|
||||
Settings.ShowWindowTitle || Settings.PutVisibleWindowProcessesTop ?
|
||||
ProcessHelper.GetProcessesWithNonEmptyWindowTitle() :
|
||||
new Dictionary<int, string>();
|
||||
if (string.IsNullOrWhiteSpace(searchTerm))
|
||||
{
|
||||
foreach (var p in allPocessList)
|
||||
|
|
@ -91,12 +94,22 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
if (processWindowTitle.TryGetValue(p.Id, out var windowTitle))
|
||||
{
|
||||
// Add score to prioritize processes with visible windows
|
||||
// And use window title for those processes
|
||||
processlist.Add(new ProcessResult(p, Settings.PutVisibleWindowProcessesTop ? 200 : 0, windowTitle, null, progressNameIdTitle));
|
||||
// Use window title for those processes if enabled
|
||||
processlist.Add(new ProcessResult(
|
||||
p,
|
||||
Settings.PutVisibleWindowProcessesTop ? 200 : 0,
|
||||
Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle,
|
||||
null,
|
||||
progressNameIdTitle));
|
||||
}
|
||||
else
|
||||
{
|
||||
processlist.Add(new ProcessResult(p, 0, progressNameIdTitle, null, progressNameIdTitle));
|
||||
processlist.Add(new ProcessResult(
|
||||
p,
|
||||
0,
|
||||
progressNameIdTitle,
|
||||
null,
|
||||
progressNameIdTitle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -115,13 +128,17 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
if (score > 0)
|
||||
{
|
||||
// Add score to prioritize processes with visible windows
|
||||
// And use window title for those processes
|
||||
// Use window title for those processes
|
||||
if (Settings.PutVisibleWindowProcessesTop)
|
||||
{
|
||||
score += 200;
|
||||
}
|
||||
processlist.Add(new ProcessResult(p, score, windowTitle,
|
||||
score == windowTitleMatch.Score ? windowTitleMatch : null, progressNameIdTitle));
|
||||
processlist.Add(new ProcessResult(
|
||||
p,
|
||||
score,
|
||||
Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle,
|
||||
score == windowTitleMatch.Score ? windowTitleMatch : null,
|
||||
progressNameIdTitle));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -130,7 +147,12 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
var score = processNameIdMatch.Score;
|
||||
if (score > 0)
|
||||
{
|
||||
processlist.Add(new ProcessResult(p, score, progressNameIdTitle, processNameIdMatch, progressNameIdTitle));
|
||||
processlist.Add(new ProcessResult(
|
||||
p,
|
||||
score,
|
||||
progressNameIdTitle,
|
||||
processNameIdMatch,
|
||||
progressNameIdTitle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.System.Threading;
|
||||
|
|
@ -72,8 +74,21 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
/// </summary>
|
||||
public static unsafe Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle()
|
||||
{
|
||||
var processDict = new Dictionary<int, string>();
|
||||
// Collect all window handles
|
||||
var windowHandles = new List<HWND>();
|
||||
PInvoke.EnumWindows((hWnd, _) =>
|
||||
{
|
||||
if (PInvoke.IsWindowVisible(hWnd))
|
||||
{
|
||||
windowHandles.Add(hWnd);
|
||||
}
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
|
||||
// Concurrently process each window handle
|
||||
var processDict = new ConcurrentDictionary<int, string>();
|
||||
var processedProcessIds = new ConcurrentDictionary<int, byte>();
|
||||
Parallel.ForEach(windowHandles, hWnd =>
|
||||
{
|
||||
var windowTitle = GetWindowTitle(hWnd);
|
||||
if (!string.IsNullOrWhiteSpace(windowTitle) && PInvoke.IsWindowVisible(hWnd))
|
||||
|
|
@ -82,20 +97,26 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
var result = PInvoke.GetWindowThreadProcessId(hWnd, &processId);
|
||||
if (result == 0u || processId == 0u)
|
||||
{
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
var process = Process.GetProcessById((int)processId);
|
||||
if (!processDict.ContainsKey((int)processId))
|
||||
// Ensure each process ID is processed only once
|
||||
if (processedProcessIds.TryAdd((int)processId, 0))
|
||||
{
|
||||
processDict.Add((int)processId, windowTitle);
|
||||
try
|
||||
{
|
||||
var process = Process.GetProcessById((int)processId);
|
||||
processDict.TryAdd((int)processId, windowTitle);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Handle exceptions (e.g., process exited)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
|
||||
return processDict;
|
||||
return new Dictionary<int, string>(processDict);
|
||||
}
|
||||
|
||||
private static unsafe string GetWindowTitle(HWND hwnd)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
{
|
||||
public class Settings
|
||||
{
|
||||
public bool ShowWindowTitle { get; set; } = true;
|
||||
|
||||
public bool PutVisibleWindowProcessesTop { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
Settings = settings;
|
||||
}
|
||||
|
||||
public bool ShowWindowTitle
|
||||
{
|
||||
get => Settings.ShowWindowTitle;
|
||||
set => Settings.ShowWindowTitle = value;
|
||||
}
|
||||
|
||||
public bool PutVisibleWindowProcessesTop
|
||||
{
|
||||
get => Settings.PutVisibleWindowProcessesTop;
|
||||
|
|
|
|||
|
|
@ -12,10 +12,16 @@
|
|||
<Grid.ColumnDefinitions />
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<CheckBox
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource SettingPanelItemRightTopBottomMargin}"
|
||||
Content="{DynamicResource flowlauncher_plugin_processkiller_show_window_title}"
|
||||
IsChecked="{Binding ShowWindowTitle}" />
|
||||
<CheckBox
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource SettingPanelItemRightTopBottomMargin}"
|
||||
Content="{DynamicResource flowlauncher_plugin_processkiller_put_visible_window_process_top}"
|
||||
IsChecked="{Binding PutVisibleWindowProcessesTop}" />
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
programSourceView.Items.Refresh();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void ReIndexing()
|
||||
{
|
||||
ViewRefresh();
|
||||
|
|
@ -183,6 +184,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
EditProgramSource(selectedProgramSource);
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void EditProgramSource(ProgramSource selectedProgramSource)
|
||||
{
|
||||
if (selectedProgramSource == null)
|
||||
|
|
@ -277,6 +279,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await ProgramSettingDisplay.DisplayAllProgramsAsync();
|
||||
|
|
@ -284,6 +287,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
ViewRefresh();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectedItems = programSourceView
|
||||
|
|
|
|||
|
|
@ -362,6 +362,7 @@ namespace Flow.Launcher.Plugin.Sys
|
|||
Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xe89f"),
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.HideMainWindow();
|
||||
Application.Current.MainWindow.Close();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
Initialize(sources, context, Action.Add);
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void Initialize(IList<SearchSource> sources, PluginInitContext context, Action action)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
|
@ -124,6 +125,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "<Pending>")]
|
||||
private async void OnSelectIconClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
const string filter = "Image files (*.jpg, *.jpeg, *.gif, *.png, *.bmp) |*.jpg; *.jpeg; *.gif; *.png; *.bmp";
|
||||
|
|
|
|||
|
|
@ -351,6 +351,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea
|
|||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/itsonlyfrans"><img src="https://avatars.githubusercontent.com/u/46535667?v=4" width="10%" /></a>
|
||||
<a href="https://github.com/atilford"><img src="https://avatars.githubusercontent.com/u/13649625?v=4" width="10%" /></a>
|
||||
<a href="https://github.com/andreqramos"><img src="https://avatars.githubusercontent.com/u/49326063?v=4" width="10%" /></a>
|
||||
<a href="https://github.com/Yuba4"><img src="https://avatars.githubusercontent.com/u/46278200?v=4" width="10%" /></a>
|
||||
<a href="https://github.com/Mavrik327"><img src="https://avatars.githubusercontent.com/u/121626149?v=4" width="10%" /></a>
|
||||
|
|
|
|||
Loading…
Reference in a new issue