mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #1476 from LeLocTai/dev
[Program Plugin] Support .url file and Steam/Epic shortcuts
This commit is contained in:
commit
e17ec6ac65
8 changed files with 337 additions and 30 deletions
|
|
@ -163,15 +163,17 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
var loadFullImage = (Path.GetExtension(imagePath) ?? "").Equals(".url", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (ImageLoader.CacheContainImage(imagePath))
|
||||
{
|
||||
// will get here either when icoPath has value\icon delegate is null\when had exception in delegate
|
||||
image = ImageLoader.Load(imagePath);
|
||||
image = ImageLoader.Load(imagePath, loadFullImage);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to modify the property not field here to trigger the OnPropertyChanged event
|
||||
Image = await Task.Run(() => ImageLoader.Load(imagePath)).ConfigureAwait(false);
|
||||
Image = await Task.Run(() => ImageLoader.Load(imagePath, loadFullImage)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Result Result { get; }
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ini-parser" Version="2.5.2" />
|
||||
<PackageReference Include="System.Runtime" Version="4.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<!-- Program setting -->
|
||||
<system:String x:Key="flowlauncher_plugin_program_reset">Reset Default</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_delete">Delete</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_edit">Edit</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_add">Add</system:String>
|
||||
|
|
@ -12,7 +13,7 @@
|
|||
<system:String x:Key="flowlauncher_plugin_program_disable">Disable</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_location">Location</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_all_programs">All Programs</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes">File Suffixes</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes">File Type</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_reindex">Reindex</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_indexing">Indexing</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_start">Index Start Menu</system:String>
|
||||
|
|
@ -35,9 +36,21 @@
|
|||
<system:String x:Key="flowlauncher_plugin_program_delete_program_source">Are you sure you want to delete the selected program sources?</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_program_update">OK</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_only_index_tip">Flow Launcher will only index files that end with the following suffixes. (Each suffix should split by ';' )</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_only_index_tip">Program Plugin will only index files with selected suffixes and .url files with selected protocols.</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_update_file_suffixes">Successfully updated file suffixes</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes_cannot_empty">File suffixes can't be empty</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_protocols_cannot_empty">Protocols can't be empty</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes_excutable_types">File Suffixes</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes_URL_types">URL Protocols</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes_custom_urls">Custom URL Protocols</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes_custom_file_types">Custom File Suffixes</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_suffixes_tooltip">
|
||||
Insert file suffixes you want to index. Suffixes should be separated by ';'. (ex>bat;py)
|
||||
</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_protocol_tooltip">
|
||||
Insert protocols of .url files you want to index. Protocols should be separated by ';'. (ex>ftp;netflix)
|
||||
</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_program_run_as_different_user">Run As Different User</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_run_as_administrator">Run As Administrator</system:String>
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@
|
|||
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="http://schemas.modernwpf.com/2019"
|
||||
Title="{DynamicResource flowlauncher_plugin_program_suffixes}"
|
||||
Width="400"
|
||||
Width="600"
|
||||
Background="{DynamicResource PopuBGColor}"
|
||||
Foreground="{DynamicResource PopupTextColor}"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
ResizeMode="NoResize"
|
||||
SizeToContent="Height"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
|
|
@ -15,9 +17,73 @@
|
|||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
|
||||
</WindowChrome.WindowChrome>
|
||||
<Grid>
|
||||
<Window.Resources>
|
||||
<Style
|
||||
x:Key="CustomFileTypeTextBox"
|
||||
BasedOn="{StaticResource DefaultTextBoxStyle}"
|
||||
TargetType="TextBox">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=CustomFiles, Path=IsChecked}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="CustomURLTypeTextBox"
|
||||
BasedOn="{StaticResource DefaultTextBoxStyle}"
|
||||
TargetType="TextBox">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=CustomProtocol, Path=IsChecked}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SettingGroupBoxSuffixToolTip" TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource Color00B}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Color03B}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
<Setter Property="Margin" Value="0,5,0,0" />
|
||||
<Setter Property="Padding" Value="15,15,15,15" />
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=tbSuffixes, Path=IsFocused}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ElementName=tbSuffixes, Path=IsFocused}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SettingGroupBoxURLToolTip" TargetType="Border">
|
||||
<Setter Property="Background" Value="{DynamicResource Color00B}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Color03B}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
<Setter Property="Margin" Value="0,5,0,0" />
|
||||
<Setter Property="Padding" Value="15,15,15,15" />
|
||||
<Setter Property="SnapsToDevicePixels" Value="True" />
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ElementName=tbProtocols, Path=IsFocused}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ElementName=tbProtocols, Path=IsFocused}" Value="False">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
</Window.Resources>
|
||||
|
||||
<Grid x:Name="WindowArea">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="80" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
|
@ -55,7 +121,9 @@
|
|||
</Grid>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="26,12,26,0">
|
||||
|
||||
<StackPanel Margin="0,0,0,12">
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Margin="0,0,0,0"
|
||||
|
|
@ -65,10 +133,77 @@
|
|||
TextAlignment="Left" />
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,10"
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_only_index_tip}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBox x:Name="tbSuffixes" Margin="0,20,0,20" />
|
||||
<Border Style="{DynamicResource SettingGroupBoxURLToolTip}">
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_protocol_tooltip}"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
|
||||
<Border Style="{DynamicResource SettingGroupBoxSuffixToolTip}">
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_suffixes_tooltip}"
|
||||
TextWrapping="Wrap" />
|
||||
</Border>
|
||||
|
||||
<Grid Margin="0,20,0,12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="250" />
|
||||
<ColumnDefinition Width="250" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0" Margin="0,0,0,0">
|
||||
<TextBlock
|
||||
Margin="0,0,0,8"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_suffixes_excutable_types}" />
|
||||
<CheckBox Name="apprefMS" Margin="10,0,0,0" IsChecked="{Binding SuffixesStatus[appref-ms]}">appref-ms</CheckBox>
|
||||
<CheckBox Name="exe" Margin="10,0,0,0" IsChecked="{Binding SuffixesStatus[exe]}">exe</CheckBox>
|
||||
<CheckBox Name="lnk" Margin="10,0,0,0" IsChecked="{Binding SuffixesStatus[lnk]}">lnk</CheckBox>
|
||||
<CheckBox
|
||||
Name="CustomFiles"
|
||||
Margin="10,0,0,0"
|
||||
IsChecked="{Binding UseCustomSuffixes}"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_suffixes_custom_file_types}" />
|
||||
<TextBox
|
||||
x:Name="tbSuffixes"
|
||||
Margin="10,4,0,6"
|
||||
Style="{StaticResource CustomFileTypeTextBox}" />
|
||||
</StackPanel>
|
||||
|
||||
<Border
|
||||
Grid.Column="1"
|
||||
Margin="20,0,0,10"
|
||||
Padding="20,0,0,0"
|
||||
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
|
||||
BorderThickness="1,0,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="0,0,0,8"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_suffixes_URL_types}" />
|
||||
<CheckBox Name="steam" Margin="10,0,0,0" IsChecked="{Binding ProtocolsStatus[steam]}">Steam Games</CheckBox>
|
||||
<CheckBox Name="epic" Margin="10,0,0,0" IsChecked="{Binding ProtocolsStatus[epic]}">Epic Games</CheckBox>
|
||||
<CheckBox Name="http" Margin="10,0,0,0" IsChecked="{Binding ProtocolsStatus[http]}">Http/Https</CheckBox>
|
||||
<CheckBox
|
||||
Name="CustomProtocol"
|
||||
Margin="10,0,0,0"
|
||||
IsChecked="{Binding UseCustomProtocols}"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_suffixes_custom_urls}" />
|
||||
<TextBox
|
||||
x:Name="tbProtocols"
|
||||
Margin="10,4,0,6"
|
||||
Style="{StaticResource CustomURLTypeTextBox}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<Border
|
||||
|
|
@ -78,10 +213,17 @@
|
|||
BorderThickness="0,1,0,0">
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
x:Name="btnReset"
|
||||
Height="30"
|
||||
MinWidth="140"
|
||||
Margin="0,0,5,0"
|
||||
Click="BtnReset_OnClick"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_reset}" />
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
Height="30"
|
||||
MinWidth="140"
|
||||
Margin="5,0,5,0"
|
||||
Click="BtnCancel_OnClick"
|
||||
Content="{DynamicResource cancel}" />
|
||||
|
||||
|
|
@ -90,7 +232,7 @@
|
|||
MinWidth="140"
|
||||
Margin="5,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Click="ButtonBase_OnClick"
|
||||
Click="BtnAdd_OnClick"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_update}"
|
||||
Style="{DynamicResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
|
|
|
|||
|
|
@ -1,44 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program
|
||||
{
|
||||
/// <summary>
|
||||
/// ProgramSuffixes.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ProgramSuffixes
|
||||
{
|
||||
private PluginInitContext context;
|
||||
private Settings _settings;
|
||||
public Dictionary<string, bool> SuffixesStatus { get; set; }
|
||||
public Dictionary<string, bool> ProtocolsStatus { get; set; }
|
||||
public bool UseCustomSuffixes { get; set; }
|
||||
public bool UseCustomProtocols { get; set; }
|
||||
|
||||
public ProgramSuffixes(PluginInitContext context, Settings settings)
|
||||
{
|
||||
this.context = context;
|
||||
InitializeComponent();
|
||||
_settings = settings;
|
||||
tbSuffixes.Text = string.Join(Settings.SuffixSeperator.ToString(), _settings.ProgramSuffixes);
|
||||
SuffixesStatus = new Dictionary<string, bool>(_settings.BuiltinSuffixesStatus);
|
||||
ProtocolsStatus = new Dictionary<string, bool>(_settings.BuiltinProtocolsStatus);
|
||||
UseCustomSuffixes = _settings.UseCustomSuffixes;
|
||||
UseCustomProtocols = _settings.UseCustomProtocols;
|
||||
InitializeComponent();
|
||||
tbSuffixes.Text = string.Join(Settings.SuffixSeparator, _settings.CustomSuffixes);
|
||||
tbProtocols.Text = string.Join(Settings.SuffixSeparator, _settings.CustomProtocols);
|
||||
}
|
||||
|
||||
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var suffixes = tbSuffixes.Text.Split(Settings.SuffixSeperator, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (suffixes.Length == 0)
|
||||
private void BtnAdd_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var suffixes = tbSuffixes.Text.Split(Settings.SuffixSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
var protocols = tbProtocols.Text.Split(Settings.SuffixSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (suffixes.Length == 0 && UseCustomSuffixes)
|
||||
{
|
||||
string warning = context.API.GetTranslation("flowlauncher_plugin_program_suffixes_cannot_empty");
|
||||
MessageBox.Show(warning);
|
||||
return;
|
||||
}
|
||||
|
||||
_settings.ProgramSuffixes = suffixes;
|
||||
if (protocols.Length == 0 && UseCustomProtocols)
|
||||
{
|
||||
string warning = context.API.GetTranslation("flowlauncher_plugin_protocols_cannot_empty");
|
||||
MessageBox.Show(warning);
|
||||
return;
|
||||
}
|
||||
|
||||
string msg = context.API.GetTranslation("flowlauncher_plugin_program_update_file_suffixes");
|
||||
MessageBox.Show(msg);
|
||||
_settings.CustomSuffixes = suffixes;
|
||||
_settings.CustomProtocols = protocols;
|
||||
_settings.BuiltinSuffixesStatus = new Dictionary<string, bool>(SuffixesStatus);
|
||||
_settings.BuiltinProtocolsStatus = new Dictionary<string, bool>(ProtocolsStatus);
|
||||
_settings.UseCustomSuffixes = UseCustomSuffixes;
|
||||
_settings.UseCustomProtocols = UseCustomProtocols;
|
||||
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
private void BtnReset_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
apprefMS.IsChecked = true;
|
||||
exe.IsChecked = true;
|
||||
lnk.IsChecked = true;
|
||||
CustomFiles.IsChecked = false;
|
||||
|
||||
steam.IsChecked = true;
|
||||
epic.IsChecked = true;
|
||||
http.IsChecked = false;
|
||||
CustomProtocol.IsChecked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ using System.Collections;
|
|||
using System.Diagnostics;
|
||||
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Channels;
|
||||
using Flow.Launcher.Infrastructure.Image;
|
||||
using IniParser;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program.Programs
|
||||
{
|
||||
|
|
@ -36,6 +39,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
public string Location => ParentDirectory;
|
||||
|
||||
private const string ShortcutExtension = "lnk";
|
||||
private const string UrlExtension = "url";
|
||||
private const string ExeExtension = "exe";
|
||||
|
||||
private static readonly Win32 Default = new Win32()
|
||||
|
|
@ -287,6 +291,45 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
#endif
|
||||
}
|
||||
|
||||
private static Win32 UrlProgram(string path)
|
||||
{
|
||||
var program = Win32Program(path);
|
||||
program.Valid = false;
|
||||
|
||||
try
|
||||
{
|
||||
var parser = new FileIniDataParser();
|
||||
var data = parser.ReadFile(path);
|
||||
var urlSection = data["InternetShortcut"];
|
||||
var url = urlSection?["URL"];
|
||||
if (String.IsNullOrEmpty(url))
|
||||
{
|
||||
return program;
|
||||
}
|
||||
foreach(var protocol in Main._settings.GetProtocols())
|
||||
{
|
||||
if(url.StartsWith(protocol))
|
||||
{
|
||||
program.LnkResolvedPath = url;
|
||||
program.Valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var iconPath = urlSection?["IconFile"];
|
||||
if (!String.IsNullOrEmpty(iconPath))
|
||||
{
|
||||
program.IcoPath = iconPath;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Many files do not have the required fields, so no logging is done.
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
private static Win32 ExeProgram(string path)
|
||||
{
|
||||
try
|
||||
|
|
@ -343,6 +386,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
{
|
||||
ExeExtension => ExeProgram(x),
|
||||
ShortcutExtension => LnkProgram(x),
|
||||
UrlExtension => UrlProgram(x),
|
||||
_ => Win32Program(x)
|
||||
});
|
||||
|
||||
|
|
@ -365,6 +409,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
.Select(x => Extension(x) switch
|
||||
{
|
||||
ShortcutExtension => LnkProgram(x),
|
||||
UrlExtension => UrlProgram(x),
|
||||
_ => Win32Program(x)
|
||||
}).Where(x => x.Valid);
|
||||
return programs;
|
||||
|
|
@ -504,7 +549,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
{
|
||||
var programs = Enumerable.Empty<Win32>();
|
||||
|
||||
var unregistered = UnregisteredPrograms(settings.ProgramSources, settings.ProgramSuffixes);
|
||||
var unregistered = UnregisteredPrograms(settings.ProgramSources, settings.GetSuffixes());
|
||||
|
||||
programs = programs.Concat(unregistered);
|
||||
|
||||
|
|
@ -512,13 +557,13 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
|
||||
if (settings.EnableRegistrySource)
|
||||
{
|
||||
var appPaths = AppPathsPrograms(settings.ProgramSuffixes);
|
||||
var appPaths = AppPathsPrograms(settings.GetSuffixes());
|
||||
autoIndexPrograms = autoIndexPrograms.Concat(appPaths);
|
||||
}
|
||||
|
||||
if (settings.EnableStartMenuSource)
|
||||
{
|
||||
var startMenu = StartMenuPrograms(settings.ProgramSuffixes);
|
||||
var startMenu = StartMenuPrograms(settings.GetSuffixes());
|
||||
autoIndexPrograms = autoIndexPrograms.Concat(startMenu);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program
|
||||
{
|
||||
|
|
@ -9,17 +11,87 @@ namespace Flow.Launcher.Plugin.Program
|
|||
public DateTime LastIndexTime { get; set; }
|
||||
public List<ProgramSource> ProgramSources { get; set; } = new List<ProgramSource>();
|
||||
public List<DisabledProgramSource> DisabledProgramSources { get; set; } = new List<DisabledProgramSource>();
|
||||
public string[] ProgramSuffixes { get; set; } = {"appref-ms", "exe", "lnk"};
|
||||
public string[] CustomSuffixes { get; set; } = Array.Empty<string>();
|
||||
public string[] CustomProtocols { get; set; } = Array.Empty<string>();
|
||||
|
||||
public Dictionary<string, bool> BuiltinSuffixesStatus { get; set; } = new Dictionary<string, bool>{
|
||||
{ "exe", true }, { "appref-ms", true }, { "lnk", true }
|
||||
};
|
||||
|
||||
public Dictionary<string, bool> BuiltinProtocolsStatus { get; set; } = new Dictionary<string, bool>{
|
||||
{ "steam", true }, { "epic", true }, { "http", false }
|
||||
};
|
||||
|
||||
[JsonIgnore]
|
||||
public Dictionary<string, string> BuiltinProtocols { get; set; } = new Dictionary<string, string>{
|
||||
{ "steam", $"steam://run/{SuffixSeparator}steam://rungameid/" }, { "epic", "com.epicgames.launcher://apps/" }, { "http", $"http://{SuffixSeparator}https://"}
|
||||
};
|
||||
|
||||
public bool UseCustomSuffixes { get; set; } = false;
|
||||
public bool UseCustomProtocols { get; set; } = false;
|
||||
|
||||
public string[] GetSuffixes()
|
||||
{
|
||||
List<string> extensions = new List<string>();
|
||||
foreach (var item in BuiltinSuffixesStatus)
|
||||
{
|
||||
if (item.Value)
|
||||
{
|
||||
extensions.Add(item.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if (BuiltinProtocolsStatus.Values.Any(x => x == true) || UseCustomProtocols)
|
||||
{
|
||||
extensions.Add("url");
|
||||
}
|
||||
|
||||
if (UseCustomSuffixes)
|
||||
{
|
||||
return extensions.Concat(CustomSuffixes).DistinctBy(x => x.ToLower()).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return extensions.DistinctBy(x => x.ToLower()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public string[] GetProtocols()
|
||||
{
|
||||
List<string> protocols = new List<string>();
|
||||
foreach (var item in BuiltinProtocolsStatus)
|
||||
{
|
||||
if (item.Value)
|
||||
{
|
||||
if (BuiltinProtocols.TryGetValue(item.Key, out string ps))
|
||||
{
|
||||
var tmp = ps.Split(SuffixSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var protocol in tmp)
|
||||
{
|
||||
protocols.Add(protocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UseCustomProtocols)
|
||||
{
|
||||
return protocols.Concat(CustomProtocols).DistinctBy(x => x.ToLower()).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return protocols.DistinctBy(x => x.ToLower()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableStartMenuSource { get; set; } = true;
|
||||
|
||||
public bool EnableDescription { get; set; } = false;
|
||||
public bool HideAppsPath { get; set; } = true;
|
||||
public bool EnableRegistrySource { get; set; } = true;
|
||||
public string CustomizedExplorer { get; set; } = Explorer;
|
||||
public string CustomizedArgs { get; set; } = ExplorerArgs;
|
||||
|
||||
internal const char SuffixSeperator = ';';
|
||||
internal const char SuffixSeparator = ';';
|
||||
|
||||
internal const string Explorer = "explorer";
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Flow.Launcher.Plugin.Program
|
|||
var text = value as string[];
|
||||
if (text != null)
|
||||
{
|
||||
return string.Join(";", text);
|
||||
return string.Join(Settings.SuffixSeparator, text);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue