Merge Dev

This commit is contained in:
DB p 2021-12-05 21:28:16 +09:00
commit a5e0d23e0a
122 changed files with 52943 additions and 3761 deletions

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
@ -45,8 +45,56 @@ namespace Flow.Launcher.Core.Plugin
}
}
}
return allPluginMetadata;
(List<PluginMetadata> uniqueList, List<PluginMetadata> duplicateList) = GetUniqueLatestPluginMetadata(allPluginMetadata);
duplicateList
.ForEach(
x => Log.Warn("PluginConfig",
string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " +
"not loaded due to version not the highest of the duplicates",
x.Name, x.ID, x.Version),
"GetUniqueLatestPluginMetadata"));
return uniqueList;
}
internal static (List<PluginMetadata>, List<PluginMetadata>) GetUniqueLatestPluginMetadata(List<PluginMetadata> allPluginMetadata)
{
var duplicate_list = new List<PluginMetadata>();
var unique_list = new List<PluginMetadata>();
var duplicateGroups = allPluginMetadata.GroupBy(x => x.ID).Where(g => g.Count() > 1).Select(y => y).ToList();
foreach (var metadata in allPluginMetadata)
{
var duplicatesExist = false;
foreach (var group in duplicateGroups)
{
if (metadata.ID == group.Key)
{
duplicatesExist = true;
// If metadata's version greater than each duplicate's version, CompareTo > 0
var count = group.Where(x => metadata.Version.CompareTo(x.Version) > 0).Count();
// Only add if the meatadata's version is the highest of all duplicates in the group
if (count == group.Count() - 1)
{
unique_list.Add(metadata);
}
else
{
duplicate_list.Add(metadata);
}
}
}
if (!duplicatesExist)
unique_list.Add(metadata);
}
return (unique_list, duplicate_list);
}
private static PluginMetadata GetPluginMetadata(string pluginDirectory)

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
@ -28,6 +28,11 @@ namespace Flow.Launcher.Core.Plugin
var path = Path.Combine(Constant.ProgramDirectory, JsonRPC);
_startInfo.EnvironmentVariables["PYTHONPATH"] = path;
_startInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version;
_startInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory;
_startInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory;
//Add -B flag to tell python don't write .py[co] files. Because .pyc contains location infos which will prevent python portable
_startInfo.ArgumentList.Add("-B");
}
@ -57,4 +62,4 @@ namespace Flow.Launcher.Core.Plugin
return Task.CompletedTask;
}
}
}
}

View file

@ -10,6 +10,7 @@ using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using System.Globalization;
using System.Threading.Tasks;
namespace Flow.Launcher.Core.Resource
{
@ -95,10 +96,13 @@ namespace Flow.Launcher.Core.Resource
{
LoadLanguage(language);
}
UpdatePluginMetadataTranslations();
Settings.Language = language.LanguageCode;
CultureInfo.CurrentCulture = new CultureInfo(language.LanguageCode);
CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture;
Task.Run(() =>
{
UpdatePluginMetadataTranslations();
});
}
public bool PromptShouldUsePinyin(string languageCodeToSet)

View file

@ -35,8 +35,16 @@ namespace Flow.Launcher.Infrastructure
public const string DefaultTheme = "Win11Light";
public const string Light = "Light";
public const string Dark = "Dark";
public const string System = "System";
public const string Themes = "Themes";
public const string Settings = "Settings";
public const string Logs = "Logs";
public const string Website = "https://flow-launcher.github.io";
public const string GitHub = "https://github.com/Flow-Launcher/Flow.Launcher";
public const string Docs = "https://flow-launcher.github.io/docs";
}
}

View file

@ -15,6 +15,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
private string language = "en";
public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
public string ColorScheme { get; set; } = "System";
public bool ShowOpenResultHotkey { get; set; } = true;
public double WindowSize { get; set; } = 580;
@ -151,7 +152,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public bool DontPromptUpdateMsg { get; set; }
public bool EnableUpdateLog { get; set; }
public bool StartFlowLauncherOnSystemStartup { get; set; } = true;
public bool StartFlowLauncherOnSystemStartup { get; set; } = false;
public bool HideOnStartup { get; set; }
bool _hideNotifyIcon { get; set; }
public bool HideNotifyIcon
@ -184,4 +185,11 @@ namespace Flow.Launcher.Infrastructure.UserSettings
Empty,
Preserved
}
public enum ColorSchemes
{
System,
Light,
Dark
}
}

View file

@ -1,4 +1,6 @@
namespace Flow.Launcher.Plugin
using System.Globalization;
namespace Flow.Launcher.Plugin
{
/// <summary>
/// Represent plugins that support internationalization
@ -8,5 +10,13 @@
string GetTranslatedPluginTitle();
string GetTranslatedPluginDescription();
/// <summary>
/// The method will be invoked when language of flow changed
/// </summary>
void OnCultureInfoChanged(CultureInfo newCulture)
{
}
}
}

View file

@ -29,6 +29,21 @@ namespace Flow.Launcher.Plugin
/// </summary>
void RestartApp();
/// <summary>
/// Run a shell command
/// </summary>
/// <param name="cmd">The command or program to run</param>
/// <param name="filename">the shell type to run, e.g. powershell.exe</param>
/// <exception cref="FileNotFoundException">Thrown when unable to find the file specified in the command </exception>
/// <exception cref="Win32Exception">Thrown when error occurs during the execution of the command </exception>
void ShellRun(string cmd, string filename = "cmd.exe");
/// <summary>
/// Copy Text to clipboard
/// </summary>
/// <param name="Text">Text to save on clipboard</param>
public void CopyToClipboard(string text);
/// <summary>
/// Save everything, all of Flow Launcher and plugins' data and settings
/// </summary>

View file

@ -50,7 +50,7 @@ namespace Flow.Launcher.Plugin
/// <summary>
/// Delegate to Get Image Source
/// </summary>
public IconDelegate Icon { get; set; }
public IconDelegate Icon;
/// <summary>
/// Information for Glyph Icon

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -60,17 +60,39 @@ namespace Flow.Launcher.Plugin.SharedCommands
return sb.ToString();
}
public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "")
public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "", bool createNoWindow = false)
{
var info = new ProcessStartInfo
{
FileName = fileName,
WorkingDirectory = workingDirectory,
Arguments = arguments,
Verb = verb
Verb = verb,
CreateNoWindow = createNoWindow
};
return info;
}
/// <summary>
/// Runs a windows command using the provided ProcessStartInfo
/// </summary>
/// <exception cref="FileNotFoundException">Thrown when unable to find the file specified in the command </exception>
/// <exception cref="Win32Exception">Thrown when error occurs during the execution of the command </exception>
public static void Execute(ProcessStartInfo info)
{
Execute(Process.Start, info);
}
/// <summary>
/// Runs a windows command using the provided ProcessStartInfo using a custom execute command function
/// </summary>
/// <param name="Func startProcess">allows you to pass in a custom command execution function</param>
/// <exception cref="FileNotFoundException">Thrown when unable to find the file specified in the command </exception>
/// <exception cref="Win32Exception">Thrown when error occurs during the execution of the command </exception>
public static void Execute(Func<ProcessStartInfo, Process> startProcess, ProcessStartInfo info)
{
startProcess(info);
}
}
}

View file

@ -0,0 +1,92 @@
using NUnit.Framework;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Plugin;
using System.Collections.Generic;
using System.Linq;
namespace Flow.Launcher.Test
{
[TestFixture]
class PluginLoadTest
{
[Test]
public void GivenDuplicatePluginMetadatasWhenLoadedThenShouldReturnOnlyUniqueList()
{
// Given
var duplicateList = new List<PluginMetadata>
{
new PluginMetadata
{
ID = "CEA0TYUC6D3B4085823D60DC76F28855",
Version = "1.0.0"
},
new PluginMetadata
{
ID = "CEA0TYUC6D3B4085823D60DC76F28855",
Version = "1.0.1"
},
new PluginMetadata
{
ID = "CEA0TYUC6D3B4085823D60DC76F28855",
Version = "1.0.2"
},
new PluginMetadata
{
ID = "CEA0TYUC6D3B4085823D60DC76F28855",
Version = "1.0.0"
},
new PluginMetadata
{
ID = "CEA0TYUC6D3B4085823D60DC76F28855",
Version = "1.0.0"
},
new PluginMetadata
{
ID = "ABC0TYUC6D3B7855823D60DC76F28855",
Version = "1.0.0"
},
new PluginMetadata
{
ID = "ABC0TYUC6D3B7855823D60DC76F28855",
Version = "1.0.0"
}
};
// When
(var unique, var duplicates) = PluginConfig.GetUniqueLatestPluginMetadata(duplicateList);
// Then
Assert.True(unique.FirstOrDefault().ID == "CEA0TYUC6D3B4085823D60DC76F28855" && unique.FirstOrDefault().Version == "1.0.2");
Assert.True(unique.Count() == 1);
Assert.False(duplicates.Any(x => x.Version == "1.0.2" && x.ID == "CEA0TYUC6D3B4085823D60DC76F28855"));
Assert.True(duplicates.Count() == 6);
}
[Test]
public void GivenDuplicatePluginMetadatasWithNoUniquePluginWhenLoadedThenShouldReturnEmptyList()
{
// Given
var duplicateList = new List<PluginMetadata>
{
new PluginMetadata
{
ID = "CEA0TYUC6D3B7855823D60DC76F28855",
Version = "1.0.0"
},
new PluginMetadata
{
ID = "CEA0TYUC6D3B7855823D60DC76F28855",
Version = "1.0.0"
}
};
// When
(var unique, var duplicates) = PluginConfig.GetUniqueLatestPluginMetadata(duplicateList);
// Then
Assert.True(unique.Count() == 0);
Assert.True(duplicates.Count() == 2);
}
}
}

View file

@ -1,17 +0,0 @@
using NUnit.Framework;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Infrastructure.Exception;
namespace Flow.Launcher.Test.Plugins
{
[TestFixture]
public class PluginInitTest
{
[Test]
public void PublicAPIIsNullTest()
{
//Assert.Throws(typeof(Flow.LauncherFatalException), () => PluginManager.Initialize(null));
}
}
}

View file

@ -13,7 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{3A73
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher", "Flow.Launcher\Flow.Launcher.csproj", "{DB90F671-D861-46BB-93A3-F1304F5BA1C5}"
ProjectSection(ProjectDependencies) = postProject
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0} = {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}
{0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {0B9DE348-9361-4940-ADB6-F5953BFFCCEC}
{4792A74A-0CEA-4173-A8B2-30E6764C6217} = {4792A74A-0CEA-4173-A8B2-30E6764C6217}
{FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {FDB3555B-58EF-4AE6-B5F1-904719637AB4}
@ -23,6 +22,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher", "Flow.Launc
{9B130CC5-14FB-41FF-B310-0A95B6894C37} = {9B130CC5-14FB-41FF-B310-0A95B6894C37}
{FDED22C8-B637-42E8-824A-63B5B6E05A3A} = {FDED22C8-B637-42E8-824A-63B5B6E05A3A}
{A3DCCBCA-ACC1-421D-B16E-210896234C26} = {A3DCCBCA-ACC1-421D-B16E-210896234C26}
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {5043CECE-E6A7-4867-9CBE-02D27D83747A}
{403B57F2-1856-4FC7-8A24-36AB346B763E} = {403B57F2-1856-4FC7-8A24-36AB346B763E}
{588088F4-3262-4F9F-9663-A05DE12534C3} = {588088F4-3262-4F9F-9663-A05DE12534C3}
EndProjectSection
@ -35,8 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Progra
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.WebSearch", "Plugins\Flow.Launcher.Plugin.WebSearch\Flow.Launcher.Plugin.WebSearch.csproj", "{403B57F2-1856-4FC7-8A24-36AB346B763E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.ControlPanel", "Plugins\Flow.Launcher.Plugin.ControlPanel\Flow.Launcher.Plugin.ControlPanel.csproj", "{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.PluginIndicator", "Plugins\Flow.Launcher.Plugin.PluginIndicator\Flow.Launcher.Plugin.PluginIndicator.csproj", "{FDED22C8-B637-42E8-824A-63B5B6E05A3A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Sys", "Plugins\Flow.Launcher.Plugin.Sys\Flow.Launcher.Plugin.Sys.csproj", "{0B9DE348-9361-4940-ADB6-F5953BFFCCEC}"
@ -68,6 +66,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Proces
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.PluginsManager", "Plugins\Flow.Launcher.Plugin.PluginsManager\Flow.Launcher.Plugin.PluginsManager.csproj", "{4792A74A-0CEA-4173-A8B2-30E6764C6217}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.WindowsSettings", "Plugins\Flow.Launcher.Plugin.WindowsSettings\Flow.Launcher.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -162,18 +162,6 @@ Global
{403B57F2-1856-4FC7-8A24-36AB346B763E}.Release|x64.Build.0 = Release|Any CPU
{403B57F2-1856-4FC7-8A24-36AB346B763E}.Release|x86.ActiveCfg = Release|Any CPU
{403B57F2-1856-4FC7-8A24-36AB346B763E}.Release|x86.Build.0 = Release|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x64.ActiveCfg = Debug|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x64.Build.0 = Debug|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x86.ActiveCfg = Debug|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x86.Build.0 = Debug|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|Any CPU.Build.0 = Release|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x64.ActiveCfg = Release|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x64.Build.0 = Release|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x86.ActiveCfg = Release|Any CPU
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x86.Build.0 = Release|Any CPU
{FDED22C8-B637-42E8-824A-63B5B6E05A3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FDED22C8-B637-42E8-824A-63B5B6E05A3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FDED22C8-B637-42E8-824A-63B5B6E05A3A}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -283,6 +271,18 @@ Global
{4792A74A-0CEA-4173-A8B2-30E6764C6217}.Release|x64.Build.0 = Release|Any CPU
{4792A74A-0CEA-4173-A8B2-30E6764C6217}.Release|x86.ActiveCfg = Release|Any CPU
{4792A74A-0CEA-4173-A8B2-30E6764C6217}.Release|x86.Build.0 = Release|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.ActiveCfg = Debug|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.Build.0 = Debug|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x86.ActiveCfg = Debug|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x86.Build.0 = Debug|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|Any CPU.Build.0 = Release|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.Build.0 = Release|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x86.ActiveCfg = Release|Any CPU
{5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -290,7 +290,6 @@ Global
GlobalSection(NestedProjects) = preSolution
{FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{403B57F2-1856-4FC7-8A24-36AB346B763E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{1EE20B48-82FB-48A2-8086-675D6DDAB4F0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{FDED22C8-B637-42E8-824A-63B5B6E05A3A} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{A3DCCBCA-ACC1-421D-B16E-210896234C26} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
@ -300,6 +299,7 @@ Global
{F9C4C081-4CC3-4146-95F1-E102B4E10A5F} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{588088F4-3262-4F9F-9663-A05DE12534C3} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{4792A74A-0CEA-4173-A8B2-30E6764C6217} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F26ACB50-3F6C-4907-B0C9-1ADACC1D0DED}

View file

@ -1,85 +1,137 @@
<Window x:Class="Flow.Launcher.ActionKeywords"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{DynamicResource actionKeywordsTitle}"
Icon="Images\app.png"
ResizeMode="NoResize"
Loaded="ActionKeyword_OnLoaded"
WindowStartupLocation="CenterScreen"
Height="365" Width="450" Background="#F3F3F3" BorderBrush="#cecece">
<Window
x:Class="Flow.Launcher.ActionKeywords"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{DynamicResource actionKeywordsTitle}"
Width="450"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
Icon="Images\app.png"
Loaded="ActionKeyword_OnLoaded"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80"/>
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Border BorderThickness="0 0 0 1" BorderBrush="#e5e5e5" Background="#ffffff" Padding="26 26 26 0">
<Grid>
<Grid>
<StackPanel Grid.Row="0">
<StackPanel>
<StackPanel Grid.Row="0" Margin="0 0 0 12">
<TextBlock Grid.Column="0" Text="{DynamicResource actionKeywordsTitle}" FontSize="20" FontWeight="SemiBold" FontFamily="Segoe UI" TextAlignment="Left"
Margin="0 0 0 0" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<StackPanel Grid.Row="0" Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource actionKeywordsTitle}"
TextAlignment="Left" />
</StackPanel>
<StackPanel>
<TextBlock
Text="{DynamicResource actionkeyword_tips}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left"/>
<TextBlock
FontSize="14"
Text="{DynamicResource actionkeyword_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 18 0 0">
<TextBlock FontSize="14" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource currentActionKeywords}" />
<TextBlock x:Name="tbOldActionKeyword" Grid.Row="0" Grid.Column="1" Margin="14 10 10 10" FontSize="14"
VerticalAlignment="Center" HorizontalAlignment="Left" FontWeight="SemiBold"/>
<StackPanel Margin="0,18,0,0" Orientation="Horizontal">
<TextBlock
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource currentActionKeywords}" />
<TextBlock
x:Name="tbOldActionKeyword"
Grid.Row="0"
Grid.Column="1"
Margin="14,10,10,10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock FontSize="14" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource newActionKeyword}" />
<TextBox x:Name="tbAction" Margin="10 10 15 10" Width="105" VerticalAlignment="Center" HorizontalAlignment="Left" />
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource newActionKeyword}" />
<TextBox
x:Name="tbAction"
Width="105"
Margin="10,10,15,10"
HorizontalAlignment="Left"
VerticalAlignment="Center" />
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="145"
Height="30"
Margin="10,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="145"
Height="30"
Margin="5,0,10,0"
Click="btnDone_OnClick"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="1">
<Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 5 0" Width="100" Height="30"
Content="{DynamicResource cancel}" />
<Button x:Name="btnDone" Margin="5 0 10 0" Width="100" Height="30" Click="btnDone_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Grid>
<!--
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="60"/>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock FontSize="14" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource currentActionKeywords}" />
<TextBlock x:Name="tbOldActionKeyword" Grid.Row="0" Grid.Column="1" Margin="170 10 10 10" FontSize="14"
VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock FontSize="14" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource newActionKeyword}" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Grid.Column="1">
<TextBox x:Name="tbAction" Margin="170 10 15 10" Width="105" VerticalAlignment="Center" HorizontalAlignment="Left" />
</StackPanel>
<TextBlock Grid.Row="2" Grid.ColumnSpan="1" Grid.Column="1" Foreground="Gray"
Text="{DynamicResource actionkeyword_tips}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="3" Grid.Column="1">
<Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 10 0" Width="80" Height="30"
Content="{DynamicResource cancel}" />
<Button x:Name="btnDone" Margin="10 0 10 0" Width="80" Height="30" Click="btnDone_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Grid>
-->
</Window>

View file

@ -1,16 +1,30 @@
<Application x:Class="Flow.Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.modernwpf.com/2019"
ShutdownMode="OnMainWindowClose"
Startup="OnStartupAsync">
<Application
x:Class="Flow.Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.modernwpf.com/2019"
ShutdownMode="OnMainWindowClose"
Startup="OnStartupAsync">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemeResources RequestedTheme="Light" />
<ui:ThemeResources>
<ui:ThemeResources.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Resources/Light.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Resources/Dark.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ui:ThemeResources.ThemeDictionaries>
</ui:ThemeResources>
<ui:XamlControlsResources />
<ResourceDictionary Source="pack://application:,,,/Resources/CustomControlTemplate.xaml" />
<ResourceDictionary Source="pack://application:,,,/Themes/Win11Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/Themes/Win11System.xaml" />
<ResourceDictionary Source="pack://application:,,,/Languages/en.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View file

@ -100,8 +100,6 @@ namespace Flow.Launcher
AutoUpdates();
API.SaveAppAllSettings();
_mainVM.MainWindowVisibility = _settings.HideOnStartup ? Visibility.Hidden : Visibility.Visible;
Log.Info("|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- ");
});
}
@ -178,7 +176,7 @@ namespace Flow.Launcher
public void OnSecondAppStarted()
{
Current.MainWindow.Visibility = Visibility.Visible;
Current.MainWindow.Show();
}
}
}

View file

@ -1,59 +1,160 @@
<Window x:Class="Flow.Launcher.CustomQueryHotkeySetting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
Icon="Images\app.png"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
MouseDown="window_MouseDown"
Title="{DynamicResource customeQueryHotkeyTitle}" Height="345" Width="500" Background="#F3F3F3" BorderBrush="#cecece">
<Window
x:Class="Flow.Launcher.CustomQueryHotkeySetting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
Title="{DynamicResource customeQueryHotkeyTitle}"
Width="500"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
Icon="Images\app.png"
MouseDown="window_MouseDown"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Window.InputBindings>
<KeyBinding Key="Escape" Command="Close"/>
<KeyBinding Key="Escape" Command="Close" />
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="Close" Executed="cmdEsc_OnPress"/>
<CommandBinding Command="Close" Executed="cmdEsc_OnPress" />
</Window.CommandBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80"/>
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Border BorderThickness="0 0 0 1" BorderBrush="#e5e5e5" Background="#ffffff" Padding="26 26 26 0">
<Grid>
<StackPanel>
<StackPanel Grid.Row="0" Margin="0 0 0 12">
<TextBlock Grid.Column="0" Text="{DynamicResource customeQueryHotkeyTitle}" FontSize="20" FontWeight="SemiBold" FontFamily="Segoe UI" TextAlignment="Left"
Margin="0 0 0 0" />
</StackPanel>
<StackPanel>
<TextBlock
Text="{DynamicResource customeQueryHotkeyTips}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 20 0 0">
<TextBlock Margin="10" FontSize="14" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource hotkey}" Width="60"/>
<flowlauncher:HotkeyControl x:Name="ctlHotkey" Margin="10,0,10,0" Grid.Column="1" VerticalAlignment="Center" Height="32" HorizontalAlignment="Left" HorizontalContentAlignment="Left" Width="200"/>
<TextBlock Margin="10" FontSize="14" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource actionKeyword}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 0 0 0">
<TextBlock Margin="10" FontSize="14" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Width="60"
HorizontalAlignment="Left" Text="{DynamicResource customQuery}" />
<TextBox x:Name="tbAction" Margin="10" Width="250" VerticalAlignment="Center" HorizontalAlignment="Left" />
<Button x:Name="btnTestActionKeyword" Padding="10 5 10 5" Height="30" Click="BtnTestActionKeyword_OnClick"
Content="{DynamicResource preview}" />
</StackPanel>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,0,26,0">
<StackPanel Grid.Row="0" Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource customeQueryHotkeyTitle}"
TextAlignment="Left" />
</StackPanel>
</Grid>
</Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="1">
<Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 5 0" Width="100" Height="32"
Content="{DynamicResource cancel}" />
<Button x:Name="btnAdd" Margin="5 0 10 0" Width="100" Height="32" Click="btnAdd_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
<StackPanel>
<TextBlock
FontSize="14"
Text="{DynamicResource customeQueryHotkeyTips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Margin="0,20,0,0" Orientation="Horizontal">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Width="60"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource hotkey}" />
<flowlauncher:HotkeyControl
x:Name="ctlHotkey"
Grid.Column="1"
Width="200"
Height="34"
Margin="10,0,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
HorizontalContentAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource actionKeyword}" />
</StackPanel>
<StackPanel Margin="0,0,0,0" Orientation="Horizontal">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Width="60"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource customQuery}" />
<TextBox
x:Name="tbAction"
Width="250"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center" />
<Button
x:Name="btnTestActionKeyword"
Height="30"
Padding="10,5,10,5"
Click="BtnTestActionKeyword_OnClick"
Content="{DynamicResource preview}" />
</StackPanel>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Margin="0,14,0,0"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="100"
Height="32"
Margin="10,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnAdd"
Width="100"
Height="32"
Margin="5,0,10,0"
Click="btnAdd_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Border>
</Grid>
</Window>

View file

@ -1,8 +1,6 @@
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
@ -91,9 +89,9 @@ namespace Flow.Launcher
private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e)
{
App.API.ChangeQuery(tbAction.Text);
Application.Current.MainWindow.Visibility = Visibility.Visible;
Application.Current.MainWindow.Show();
Application.Current.MainWindow.Opacity = 1;
Application.Current.MainWindow.Focus();
}
private void cmdEsc_OnPress(object sender, ExecutedRoutedEventArgs e)

View file

@ -104,6 +104,12 @@
<ProjectReference Include="..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="Resources\open.wav">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="taskkill /f /fi &quot;IMAGENAME eq Flow.Launcher.exe&quot;" />
</Target>

View file

@ -6,8 +6,6 @@ using NHotkey.Wpf;
using Flow.Launcher.Core.Resource;
using System.Windows;
using Flow.Launcher.ViewModel;
using System.Threading.Tasks;
using System.Threading;
namespace Flow.Launcher.Helper
{
@ -27,7 +25,8 @@ namespace Flow.Launcher.Helper
internal static void OnToggleHotkey(object sender, HotkeyEventArgs args)
{
mainViewModel.ToggleFlowLauncher();
if (!mainViewModel.GameModeStatus)
mainViewModel.ToggleFlowLauncher();
}
private static void SetHotkey(string hotkeyStr, EventHandler<HotkeyEventArgs> action)
@ -75,10 +74,10 @@ namespace Flow.Launcher.Helper
{
SetHotkey(hotkey.Hotkey, (s, e) =>
{
if (mainViewModel.ShouldIgnoreHotkeys())
if (mainViewModel.ShouldIgnoreHotkeys() || mainViewModel.GameModeStatus)
return;
mainViewModel.MainWindowVisibility = Visibility.Visible;
mainViewModel.Show();
mainViewModel.ChangeQueryText(hotkey.ActionKeyword, true);
});
}

View file

@ -10,7 +10,6 @@ namespace Flow.Launcher.Helper
{
var window = Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.GetType() == typeof(T))
?? (T)Activator.CreateInstance(typeof(T), args);
Application.Current.MainWindow.Hide();
// Fix UI bug
// Add `window.WindowState = WindowState.Normal`

View file

@ -1,26 +1,55 @@
<UserControl x:Class="Flow.Launcher.HotkeyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
mc:Ignorable="d"
Height="24"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl
x:Class="Flow.Launcher.HotkeyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="24"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Popup x:Name="popup" AllowDrop="True" PopupAnimation="Fade" PlacementTarget="{Binding ElementName=tbHotkey}" IsOpen="{Binding IsKeyboardFocused, ElementName=tbHotkey, Mode=OneWay}" StaysOpen="True" AllowsTransparency="True" Placement="Top" VerticalOffset="-5">
<Border Background="#f6f6f6" BorderBrush="#cecece" BorderThickness="1" CornerRadius="6" Width="120" Height="30">
<TextBlock x:Name="tbMsg" FontSize="13" FontWeight="SemiBold" Visibility="Visible" Margin="0 0 0 0" VerticalAlignment="Center" HorizontalAlignment="Center">
press key
<Popup
x:Name="popup"
AllowDrop="True"
AllowsTransparency="True"
IsOpen="{Binding IsKeyboardFocused, ElementName=tbHotkey, Mode=OneWay}"
Placement="Top"
PlacementTarget="{Binding ElementName=tbHotkey}"
PopupAnimation="Fade"
StaysOpen="True"
VerticalOffset="-5">
<Border
Width="140"
Height="30"
Background="{DynamicResource Color01B}"
BorderBrush="{DynamicResource Color21B}"
BorderThickness="1"
CornerRadius="4">
<TextBlock
x:Name="tbMsg"
Margin="0,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}"
Visibility="Visible">
Press key
</TextBlock>
</Border>
</Popup>
<TextBox x:Name="tbHotkey" TabIndex="100" VerticalContentAlignment="Center"
PreviewKeyDown="TbHotkey_OnPreviewKeyDown" input:InputMethod.IsInputMethodEnabled="False" Margin="0 0 18 0">
</TextBox>
<TextBox
x:Name="tbHotkey"
Margin="0,0,18,0"
VerticalContentAlignment="Center"
input:InputMethod.IsInputMethodEnabled="False"
PreviewKeyDown="TbHotkey_OnPreviewKeyDown"
TabIndex="100" />
</Grid>
</UserControl>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View file

@ -15,6 +15,8 @@
<system:String x:Key="iconTrayAbout">About</system:String>
<system:String x:Key="iconTrayExit">Exit</system:String>
<system:String x:Key="closeWindow">Close</system:String>
<system:String x:Key="GameMode">Game Mode</system:String>
<system:String x:Key="GameModeToolTip">Suspend the use of Hotkeys.</system:String>
<!-- Setting General -->
<system:String x:Key="flowlauncher_settings">Flow Launcher Settings</system:String>
@ -56,15 +58,17 @@
<system:String x:Key="disable">Off</system:String>
<system:String x:Key="actionKeywordsTitle">Action keyword Setting</system:String>
<system:String x:Key="actionKeywords">Action keyword</system:String>
<system:String x:Key="currentActionKeywords">Current action keyword:</system:String>
<system:String x:Key="newActionKeyword">New action keyword:</system:String>
<system:String x:Key="currentPriority">Current Priority:</system:String>
<system:String x:Key="newPriority">New Priority:</system:String>
<system:String x:Key="currentActionKeywords">Current action keyword</system:String>
<system:String x:Key="newActionKeyword">New action keyword</system:String>
<system:String x:Key="currentPriority">Current Priority</system:String>
<system:String x:Key="newPriority">New Priority</system:String>
<system:String x:Key="priority">Priority</system:String>
<system:String x:Key="pluginDirectory">Plugin Directory</system:String>
<system:String x:Key="author">Author:</system:String>
<system:String x:Key="plugin_init_time">Init time:</system:String>
<system:String x:Key="plugin_query_time">Query time:</system:String>
<system:String x:Key="plugin_query_version">| Version</system:String>
<system:String x:Key="plugin_query_web">Website</system:String>
<!-- Setting Plugin Store -->
@ -85,6 +89,14 @@
<system:String x:Key="theme_load_failure_parse_error">Fail to load theme {0}, fallback to default theme</system:String>
<system:String x:Key="ThemeFolder">Theme Folder</system:String>
<system:String x:Key="OpenThemeFolder">Open Theme Folder</system:String>
<system:String x:Key="ColorScheme">Color Scheme</system:String>
<system:String x:Key="ColorSchemeSystem">System Default</system:String>
<system:String x:Key="ColorSchemeLight">Light</system:String>
<system:String x:Key="ColorSchemeDark">Dark</system:String>
<system:String x:Key="SoundEffect">Sound Effect</system:String>
<system:String x:Key="SoundEffectTip">Play a small sound when the search window opens</system:String>
<system:String x:Key="Animation">Animation</system:String>
<system:String x:Key="AnimationTip">Use Animation in UI</system:String>
<!-- Setting Hotkey -->
<system:String x:Key="hotkey">Hotkey</system:String>
@ -126,6 +138,8 @@
<!-- Setting About -->
<system:String x:Key="about">About</system:String>
<system:String x:Key="website">Website</system:String>
<system:String x:Key="github">Github</system:String>
<system:String x:Key="docs">Docs</system:String>
<system:String x:Key="version">Version</system:String>
<system:String x:Key="about_activate_times">You have activated Flow Launcher {0} times</system:String>
<system:String x:Key="checkUpdates">Check for Updates</system:String>
@ -136,7 +150,10 @@
or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually.
</system:String>
<system:String x:Key="releaseNotes">Release Notes</system:String>
<system:String x:Key="documentation">Usage Tips:</system:String>
<system:String x:Key="documentation">Usage Tips</system:String>
<system:String x:Key="devtool">DevTools</system:String>
<system:String x:Key="settingfolder">Setting Folder</system:String>
<system:String x:Key="logfolder">Log Folder</system:String>
<!-- FileManager Setting Dialog -->
<system:String x:Key="fileManagerWindow">Select File Manager</system:String>
@ -173,7 +190,7 @@
<system:String x:Key="newActionKeywordsHasBeenAssigned">This new Action Keyword is already assigned to another plugin, please choose a different one</system:String>
<system:String x:Key="success">Success</system:String>
<system:String x:Key="completedSuccessfully">Completed successfully</system:String>
<system:String x:Key="actionkeyword_tips">Enter the action keyword you need to start the plug-in. Use * if you don't want to specify an action keyword. In the case, The plug-in works without keywords.</system:String>
<system:String x:Key="actionkeyword_tips">Enter the action keyword you like to use to start the plugin. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords.</system:String>
<!-- Custom Query Hotkey Dialog -->
<system:String x:Key="customeQueryHotkeyTitle">Custom Query Hotkey</system:String>

View file

@ -1,7 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow-->
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- MainWindow -->
<system:String x:Key="registerHotkeyFailed">핫키 등록 실패: {0}</system:String>
<system:String x:Key="couldnotStartCmd">{0}을 실행할 수 없습니다.</system:String>
<system:String x:Key="invalidFlowLauncherPluginFileFormat">Flow Launcher 플러그인 파일 형식이 유효하지 않습니다.</system:String>
@ -14,8 +15,10 @@
<system:String x:Key="iconTrayAbout">정보</system:String>
<system:String x:Key="iconTrayExit">종료</system:String>
<system:String x:Key="closeWindow">닫기</system:String>
<system:String x:Key="GameMode">게임 모드</system:String>
<system:String x:Key="GameModeToolTip">핫키 사용을 일시중단합니다.</system:String>
<!--Setting General-->
<!-- Setting General -->
<system:String x:Key="flowlauncher_settings">Flow Launcher 설정</system:String>
<system:String x:Key="general">일반</system:String>
<system:String x:Key="portableMode">포터블 모드</system:String>
@ -33,41 +36,48 @@
<system:String x:Key="maxShowResults">표시할 결과 수</system:String>
<system:String x:Key="ignoreHotkeysOnFullscreen">전체화면 모드에서는 핫키 무시</system:String>
<system:String x:Key="ignoreHotkeysOnFullscreenToolTip">게이머라면 켜는 것을 추천합니다.</system:String>
<system:String x:Key="defaultFileManager">기본 파일관리자</system:String>
<system:String x:Key="defaultFileManagerToolTip">폴더를 열 때 사용할 파일관리자를 선택하세요.</system:String>
<system:String x:Key="pythonDirectory">Python 디렉토리</system:String>
<system:String x:Key="autoUpdates">자동 업데이트</system:String>
<system:String x:Key="selectPythonDirectory">선택</system:String>
<system:String x:Key="hideOnStartup">시작 시 Flow Launcher 숨김</system:String>
<system:String x:Key="hideNotifyIcon">트레이 아이콘 숨기기</system:String>
<system:String x:Key="querySearchPrecision">쿼리 검색 정도</system:String>
<system:String x:Key="querySearchPrecisionToolTip">검색 결과가 좀 더 정확해집니다.</system:String>
<system:String x:Key="querySearchPrecision">쿼리 검색 정도</system:String>
<system:String x:Key="querySearchPrecisionToolTip">검색 결과에 필요한 최소 매치 점수를 변경합니다.</system:String>
<system:String x:Key="ShouldUsePinyin">항상 Pinyin 사용</system:String>
<system:String x:Key="ShouldUsePinyinToolTip">Pinyin을 사용하여 검색할 수 있습니다. Pinyin(병음)은 로마자 중국어 입력 방식입니다.</system:String>
<system:String x:Key="shadowEffectNotAllowed">반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다.</system:String>
<!--Setting Plugin-->
<!-- Setting Plugin -->
<system:String x:Key="plugin">플러그인</system:String>
<system:String x:Key="browserMorePlugins">플러그인 더 찾아보기</system:String>
<system:String x:Key="enable">On</system:String>
<system:String x:Key="disable">Off</system:String>
<system:String x:Key="enable"></system:String>
<system:String x:Key="disable"></system:String>
<system:String x:Key="actionKeywords">액션 키워드</system:String>
<system:String x:Key="currentActionKeywords">현재 액션 키워드</system:String>
<system:String x:Key="newActionKeyword">새 액션 키워드</system:String>
<system:String x:Key="currentPriority">현재 중요도:</system:String>
<system:String x:Key="newPriority">새 중요도:</system:String>
<system:String x:Key="priority">중요도</system:String>
<system:String x:Key="pluginDirectory">플러그인 디렉토리</system:String>
<system:String x:Key="author">자</system:String>
<system:String x:Key="pluginDirectory">플러그인 폴더</system:String>
<system:String x:Key="author">제작자</system:String>
<system:String x:Key="plugin_init_time">초기화 시간:</system:String>
<system:String x:Key="plugin_query_time">쿼리 시간:</system:String>
<!--Setting Plugin Store-->
<system:String x:Key="plugin_query_version">| 버전</system:String>
<system:String x:Key="plugin_query_web">웹사이트</system:String>
<!-- Setting Plugin Store -->
<system:String x:Key="pluginStore">플러그인 스토어</system:String>
<system:String x:Key="refresh">새로고침</system:String>
<system:String x:Key="install">설치</system:String>
<!--Setting Theme-->
<!-- Setting Theme -->
<system:String x:Key="theme">테마</system:String>
<system:String x:Key="browserMoreThemes">테마 더 찾아보기</system:String>
<system:String x:Key="browserMoreThemes">테마 갤러리</system:String>
<system:String x:Key="howToCreateTheme">테마 제작 안내</system:String>
<system:String x:Key="hiThere">Hi There</system:String>
<system:String x:Key="queryBoxFont">쿼리 상자 글꼴</system:String>
<system:String x:Key="resultItemFont">결과 항목 글꼴</system:String>
@ -77,8 +87,16 @@
<system:String x:Key="theme_load_failure_parse_error">{0} 테마 로드에 실패했습니다. 기본 테마로 변경합니다.</system:String>
<system:String x:Key="ThemeFolder">테마 폴더</system:String>
<system:String x:Key="OpenThemeFolder">테마 폴더 열기</system:String>
<system:String x:Key="ColorScheme">앱 색상</system:String>
<system:String x:Key="ColorSchemeSystem">시스템 기본</system:String>
<system:String x:Key="ColorSchemeLight">밝게</system:String>
<system:String x:Key="ColorSchemeDark">어둡게</system:String>
<system:String x:Key="SoundEffect">소리 효과</system:String>
<system:String x:Key="SoundEffectTip">검색창을 열 때 작은 소리를 재생합니다.</system:String>
<system:String x:Key="Animation">애니메이션</system:String>
<system:String x:Key="AnimationTip">일부 UI에 애니메이션을 사용합니다.</system:String>
<!--Setting Hotkey-->
<!-- Setting Hotkey -->
<system:String x:Key="hotkey">핫키</system:String>
<system:String x:Key="flowlauncherHotkey">Flow Launcher 핫키</system:String>
<system:String x:Key="flowlauncherHotkeyToolTip">Flow Launcher를 열 때 사용할 단축키를 입력합니다.</system:String>
@ -87,7 +105,7 @@
<system:String x:Key="showOpenResultHotkey">단축키 표시</system:String>
<system:String x:Key="showOpenResultHotkeyToolTip">결과창에서 결과 선택 단축키를 표시합니다.</system:String>
<system:String x:Key="customQueryHotkey">사용자지정 쿼리 핫키</system:String>
<system:String x:Key="customQuery">Query</system:String>
<system:String x:Key="customQuery">쿼리</system:String>
<system:String x:Key="delete">삭제</system:String>
<system:String x:Key="edit">편집</system:String>
<system:String x:Key="add">추가</system:String>
@ -95,10 +113,11 @@
<system:String x:Key="deleteCustomHotkeyWarning">{0} 플러그인 핫키를 삭제하시겠습니까?</system:String>
<system:String x:Key="queryWindowShadowEffect">그림자 효과</system:String>
<system:String x:Key="shadowEffectCPUUsage">그림자 효과는 GPU를 사용합니다. 컴퓨터 퍼포먼스가 제한적인 경우 사용을 추천하지 않습니다.</system:String>
<system:String x:Key="windowWidthSize">창 넓이</system:String>
<system:String x:Key="useGlyphUI">플루언트 아이콘 사용</system:String>
<system:String x:Key="useGlyphUIEffect">결과 및 일부 메뉴에서 플루언트 아이콘을 사용합니다.</system:String>
<!--Setting Proxy-->
<!-- Setting Proxy -->
<system:String x:Key="proxy">HTTP 프록시</system:String>
<system:String x:Key="enableProxy">HTTP 프록시 켜기</system:String>
<system:String x:Key="server">HTTP 서버</system:String>
@ -114,26 +133,41 @@
<system:String x:Key="proxyIsCorrect">프록시 설정 정상</system:String>
<system:String x:Key="proxyConnectFailed">프록시 연결 실패</system:String>
<!--Setting About-->
<!-- Setting About -->
<system:String x:Key="about">정보</system:String>
<system:String x:Key="website">웹사이트</system:String>
<system:String x:Key="github">Github</system:String>
<system:String x:Key="docs">문서</system:String>
<system:String x:Key="version">버전</system:String>
<system:String x:Key="about_activate_times">Flow Launcher를 {0}번 실행했습니다.</system:String>
<system:String x:Key="checkUpdates">업데이트 확인</system:String>
<system:String x:Key="newVersionTips">새 버전({0})이 있습니다. Flow Launcher를 재시작하세요.</system:String>
<system:String x:Key="checkUpdatesFailed">업데이트 확인을 실패했습니다. api.github.com로의 연결 또는 프록시 설정을 확인해주세요.</system:String>
<system:String x:Key="downloadUpdatesFailed">
업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요.
업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요.
수동 다운로드를 하려면 https://github.com/Flow-Launcher/Flow.Launcher/releases 으로 방문하세요.
</system:String>
<system:String x:Key="releaseNotes">릴리즈 노트:</system:String>
<system:String x:Key="documentation">사용 팁:</system:String>
<system:String x:Key="releaseNotes">릴리즈 노트</system:String>
<system:String x:Key="documentation">사용 팁</system:String>
<system:String x:Key="devtool">개발자도구</system:String>
<system:String x:Key="settingfolder">설정 폴더</system:String>
<system:String x:Key="logfolder">로그 폴더</system:String>
<!--Priority Setting Dialog-->
<!-- FileManager Setting Dialog -->
<system:String x:Key="fileManagerWindow">파일관리자 선택</system:String>
<system:String x:Key="fileManager_tips">사용하려는 파일관리자를 선택하고 필요한 경우 인수를 추가하세요. 기본 인수는 &quot;%d&quot; 이며 해당 위치에 경로가 입력됩니다. 예를들어 &quot;totalcmd.exe /A c:\windows&quot;와 같은 명령이 필요한 경우, 인수는 /A &quot;%d&quot; 입니다.</system:String>
<system:String x:Key="fileManager_tips2">&quot;%f&quot;는 특정 파일의 경로를 나타냅니다. 파일관리자에서 선택한 파일/폴더의 위치를 강조하는 기능에서 사용됩니다. 이 인수는 &quot;파일경로 인수&quot; 항목에서만 사용할 수 있습니다. 파일관리자에 해당 기능이 없거나 잘 모를 경우 &quot;%d&quot; 인수를 사용할 수 있습니다.</system:String>
<system:String x:Key="fileManager_name">파일관리자</system:String>
<system:String x:Key="fileManager_profile_name">프로필 이름</system:String>
<system:String x:Key="fileManager_path">파일관리자 경로</system:String>
<system:String x:Key="fileManager_directory_arg">폴더경로 인수</system:String>
<system:String x:Key="fileManager_file_arg">파일경로 인수</system:String>
<!-- Priority Setting Dialog -->
<system:String x:Key="changePriorityWindow">중요도 변경</system:String>
<system:String x:Key="priority_tips">높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮추고 싶다면, 그보다 낮은 수를 입력하세요.</system:String>
<system:String x:Key="priority_tips">높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮춰 표시하고 싶다면, 그보다 낮은 수를 입력하세요.</system:String>
<system:String x:Key="invalidPriority">중요도에 올바른 정수를 입력하세요.</system:String>
<!--Action Keyword Setting Dialog-->
<!-- Action Keyword Setting Dialog -->
<system:String x:Key="oldActionKeywords">예전 액션 키워드</system:String>
<system:String x:Key="newActionKeywords">새 액션 키워드</system:String>
<system:String x:Key="cancel">취소</system:String>
@ -143,19 +177,20 @@
<system:String x:Key="newActionKeywordsHasBeenAssigned">새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요.</system:String>
<system:String x:Key="success">성공</system:String>
<system:String x:Key="completedSuccessfully">성공적으로 완료했습니다.</system:String>
<system:String x:Key="actionkeyword_tips">액션 키워드를 지정하지 않으려면 *를 사용하세요.</system:String>
<system:String x:Key="actionkeyword_tips">플러그인을 시작하는데 필요한 액션 키워드를 입력하세요. 액션 키워드를 지정하지 않으려면 *를 사용하세요. 이 경우 키워드를 입력하지 않아도 동작합니다.</system:String>
<!--Custom Query Hotkey Dialog-->
<!-- Custom Query Hotkey Dialog -->
<system:String x:Key="customeQueryHotkeyTitle">커스텀 플러그인 핫키</system:String>
<system:String x:Key="customeQueryHotkeyTips">단축키를 지정하여 특정 쿼리를 자동으로 입력할 수 있습니다. 사용하고 싶은 단축키를 눌러 지정한 후, 사용할 쿼리를 입력하세요.</system:String>
<system:String x:Key="preview">미리보기</system:String>
<system:String x:Key="hotkeyIsNotUnavailable">핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요.</system:String>
<system:String x:Key="invalidPluginHotkey">플러그인 핫키가 유효하지 않습니다.</system:String>
<system:String x:Key="update">업데이트</system:String>
<!--Hotkey Control-->
<!-- Hotkey Control -->
<system:String x:Key="hotkeyUnavailable">핫키를 사용할 수 없습니다.</system:String>
<!--Crash Reporter-->
<!-- Crash Reporter -->
<system:String x:Key="reportWindow_version">버전</system:String>
<system:String x:Key="reportWindow_time">시간</system:String>
<system:String x:Key="reportWindow_reproduce">수정을 위해 애플리케이션이 어떻게 충돌했는지 알려주세요.</system:String>
@ -170,17 +205,19 @@
<system:String x:Key="reportWindow_report_succeed">보고서를 정상적으로 보냈습니다.</system:String>
<system:String x:Key="reportWindow_report_failed">보고서를 보내지 못했습니다.</system:String>
<system:String x:Key="reportWindow_flowlauncher_got_an_error">Flow Launcher에 문제가 발생했습니다.</system:String>
<!--General Notice-->
<!-- General Notice -->
<system:String x:Key="pleaseWait">잠시 기다려주세요...</system:String>
<!--update-->
<!-- update -->
<system:String x:Key="update_flowlauncher_update_check">새 업데이트 확인 중</system:String>
<system:String x:Key="update_flowlauncher_update_new_version_available">새 Flow Launcher 버전({0})을 사용할 수 있습니다.</system:String>
<system:String x:Key="update_flowlauncher_already_on_latest">이미 가장 최신 버전의 Flow Launcher를 사용중입니다.</system:String>
<system:String x:Key="update_flowlauncher_update_found">업데이트 발견</system:String>
<system:String x:Key="update_flowlauncher_updating">업데이트 중...</system:String>
<system:String x:Key="update_flowlauncher_fail_moving_portable_user_profile_data">Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다.
프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요. </system:String>
<system:String x:Key="update_flowlauncher_fail_moving_portable_user_profile_data">
Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다.
프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요.
</system:String>
<system:String x:Key="update_flowlauncher_new_update">새 업데이트</system:String>
<system:String x:Key="update_flowlauncher_update_error">소프트웨어 업데이트를 설치하는 중에 오류가 발생했습니다.</system:String>
<system:String x:Key="update_flowlauncher_update">업데이트</system:String>

View file

@ -1,105 +1,200 @@
<Window x:Class="Flow.Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
mc:Ignorable="d"
Title="Flow Launcher"
Topmost="True"
SizeToContent="Height"
ResizeMode="NoResize"
WindowStyle="None"
WindowStartupLocation="Manual"
AllowDrop="True"
ShowInTaskbar="False"
Style="{DynamicResource WindowStyle}"
Icon="Images/app.png"
AllowsTransparency="True"
Background="Transparent"
Loaded="OnLoaded"
Initialized="OnInitialized"
Closing="OnClosing"
LocationChanged="OnLocationChanged"
Deactivated="OnDeactivated"
PreviewKeyDown="OnKeyDown"
MinWidth="{Binding MainWindowWidth, Mode=OneWay}"
MaxWidth="{Binding MainWindowWidth, Mode=OneWay}"
Visibility="{Binding MainWindowVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
d:DataContext="{d:DesignInstance vm:MainViewModel}">
<Window
x:Class="Flow.Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:Flow.Launcher.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
Name="FlowMainWindow"
Title="Flow Launcher"
MinWidth="{Binding MainWindowWidth, Mode=OneWay}"
MaxWidth="{Binding MainWindowWidth, Mode=OneWay}"
d:DataContext="{d:DesignInstance vm:MainViewModel}"
AllowDrop="True"
AllowsTransparency="True"
Background="Transparent"
Closing="OnClosing"
Deactivated="OnDeactivated"
Icon="Images/app.png"
Initialized="OnInitialized"
Loaded="OnLoaded"
LocationChanged="OnLocationChanged"
Opacity="{Binding MainWindowOpacity, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
PreviewKeyDown="OnKeyDown"
ResizeMode="NoResize"
ShowInTaskbar="False"
SizeToContent="Height"
Style="{DynamicResource WindowStyle}"
Topmost="True"
Visibility="{Binding MainWindowVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
WindowStartupLocation="Manual"
WindowStyle="None"
mc:Ignorable="d">
<Window.Resources>
<converters:QuerySuggestionBoxConverter x:Key="QuerySuggestionBoxConverter"/>
<converters:BorderClipConverter x:Key="BorderClipConverter"/>
<converters:QuerySuggestionBoxConverter x:Key="QuerySuggestionBoxConverter" />
<converters:BorderClipConverter x:Key="BorderClipConverter" />
</Window.Resources>
<Window.InputBindings>
<KeyBinding Key="Escape" Command="{Binding EscCommand}"></KeyBinding>
<KeyBinding Key="F1" Command="{Binding StartHelpCommand}"></KeyBinding>
<KeyBinding Key="F5" Command="{Binding ReloadPluginDataCommand}"></KeyBinding>
<KeyBinding Key="Tab" Command="{Binding SelectNextItemCommand}"></KeyBinding>
<KeyBinding Key="Tab" Modifiers="Shift" Command="{Binding SelectPrevItemCommand}"></KeyBinding>
<KeyBinding Key="N" Modifiers="Ctrl" Command="{Binding SelectNextItemCommand}"></KeyBinding>
<KeyBinding Key="J" Modifiers="Ctrl" Command="{Binding SelectNextItemCommand}"></KeyBinding>
<KeyBinding Key="D" Modifiers="Ctrl" Command="{Binding SelectNextPageCommand}"></KeyBinding>
<KeyBinding Key="P" Modifiers="Ctrl" Command="{Binding SelectPrevItemCommand}"></KeyBinding>
<KeyBinding Key="K" Modifiers="Ctrl" Command="{Binding SelectPrevItemCommand}"></KeyBinding>
<KeyBinding Key="U" Modifiers="Ctrl" Command="{Binding SelectPrevPageCommand}"></KeyBinding>
<KeyBinding Key="Home" Modifiers="Alt" Command="{Binding SelectFirstResultCommand}"></KeyBinding>
<KeyBinding Key="O" Modifiers="Ctrl" Command="{Binding LoadContextMenuCommand}"></KeyBinding>
<KeyBinding Key="Right" Command="{Binding LoadContextMenuCommand}"></KeyBinding>
<KeyBinding Key="Left" Command="{Binding EscCommand}"></KeyBinding>
<KeyBinding Key="H" Modifiers="Ctrl" Command="{Binding LoadHistoryCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Ctrl+Shift" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Shift" Command="{Binding LoadContextMenuCommand}"></KeyBinding>
<KeyBinding Key="Enter" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Ctrl" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="Enter" Modifiers="Alt" Command="{Binding OpenResultCommand}"></KeyBinding>
<KeyBinding Key="D1" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="0"></KeyBinding>
<KeyBinding Key="D2" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="1"></KeyBinding>
<KeyBinding Key="D3" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="2"></KeyBinding>
<KeyBinding Key="D4" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="3"></KeyBinding>
<KeyBinding Key="D5" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="4"></KeyBinding>
<KeyBinding Key="D6" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="5"></KeyBinding>
<KeyBinding Key="D7" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="6"></KeyBinding>
<KeyBinding Key="D8" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="7"></KeyBinding>
<KeyBinding Key="D9" Modifiers="{Binding OpenResultCommandModifiers}" Command="{Binding OpenResultCommand}" CommandParameter="8"></KeyBinding>
<KeyBinding Key="Escape" Command="{Binding EscCommand}" />
<KeyBinding Key="F1" Command="{Binding StartHelpCommand}" />
<KeyBinding Key="F5" Command="{Binding ReloadPluginDataCommand}" />
<KeyBinding Key="Tab" Command="{Binding SelectNextItemCommand}" />
<KeyBinding
Key="Tab"
Command="{Binding SelectPrevItemCommand}"
Modifiers="Shift" />
<KeyBinding
Key="I"
Command="{Binding OpenSettingCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="N"
Command="{Binding SelectNextItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="J"
Command="{Binding SelectNextItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="D"
Command="{Binding SelectNextPageCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="P"
Command="{Binding SelectPrevItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="K"
Command="{Binding SelectPrevItemCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="U"
Command="{Binding SelectPrevPageCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="Home"
Command="{Binding SelectFirstResultCommand}"
Modifiers="Alt" />
<KeyBinding
Key="O"
Command="{Binding LoadContextMenuCommand}"
Modifiers="Ctrl" />
<KeyBinding Key="Right" Command="{Binding LoadContextMenuCommand}" />
<KeyBinding Key="Left" Command="{Binding EscCommand}" />
<KeyBinding
Key="H"
Command="{Binding LoadHistoryCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="Enter"
Command="{Binding OpenResultCommand}"
Modifiers="Ctrl+Shift" />
<KeyBinding
Key="Enter"
Command="{Binding LoadContextMenuCommand}"
Modifiers="Shift" />
<KeyBinding Key="Enter" Command="{Binding OpenResultCommand}" />
<KeyBinding
Key="Enter"
Command="{Binding OpenResultCommand}"
Modifiers="Ctrl" />
<KeyBinding
Key="Enter"
Command="{Binding OpenResultCommand}"
Modifiers="Alt" />
<KeyBinding
Key="D1"
Command="{Binding OpenResultCommand}"
CommandParameter="0"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D2"
Command="{Binding OpenResultCommand}"
CommandParameter="1"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D3"
Command="{Binding OpenResultCommand}"
CommandParameter="2"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D4"
Command="{Binding OpenResultCommand}"
CommandParameter="3"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D5"
Command="{Binding OpenResultCommand}"
CommandParameter="4"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D6"
Command="{Binding OpenResultCommand}"
CommandParameter="5"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D7"
Command="{Binding OpenResultCommand}"
CommandParameter="6"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D8"
Command="{Binding OpenResultCommand}"
CommandParameter="7"
Modifiers="{Binding OpenResultCommandModifiers}" />
<KeyBinding
Key="D9"
Command="{Binding OpenResultCommand}"
CommandParameter="8"
Modifiers="{Binding OpenResultCommandModifiers}" />
</Window.InputBindings>
<Grid>
<Border Style="{DynamicResource WindowBorderStyle}" MouseDown="OnMouseDown">
<Border MouseDown="OnMouseDown" Style="{DynamicResource WindowBorderStyle}">
<StackPanel Orientation="Vertical">
<Grid>
<TextBox x:Name="QueryTextSuggestionBox"
Style="{DynamicResource QuerySuggestionBoxStyle}"
IsEnabled="False">
<TextBox
x:Name="QueryTextSuggestionBox"
IsEnabled="False"
Style="{DynamicResource QuerySuggestionBoxStyle}">
<TextBox.Text>
<MultiBinding Converter="{StaticResource QuerySuggestionBoxConverter}">
<Binding ElementName="QueryTextBox" Path="Text"/>
<Binding ElementName="ResultListBox" Path="SelectedItem"/>
<Binding ElementName="QueryTextBox" Path="Text" />
<Binding ElementName="ResultListBox" Path="SelectedItem" />
</MultiBinding>
</TextBox.Text>
</TextBox>
<TextBox x:Name="QueryTextBox"
Style="{DynamicResource QueryBoxStyle}"
Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
PreviewDragOver="OnPreviewDragOver"
AllowDrop="True"
Visibility="Visible"
Background="Transparent">
<TextBox
x:Name="QueryTextBox"
AllowDrop="True"
Background="Transparent"
PreviewDragOver="OnPreviewDragOver"
Style="{DynamicResource QueryBoxStyle}"
Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Visibility="Visible">
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Command="ApplicationCommands.Cut"/>
<MenuItem Command="ApplicationCommands.Copy"/>
<MenuItem Command="ApplicationCommands.Paste"/>
<Separator />
<MenuItem Header="{DynamicResource flowlauncher_settings}" Click="OnContextMenusForSettingsClick" />
<MenuItem Command="{Binding EscCommand}" Header="{DynamicResource closeWindow}"/>
<MenuItem Command="ApplicationCommands.Cut" />
<MenuItem Command="ApplicationCommands.Copy" />
<MenuItem Command="ApplicationCommands.Paste" />
<Separator
Margin="0"
Padding="0,4,0,4"
Background="{DynamicResource ContextSeparator}" />
<MenuItem Click="OnContextMenusForSettingsClick" Header="{DynamicResource flowlauncher_settings}" />
<MenuItem Command="{Binding EscCommand}" Header="{DynamicResource closeWindow}" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
<Canvas Style="{DynamicResource SearchIconPosition}">
<Path Data="{DynamicResource SearchIconImg}" Style="{DynamicResource SearchIconStyle}" Margin="0" Stretch="Fill"/>
<Path
Name="SearchIcon"
Margin="0"
Data="{DynamicResource SearchIconImg}"
Stretch="Fill"
Style="{DynamicResource SearchIconStyle}" />
</Canvas>
</Grid>
@ -121,49 +216,69 @@
</Style.Triggers>
</Style>
</ContentControl.Style>
<Rectangle Width="Auto" HorizontalAlignment="Stretch" Style="{DynamicResource SeparatorStyle}"/>
<Rectangle
Width="Auto"
HorizontalAlignment="Stretch"
Style="{DynamicResource SeparatorStyle}" />
</ContentControl>
<Line x:Name="ProgressBar" HorizontalAlignment="Right"
Style="{DynamicResource PendingLineStyle}" Visibility="{Binding ProgressBarVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Y1="0" Y2="0" X1="-150" X2="-50" Height="2" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}},Path=ActualWidth}" StrokeThickness="1">
</Line>
<Line
x:Name="ProgressBar"
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="2"
HorizontalAlignment="Right"
StrokeThickness="1"
Style="{DynamicResource PendingLineStyle}"
Visibility="{Binding ProgressBarVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
X1="-150"
X2="-50"
Y1="0"
Y2="0" />
</Grid>
<Border Style="{DynamicResource WindowRadius}">
<Border.Clip>
<MultiBinding Converter="{StaticResource BorderClipConverter}">
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" />
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.Clip>
<ContentControl>
<flowlauncher:ResultListBox x:Name="ResultListBox" DataContext="{Binding Results}" PreviewMouseDown="OnPreviewMouseButtonDown" />
<flowlauncher:ResultListBox
x:Name="ResultListBox"
DataContext="{Binding Results}"
PreviewMouseDown="OnPreviewMouseButtonDown" />
</ContentControl>
</Border>
<Border Style="{DynamicResource WindowRadius}">
<Border.Clip>
<MultiBinding Converter="{StaticResource BorderClipConverter}">
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" />
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.Clip>
<ContentControl>
<flowlauncher:ResultListBox DataContext="{Binding ContextMenu}" PreviewMouseDown="OnPreviewMouseButtonDown" x:Name="ContextMenu"/>
</ContentControl>
<ContentControl>
<flowlauncher:ResultListBox
x:Name="ContextMenu"
DataContext="{Binding ContextMenu}"
PreviewMouseDown="OnPreviewMouseButtonDown" />
</ContentControl>
</Border>
<Border Style="{DynamicResource WindowRadius}">
<Border.Clip>
<Border.Clip>
<MultiBinding Converter="{StaticResource BorderClipConverter}">
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" />
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Border.Clip>
<ContentControl>
<flowlauncher:ResultListBox DataContext="{Binding History}" PreviewMouseDown="OnPreviewMouseButtonDown" x:Name="History"/>
</ContentControl>
</Border.Clip>
<ContentControl>
<flowlauncher:ResultListBox
x:Name="History"
DataContext="{Binding History}"
PreviewMouseDown="OnPreviewMouseButtonDown" />
</ContentControl>
</Border>
</StackPanel>
</Border>

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
@ -11,16 +11,12 @@ using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.ViewModel;
using Microsoft.AspNetCore.Authorization;
using Application = System.Windows.Application;
using Screen = System.Windows.Forms.Screen;
using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip;
using DataFormats = System.Windows.DataFormats;
using DragEventArgs = System.Windows.DragEventArgs;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MessageBox = System.Windows.MessageBox;
using NotifyIcon = System.Windows.Forms.NotifyIcon;
using System.Windows.Interop;
using Flow.Launcher.Infrastructure;
namespace Flow.Launcher
{
@ -34,6 +30,7 @@ namespace Flow.Launcher
private NotifyIcon _notifyIcon;
private ContextMenu contextMenu;
private MainViewModel _viewModel;
private bool _animating;
#endregion
@ -43,6 +40,7 @@ namespace Flow.Launcher
_viewModel = mainVM;
_settings = settings;
InitializeComponent();
InitializePosition();
}
public MainWindow()
@ -52,6 +50,8 @@ namespace Flow.Launcher
private async void OnClosing(object sender, CancelEventArgs e)
{
_settings.WindowTop = Top;
_settings.WindowLeft = Left;
_notifyIcon.Visible = false;
_viewModel.Save();
e.Cancel = true;
@ -65,12 +65,12 @@ namespace Flow.Launcher
private void OnLoaded(object sender, RoutedEventArgs _)
{
HideStartup();
// show notify icon when flowlauncher is hidden
InitializeNotifyIcon();
InitializeColorScheme();
WindowsInteropHelper.DisableControlBox(this);
InitProgressbarAnimation();
InitializePosition();
// since the default main window visibility is visible
// so we need set focus during startup
QueryTextBox.Focus();
@ -79,13 +79,13 @@ namespace Flow.Launcher
{
switch (e.PropertyName)
{
case nameof(MainViewModel.MainWindowVisibility):
case nameof(MainViewModel.MainWindowVisibilityStatus):
{
if (_viewModel.MainWindowVisibility == Visibility.Visible)
if (_viewModel.MainWindowVisibilityStatus)
{
UpdatePosition();
Activate();
QueryTextBox.Focus();
UpdatePosition();
_settings.ActivateTimes++;
if (!_viewModel.LastQuerySelected)
{
@ -117,7 +117,7 @@ namespace Flow.Launcher
_progressBarStoryboard.Stop(ProgressBar);
isProgressBarStoryboardPaused = true;
}
else if (_viewModel.MainWindowVisibility == Visibility.Visible &&
else if (_viewModel.MainWindowVisibilityStatus &&
isProgressBarStoryboardPaused)
{
_progressBarStoryboard.Begin(ProgressBar, true);
@ -148,24 +148,29 @@ namespace Flow.Launcher
break;
}
};
InitializePosition();
}
private void InitializePosition()
{
Top = WindowTop();
Left = WindowLeft();
_settings.WindowTop = Top;
_settings.WindowLeft = Left;
if (_settings.RememberLastLaunchLocation)
{
Top = _settings.WindowTop;
Left = _settings.WindowLeft;
}
else
{
Left = WindowLeft();
Top = WindowTop();
}
}
private void UpdateNotifyIconText()
{
var menu = contextMenu;
((MenuItem)menu.Items[1]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen");
((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings");
((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit");
((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("GameMode");
((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings");
((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit");
}
private void InitializeNotifyIcon()
@ -180,13 +185,17 @@ namespace Flow.Launcher
var header = new MenuItem
{
Header = "Flow Launcher",
Header = "Flow Launcher",
IsEnabled = false
};
var open = new MenuItem
{
Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen")
};
var gamemode = new MenuItem
{
Header = InternationalizationManager.Instance.GetTranslation("GameMode")
};
var settings = new MenuItem
{
Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings")
@ -196,11 +205,14 @@ namespace Flow.Launcher
Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit")
};
open.Click += (o, e) => Visibility = Visibility.Visible;
open.Click += (o, e) => _viewModel.ToggleFlowLauncher();
gamemode.Click += (o, e) => ToggleGameMode();
settings.Click += (o, e) => App.API.OpenSettingDialog();
exit.Click += (o, e) => Close();
contextMenu.Items.Add(header);
contextMenu.Items.Add(open);
gamemode.ToolTip = InternationalizationManager.Instance.GetTranslation("GameModeToolTip");
contextMenu.Items.Add(gamemode);
contextMenu.Items.Add(settings);
contextMenu.Items.Add(exit);
@ -220,6 +232,19 @@ namespace Flow.Launcher
};
}
private void ToggleGameMode()
{
if (_viewModel.GameModeStatus)
{
_notifyIcon.Icon = Properties.Resources.app;
_viewModel.GameModeStatus = false;
}
else
{
_notifyIcon.Icon = Properties.Resources.gamemode;
_viewModel.GameModeStatus = true;
}
}
private void InitProgressbarAnimation()
{
var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 150,
@ -235,6 +260,54 @@ namespace Flow.Launcher
isProgressBarStoryboardPaused = true;
}
public void WindowAnimator()
{
if (_animating)
return;
_animating = true;
UpdatePosition();
Storyboard sb = new Storyboard();
Storyboard iconsb = new Storyboard();
CircleEase easing = new CircleEase(); // or whatever easing class you want
easing.EasingMode = EasingMode.EaseInOut;
var da = new DoubleAnimation
{
From = 0,
To = 1,
Duration = TimeSpan.FromSeconds(0.25),
FillBehavior = FillBehavior.Stop
};
var da2 = new DoubleAnimation
{
From = Top + 10,
To = Top,
Duration = TimeSpan.FromSeconds(0.25),
FillBehavior = FillBehavior.Stop
};
var da3 = new DoubleAnimation
{
From = 12,
To = 0,
EasingFunction = easing,
Duration = TimeSpan.FromSeconds(0.36),
FillBehavior = FillBehavior.Stop
};
Storyboard.SetTarget(da, this);
Storyboard.SetTargetProperty(da, new PropertyPath(Window.OpacityProperty));
Storyboard.SetTargetProperty(da2, new PropertyPath(Window.TopProperty));
Storyboard.SetTargetProperty(da3, new PropertyPath(TopProperty));
sb.Children.Add(da);
sb.Children.Add(da2);
iconsb.Children.Add(da3);
sb.Completed += (_, _) => _animating = false;
_settings.WindowLeft = Left;
_settings.WindowTop = Top;
iconsb.Begin(SearchIcon);
sb.Begin(FlowMainWindow);
}
private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left) DragMove();
@ -267,22 +340,41 @@ namespace Flow.Launcher
e.Handled = true;
}
private void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e)
private async void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e)
{
_viewModel.Hide();
if(_settings.UseAnimation)
await Task.Delay(100);
App.API.OpenSettingDialog();
}
private void OnDeactivated(object sender, EventArgs e)
private async void OnDeactivated(object sender, EventArgs e)
{
if (_settings.HideWhenDeactive)
//This condition stops extra hide call when animator is on,
// which causes the toggling to occasional hide instead of show.
if (_viewModel.MainWindowVisibilityStatus)
{
_viewModel.Hide();
// Need time to initialize the main query window animation.
// This also stops the mainwindow from flickering occasionally after Settings window is opened
// and always after Settings window is closed.
if (_settings.UseAnimation)
await Task.Delay(100);
if (_settings.HideWhenDeactive)
{
_viewModel.Hide();
}
}
}
private void UpdatePosition()
{
if (_animating)
return;
if (_settings.RememberLastLaunchLocation)
{
Left = _settings.WindowLeft;
@ -297,6 +389,8 @@ namespace Flow.Launcher
private void OnLocationChanged(object sender, EventArgs e)
{
if (_animating)
return;
if (_settings.RememberLastLaunchLocation)
{
_settings.WindowLeft = Left;
@ -304,7 +398,20 @@ namespace Flow.Launcher
}
}
private double WindowLeft()
public void HideStartup()
{
UpdatePosition();
if (_settings.HideOnStartup)
{
_viewModel.Hide();
}
else
{
_viewModel.Show();
}
}
public double WindowLeft()
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
@ -313,7 +420,7 @@ namespace Flow.Launcher
return left;
}
private double WindowTop()
public double WindowTop()
{
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
@ -372,5 +479,17 @@ namespace Flow.Launcher
{
QueryTextBox.CaretIndex = QueryTextBox.Text.Length;
}
public void InitializeColorScheme()
{
if (_settings.ColorScheme == Constant.Light)
{
ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Light;
}
else if (_settings.ColorScheme == Constant.Dark)
{
ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Dark;
}
}
}
}

View file

@ -7,84 +7,118 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{DynamicResource changePriorityWindow}"
Background="#F3F3F3"
BorderBrush="#cecece"
Width="350"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
Loaded="PriorityChangeWindow_Loaded"
MouseDown="window_MouseDown"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid Width="350">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Border
Padding="26,26,26,0"
Background="#ffffff"
BorderBrush="#e5e5e5"
BorderThickness="0,0,0,1">
<Grid>
<StackPanel>
<StackPanel Grid.Row="0" Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource changePriorityWindow}"
TextAlignment="Left" />
</StackPanel>
<StackPanel>
<TextBlock
FontSize="14"
Foreground="#1b1b1b"
Text="{DynamicResource priority_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Margin="0,24,0,24" Orientation="Horizontal">
<TextBlock
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource priority}" />
<ui:NumberBox
x:Name="tbAction"
Width="190"
Height="34"
Margin="10,0,15,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Minimum="0"
SmallChange="1"
SpinButtonPlacementMode="Inline" />
</StackPanel>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<StackPanel Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource changePriorityWindow}"
TextAlignment="Left" />
</StackPanel>
</Grid>
</Border>
<StackPanel
Grid.Row="1"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="100"
Height="30"
Margin="0,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="100"
Height="30"
Margin="5,0,0,0"
Click="btnDone_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
<StackPanel>
<TextBlock
FontSize="14"
Text="{DynamicResource priority_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Margin="0,24,0,24" Orientation="Horizontal">
<TextBlock
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource priority}" />
<ui:NumberBox
x:Name="tbAction"
Width="200"
Margin="10,0,15,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
CornerRadius="4"
Minimum="0"
SmallChange="1"
SpinButtonPlacementMode="Inline" />
</StackPanel>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="145"
Height="30"
Margin="0,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="145"
Height="30"
Margin="5,0,0,0"
Click="btnDone_OnClick"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Border>
</Grid>
</Window>

View file

@ -69,5 +69,13 @@ namespace Flow.Launcher.Properties {
return ((System.Drawing.Icon)(obj));
}
}
internal static System.Drawing.Icon gamemode
{
get
{
object obj = ResourceManager.GetObject("gamemode", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}

View file

@ -112,13 +112,16 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="app" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="gamemode" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Images\gamemode.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
@ -14,6 +14,7 @@ using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel;
using Flow.Launcher.Plugin.SharedModels;
using Flow.Launcher.Plugin.SharedCommands;
using System.Threading;
using System.IO;
using Flow.Launcher.Infrastructure.Http;
@ -55,7 +56,7 @@ namespace Flow.Launcher
public void RestartApp()
{
_mainVM.MainWindowVisibility = Visibility.Hidden;
_mainVM.Hide();
// we must manually save
// UpdateManager.RestartApp() will call Environment.Exit(0)
@ -70,7 +71,7 @@ namespace Flow.Launcher
public void RestarApp() => RestartApp();
public void ShowMainWindow() => _mainVM.MainWindowVisibility = Visibility.Visible;
public void ShowMainWindow() => _mainVM.Show();
public void CheckForNewUpdate() => _settingsVM.UpdateApp();
@ -106,6 +107,19 @@ namespace Flow.Launcher
});
}
public void ShellRun(string cmd, string filename = "cmd.exe")
{
var args = filename == "cmd.exe" ? $"/C {cmd}" : $"{cmd}";
var startInfo = ShellCommand.SetProcessStartInfo(filename, arguments: args, createNoWindow: true);
ShellCommand.Execute(startInfo);
}
public void CopyToClipboard(string text)
{
Clipboard.SetDataObject(text);
}
public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible;
public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed;
@ -213,4 +227,4 @@ namespace Flow.Launcher
#endregion
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -1,25 +1,32 @@
<ListBox x:Class="Flow.Launcher.ResultListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
xmlns:converter="clr-namespace:Flow.Launcher.Converters"
mc:Ignorable="d" d:DesignWidth="100" d:DesignHeight="100"
d:DataContext="{d:DesignInstance vm:ResultsViewModel}"
MaxHeight="{Binding MaxHeight}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
HorizontalContentAlignment="Stretch" ItemsSource="{Binding Results}"
Margin="{Binding Margin}"
Visibility="{Binding Visbility}"
Style="{DynamicResource BaseListboxStyle}" Focusable="False"
KeyboardNavigation.DirectionalNavigation="Cycle" SelectionMode="Single"
VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Standard"
SelectionChanged="OnSelectionChanged"
IsSynchronizedWithCurrentItem="True"
PreviewMouseDown="ListBox_PreviewMouseDown">
<!--IsSynchronizedWithCurrentItem: http://stackoverflow.com/a/7833798/2833083-->
<ListBox
x:Class="Flow.Launcher.ResultListBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:Flow.Launcher.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Flow.Launcher.ViewModel"
MaxHeight="{Binding MaxHeight}"
Margin="{Binding Margin}"
HorizontalContentAlignment="Stretch"
d:DataContext="{d:DesignInstance vm:ResultsViewModel}"
d:DesignHeight="100"
d:DesignWidth="100"
Focusable="False"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Results}"
KeyboardNavigation.DirectionalNavigation="Cycle"
PreviewMouseDown="ListBox_PreviewMouseDown"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
SelectionChanged="OnSelectionChanged"
SelectionMode="Single"
Style="{DynamicResource BaseListboxStyle}"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard"
Visibility="{Binding Visbility}"
mc:Ignorable="d">
<!-- IsSynchronizedWithCurrentItem: http://stackoverflow.com/a/7833798/2833083 -->
<ListBox.ItemTemplate>
<DataTemplate>
@ -30,46 +37,88 @@
</ControlTemplate>
</Button.Template>
<Button.Content>
<Grid HorizontalAlignment="Left" VerticalAlignment="Stretch" Margin="0"
Cursor="Hand" UseLayoutRounding="False">
<Grid
Margin="0"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Cursor="Hand"
UseLayoutRounding="False">
<Grid.Resources>
<converter:HighlightTextConverter x:Key="HighlightTextConverter"/>
<converter:HighlightTextConverter x:Key="HighlightTextConverter" />
<converter:OrdinalConverter x:Key="OrdinalConverter" />
<converter:OpenResultHotkeyVisibilityConverter x:Key="OpenResultHotkeyVisibilityConverter" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Visibility="{Binding ShowOpenResultHotkey}" Grid.Column="2" Margin="0 0 10 0">
<TextBlock Margin="12 0 12 0" Style="{DynamicResource ItemHotkeyStyle}" HorizontalAlignment="Right" Opacity="0.8" VerticalAlignment="Center" Padding="0 10 0 10" x:Name="Hotkey">
<StackPanel
Grid.Column="2"
Margin="0,0,10,0"
Visibility="{Binding ShowOpenResultHotkey}">
<TextBlock
x:Name="Hotkey"
Margin="12,0,12,0"
Padding="0,10,0,10"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Opacity="0.8"
Style="{DynamicResource ItemHotkeyStyle}">
<TextBlock.Visibility>
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}" Converter="{StaticResource ResourceKey=OpenResultHotkeyVisibilityConverter}" />
<Binding Converter="{StaticResource ResourceKey=OpenResultHotkeyVisibilityConverter}" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}" />
</TextBlock.Visibility>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}+{1}">
<Binding Path="OpenResultModifiers" />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}" Converter="{StaticResource ResourceKey=OrdinalConverter}" />
<Binding Converter="{StaticResource ResourceKey=OrdinalConverter}" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<Border BorderThickness="0" BorderBrush="Transparent" Margin="9 0 0 0">
<Image x:Name="ImageIcon" Width="32" Height="32" HorizontalAlignment="Center" Source="{Binding Image}" Visibility="{Binding ShowIcon}" Margin="0 0 0 0" Stretch="UniformToFill"/>
<Border
Margin="9,0,0,0"
BorderBrush="Transparent"
BorderThickness="0">
<Image
x:Name="ImageIcon"
Width="32"
Height="32"
Margin="0,0,0,0"
HorizontalAlignment="Center"
Source="{Binding Image}"
Stretch="Uniform"
Visibility="{Binding ShowIcon}" />
</Border>
<Border BorderThickness="0" BorderBrush="Transparent" Margin="9 0 0 0">
<TextBlock Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding Glyph.Glyph}" FontFamily="{Binding Glyph.FontFamily}" Visibility="{Binding ShowGlyph}" Style="{DynamicResource ItemGlyph}"/>
<Border
Margin="9,0,0,0"
BorderBrush="Transparent"
BorderThickness="0">
<TextBlock
Grid.Column="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{Binding Glyph.FontFamily}"
Style="{DynamicResource ItemGlyph}"
Text="{Binding Glyph.Glyph}"
Visibility="{Binding ShowGlyph}" />
</Border>
<Grid Margin="6 0 10 0" Grid.Column="1" HorizontalAlignment="Stretch">
<Grid
Grid.Column="1"
Margin="6,0,10,0"
HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" x:Name="SubTitleRowDefinition" />
<RowDefinition x:Name="SubTitleRowDefinition" Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Style="{DynamicResource ItemTitleStyle}" DockPanel.Dock="Left"
VerticalAlignment="Center" ToolTip="{Binding ShowTitleToolTip}" x:Name="Title"
Text="{Binding Result.Title}">
<TextBlock
x:Name="Title"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Style="{DynamicResource ItemTitleStyle}"
Text="{Binding Result.Title}"
ToolTip="{Binding ShowTitleToolTip}">
<vm:ResultsViewModel.FormattedText>
<MultiBinding Converter="{StaticResource HighlightTextConverter}">
<Binding Path="Result.Title" />
@ -77,8 +126,13 @@
</MultiBinding>
</vm:ResultsViewModel.FormattedText>
</TextBlock>
<TextBlock Style="{DynamicResource ItemSubTitleStyle}" ToolTip="{Binding ShowSubTitleToolTip}"
Grid.Row="1" x:Name="SubTitle" Text="{Binding Result.SubTitle}" MinWidth="750">
<TextBlock
x:Name="SubTitle"
Grid.Row="1"
MinWidth="750"
Style="{DynamicResource ItemSubTitleStyle}"
Text="{Binding Result.SubTitle}"
ToolTip="{Binding ShowSubTitleToolTip}">
<vm:ResultsViewModel.FormattedText>
<MultiBinding Converter="{StaticResource HighlightTextConverter}">
<Binding Path="Result.SubTitle" />
@ -92,11 +146,9 @@
</Grid>
</Button.Content>
</Button>
<!-- a result item height is 52 including margin -->
<!-- a result item height is 52 including margin -->
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}}, Path=IsSelected}"
Value="True">
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="Title" Property="Style" Value="{DynamicResource ItemTitleSelectedStyle}" />
<Setter TargetName="SubTitle" Property="Style" Value="{DynamicResource ItemSubTitleSelectedStyle}" />
<Setter TargetName="Hotkey" Property="Style" Value="{DynamicResource ItemHotkeySelectedStyle}" />
@ -105,7 +157,7 @@
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<!--http://stackoverflow.com/questions/16819577/setting-background-color-or-wpf-4-0-listbox-windows-8/#16820062-->
<!-- http://stackoverflow.com/questions/16819577/setting-background-color-or-wpf-4-0-listbox-windows-8/#16820062 -->
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="MouseEnter" Handler="OnMouseEnter" />
@ -117,23 +169,23 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Border
x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
SnapsToDevicePixels="True">
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background"
Value="{DynamicResource ItemSelectedBackgroundColor}" />
<Setter TargetName="Bd" Property="BorderBrush"
Value="{DynamicResource ItemSelectedBackgroundColor}" />
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource ItemSelectedBackgroundColor}" />
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource ItemSelectedBackgroundColor}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

View file

@ -7,25 +7,58 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{DynamicResource fileManagerWindow}"
Background="#f3f3f3"
Width="600"
Background="{DynamicResource PopuBGColor}"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Foreground="{DynamicResource PopupTextColor}"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Grid Width="600">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Border
Padding="26,26,26,0"
Background="#ffffff"
BorderBrush="#e5e5e5"
BorderThickness="0,0,0,1">
<Grid>
<Grid>
<StackPanel>
<StackPanel>
<StackPanel Grid.Row="0" Margin="0,0,0,12">
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="btnCancel_Click"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<StackPanel Grid.Row="1" Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
@ -38,14 +71,10 @@
<StackPanel>
<TextBlock
FontSize="14"
Foreground="#1b1b1b"
Text="{DynamicResource fileManager_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,14,0,0"
FontSize="14"
Foreground="#1b1b1b">
<TextBlock Margin="0,14,0,0" FontSize="14">
<TextBlock Text="{DynamicResource fileManager_tips2}" TextWrapping="WrapWithOverflow" />
</TextBlock>
</StackPanel>
@ -86,7 +115,7 @@
<Rectangle
Height="1"
Margin="0,20,0,12"
Fill="#cecece" />
Fill="{StaticResource Color03B}" />
<StackPanel
Margin="0,0,0,0"
HorizontalAlignment="Stretch"
@ -199,46 +228,48 @@
</Grid>
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
<Border
Grid.Row="2"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="145"
Margin="0,0,5,0"
Click="btnCancel_Click"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="145"
Margin="5,0,0,0"
Click="btnDone_Click"
Content="{DynamicResource done}"
ForceCursor="True">
<Button.Style>
<Style BasedOn="{StaticResource AccentButtonStyle}" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=ProfileTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=PathTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=directoryArgTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=fileArgTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Border>
<StackPanel
Grid.Row="1"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="100"
Height="30"
Margin="0,0,5,0"
Click="btnCancel_Click"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="100"
Height="30"
Margin="5,0,0,0"
Click="btnDone_Click"
Content="{DynamicResource done}"
ForceCursor="True">
<Button.Style>
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=ProfileTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=PathTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=directoryArgTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding Text.Length, ElementName=fileArgTextBox, UpdateSourceTrigger=PropertyChanged}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>
</Window>

File diff suppressed because it is too large Load diff

View file

@ -1,20 +1,26 @@
using System;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Navigation;
using Microsoft.Win32;
using Flow.Launcher.Core.ExternalPlugins;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.ViewModel;
using Flow.Launcher.Helper;
using System.Windows.Controls;
using Flow.Launcher.Core.ExternalPlugins;
using Microsoft.Win32;
using ModernWpf;
using System;
using System.IO;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Navigation;
using Button = System.Windows.Controls.Button;
using Control = System.Windows.Controls.Control;
using MessageBox = System.Windows.MessageBox;
using TextBox = System.Windows.Controls.TextBox;
using ThemeManager = ModernWpf.ThemeManager;
namespace Flow.Launcher
{
@ -39,6 +45,7 @@ namespace Flow.Launcher
#region General
private void OnLoaded(object sender, RoutedEventArgs e)
{
RefreshMaximizeRestoreButton();
// Fix (workaround) for the window freezes after lock screen (Win+L)
// https://stackoverflow.com/questions/4951058/software-rendering-mode-wpf
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
@ -58,39 +65,30 @@ namespace Flow.Launcher
public static void SetStartup()
{
using (var key = Registry.CurrentUser.OpenSubKey(StartupPath, true))
{
key?.SetValue(Infrastructure.Constant.FlowLauncher, Infrastructure.Constant.ExecutablePath);
}
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
key?.SetValue(Constant.FlowLauncher, Constant.ExecutablePath);
}
private void RemoveStartup()
{
using (var key = Registry.CurrentUser.OpenSubKey(StartupPath, true))
{
key?.DeleteValue(Infrastructure.Constant.FlowLauncher, false);
}
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
key?.DeleteValue(Constant.FlowLauncher, false);
}
public static bool StartupSet()
{
using (var key = Registry.CurrentUser.OpenSubKey(StartupPath, true))
using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
var path = key?.GetValue(Constant.FlowLauncher) as string;
if (path != null)
{
var path = key?.GetValue(Infrastructure.Constant.FlowLauncher) as string;
if (path != null)
{
return path == Infrastructure.Constant.ExecutablePath;
}
else
{
return false;
}
return path == Constant.ExecutablePath;
}
return false;
}
private void OnSelectPythonDirectoryClick(object sender, RoutedEventArgs e)
{
var dlg = new System.Windows.Forms.FolderBrowserDialog
var dlg = new FolderBrowserDialog
{
SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
};
@ -225,7 +223,7 @@ namespace Flow.Launcher
var uri = new Uri(website);
if (Uri.CheckSchemeName(uri.Scheme))
{
SearchWeb.NewTabInBrowser(website);
website.NewTabInBrowser();
}
}
}
@ -259,7 +257,7 @@ namespace Flow.Launcher
private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
{
SearchWeb.NewTabInBrowser(e.Uri.AbsoluteUri);
e.Uri.AbsoluteUri.NewTabInBrowser();
e.Handled = true;
}
@ -273,11 +271,21 @@ namespace Flow.Launcher
Close();
}
private void OpenPluginFolder(object sender, RoutedEventArgs e)
private void OpenThemeFolder(object sender, RoutedEventArgs e)
{
PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Themes));
}
private void OpenSettingFolder(object sender, RoutedEventArgs e)
{
PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Settings));
}
private void OpenLogFolder(object sender, RoutedEventArgs e)
{
PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Logs, Constant.Version));
}
private void OnPluginStoreRefreshClick(object sender, RoutedEventArgs e)
{
_ = viewModel.RefreshExternalPluginsAsync();
@ -288,20 +296,65 @@ namespace Flow.Launcher
if(sender is Button { DataContext: UserPlugin plugin })
{
var pluginsManagerPlugin = PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7");
var actionKeywrod = pluginsManagerPlugin.Metadata.ActionKeywords.Count == 0 ? "" : pluginsManagerPlugin.Metadata.ActionKeywords[0];
API.ChangeQuery($"{actionKeywrod} install {plugin.Name}");
var actionKeyword = pluginsManagerPlugin.Metadata.ActionKeywords.Count == 0 ? "" : pluginsManagerPlugin.Metadata.ActionKeywords[0];
API.ChangeQuery($"{actionKeyword} install {plugin.Name}");
API.ShowMainWindow();
}
}
private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */
{
TextBox textBox = Keyboard.FocusedElement as TextBox;
if (textBox != null)
if (Keyboard.FocusedElement is not TextBox textBox)
{
TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next);
textBox.MoveFocus(tRequest);
return;
}
var tRequest = new TraversalRequest(FocusNavigationDirection.Next);
textBox.MoveFocus(tRequest);
}
private void ColorSchemeSelectedIndexChanged(object sender, EventArgs e)
=> ThemeManager.Current.ApplicationTheme = settings.ColorScheme switch
{
Constant.Light => ApplicationTheme.Light,
Constant.Dark => ApplicationTheme.Dark,
Constant.System => null,
_ => ThemeManager.Current.ApplicationTheme
};
/* Custom TitleBar */
private void OnMinimizeButtonClick(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Minimized;
}
private void OnMaximizeRestoreButtonClick(object sender, RoutedEventArgs e)
{
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
}
private void OnCloseButtonClick(object sender, RoutedEventArgs e)
{
Close();
}
private void RefreshMaximizeRestoreButton()
{
if (WindowState == WindowState.Maximized)
{
maximizeButton.Visibility = Visibility.Collapsed;
restoreButton.Visibility = Visibility.Visible;
}
else
{
maximizeButton.Visibility = Visibility.Visible;
restoreButton.Visibility = Visibility.Collapsed;
}
}
private void Window_StateChanged(object sender, EventArgs e)
{
RefreshMaximizeRestoreButton();
}
}
}

View file

@ -0,0 +1,103 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ItemGlyph" BasedOn="{StaticResource BaseGlyphStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#9fb2bf" />
</Style>
<Style x:Key="QueryBoxStyle" BasedOn="{StaticResource BaseQueryBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="SelectionBrush" Value="#515a6b"/>
<Setter Property="FontSize" Value="24" />
<Setter Property="Background" Value="#282c34" />
<Setter Property="Foreground" Value="#61afef" />
<Setter Property="CaretBrush" Value="#ffb86c" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0 4 66 0" />
<Setter Property="Height" Value="42" />
</Style>
<Style x:Key="QuerySuggestionBoxStyle" BasedOn="{StaticResource BaseQuerySuggestionBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="#282c34" />
<Setter Property="Foreground" Value="#454e61" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0 4 66 0" />
<Setter Property="Height" Value="42" />
</Style>
<Style x:Key="WindowBorderStyle" BasedOn="{StaticResource BaseWindowBorderStyle}" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="#44475a" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Background" Value="#282c34" />
</Style>
<Style x:Key="WindowStyle" BasedOn="{StaticResource BaseWindowStyle}" TargetType="{x:Type Window}">
<Setter Property="Width" Value="576" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled"/>
</Style>
<Style x:Key="PendingLineStyle" BasedOn="{StaticResource BasePendingLineStyle}" TargetType="{x:Type Line}">
</Style>
<!-- Item Style -->
<Style x:Key="ItemTitleStyle" BasedOn="{StaticResource BaseItemTitleStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#9fb2bf" />
</Style>
<Style x:Key="ItemSubTitleStyle" BasedOn="{StaticResource BaseItemSubTitleStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#6272a4 " />
<Setter Property="FontSize" Value="13" />
</Style>
<Style x:Key="ItemNumberStyle" BasedOn="{StaticResource BaseItemNumberStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<Style x:Key="ItemTitleSelectedStyle" BasedOn="{StaticResource BaseItemTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#e5c07b" />
</Style>
<Style x:Key="ItemSubTitleSelectedStyle" BasedOn="{StaticResource BaseItemSubTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#c678dd" />
</Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#2c313c</SolidColorBrush>
<Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" >
<Setter Property="Cursor" Value="Arrow" />
</Style>
<Style x:Key="HighlightStyle">
<Setter Property="Inline.Foreground" Value="#e06c75 " />
</Style>
<Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<Style x:Key="ItemHotkeySelectedStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseItemHotkeySelecetedStyle}">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="#56b6c2" />
</Style>
<!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" BasedOn="{StaticResource BaseThumbStyle}" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Width" Value="2"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2" DockPanel.Dock="Right" Background="#b4b5b7" BorderBrush="Transparent" BorderThickness="0" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarStyle" BasedOn="{StaticResource BaseScrollBarStyle}" TargetType="{x:Type ScrollBar}">
</Style>
<Style x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#495162"/>
<Setter Property="Height" Value="1"/>
<Setter Property="Margin" Value="12 0 12 8"/>
</Style>
<Style x:Key="SearchIconStyle" TargetType="{x:Type Path}" BasedOn="{StaticResource BaseSearchIconStyle}">
<Setter Property="Fill" Value="#495162" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="Opacity" Value="0.8" />
</Style>
</ResourceDictionary>

View file

@ -0,0 +1,95 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ItemGlyph" BasedOn="{StaticResource BaseGlyphStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#ebebeb" />
</Style>
<Style x:Key="QueryBoxStyle" BasedOn="{StaticResource BaseQueryBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="#ebebeb" />
<Setter Property="Background" Value="Transparent" />
</Style>
<Style x:Key="QuerySuggestionBoxStyle" BasedOn="{StaticResource BaseQuerySuggestionBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
</Style>
<Style x:Key="WindowBorderStyle" BasedOn="{StaticResource BaseWindowBorderStyle}" TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="5" />
<Setter Property="BorderThickness" Value="1 1 0 0" />
<Setter Property="BorderBrush" Value="#666666" />
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="#333333" Opacity="0.95"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="WindowStyle" BasedOn="{StaticResource BaseWindowStyle}" TargetType="{x:Type Window}">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="White" Opacity="0.5"/>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PendingLineStyle" BasedOn="{StaticResource BasePendingLineStyle}" TargetType="{x:Type Line}">
</Style>
<!-- Item Style -->
<Style x:Key="ItemTitleStyle" BasedOn="{StaticResource BaseItemTitleStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="0, -10"/>
<Setter Property="Foreground" Value="#ebebeb"/>
</Style>
<Style x:Key="ItemSubTitleStyle" BasedOn="{StaticResource BaseItemSubTitleStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#787878"/>
</Style>
<Style x:Key="ItemTitleSelectedStyle" BasedOn="{StaticResource BaseItemTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Margin" Value="0, -10"/>
<Setter Property="Foreground" Value="#ffffff"/>
</Style>
<Style x:Key="ItemSubTitleSelectedStyle" BasedOn="{StaticResource BaseItemSubTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#949494"/>
</Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#545454</SolidColorBrush>
<!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" BasedOn="{StaticResource BaseThumbStyle}" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2" DockPanel.Dock="Right" Background="#525252" BorderBrush="Transparent" BorderThickness="0" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarStyle" BasedOn="{StaticResource BaseScrollBarStyle}" TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="#a0a0a0"/>
</Style>
<Style x:Key="SearchIconStyle" TargetType="{x:Type Path}" BasedOn="{StaticResource BaseSearchIconStyle}">
<Setter Property="Fill" Value="#FFFFFF" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="Opacity" Value="0.2" />
</Style>
<Style x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#787878"/>
<Setter Property="Height" Value="1"/>
<Setter Property="Margin" Value="0 0 0 8"/>
<Setter Property="Opacity" Value="0.3" />
</Style>
<Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="#787878" />
<Setter Property="Opacity" Value="0.1" />
</Style>
<Style x:Key="ItemHotkeySelectedStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="14" />
<Setter Property="Foreground" Value="#787878" />
<Setter Property="Opacity" Value="0.1" />
</Style>
</ResourceDictionary>

View file

@ -0,0 +1,103 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ItemGlyph" BasedOn="{StaticResource BaseGlyphStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#f8f8f2" />
</Style>
<Style x:Key="QueryBoxStyle" BasedOn="{StaticResource BaseQueryBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="SelectionBrush" Value="#ff79c6"/>
<Setter Property="FontSize" Value="24" />
<Setter Property="Background" Value="#282a36" />
<Setter Property="Foreground" Value="#f8f8f2" />
<Setter Property="CaretBrush" Value="#ffb86c" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0 4 66 0" />
<Setter Property="Height" Value="42" />
</Style>
<Style x:Key="QuerySuggestionBoxStyle" BasedOn="{StaticResource BaseQuerySuggestionBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="#282a36" />
<Setter Property="Foreground" Value="#6272a4" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0 4 66 0" />
<Setter Property="Height" Value="42" />
</Style>
<Style x:Key="WindowBorderStyle" BasedOn="{StaticResource BaseWindowBorderStyle}" TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="BorderBrush" Value="#44475a" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Background" Value="#282a36" />
</Style>
<Style x:Key="WindowStyle" BasedOn="{StaticResource BaseWindowStyle}" TargetType="{x:Type Window}">
<Setter Property="Width" Value="576" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled"/>
</Style>
<Style x:Key="PendingLineStyle" BasedOn="{StaticResource BasePendingLineStyle}" TargetType="{x:Type Line}">
</Style>
<!-- Item Style -->
<Style x:Key="ItemTitleStyle" BasedOn="{StaticResource BaseItemTitleStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#f8f8f2" />
</Style>
<Style x:Key="ItemSubTitleStyle" BasedOn="{StaticResource BaseItemSubTitleStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#6272a4" />
<Setter Property="FontSize" Value="13" />
</Style>
<Style x:Key="ItemNumberStyle" BasedOn="{StaticResource BaseItemNumberStyle}" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<Style x:Key="ItemTitleSelectedStyle" BasedOn="{StaticResource BaseItemTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#ff79c6" />
</Style>
<Style x:Key="ItemSubTitleSelectedStyle" BasedOn="{StaticResource BaseItemSubTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#44475a</SolidColorBrush>
<Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" >
<Setter Property="Cursor" Value="Arrow" />
</Style>
<Style x:Key="HighlightStyle">
<Setter Property="Inline.Foreground" Value="#bd93f9" />
</Style>
<Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="#6272a4" />
</Style>
<Style x:Key="ItemHotkeySelectedStyle" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource BaseItemHotkeySelecetedStyle}">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="#ff79c6" />
</Style>
<!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" BasedOn="{StaticResource BaseThumbStyle}" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Width" Value="2"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2" DockPanel.Dock="Right" Background="#44475a" BorderBrush="Transparent" BorderThickness="0" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarStyle" BasedOn="{StaticResource BaseScrollBarStyle}" TargetType="{x:Type ScrollBar}">
</Style>
<Style x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#44475a"/>
<Setter Property="Height" Value="1"/>
<Setter Property="Margin" Value="12 0 12 8"/>
</Style>
<Style x:Key="SearchIconStyle" TargetType="{x:Type Path}" BasedOn="{StaticResource BaseSearchIconStyle}">
<Setter Property="Fill" Value="#6272a4" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="Opacity" Value="0.8" />
</Style>
</ResourceDictionary>

View file

@ -1,72 +1,109 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ItemGlyph" BasedOn="{StaticResource BaseGlyphStyle}" TargetType="{x:Type TextBlock}">
<Style
x:Key="ItemGlyph"
BasedOn="{StaticResource BaseGlyphStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#ffffff" />
</Style>
<Style x:Key="QueryBoxStyle" BasedOn="{StaticResource BaseQueryBoxStyle}" TargetType="{x:Type TextBox}">
<Setter Property="SelectionBrush" Value="#4a5459"/>
<Style
x:Key="QueryBoxStyle"
BasedOn="{StaticResource BaseQueryBoxStyle}"
TargetType="{x:Type TextBox}">
<Setter Property="SelectionBrush" Value="#4a5459" />
<Setter Property="FontSize" Value="24" />
<Setter Property="Background" Value="#202020" />
<Setter Property="Foreground" Value="#FFFFFF" />
<Setter Property="CaretBrush" Value="#FFFFFF" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0 4 66 0" />
<Setter Property="Padding" Value="0,4,66,0" />
<Setter Property="Height" Value="42" />
</Style>
<Style x:Key="QuerySuggestionBoxStyle" BasedOn="{StaticResource BaseQuerySuggestionBoxStyle}" TargetType="{x:Type TextBox}">
<Style
x:Key="QuerySuggestionBoxStyle"
BasedOn="{StaticResource BaseQuerySuggestionBoxStyle}"
TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="#202020" />
<Setter Property="Foreground" Value="#7b7b7b" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0 4 66 0" />
<Setter Property="Padding" Value="0,4,66,0" />
<Setter Property="Height" Value="42" />
</Style>
<Style x:Key="WindowBorderStyle" BasedOn="{StaticResource BaseWindowBorderStyle}" TargetType="{x:Type Border}">
<Style
x:Key="WindowBorderStyle"
BasedOn="{StaticResource BaseWindowBorderStyle}"
TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="#3f3f3f" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Background" Value="#202020" />
</Style>
<Style x:Key="WindowStyle" BasedOn="{StaticResource BaseWindowStyle}" TargetType="{x:Type Window}">
<Style
x:Key="WindowStyle"
BasedOn="{StaticResource BaseWindowStyle}"
TargetType="{x:Type Window}">
<Setter Property="Width" Value="576" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled"/>
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled" />
</Style>
<Style x:Key="PendingLineStyle" BasedOn="{StaticResource BasePendingLineStyle}" TargetType="{x:Type Line}">
<Style
x:Key="PendingLineStyle"
BasedOn="{StaticResource BasePendingLineStyle}"
TargetType="{x:Type Line}">
<Setter Property="Stroke" Value="White" />
</Style>
<!-- Item Style -->
<Style x:Key="ItemTitleStyle" BasedOn="{StaticResource BaseItemTitleStyle}" TargetType="{x:Type TextBlock}">
<!-- Item Style -->
<Style
x:Key="ItemTitleStyle"
BasedOn="{StaticResource BaseItemTitleStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#ffffff" />
</Style>
<Style x:Key="ItemSubTitleStyle" BasedOn="{StaticResource BaseItemSubTitleStyle}" TargetType="{x:Type TextBlock}" >
<Style
x:Key="ItemSubTitleStyle"
BasedOn="{StaticResource BaseItemSubTitleStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#7b7b7b" />
<Setter Property="FontSize" Value="13" />
<Setter Property="FontWeight" Value="Regular" />
</Style>
<Style x:Key="ItemNumberStyle" BasedOn="{StaticResource BaseItemNumberStyle}" TargetType="{x:Type TextBlock}">
<Style
x:Key="ItemNumberStyle"
BasedOn="{StaticResource BaseItemNumberStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#ffffff" />
</Style>
<Style x:Key="ItemTitleSelectedStyle" BasedOn="{StaticResource BaseItemTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Style
x:Key="ItemTitleSelectedStyle"
BasedOn="{StaticResource BaseItemTitleSelectedStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#ffffff" />
</Style>
<Style x:Key="ItemSubTitleSelectedStyle" BasedOn="{StaticResource BaseItemSubTitleSelectedStyle}" TargetType="{x:Type TextBlock}" >
<Style
x:Key="ItemSubTitleSelectedStyle"
BasedOn="{StaticResource BaseItemSubTitleSelectedStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#7b7b7b" />
<Setter Property="FontSize" Value="13" />
<Setter Property="FontWeight" Value="Regular" />
</Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#2d2d2d</SolidColorBrush>
<Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" >
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#198F8F8F</SolidColorBrush>
<Style
x:Key="ItemImageSelectedStyle"
BasedOn="{StaticResource BaseItemImageSelectedStyle}"
TargetType="{x:Type Image}">
<Setter Property="Cursor" Value="Arrow" />
</Style>
<Style x:Key="HighlightStyle">
<Setter Property="Inline.FontWeight" Value="Bold" />
<Setter Property="Inline.Foreground" Value="#0078d7" />
</Style>
<Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="13" />
@ -76,29 +113,45 @@
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="#7b7b7b" />
</Style>
<!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" BasedOn="{StaticResource BaseThumbStyle}" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Width" Value="2"/>
<Setter Property="Focusable" Value="false"/>
<!-- button style in the middle of the scrollbar -->
<Style
x:Key="ThumbStyle"
BasedOn="{StaticResource BaseThumbStyle}"
TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Width" Value="2" />
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2" DockPanel.Dock="Right" Background="#9a9a9a" BorderBrush="Transparent" BorderThickness="0" />
<Border
Background="#9a9a9a"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="2"
DockPanel.Dock="Right" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarStyle" BasedOn="{StaticResource BaseScrollBarStyle}" TargetType="{x:Type ScrollBar}">
<Style
x:Key="ScrollBarStyle"
BasedOn="{StaticResource BaseScrollBarStyle}"
TargetType="{x:Type ScrollBar}" />
<Style
x:Key="SeparatorStyle"
BasedOn="{StaticResource BaseSeparatorStyle}"
TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#4d4d4d" />
<Setter Property="Height" Value="1" />
<Setter Property="Margin" Value="12,0,12,8" />
</Style>
<Style x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="#4d4d4d"/>
<Setter Property="Height" Value="1"/>
<Setter Property="Margin" Value="12 0 12 8"/>
</Style>
<Style x:Key="SearchIconStyle" TargetType="{x:Type Path}" BasedOn="{StaticResource BaseSearchIconStyle}">
<Style
x:Key="SearchIconStyle"
BasedOn="{StaticResource BaseSearchIconStyle}"
TargetType="{x:Type Path}">
<Setter Property="Fill" Value="#4d4d4d" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />

View file

@ -57,7 +57,7 @@
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#72767d" />
</Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#eaeaea</SolidColorBrush>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#198F8F8F</SolidColorBrush>
<Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" >
<Setter Property="Cursor" Value="Arrow" />
</Style>

View file

@ -0,0 +1,159 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="http://schemas.modernwpf.com/2019"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style
x:Key="ItemGlyph"
BasedOn="{StaticResource BaseGlyphStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
<Style
x:Key="QueryBoxStyle"
BasedOn="{StaticResource BaseQueryBoxStyle}"
TargetType="{x:Type TextBox}">
<Setter Property="SelectionBrush" Value="{DynamicResource QuerySelectionBrush}" />
<Setter Property="FontSize" Value="24" />
<Setter Property="Background" Value="{DynamicResource Color01B}" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
<Setter Property="CaretBrush" Value="{DynamicResource Color05B}" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0,4,66,0" />
<Setter Property="Height" Value="42" />
</Style>
<Style
x:Key="QuerySuggestionBoxStyle"
BasedOn="{StaticResource BaseQuerySuggestionBoxStyle}"
TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="{DynamicResource Color01B}" />
<Setter Property="Foreground" Value="{DynamicResource QuerySuggestionBoxForeground}" />
<Setter Property="FontSize" Value="26" />
<Setter Property="Padding" Value="0,4,66,0" />
<Setter Property="Height" Value="42" />
</Style>
<Style
x:Key="WindowBorderStyle"
BasedOn="{StaticResource BaseWindowBorderStyle}"
TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{DynamicResource SystemThemeBorder}" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="Background" Value="{DynamicResource Color01B}" />
</Style>
<Style
x:Key="WindowStyle"
BasedOn="{StaticResource BaseWindowStyle}"
TargetType="{x:Type Window}">
<Setter Property="Width" Value="576" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled" />
</Style>
<Style
x:Key="PendingLineStyle"
BasedOn="{StaticResource BasePendingLineStyle}"
TargetType="{x:Type Line}" />
<!-- Item Style -->
<Style
x:Key="ItemTitleStyle"
BasedOn="{StaticResource BaseItemTitleStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
<Style
x:Key="ItemSubTitleStyle"
BasedOn="{StaticResource BaseItemSubTitleStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{DynamicResource SubTitleForeground}" />
<Setter Property="FontSize" Value="13" />
</Style>
<Style
x:Key="ItemNumberStyle"
BasedOn="{StaticResource BaseItemNumberStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#A6A6A6" />
</Style>
<Style
x:Key="ItemTitleSelectedStyle"
BasedOn="{StaticResource BaseItemTitleSelectedStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
</Style>
<Style
x:Key="ItemSubTitleSelectedStyle"
BasedOn="{StaticResource BaseItemSubTitleSelectedStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="{DynamicResource SubTitleSelectedForeground}" />
</Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor" Color="{m:DynamicColor ItemSelectedBackgroundColorBrush}" />
<Style
x:Key="ItemImageSelectedStyle"
BasedOn="{StaticResource BaseItemImageSelectedStyle}"
TargetType="{x:Type Image}">
<Setter Property="Cursor" Value="Arrow" />
</Style>
<Style x:Key="HighlightStyle">
<Setter Property="Inline.Foreground" Value="{DynamicResource InlineHighlight}" />
</Style>
<Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="{DynamicResource HotkeyForeground}" />
</Style>
<Style
x:Key="ItemHotkeySelectedStyle"
BasedOn="{StaticResource BaseItemHotkeySelecetedStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="{DynamicResource HotkeySelectedForeground}" />
</Style>
<!-- button style in the middle of the scrollbar -->
<Style
x:Key="ThumbStyle"
BasedOn="{StaticResource BaseThumbStyle}"
TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Width" Value="2" />
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border
Background="{DynamicResource ThumbColor}"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="2"
DockPanel.Dock="Right" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="ScrollBarStyle"
BasedOn="{StaticResource BaseScrollBarStyle}"
TargetType="{x:Type ScrollBar}" />
<Style
x:Key="SeparatorStyle"
BasedOn="{StaticResource BaseSeparatorStyle}"
TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="{DynamicResource SeparatorForeground}" />
<Setter Property="Height" Value="1" />
<Setter Property="Margin" Value="12,0,12,8" />
</Style>
<Style
x:Key="SearchIconStyle"
BasedOn="{StaticResource BaseSearchIconStyle}"
TargetType="{x:Type Path}">
<Setter Property="Fill" Value="{DynamicResource SearchIconForeground}" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="Opacity" Value="1" />
</Style>
</ResourceDictionary>

View file

@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using System.Windows;
using System.Windows.Media;
using System.Windows.Input;
using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Core.Resource;
@ -20,9 +20,6 @@ using Flow.Launcher.Infrastructure.Logger;
using Microsoft.VisualStudio.Threading;
using System.Threading.Channels;
using ISavable = Flow.Launcher.Plugin.ISavable;
using System.Windows.Threading;
using NHotkey;
using Windows.Web.Syndication;
namespace Flow.Launcher.ViewModel
@ -157,25 +154,6 @@ namespace Flow.Launcher.ViewModel
}
}
private void UpdateLastQUeryMode()
{
switch (_settings.LastQueryMode)
{
case LastQueryMode.Empty:
ChangeQueryText(string.Empty);
break;
case LastQueryMode.Preserved:
LastQuerySelected = true;
break;
case LastQueryMode.Selected:
LastQuerySelected = false;
break;
default:
throw new ArgumentException($"wrong LastQueryMode: <{_settings.LastQueryMode}>");
}
}
private void InitializeKeyCommands()
{
EscCommand = new RelayCommand(_ =>
@ -215,7 +193,7 @@ namespace Flow.Launcher.ViewModel
{
SearchWeb.NewTabInBrowser("https://github.com/Flow-Launcher/Flow.Launcher/wiki/Flow-Launcher/");
});
OpenSettingCommand = new RelayCommand(_ => { App.API.OpenSettingDialog(); });
OpenResultCommand = new RelayCommand(index =>
{
var results = SelectedResults;
@ -301,9 +279,13 @@ namespace Flow.Launcher.ViewModel
#region ViewModel Properties
public ResultsViewModel Results { get; private set; }
public ResultsViewModel ContextMenu { get; private set; }
public ResultsViewModel History { get; private set; }
public bool GameModeStatus { get; set; }
private string _queryText;
public string QueryText
@ -380,6 +362,11 @@ namespace Flow.Launcher.ViewModel
public Visibility ProgressBarVisibility { get; set; }
public Visibility MainWindowVisibility { get; set; }
public double MainWindowOpacity { get; set; } = 1;
// This is to be used for determining the visibility status of the mainwindow instead of MainWindowVisibility
// because it is more accurate and reliable representation than using Visibility as a condition check
public bool MainWindowVisibilityStatus { get; set; } = true;
public double MainWindowWidth => _settings.WindowSize;
@ -393,6 +380,7 @@ namespace Flow.Launcher.ViewModel
public ICommand LoadContextMenuCommand { get; set; }
public ICommand LoadHistoryCommand { get; set; }
public ICommand OpenResultCommand { get; set; }
public ICommand OpenSettingCommand { get; set; }
public ICommand ReloadPluginDataCommand { get; set; }
public ICommand ClearQueryCommand { get; private set; }
@ -708,9 +696,9 @@ namespace Flow.Launcher.ViewModel
public void ToggleFlowLauncher()
{
if (MainWindowVisibility != Visibility.Visible)
if (!MainWindowVisibilityStatus)
{
MainWindowVisibility = Visibility.Visible;
Show();
}
else
{
@ -718,25 +706,51 @@ namespace Flow.Launcher.ViewModel
}
}
public void Show()
{
if (_settings.UseSound)
{
MediaPlayer media = new MediaPlayer();
media.Open(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav"));
media.Play();
}
MainWindowVisibility = Visibility.Visible;
MainWindowVisibilityStatus = true;
if(_settings.UseAnimation)
((MainWindow)Application.Current.MainWindow).WindowAnimator();
MainWindowOpacity = 1;
}
public async void Hide()
{
// Trick for no delay
MainWindowOpacity = 0;
switch (_settings.LastQueryMode)
{
case LastQueryMode.Empty:
ChangeQueryText(string.Empty);
Application.Current.MainWindow.Opacity = 0; // Trick for no delay
await Task.Delay(100);
Application.Current.MainWindow.Opacity = 1;
await Task.Delay(100); //Time for change to opacity
break;
case LastQueryMode.Preserved:
if (_settings.UseAnimation)
await Task.Delay(100);
LastQuerySelected = true;
break;
case LastQueryMode.Selected:
if (_settings.UseAnimation)
await Task.Delay(100);
LastQuerySelected = false;
break;
default:
throw new ArgumentException($"wrong LastQueryMode: <{_settings.LastQueryMode}>");
}
MainWindowVisibilityStatus = false;
MainWindowVisibility = Visibility.Collapsed;
}

View file

@ -15,7 +15,6 @@ using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
@ -316,6 +315,29 @@ namespace Flow.Launcher.ViewModel
}
}
public class ColorScheme
{
public string Display { get; set; }
public ColorSchemes Value { get; set; }
}
public List<ColorScheme> ColorSchemes
{
get
{
List<ColorScheme> modes = new List<ColorScheme>();
var enums = (ColorSchemes[])Enum.GetValues(typeof(ColorSchemes));
foreach (var e in enums)
{
var key = $"ColorScheme{e}";
var display = _translater.GetTranslation(key);
var m = new ColorScheme { Display = display, Value = e, };
modes.Add(m);
}
return modes;
}
}
public double WindowWidthSize
{
get => Settings.WindowSize;
@ -328,6 +350,18 @@ namespace Flow.Launcher.ViewModel
set => Settings.UseGlyphIcons = value;
}
public bool UseAnimation
{
get => Settings.UseAnimation;
set => Settings.UseAnimation = value;
}
public bool UseSound
{
get => Settings.UseSound;
set => Settings.UseSound = value;
}
public Brush PreviewBackground
{
get
@ -494,6 +528,8 @@ namespace Flow.Launcher.ViewModel
public string Website => Constant.Website;
public string ReleaseNotes => _updater.GitHubRepository + @"/releases/latest";
public string Documentation => Constant.Documentation;
public string Docs => Constant.Docs;
public string Github => Constant.GitHub;
public static string Version => Constant.Version;
public string ActivatedTimes => string.Format(_translater.GetTranslation("about_activate_times"), Settings.ActivateTimes);
#endregion

View file

@ -1,72 +1,106 @@
<UserControl x:Class="Flow.Launcher.Plugin.BrowserBookmark.Views.SettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Background="White"
d:DesignHeight="300" d:DesignWidth="500"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<UserControl
x:Class="Flow.Launcher.Plugin.BrowserBookmark.Views.SettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
d:DesignHeight="300"
d:DesignWidth="500"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="80"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="80" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackPanel>
<Grid Grid.Row="0" Margin="30 20 0 0">
<Grid Grid.Row="0" Margin="30,20,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="140" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_openBookmarks}"
FontSize="15" Margin="10 5 0 0"/>
<RadioButton Grid.Column="1" Name="NewWindowBrowser"
IsChecked="{Binding OpenInNewBrowserWindow}"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_newWindow}"/>
<RadioButton Grid.Column="2" Name="NewTabInBrowser"
IsChecked="{Binding OpenInNewTab, Mode=OneTime}"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_newTab}"/>
<Label
Grid.Column="0"
Margin="10,5,0,0"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_openBookmarks}"
FontSize="15" />
<RadioButton
Name="NewWindowBrowser"
Grid.Column="1"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_newWindow}"
IsChecked="{Binding OpenInNewBrowserWindow}" />
<RadioButton
Name="NewTabInBrowser"
Grid.Column="2"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_newTab}"
IsChecked="{Binding OpenInNewTab, Mode=OneTime}" />
</Grid>
</StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Grid.Row="1" Height="60" Margin="30,20,0,0">
<Label Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_setBrowserFromPath}"
Height="28" Margin="10"/>
<TextBox x:Name="BrowserPathBox"
HorizontalAlignment="Left"
Height="30"
TextWrapping="NoWrap"
VerticalAlignment="Center"
Text="{Binding Settings.BrowserPath}"
Width="240"
Margin="10"/>
<Button x:Name="ViewButton" Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_choose}"
HorizontalAlignment="Left" Margin="10" Width="100" Height="30" Click="OnChooseClick" FontSize="14" />
<StackPanel
Grid.Row="1"
Height="60"
Margin="30,20,0,0"
VerticalAlignment="Top"
Orientation="Horizontal">
<Label
Height="28"
Margin="10"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_setBrowserFromPath}" />
<TextBox
x:Name="BrowserPathBox"
Width="240"
Height="34"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding Settings.BrowserPath}"
TextWrapping="NoWrap" />
<Button
x:Name="ViewButton"
Width="100"
Height="30"
Margin="10"
HorizontalAlignment="Left"
Click="OnChooseClick"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_settings_choose}"
FontSize="14" />
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Vertical" Margin="30,20,0,0">
<TextBlock Text="{DynamicResource flowlauncher_plugin_browserbookmark_loadBrowserFrom}" Margin="10"/>
<ListView Grid.Row="2" ItemsSource="{Binding Settings.CustomChromiumBrowsers}"
SelectedItem="{Binding SelectedCustomBrowser}"
Margin="10"
BorderBrush="DarkGray"
BorderThickness="1"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}"
Height="auto"
Name="CustomBrowsers"
MouseDoubleClick="MouseDoubleClickOnSelectedCustomBrowser">
<StackPanel
Grid.Row="2"
Margin="30,20,0,0"
Orientation="Vertical">
<TextBlock Margin="10" Text="{DynamicResource flowlauncher_plugin_browserbookmark_loadBrowserFrom}" />
<ListView
Name="CustomBrowsers"
Grid.Row="2"
Height="auto"
Margin="10"
BorderBrush="DarkGray"
BorderThickness="1"
ItemsSource="{Binding Settings.CustomChromiumBrowsers}"
MouseDoubleClick="MouseDoubleClickOnSelectedCustomBrowser"
SelectedItem="{Binding SelectedCustomBrowser}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Name, Mode=OneWay}" Header="{DynamicResource flowlauncher_plugin_browserbookmark_browserName}"/>
<GridViewColumn DisplayMemberBinding="{Binding DataDirectoryPath, Mode=OneWay}" Header="{DynamicResource flowlauncher_plugin_browserbookmark_browserBookmarkDataDirectory}"/>
<GridViewColumn DisplayMemberBinding="{Binding Name, Mode=OneWay}" Header="{DynamicResource flowlauncher_plugin_browserbookmark_browserName}" />
<GridViewColumn DisplayMemberBinding="{Binding DataDirectoryPath, Mode=OneWay}" Header="{DynamicResource flowlauncher_plugin_browserbookmark_browserBookmarkDataDirectory}" />
</GridView>
</ListView.View>
</ListView>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_addBrowserBookmark}"
Margin="10" Click="NewCustomBrowser" Width="80" />
<Button Content="{DynamicResource flowlauncher_plugin_browserbookmark_removeBrowserBookmark}"
Margin="10" Click="DeleteCustomBrowser" Width="80"/>
<Button
Width="80"
Margin="10"
Click="NewCustomBrowser"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_addBrowserBookmark}" />
<Button
Width="80"
Margin="10"
Click="DeleteCustomBrowser"
Content="{DynamicResource flowlauncher_plugin_browserbookmark_removeBrowserBookmark}" />
</StackPanel>
</StackPanel>
</Grid>

View file

@ -1,25 +0,0 @@
using System.Diagnostics;
using System.Drawing;
namespace Flow.Launcher.Plugin.ControlPanel
{
//from:https://raw.githubusercontent.com/CoenraadS/Windows-Control-Panel-Items
public class ControlPanelItem
{
public string LocalizedString { get; private set; }
public string InfoTip { get; private set; }
public string GUID { get; private set; }
public ProcessStartInfo ExecutablePath { get; private set; }
public Icon Icon { get; private set; }
public int Score { get; set; }
public ControlPanelItem(string newLocalizedString, string newInfoTip, string newGUID, ProcessStartInfo newExecutablePath, Icon newIcon)
{
LocalizedString = newLocalizedString;
InfoTip = newInfoTip;
ExecutablePath = newExecutablePath;
Icon = newIcon;
GUID = newGUID;
}
}
}

View file

@ -1,339 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32;
namespace Flow.Launcher.Plugin.ControlPanel
{
//from:https://raw.githubusercontent.com/CoenraadS/Windows-Control-Panel-Items
public static class ControlPanelList
{
private const uint GROUP_ICON = 14;
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
private const string CONTROL = @"%SystemRoot%\System32\control.exe";
private delegate bool EnumResNameDelegate(
IntPtr hModule,
IntPtr lpszType,
IntPtr lpszName,
IntPtr lParam);
[DllImport("kernel32.dll", EntryPoint = "EnumResourceNamesW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool EnumResourceNamesWithID(IntPtr hModule, uint lpszType, EnumResNameDelegate lpEnumFunc, IntPtr lParam);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr LoadImage(IntPtr hinst, IntPtr lpszName, uint uType,
int cxDesired, int cyDesired, uint fuLoad);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool DestroyIcon(IntPtr handle);
[DllImport("kernel32.dll")]
static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
static IntPtr defaultIconPtr;
static RegistryKey nameSpace = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
static RegistryKey clsid = Registry.ClassesRoot.OpenSubKey("CLSID");
public static List<ControlPanelItem> Create(uint iconSize)
{
int size = (int)iconSize;
RegistryKey currentKey;
ProcessStartInfo executablePath;
List<ControlPanelItem> controlPanelItems = new List<ControlPanelItem>();
string localizedString;
string infoTip;
Icon myIcon;
foreach (string key in nameSpace.GetSubKeyNames())
{
currentKey = clsid.OpenSubKey(key);
if (currentKey != null)
{
executablePath = getExecutablePath(currentKey);
if (!(executablePath == null)) //Cannot have item without executable path
{
localizedString = getLocalizedString(currentKey);
if (!string.IsNullOrEmpty(localizedString))//Cannot have item without Title
{
infoTip = getInfoTip(currentKey);
myIcon = getIcon(currentKey, size);
controlPanelItems.Add(new ControlPanelItem(localizedString, infoTip, key, executablePath, myIcon));
}
}
}
}
return controlPanelItems;
}
private static ProcessStartInfo getExecutablePath(RegistryKey currentKey)
{
ProcessStartInfo executablePath = new ProcessStartInfo();
string applicationName;
if (currentKey.GetValue("System.ApplicationName") != null)
{
//CPL Files (usually native MS items)
applicationName = currentKey.GetValue("System.ApplicationName").ToString();
executablePath.FileName = Environment.ExpandEnvironmentVariables(CONTROL);
executablePath.Arguments = "-name " + applicationName;
}
else if (currentKey.OpenSubKey("Shell\\Open\\Command") != null && currentKey.OpenSubKey("Shell\\Open\\Command").GetValue(null) != null)
{
//Other files (usually third party items)
string input = "\"" + Environment.ExpandEnvironmentVariables(currentKey.OpenSubKey("Shell\\Open\\Command").GetValue(null).ToString()) + "\"";
executablePath.FileName = "cmd.exe";
executablePath.Arguments = "/C " + input;
executablePath.WindowStyle = ProcessWindowStyle.Hidden;
}
else
{
return null;
}
return executablePath;
}
private static string getLocalizedString(RegistryKey currentKey)
{
IntPtr dataFilePointer;
string[] localizedStringRaw;
uint stringTableIndex;
StringBuilder resource;
string localizedString;
if (currentKey.GetValue("LocalizedString") != null)
{
localizedStringRaw = currentKey.GetValue("LocalizedString").ToString().Split(new[] { ",-" }, StringSplitOptions.None);
if (localizedStringRaw.Length > 1)
{
if (localizedStringRaw[0][0] == '@')
{
localizedStringRaw[0] = localizedStringRaw[0].Substring(1);
}
localizedStringRaw[0] = Environment.ExpandEnvironmentVariables(localizedStringRaw[0]);
dataFilePointer = LoadLibraryEx(localizedStringRaw[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); //Load file with strings
stringTableIndex = sanitizeUint(localizedStringRaw[1]);
resource = new StringBuilder(255);
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1); //Extract needed string
FreeLibrary(dataFilePointer);
localizedString = resource.ToString();
//Some apps don't return a string, although they do have a stringIndex. Use Default value.
if (String.IsNullOrEmpty(localizedString))
{
if (currentKey.GetValue(null) != null)
{
localizedString = currentKey.GetValue(null).ToString();
}
else
{
return null; //Cannot have item without title.
}
}
}
else
{
localizedString = localizedStringRaw[0];
}
}
else if (currentKey.GetValue(null) != null)
{
localizedString = currentKey.GetValue(null).ToString();
}
else
{
return null; //Cannot have item without title.
}
return localizedString;
}
private static string getInfoTip(RegistryKey currentKey)
{
IntPtr dataFilePointer;
string[] infoTipRaw;
uint stringTableIndex;
StringBuilder resource;
string infoTip = "";
if (currentKey.GetValue("InfoTip") != null)
{
infoTipRaw = currentKey.GetValue("InfoTip").ToString().Split(new[] { ",-" }, StringSplitOptions.None);
if (infoTipRaw.Length == 2)
{
if (infoTipRaw[0][0] == '@')
{
infoTipRaw[0] = infoTipRaw[0].Substring(1);
}
infoTipRaw[0] = Environment.ExpandEnvironmentVariables(infoTipRaw[0]);
dataFilePointer = LoadLibraryEx(infoTipRaw[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); //Load file with strings
stringTableIndex = sanitizeUint(infoTipRaw[1]);
resource = new StringBuilder(255);
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1); //Extract needed string
FreeLibrary(dataFilePointer);
infoTip = resource.ToString();
}
else
{
infoTip = currentKey.GetValue("InfoTip").ToString();
}
}
else
{
infoTip = "";
}
return infoTip;
}
private static Icon getIcon(RegistryKey currentKey, int iconSize)
{
IntPtr iconPtr = IntPtr.Zero;
List<string> iconString;
IntPtr dataFilePointer;
IntPtr iconIndex;
Icon myIcon = null;
if (currentKey.OpenSubKey("DefaultIcon") != null)
{
if (currentKey.OpenSubKey("DefaultIcon").GetValue(null) != null)
{
iconString = new List<string>(currentKey.OpenSubKey("DefaultIcon").GetValue(null).ToString().Split(new[] { ',' }, 2));
if (string.IsNullOrEmpty(iconString[0]))
{
// fallback to default icon
return null;
}
if (iconString[0][0] == '@')
{
iconString[0] = iconString[0].Substring(1);
}
dataFilePointer = LoadLibraryEx(iconString[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
if (iconString.Count == 2)
{
iconIndex = (IntPtr)sanitizeUint(iconString[1]);
iconPtr = LoadImage(dataFilePointer, iconIndex, 1, iconSize, iconSize, 0);
}
if (iconPtr == IntPtr.Zero)
{
defaultIconPtr = IntPtr.Zero;
EnumResourceNamesWithID(dataFilePointer, GROUP_ICON, EnumRes, IntPtr.Zero); //Iterate through resources.
iconPtr = LoadImage(dataFilePointer, defaultIconPtr, 1, iconSize, iconSize, 0);
}
FreeLibrary(dataFilePointer);
if (iconPtr != IntPtr.Zero)
{
try
{
myIcon = Icon.FromHandle(iconPtr);
myIcon = (Icon)myIcon.Clone(); //Remove pointer dependancy.
}
catch
{
//Silently fail for now.
}
}
}
}
if (iconPtr != IntPtr.Zero)
{
DestroyIcon(iconPtr);
}
return myIcon;
}
private static uint sanitizeUint(string args) //Remove all chars before and after first set of digits.
{
int x = 0;
while (x < args.Length && !Char.IsDigit(args[x]))
{
args = args.Substring(1);
}
x = 0;
while (x < args.Length && Char.IsDigit(args[x]))
{
x++;
}
if (x < args.Length)
{
args = args.Remove(x);
}
/*If the logic is correct, this should never through an exception.
* If there is an exception, then need to analyze what the input is.
* Returning the wrong number will cause more errors */
return Convert.ToUInt32(args);
}
private static bool IS_INTRESOURCE(IntPtr value)
{
if (((uint)value) > ushort.MaxValue)
return false;
return true;
}
private static uint GET_RESOURCE_ID(IntPtr value)
{
if (IS_INTRESOURCE(value))
return (uint)value;
throw new NotSupportedException("value is not an ID!");
}
private static string GET_RESOURCE_NAME(IntPtr value)
{
if (IS_INTRESOURCE(value))
return value.ToString();
return Marshal.PtrToStringUni(value);
}
private static bool EnumRes(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam)
{
defaultIconPtr = lpszName;
return false;
}
}
}

View file

@ -1,58 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<ProjectGuid>{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}</ProjectGuid>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Flow.Launcher.Plugin.ControlPanel</RootNamespace>
<AssemblyName>Flow.Launcher.Plugin.ControlPanel</AssemblyName>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.ControlPanel\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\Output\Release\Plugins\Flow.Launcher.Plugin.ControlPanel\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<None Include="plugin.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Flow.Launcher.Infrastructure\Flow.Launcher.Infrastructure.csproj" />
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="Images\*.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Languages\*.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">Systemsteuerung</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">Suche in der Systemsteuerung</system:String>
</ResourceDictionary>

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">Control Panel</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">Search within the Control Panel</system:String>
</ResourceDictionary>

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">Panel sterowania</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">Szybie wyszukiwanie ustawień w panelu sterowania</system:String>
</ResourceDictionary>

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">Ovládací panel</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">Vyhľadáva položky Ovládacieho panela</system:String>
</ResourceDictionary>

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">Denetim Masası</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">Denetim Masası'nda arama yapın.</system:String>
</ResourceDictionary>

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">控制面板</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">搜索控制面板</system:String>
</ResourceDictionary>

View file

@ -1,8 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_name">控制台</system:String>
<system:String x:Key="flowlauncher_plugin_controlpanel_plugin_description">搜尋控制台</system:String>
</ResourceDictionary>

View file

@ -1,99 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure;
namespace Flow.Launcher.Plugin.ControlPanel
{
public class Main : IPlugin, IPluginI18n
{
private PluginInitContext context;
private List<ControlPanelItem> controlPanelItems = new List<ControlPanelItem>();
private string iconFolder;
private string fileType;
public void Init(PluginInitContext context)
{
this.context = context;
controlPanelItems = ControlPanelList.Create(48);
iconFolder = Path.Combine(context.CurrentPluginMetadata.PluginDirectory, @"Images\ControlPanelIcons\");
fileType = ".bmp";
if (!Directory.Exists(iconFolder))
{
Directory.CreateDirectory(iconFolder);
}
foreach (ControlPanelItem item in controlPanelItems)
{
if (!File.Exists(iconFolder + item.GUID + fileType) && item.Icon != null)
{
item.Icon.ToBitmap().Save(iconFolder + item.GUID + fileType);
}
}
}
public List<Result> Query(Query query)
{
List<Result> results = new List<Result>();
foreach (var item in controlPanelItems)
{
var titleMatch = StringMatcher.FuzzySearch(query.Search, item.LocalizedString);
var subTitleMatch = StringMatcher.FuzzySearch(query.Search, item.InfoTip);
item.Score = Math.Max(titleMatch.Score, subTitleMatch.Score);
if (item.Score > 0)
{
var result = new Result
{
Title = item.LocalizedString,
SubTitle = item.InfoTip,
Score = item.Score,
IcoPath = Path.Combine(context.CurrentPluginMetadata.PluginDirectory,
@"Images\\ControlPanelIcons\\" + item.GUID + fileType),
Action = e =>
{
try
{
Process.Start(item.ExecutablePath);
}
catch (Exception)
{
//Silently Fail for now.. todo
}
return true;
}
};
if (item.Score == titleMatch.Score)
{
result.TitleHighlightData = titleMatch.MatchData;
}
else
{
result.SubTitleHighlightData = subTitleMatch.MatchData;
}
results.Add(result);
}
}
List<Result> panelItems = results.OrderByDescending(o => o.Score).Take(5).ToList();
return panelItems;
}
public string GetTranslatedPluginTitle()
{
return context.API.GetTranslation("flowlauncher_plugin_controlpanel_plugin_name");
}
public string GetTranslatedPluginDescription()
{
return context.API.GetTranslation("flowlauncher_plugin_controlpanel_plugin_description");
}
}
}

View file

@ -1,12 +0,0 @@
{
"ID": "209621585B9B4D81813913C507C058C6",
"ActionKeyword": "*",
"Name": "Control Panel",
"Description": "Search within the Control Panel.",
"Author": "CoenraadS",
"Version": "1.1.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.ControlPanel.dll",
"IcoPath": "Images\\ControlPanel.png"
}

View file

@ -205,7 +205,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
}
var mainWindow = Application.Current.MainWindow;
mainWindow.Visibility = Visibility.Visible;
mainWindow.Show();
mainWindow.Focus();
return false;

View file

@ -10,7 +10,7 @@
"Name": "Explorer",
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
"Author": "Jeremy Wu",
"Version": "1.10.0",
"Version": "1.10.1",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",

View file

@ -4,13 +4,16 @@
<!--Dialogues-->
<system:String x:Key="plugin_pluginsmanager_downloading_plugin">Downloading plugin</system:String>
<system:String x:Key="plugin_pluginsmanager_please_wait">Please wait...</system:String>
<system:String x:Key="plugin_pluginsmanager_download_success">Successfully downloaded</system:String>
<system:String x:Key="plugin_pluginsmanager_download_error">Error: Unable to download the plugin</system:String>
<system:String x:Key="plugin_pluginsmanager_uninstall_prompt">{0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart.</system:String>
<system:String x:Key="plugin_pluginsmanager_install_prompt">{0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart.</system:String>
<system:String x:Key="plugin_pluginsmanager_install_title">Plugin Install</system:String>
<system:String x:Key="plugin_pluginsmanager_install_from_web">Download and install {0}</system:String>
<system:String x:Key="plugin_pluginsmanager_uninstall_title">Plugin Uninstall</system:String>
<system:String x:Key="plugin_pluginsmanager_install_errormetadatafile">Install failed: unable to find the plugin.json metadata file from the new plugin</system:String>
<system:String x:Key="plugin_pluginsmanager_install_success_restart">Plugin successfully installed. Restarting Flow, please wait...</system:String>
<system:String x:Key="plugin_pluginsmanager_install_errormetadatafile">Unable to find the plugin.json metadata file from the extracted zip file.</system:String>
<system:String x:Key="plugin_pluginsmanager_install_error_duplicate">Error: A plugin which has the same or greater version with {0} already exists.</system:String>
<system:String x:Key="plugin_pluginsmanager_install_error_title">Error installing plugin</system:String>
<system:String x:Key="plugin_pluginsmanager_install_error_subtitle">Error occured while trying to install {0}</system:String>
<system:String x:Key="plugin_pluginsmanager_update_noresult_title">No update available</system:String>
@ -21,12 +24,15 @@
<system:String x:Key="plugin_pluginsmanager_update_alreadyexists">This plugin is already installed</system:String>
<system:String x:Key="plugin_pluginsmanager_update_failed_title">Plugin Manifest Download Failed</system:String>
<system:String x:Key="plugin_pluginsmanager_update_failed_subtitle">Please check if you can connect to github.com. This error means you may not be able to install or update plugins.</system:String>
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning_title">Installing from an unknown source</system:String>
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning">You are installing this plugin from an unknown source and it may contain potential risks!{0}{0}Please ensure you understand where this plugin is from and that it is safe.{0}{0}Would you like to continue still?{0}{0}(You can switch off this warning via settings)</system:String>
<!--Controls-->
<!--Plugin Infos-->
<system:String x:Key="plugin_pluginsmanager_plugin_name">Plugins Manager</system:String>
<system:String x:Key="plugin_pluginsmanager_plugin_description">Management of installing, uninstalling or updating Flow Launcher plugins</system:String>
<system:String x:Key="plugin_pluginsmanager_unknown_author">Unknown Author</system:String>
<!--Context menu items-->
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_openwebsite_title">Open website</system:String>
@ -36,6 +42,8 @@
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_newissue_title">Suggest an enhancement or submit an issue</system:String>
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_newissue_subtitle">Suggest an enhancement or submit an issue to the plugin developer</system:String>
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_pluginsmanifest_title">Go to Flow's plugins repository</system:String>
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_pluginsmanifest_subtitle">Visit the PluginsManifest repository to see comunity-made plugin submissions</system:String>
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_pluginsmanifest_subtitle">Visit the PluginsManifest repository to see community-made plugin submissions</system:String>
<!--Settings menu items-->
<system:String x:Key="plugin_pluginsmanager_plugin_settings_unknown_source">Install from unknown source warning</system:String>
</ResourceDictionary>

View file

@ -4,7 +4,6 @@
<!--Dialogues-->
<system:String x:Key="plugin_pluginsmanager_downloading_plugin">Sťahovanie pluginu</system:String>
<system:String x:Key="plugin_pluginsmanager_please_wait">Čakajte, prosím…</system:String>
<system:String x:Key="plugin_pluginsmanager_download_success">Úspešne stiahnuté</system:String>
<system:String x:Key="plugin_pluginsmanager_uninstall_prompt">{0} od {1} {2}{3}Chcete odinštalovať tento plugin? Po odinštalovaní sa Flow automaticky reštartuje.</system:String>
<system:String x:Key="plugin_pluginsmanager_install_prompt">{0} by {1} {2}{3}Chcete nainštalovať tento plugin? Po nainštalovaní sa Flow automaticky reštartuje.</system:String>

View file

@ -4,7 +4,6 @@
<!--Dialogues-->
<system:String x:Key="plugin_pluginsmanager_downloading_plugin">下载插件</system:String>
<system:String x:Key="plugin_pluginsmanager_please_wait">请稍等...</system:String>
<system:String x:Key="plugin_pluginsmanager_download_success">下载完成</system:String>
<system:String x:Key="plugin_pluginsmanager_uninstall_prompt">{0} by {1} {2}{3} 您要卸载此插件吗? 卸载后Flow Launcher 将自动重启。</system:String>
<system:String x:Key="plugin_pluginsmanager_install_prompt">{0} by {1} {2}{3} 您要安装此插件吗? 安装后Flow Launcher 将自动重启</system:String>

View file

@ -55,7 +55,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
{
var search = query.Search.ToLower();
var search = query.Search;
if (string.IsNullOrWhiteSpace(search))
return pluginManager.GetDefaultHotKeys();
@ -70,9 +70,13 @@ namespace Flow.Launcher.Plugin.PluginsManager
return search switch
{
var s when s.StartsWith(Settings.HotKeyInstall) => await pluginManager.RequestInstallOrUpdate(s, token),
var s when s.StartsWith(Settings.HotkeyUninstall) => pluginManager.RequestUninstall(s),
var s when s.StartsWith(Settings.HotkeyUpdate) => await pluginManager.RequestUpdate(s, token),
//search could be url, no need ToLower() when passed in
var s when s.StartsWith(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase)
=> await pluginManager.RequestInstallOrUpdate(search, token),
var s when s.StartsWith(Settings.HotkeyUninstall, StringComparison.OrdinalIgnoreCase)
=> pluginManager.RequestUninstall(search),
var s when s.StartsWith(Settings.HotkeyUpdate, StringComparison.OrdinalIgnoreCase)
=> await pluginManager.RequestUpdate(search, token),
_ => pluginManager.GetDefaultHotKeys().Where(hotkey =>
{
hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score;

View file

@ -9,6 +9,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@ -17,6 +19,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
{
internal class PluginsManager
{
const string zip = "zip";
private PluginInitContext Context { get; set; }
private Settings Settings { get; set; }
@ -47,7 +51,6 @@ namespace Flow.Launcher.Plugin.PluginsManager
private Task _downloadManifestTask = Task.CompletedTask;
internal Task UpdateManifestAsync()
{
if (_downloadManifestTask.Status == TaskStatus.Running)
@ -118,7 +121,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
$"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}");
var mainWindow = Application.Current.MainWindow;
mainWindow.Visibility = Visibility.Visible;
mainWindow.Show();
mainWindow.Focus();
shouldHideWindow = false;
@ -138,13 +141,15 @@ namespace Flow.Launcher.Plugin.PluginsManager
MessageBoxButton.YesNo) == MessageBoxResult.No)
return;
var filePath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}.zip");
// at minimum should provide a name, but handle plugin that is not downloaded from plugins manifest and is a url download
var downloadFilename = string.IsNullOrEmpty(plugin.Version)
? $"{plugin.Name}-{Guid.NewGuid()}.zip"
: $"{plugin.Name}-{plugin.Version}.zip";
var filePath = Path.Combine(DataLocation.PluginsDirectory, downloadFilename);
try
{
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
await Http.DownloadAsync(plugin.UrlDownload, filePath).ConfigureAwait(false);
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
@ -154,7 +159,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
}
catch (Exception e)
{
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
if (e is HttpRequestException)
MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_download_error"),
Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"));
Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"),
string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
plugin.Name));
@ -163,6 +172,9 @@ namespace Flow.Launcher.Plugin.PluginsManager
return;
}
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_title"),
Context.API.GetTranslation("plugin_pluginsmanager_install_success_restart"));
Context.API.RestartApp();
}
@ -183,7 +195,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (autocompletedResults.Any())
return autocompletedResults;
var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty).TrimStart();
var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart();
var resultsForUpdate =
from existingPlugin in Context.API.GetAllPlugins()
@ -239,10 +251,6 @@ namespace Flow.Launcher.Plugin.PluginsManager
Task.Run(async delegate
{
Context.API.ShowMsg(
Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
Context.API.GetTranslation("plugin_pluginsmanager_please_wait"));
await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath)
.ConfigureAwait(false);
@ -302,6 +310,62 @@ namespace Flow.Launcher.Plugin.PluginsManager
.ToList();
}
internal List<Result> InstallFromWeb(string url)
{
var filename = url.Split("/").Last();
var name = filename.Split(string.Format(".{0}", zip)).First();
var plugin = new UserPlugin
{
ID = "",
Name = name,
Version = string.Empty,
Author = Context.API.GetTranslation("plugin_pluginsmanager_unknown_author"),
UrlDownload = url
};
var result = new Result
{
Title = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_from_web"), filename),
SubTitle = plugin.UrlDownload,
IcoPath = icoPath,
Action = e =>
{
if (e.SpecialKeyState.CtrlPressed)
{
SearchWeb.NewTabInBrowser(plugin.UrlDownload);
return ShouldHideWindow;
}
if (Settings.WarnFromUnknownSource)
{
if (!InstallSourceKnown(plugin.UrlDownload)
&& MessageBox.Show(string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning"),
Environment.NewLine),
Context.API.GetTranslation("plugin_pluginsmanager_install_unknown_source_warning_title"),
MessageBoxButton.YesNo) == MessageBoxResult.No)
return false;
}
Application.Current.MainWindow.Hide();
_ = InstallOrUpdate(plugin);
return ShouldHideWindow;
}
};
return new List<Result> { result };
}
private bool InstallSourceKnown(string url)
{
var author = url.Split('/')[3];
var acceptedSource = "https://github.com";
var contructedUrlPart = string.Format("{0}/{1}/", acceptedSource, author);
return url.StartsWith(acceptedSource) && Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(contructedUrlPart));
}
internal async ValueTask<List<Result>> RequestInstallOrUpdate(string searchName, CancellationToken token)
{
if (!PluginsManifest.UserPlugins.Any())
@ -311,7 +375,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
token.ThrowIfCancellationRequested();
var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty).Trim();
var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty, StringComparison.OrdinalIgnoreCase).Trim();
if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute)
&& searchNameWithoutKeyword.Split('.').Last() == zip)
return InstallFromWeb(searchNameWithoutKeyword);
var results =
PluginsManifest
@ -369,11 +437,26 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (string.IsNullOrEmpty(metadataJsonFilePath) || string.IsNullOrEmpty(pluginFolderPath))
{
MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"));
return;
MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"),
Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"));
throw new FileNotFoundException (
string.Format("Unable to find plugin.json from the extracted zip file, or this path {0} does not exist", pluginFolderPath));
}
string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}");
if (SameOrLesserPluginVersionExists(metadataJsonFilePath))
{
MessageBox.Show(string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name),
Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"));
throw new InvalidOperationException(
string.Format("A plugin with the same ID and version already exists, " +
"or the version is greater than this downloaded plugin {0}",
plugin.Name));
}
var directory = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}";
var newPluginPath = Path.Combine(DataLocation.PluginsDirectory, directory);
FilesFolders.CopyAll(pluginFolderPath, newPluginPath);
@ -390,7 +473,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (autocompletedResults.Any())
return autocompletedResults;
var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty).TrimStart();
var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart();
var results = Context.API
.GetAllPlugins()
@ -466,5 +549,13 @@ namespace Flow.Launcher.Plugin.PluginsManager
return new List<Result>();
}
private bool SameOrLesserPluginVersionExists(string metadataPath)
{
var newMetadata = JsonSerializer.Deserialize<PluginMetadata>(File.ReadAllText(metadataPath));
return Context.API.GetAllPlugins()
.Any(x => x.Metadata.ID == newMetadata.ID
&& newMetadata.Version.CompareTo(x.Metadata.Version) <= 0);
}
}
}
}

View file

@ -7,8 +7,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
internal class Settings
{
internal string HotKeyInstall { get; set; } = "install";
internal string HotkeyUninstall { get; set; } = "uninstall";
internal string HotkeyUpdate { get; set; } = "update";
public bool WarnFromUnknownSource { get; set; } = true;
}
}

View file

@ -14,5 +14,11 @@ namespace Flow.Launcher.Plugin.PluginsManager.ViewModels
Context = context;
Settings = settings;
}
public bool WarnFromUnknownSource
{
get => Settings.WarnFromUnknownSource;
set => Settings.WarnFromUnknownSource = value;
}
}
}

View file

@ -3,10 +3,18 @@
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:local="clr-namespace:Flow.Launcher.Plugin.PluginsManager.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Grid Margin="70 15 0 15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{DynamicResource plugin_pluginsmanager_plugin_settings_unknown_source}"
VerticalAlignment="Center"
FontSize="14"/>
<CheckBox Grid.Column="1" IsChecked="{Binding WarnFromUnknownSource}" />
</Grid>
</UserControl>

View file

@ -16,7 +16,7 @@ namespace Flow.Launcher.Plugin.PluginsManager.Views
this.viewModel = viewModel;
//RefreshView();
this.DataContext = viewModel;
}
}
}

View file

@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
"Version": "1.9.0",
"Version": "1.10.0",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",

View file

@ -1,22 +1,132 @@
<Window x:Class="Flow.Launcher.Plugin.Program.AddProgramSource"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Width="400"
Height="130"
WindowStartupLocation="CenterScreen">
<Window
x:Class="Flow.Launcher.Plugin.Program.AddProgramSource"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
Title="{DynamicResource flowlauncher_plugin_program_directory}"
Width="400"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<StackPanel Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource flowlauncher_plugin_program_directory}"
TextAlignment="Left" />
</StackPanel>
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBox
Name="Directory"
Width="268"
Margin="0,7"
VerticalAlignment="Center" />
<Button
Width="70"
Margin="10"
HorizontalAlignment="Right"
Click="BrowseButton_Click"
Content="{DynamicResource flowlauncher_plugin_program_browse}" />
</StackPanel>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="100"
Margin="0,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
Width="100"
Margin="5,0,0,0"
HorizontalAlignment="Right"
Click="ButtonAdd_OnClick"
Content="{DynamicResource flowlauncher_plugin_program_update}" />
</StackPanel>
</Border>
</Grid>
<!--
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Label Content="{DynamicResource flowlauncher_plugin_program_directory}" Margin="15,10"/>
<TextBox Name="Directory" VerticalAlignment="Center" Width="278" Margin="10,7" />
<Label Margin="15,10" Content="{DynamicResource flowlauncher_plugin_program_directory}" />
<TextBox
Name="Directory"
Width="278"
Margin="10,7"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Click="BrowseButton_Click" Content="{DynamicResource flowlauncher_plugin_program_browse}"
HorizontalAlignment="Right" Margin="10" Height="31" Width="70" />
<Button Click="ButtonAdd_OnClick" Content="{DynamicResource flowlauncher_plugin_program_update}"
HorizontalAlignment="Right" Margin="10" Height="31" Width="70" />
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button
Width="70"
Height="31"
Margin="10"
HorizontalAlignment="Right"
Click="BrowseButton_Click"
Content="{DynamicResource flowlauncher_plugin_program_browse}" />
<Button
Width="70"
Height="31"
Margin="10"
HorizontalAlignment="Right"
Click="ButtonAdd_OnClick"
Content="{DynamicResource flowlauncher_plugin_program_update}" />
</StackPanel>
</StackPanel>
-->
</Window>

View file

@ -42,6 +42,11 @@ namespace Flow.Launcher.Plugin.Program
}
}
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
{
Close();
}
private void ButtonAdd_OnClick(object sender, RoutedEventArgs e)
{
string s = Directory.Text;

View file

@ -1,8 +1,9 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--Program setting-->
<!-- Program setting -->
<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>
@ -16,12 +17,14 @@
<system:String x:Key="flowlauncher_plugin_program_index_start_tooltip">When enabled, Flow will load programs from the start menu</system:String>
<system:String x:Key="flowlauncher_plugin_program_index_registry">Index Registry</system:String>
<system:String x:Key="flowlauncher_plugin_program_index_registry_tooltip">When enabled, Flow will load programs from the registry</system:String>
<system:String x:Key="flowlauncher_plugin_program_enable_description">Enable Program Description</system:String>
<system:String x:Key="flowlauncher_plugin_program_enable_hidelnkpath">Hide app path</system:String>
<system:String x:Key="flowlauncher_plugin_program_enable_hidelnkpath_tooltip">For executable files such as UWP or lnk, hide the file path from being visible</system:String>
<system:String x:Key="flowlauncher_plugin_program_enable_description">Search in Program Description</system:String>
<system:String x:Key="flowlauncher_plugin_program_enable_description_tooltip">Disabling this will also stop Flow from searching via the program desciption</system:String>
<system:String x:Key="flowlauncher_plugin_program_suffixes_header">Suffixes</system:String>
<system:String x:Key="flowlauncher_plugin_program_max_depth_header">Max Depth</system:String>
<system:String x:Key="flowlauncher_plugin_program_directory">Directory:</system:String>
<system:String x:Key="flowlauncher_plugin_program_directory">Directory</system:String>
<system:String x:Key="flowlauncher_plugin_program_browse">Browse</system:String>
<system:String x:Key="flowlauncher_plugin_program_file_suffixes">File Suffixes:</system:String>
<system:String x:Key="flowlauncher_plugin_program_max_search_depth">Maximum Search Depth (-1 is unlimited):</system:String>
@ -30,8 +33,7 @@
<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:</system:String>
<system:String x:Key="flowlauncher_plugin_program_split_by_tip">(Each suffix should split by ';' )</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_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>
@ -50,7 +52,7 @@
<system:String x:Key="flowlauncher_plugin_program_tooltip_customizedexplorer">You can customized the explorer used for opening the container folder by inputing the Environmental Variable of the explorer you want to use. It will be useful to use CMD to test whether the Environmental Variable is avaliable.</system:String>
<system:String x:Key="flowlauncher_plugin_program_tooltip_args">Enter the customized args you want to add for your customized explorer. %s for parent directory, %f for full path (which only works for win32). Check the explorer's website for details.</system:String>
<!--Dialogs-->
<!-- Dialogs -->
<system:String x:Key="flowlauncher_plugin_program_disable_dlgtitle_success">Success</system:String>
<system:String x:Key="flowlauncher_plugin_program_disable_dlgtitle_success_message">Successfully disabled this program from displaying in your query</system:String>
<system:String x:Key="flowlauncher_plugin_program_run_as_administrator_not_supported_message">This app is not intended to be run as administrator</system:String>

View file

@ -147,10 +147,15 @@ namespace Flow.Launcher.Plugin.Program
var t1 = Task.Run(IndexWin32Programs);
var t2 = Task.Run(IndexUwpPrograms);
await Task.WhenAll(t1, t2).ConfigureAwait(false);
ResetCache();
_settings.LastIndexTime = DateTime.Today;
}
internal static void ResetCache()
{
var oldCache = cache;
cache = new MemoryCache(cacheOptions);
oldCache.Dispose();
_settings.LastIndexTime = DateTime.Today;
}
public Control CreateSettingPanel()

View file

@ -1,19 +1,101 @@
<Window x:Class="Flow.Launcher.Plugin.Program.ProgramSuffixes"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Width="400"
Height="180"
WindowStartupLocation="CenterScreen"
d:DesignHeight="400" d:DesignWidth="300">
<StackPanel>
<TextBlock Margin="10 10 0 0" Foreground="Gray" Text="{DynamicResource flowlauncher_plugin_program_only_index_tip}" />
<TextBlock Margin="10 10 0 0" Foreground="Gray" Text="{DynamicResource flowlauncher_plugin_program_split_by_tip}" />
<TextBox x:Name="tbSuffixes" Margin="10"/>
<Button HorizontalAlignment="Right" Height="30" Width="80" Click="ButtonBase_OnClick" Margin="0 0 10 0" Content="{DynamicResource flowlauncher_plugin_program_update}" />
</StackPanel>
<Window
x:Class="Flow.Launcher.Plugin.Program.ProgramSuffixes"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
Title="{DynamicResource flowlauncher_plugin_program_suffixes}"
Width="400"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<StackPanel Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource flowlauncher_plugin_program_suffixes}"
TextAlignment="Left" />
</StackPanel>
<TextBlock
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_program_only_index_tip}"
TextWrapping="Wrap" />
<TextBox x:Name="tbSuffixes" Margin="0,20,0,20" />
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="100"
Height="30"
Margin="0,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
Width="100"
Height="30"
Margin="5,0,0,0"
HorizontalAlignment="Right"
Click="ButtonBase_OnClick"
Content="{DynamicResource flowlauncher_plugin_program_update}" />
</StackPanel>
</Border>
</Grid>
</Window>

View file

@ -18,7 +18,10 @@ namespace Flow.Launcher.Plugin.Program
_settings = settings;
tbSuffixes.Text = string.Join(Settings.SuffixSeperator.ToString(), _settings.ProgramSuffixes);
}
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);

View file

@ -314,7 +314,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
var result = new Result
{
Title = title,
SubTitle = Package.Location,
SubTitle = Main._settings.HideAppsPath ? string.Empty : Package.Location,
Icon = Logo,
Score = matchResult.Score,
TitleHighlightData = matchResult.MatchData,

View file

@ -97,7 +97,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
var result = new Result
{
Title = title,
SubTitle = LnkResolvedPath ?? FullPath,
SubTitle = Main._settings.HideAppsPath ? string.Empty : LnkResolvedPath ?? FullPath,
IcoPath = IcoPath,
Score = matchResult.Score,
TitleHighlightData = matchResult.MatchData,

View file

@ -13,7 +13,8 @@ namespace Flow.Launcher.Plugin.Program
public bool EnableStartMenuSource { get; set; } = true;
public bool EnableDescription { 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;

View file

@ -5,75 +5,110 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:program="clr-namespace:Flow.Launcher.Plugin.Program"
Height="450"
d:DesignHeight="404.508"
d:DesignWidth="600"
Height="520"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d">
<Grid Margin="20">
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition Height="120" />
<RowDefinition Height="170" />
<RowDefinition Height="*" />
<RowDefinition Height="50" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<StackPanel
Grid.Row="0"
HorizontalAlignment="Stretch"
Orientation="Horizontal">
Orientation="Vertical">
<StackPanel Width="Auto" Orientation="Vertical">
<CheckBox
Name="StartMenuEnabled"
Margin="5"
Content="{DynamicResource flowlauncher_plugin_program_index_start}"
IsChecked="{Binding EnableStartMenuSource}"
ToolTip="{DynamicResource flowlauncher_plugin_program_index_start_tooltip}" />
<CheckBox
Name="RegistryEnabled"
Margin="5"
Content="{DynamicResource flowlauncher_plugin_program_index_registry}"
IsChecked="{Binding EnableRegistrySource}"
ToolTip="{DynamicResource flowlauncher_plugin_program_index_registry_tooltip}" />
<CheckBox
Name="DescriptionEnabled"
Margin="5"
Content="{DynamicResource flowlauncher_plugin_program_enable_description}"
IsChecked="{Binding EnableDescription}"
ToolTip="{DynamicResource flowlauncher_plugin_program_enable_description_tooltip}" />
<StackPanel Width="Auto" Orientation="Horizontal">
<CheckBox
Name="StartMenuEnabled"
Width="200"
Margin="70,8,10,8"
Content="{DynamicResource flowlauncher_plugin_program_index_start}"
IsChecked="{Binding EnableStartMenuSource}"
ToolTip="{DynamicResource flowlauncher_plugin_program_index_start_tooltip}" />
<CheckBox
Name="RegistryEnabled"
Margin="70,8,10,8"
Content="{DynamicResource flowlauncher_plugin_program_index_registry}"
IsChecked="{Binding EnableRegistrySource}"
ToolTip="{DynamicResource flowlauncher_plugin_program_index_registry_tooltip}" />
</StackPanel>
<Separator
Height="1"
BorderBrush="{DynamicResource Color03B}"
BorderThickness="1" />
<StackPanel Width="Auto" Orientation="Horizontal">
<CheckBox
Name="HideLnkEnabled"
Width="200"
Margin="70,8,10,8"
Content="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath}"
IsChecked="{Binding HideAppsPath}"
ToolTip="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath_tooltip}" />
<CheckBox
Name="DescriptionEnabled"
Margin="70,8,10,8"
Content="{DynamicResource flowlauncher_plugin_program_enable_description}"
IsChecked="{Binding EnableDescription}"
ToolTip="{DynamicResource flowlauncher_plugin_program_enable_description_tooltip}" />
</StackPanel>
<Separator
Height="1"
BorderBrush="{DynamicResource Color03B}"
BorderThickness="1" />
</StackPanel>
<StackPanel
Width="Auto"
HorizontalAlignment="Right"
Margin="10,6,0,0"
HorizontalAlignment="Left"
Orientation="Horizontal">
<Button
x:Name="btnLoadAllProgramSource"
Width="100"
Height="31"
Margin="10"
Width="120"
Margin="10,10,5,10"
HorizontalAlignment="Right"
Click="btnLoadAllProgramSource_OnClick"
Content="{DynamicResource flowlauncher_plugin_program_all_programs}" />
<Button
x:Name="btnProgramSuffixes"
Width="100"
Height="31"
Margin="10"
Width="120"
Margin="5,10,5,10"
HorizontalAlignment="Right"
Click="BtnProgramSuffixes_OnClick"
Content="{DynamicResource flowlauncher_plugin_program_suffixes}" />
<Button
x:Name="btnReindex"
Width="100"
Height="31"
Margin="10"
Width="120"
Margin="5,10,5,10"
HorizontalAlignment="Right"
Click="btnReindex_Click"
Content="{DynamicResource flowlauncher_plugin_program_reindex}" />
<StackPanel
x:Name="indexingPanel"
HorizontalAlignment="Left"
Orientation="Horizontal"
Visibility="Hidden">
<ProgressBar
x:Name="progressBarIndexing"
Width="80"
Height="20"
IsIndeterminate="True"
Maximum="100"
Minimum="0" />
<TextBlock
Height="20"
Margin="10,0,0,0"
HorizontalAlignment="Center"
Text="{DynamicResource flowlauncher_plugin_program_indexing}" />
</StackPanel>
</StackPanel>
</StackPanel>
<ListView
x:Name="programSourceView"
Grid.Row="1"
Margin="0,13,0,10"
Margin="20,0,20,0"
AllowDrop="True"
BorderBrush="DarkGray"
BorderThickness="1"
@ -81,14 +116,7 @@
Drop="programSourceView_Drop"
GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
PreviewMouseRightButtonUp="ProgramSourceView_PreviewMouseRightButtonUp"
SelectionMode="Extended"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewMouseUp" Handler="Row_OnClick" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
SelectionMode="Extended">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Name">
@ -121,25 +149,7 @@
<DockPanel
Grid.Row="2"
Grid.RowSpan="1"
Margin="0,0,0,0">
<StackPanel
x:Name="indexingPanel"
HorizontalAlignment="Left"
Orientation="Horizontal"
Visibility="Hidden">
<ProgressBar
x:Name="progressBarIndexing"
Width="80"
Height="20"
IsIndeterminate="True"
Maximum="100"
Minimum="0" />
<TextBlock
Height="20"
Margin="10,0,0,0"
HorizontalAlignment="Center"
Text="{DynamicResource flowlauncher_plugin_program_indexing}" />
</StackPanel>
Margin="0,0,20,10">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button
x:Name="btnProgramSourceStatus"

View file

@ -30,7 +30,20 @@ namespace Flow.Launcher.Plugin.Program.Views
public bool EnableDescription
{
get => _settings.EnableDescription;
set => _settings.EnableDescription = value;
set
{
Main.ResetCache();
_settings.EnableDescription = value;
}
}
public bool HideAppsPath
{
get => _settings.HideAppsPath;
set
{
Main.ResetCache();
_settings.HideAppsPath = value;
}
}
public bool EnableRegistrySource
@ -105,7 +118,6 @@ namespace Flow.Launcher.Plugin.Program.Views
private async void ReIndexing()
{
ViewRefresh();
indexingPanel.Visibility = Visibility.Visible;
await Main.IndexPrograms();
indexingPanel.Visibility = Visibility.Hidden;

View file

@ -4,7 +4,7 @@
"Name": "Program",
"Description": "Search programs in Flow.Launcher",
"Author": "qianlifeng",
"Version": "1.7.0",
"Version": "1.8.0",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Program.dll",

View file

@ -193,51 +193,63 @@ namespace Flow.Launcher.Plugin.Shell
var workingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var runAsAdministratorArg = !runAsAdministrator && !_settings.RunAsAdministrator ? "" : "runas";
ProcessStartInfo info;
if (_settings.Shell == Shell.Cmd)
ProcessStartInfo info = new()
{
var arguments = _settings.LeaveShellOpen ? $"/k \"{command}\"" : $"/c \"{command}\" & pause";
info = ShellCommand.SetProcessStartInfo("cmd.exe", workingDirectory, arguments, runAsAdministratorArg);
}
else if (_settings.Shell == Shell.Powershell)
Verb = runAsAdministratorArg,
WorkingDirectory = workingDirectory,
};
switch (_settings.Shell)
{
string arguments;
if (_settings.LeaveShellOpen)
{
arguments = $"-NoExit \"{command}\"";
}
else
{
arguments = $"\"{command} ; Read-Host -Prompt \\\"Press Enter to continue\\\"\"";
}
info = ShellCommand.SetProcessStartInfo("powershell.exe", workingDirectory, arguments, runAsAdministratorArg);
}
else if (_settings.Shell == Shell.RunCommand)
{
var parts = command.Split(new[] { ' ' }, 2);
if (parts.Length == 2)
{
var filename = parts[0];
if (ExistInPath(filename))
case Shell.Cmd:
{
var arguments = parts[1];
info = ShellCommand.SetProcessStartInfo(filename, workingDirectory, arguments, runAsAdministratorArg);
info.FileName = "cmd.exe";
info.ArgumentList.Add(_settings.LeaveShellOpen ? "/k" : "/c");
info.ArgumentList.Add(command);
break;
}
else
case Shell.Powershell:
{
info = ShellCommand.SetProcessStartInfo(command, verb: runAsAdministratorArg);
info.FileName = "powershell.exe";
if (_settings.LeaveShellOpen)
{
info.ArgumentList.Add("-NoExit");
info.ArgumentList.Add(command);
}
else
{
info.ArgumentList.Add("-Command");
info.ArgumentList.Add(command);
}
break;
}
}
else
{
info = ShellCommand.SetProcessStartInfo(command, verb: runAsAdministratorArg);
}
}
else
{
throw new NotImplementedException();
case Shell.RunCommand:
{
var parts = command.Split(new[] { ' ' }, 2);
if (parts.Length == 2)
{
var filename = parts[0];
if (ExistInPath(filename))
{
var arguments = parts[1];
info.FileName = filename;
info.ArgumentList.Add(arguments);
}
else
{
info.FileName = command;
}
}
else
{
info.FileName = command;
}
break;
}
default:
throw new NotImplementedException();
}
info.UseShellExecute = true;
@ -251,7 +263,7 @@ namespace Flow.Launcher.Plugin.Shell
{
try
{
startProcess(info);
ShellCommand.Execute(startProcess, info);
}
catch (FileNotFoundException e)
{
@ -329,7 +341,7 @@ namespace Flow.Launcher.Plugin.Shell
// show the main window and set focus to the query box
Window mainWindow = Application.Current.MainWindow;
mainWindow.Visibility = Visibility.Visible;
mainWindow.Show();
mainWindow.Focus();
}

View file

@ -4,7 +4,7 @@
"Name": "Shell",
"Description": "Provide executing commands from Flow Launcher",
"Author": "qianlifeng",
"Version": "1.4.5",
"Version": "1.4.6",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll",

View file

@ -190,8 +190,8 @@ namespace Flow.Launcher.Plugin.Sys
var info = ShellCommand.SetProcessStartInfo("shutdown", arguments:"/h");
info.WindowStyle = ProcessWindowStyle.Hidden;
info.UseShellExecute = true;
Process.Start(info);
ShellCommand.Execute(info);
return true;
}

View file

@ -4,7 +4,7 @@
"Name": "System Commands",
"Description": "Provide System related commands. e.g. shutdown,lock, setting etc.",
"Author": "qianlifeng",
"Version": "1.5.0",
"Version": "1.5.1",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Sys.dll",

View file

@ -1,75 +1,365 @@
<Window x:Class="Flow.Launcher.Plugin.WebSearch.SearchSourceSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch"
mc:Ignorable="d" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
Title="{DynamicResource flowlauncher_plugin_websearch_window_title}" Height="590" Width="550"
d:DataContext="{d:DesignInstance vm:SearchSourceViewModel}" Background="#F3F3F3" BorderBrush="#cecece">
<Window
x:Class="Flow.Launcher.Plugin.WebSearch.SearchSourceSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch"
Title="{DynamicResource flowlauncher_plugin_websearch_window_title}"
Width="550"
d:DataContext="{d:DesignInstance vm:SearchSourceViewModel}"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80"/>
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Border BorderThickness="0 0 0 1" BorderBrush="#e5e5e5" Background="#ffffff" Padding="26 26 26 0">
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="OnCancelButtonClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<Grid>
<StackPanel>
<StackPanel Grid.Row="0" Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource flowlauncher_plugin_websearch_window_title}"
TextAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_1}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,12,0,12"
FontSize="14"
FontWeight="SemiBold"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_2}"
TextAlignment="Center"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,0,0,14"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_3}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Width="100"
Margin="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_title}" />
<TextBox
Width="330"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding SearchSource.Title}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="4"
Grid.Column="0"
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_icon}" />
<Button
Height="35"
Margin="10,0,0,0"
VerticalAlignment="Center"
Click="OnSelectIconClick"
Content="{DynamicResource flowlauncher_plugin_websearch_select_icon}" />
<Image
Name="imgPreviewIcon"
Width="24"
Height="24"
Margin="14,0,0,0"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_url}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Width="330"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding SearchSource.Url}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="2"
Grid.Column="0"
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_action_keyword}" />
<TextBox
Grid.Row="2"
Grid.Column="1"
Width="330"
Margin="10,0,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding SearchSource.ActionKeyword}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="3"
Grid.Column="0"
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_enable}" />
<CheckBox
Grid.Row="3"
Grid.Column="1"
Margin="10"
VerticalAlignment="Center"
IsChecked="{Binding SearchSource.Enabled}" />
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
Width="100"
Margin="10,0,5,0"
Click="OnCancelButtonClick"
Content="{DynamicResource flowlauncher_plugin_websearch_cancel}" />
<Button
Width="100"
Margin="5,0,10,0"
Click="OnConfirmButtonClick"
Content="{DynamicResource flowlauncher_plugin_websearch_confirm}" />
</StackPanel>
</Border>
</Grid>
<!--
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Border
Padding="26,26,26,0"
Background="#ffffff"
BorderBrush="#e5e5e5"
BorderThickness="0,0,0,1">
<Grid>
<StackPanel>
<StackPanel Grid.Row="0" Margin="0 0 0 12">
<TextBlock Grid.Column="0" Text="{DynamicResource flowlauncher_plugin_websearch_window_title}" FontSize="20" FontWeight="SemiBold" FontFamily="Segoe UI" TextAlignment="Left"
Margin="0 0 0 0" />
<StackPanel Grid.Row="0" Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontFamily="Segoe UI"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource flowlauncher_plugin_websearch_window_title}"
TextAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock
Text="{DynamicResource flowlauncher_plugin_websearch_guide_1}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left"/>
<TextBlock
Text="{DynamicResource flowlauncher_plugin_websearch_guide_2}" FontWeight="SemiBold" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Center" Margin="0 12 0 12"/>
<TextBlock
Text="{DynamicResource flowlauncher_plugin_websearch_guide_3}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left" Margin="0 0 0 14"/>
<TextBlock
FontSize="14"
Foreground="#1b1b1b"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_1}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,12,0,12"
FontSize="14"
FontWeight="SemiBold"
Foreground="#1b1b1b"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_2}"
TextAlignment="Center"
TextWrapping="WrapWithOverflow" />
<TextBlock
Margin="0,0,0,14"
FontSize="14"
Foreground="#1b1b1b"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_3}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" VerticalAlignment="Center" Width="100"
HorizontalAlignment="Stretch" Text="{DynamicResource flowlauncher_plugin_websearch_title}" />
<TextBox Text="{Binding SearchSource.Title}" Margin="10" Width="330"
VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock
Width="100"
Margin="10"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_title}" />
<TextBox
Width="330"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding SearchSource.Title}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_icon}" Width="100" />
<Button Click="OnSelectIconClick" Height="35" VerticalAlignment="Center" Margin="10 0 0 0"
Content="{DynamicResource flowlauncher_plugin_websearch_select_icon}" />
<Image Name="imgPreviewIcon" Width="24" Height="24" Margin="14 0 0 0" VerticalAlignment="Center"/>
<TextBlock
Grid.Row="4"
Grid.Column="0"
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_icon}" />
<Button
Height="35"
Margin="10,0,0,0"
VerticalAlignment="Center"
Click="OnSelectIconClick"
Content="{DynamicResource flowlauncher_plugin_websearch_select_icon}" />
<Image
Name="imgPreviewIcon"
Width="24"
Height="24"
Margin="14,0,0,0"
VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" VerticalAlignment="Center" Width="100"
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_url}" />
<TextBox Text="{Binding SearchSource.Url}" Margin="10" Grid.Row="1" Width="330" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_url}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Width="330"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding SearchSource.Url}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Width="100"
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_action_keyword}" />
<TextBox Text="{Binding SearchSource.ActionKeyword}" Margin="10 0 10 0" Grid.Row="2" Width="330" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_action_keyword}" />
<TextBox
Grid.Row="2"
Grid.Column="1"
Width="330"
Margin="10,0,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding SearchSource.ActionKeyword}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Width="100"
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_enable}" />
<CheckBox IsChecked="{Binding SearchSource.Enabled}" Margin="10" Grid.Row="3" Grid.Column="1"
VerticalAlignment="Center" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Width="100"
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource flowlauncher_plugin_websearch_enable}" />
<CheckBox
Grid.Row="3"
Grid.Column="1"
Margin="10"
VerticalAlignment="Center"
IsChecked="{Binding SearchSource.Enabled}" />
</StackPanel>
</StackPanel>
</Grid>
</Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="1">
<Button Click="OnCancelButtonClick"
Margin="10 0 5 0" Width="100" Height="35"
Content="{DynamicResource flowlauncher_plugin_websearch_cancel}" />
<Button Click="OnConfirmButtonClick"
Margin="5 0 10 0" Width="100" Height="35"
Content="{DynamicResource flowlauncher_plugin_websearch_confirm}" />
<StackPanel
Grid.Row="1"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
Width="100"
Margin="10,0,5,0"
Click="OnCancelButtonClick"
Content="{DynamicResource flowlauncher_plugin_websearch_cancel}" />
<Button
Width="100"
Margin="5,0,10,0"
Click="OnConfirmButtonClick"
Content="{DynamicResource flowlauncher_plugin_websearch_confirm}" />
</StackPanel>
</Grid>
-->
</Window>

View file

@ -1,128 +1,203 @@
<UserControl x:Class="Flow.Launcher.Plugin.WebSearch.SettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch"
mc:Ignorable="d"
Background="White"
d:DataContext="{d:DesignInstance vm:SettingsViewModel}"
d:DesignHeight="300" d:DesignWidth="500">
<UserControl
x:Class="Flow.Launcher.Plugin.WebSearch.SettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch"
d:DataContext="{d:DesignInstance vm:SettingsViewModel}"
d:DesignHeight="300"
d:DesignWidth="500"
mc:Ignorable="d">
<UserControl.Resources>
<Style TargetType="TextBox" x:Key="BrowserPathBoxStyle">
<Setter Property="Height" Value="28"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Style x:Key="BrowserPathBoxStyle" TargetType="TextBox">
<Setter Property="Height" Value="28" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
<DataTemplate x:Key="HeaderTemplateArrowUp">
<DockPanel>
<TextBlock HorizontalAlignment="Center" Text="{Binding}"/>
<Path x:Name="arrow"
StrokeThickness = "1"
Fill = "gray"
Data = "M 5,10 L 15,10 L 10,5 L 5,10"/>
<TextBlock HorizontalAlignment="Center" Text="{Binding}" />
<Path
x:Name="arrow"
Data="M 5,10 L 15,10 L 10,5 L 5,10"
Fill="gray"
StrokeThickness="1" />
</DockPanel>
</DataTemplate>
<DataTemplate x:Key="HeaderTemplateArrowDown">
<DockPanel>
<TextBlock HorizontalAlignment="Center" Text="{Binding }"/>
<Path x:Name="arrow"
StrokeThickness = "1"
Fill = "gray"
Data = "M 5,5 L 10,10 L 15,5 L 5,5"/>
<TextBlock HorizontalAlignment="Center" Text="{Binding}" />
<Path
x:Name="arrow"
Data="M 5,5 L 10,10 L 15,5 L 5,5"
Fill="gray"
StrokeThickness="1" />
</DockPanel>
</DataTemplate>
</UserControl.Resources>
<Grid Margin="14 14 14 0">
<Grid Margin="14,14,14,0">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="40" />
<RowDefinition />
<RowDefinition Height="56"/>
<RowDefinition Height="56" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" HorizontalAlignment="Left" Orientation="Horizontal" Margin="14 0 0 0">
<Label Content="{DynamicResource flowlauncher_plugin_websearch_open_search_in}" Margin="0 15 20 0"/>
<RadioButton Name="NewWindowBrowser" GroupName="OpenSearchBehaviour" Content="{DynamicResource flowlauncher_plugin_websearch_new_window}" Click="OnNewBrowserWindowClick"
Margin="0 0 20 0"/>
<RadioButton Name="NewTabInBrowser" GroupName="OpenSearchBehaviour" Content="{DynamicResource flowlauncher_plugin_websearch_new_tab}" Click="OnNewTabClick" />
<StackPanel
Grid.Row="0"
Margin="14,0,0,0"
HorizontalAlignment="Left"
Orientation="Horizontal">
<Label Margin="0,15,20,0" Content="{DynamicResource flowlauncher_plugin_websearch_open_search_in}" />
<RadioButton
Name="NewWindowBrowser"
Margin="0,0,20,0"
Click="OnNewBrowserWindowClick"
Content="{DynamicResource flowlauncher_plugin_websearch_new_window}"
GroupName="OpenSearchBehaviour" />
<RadioButton
Name="NewTabInBrowser"
Click="OnNewTabClick"
Content="{DynamicResource flowlauncher_plugin_websearch_new_tab}"
GroupName="OpenSearchBehaviour" />
</StackPanel>
<StackPanel Grid.Row="1" HorizontalAlignment="Left" Margin="14 3 0 0" Orientation="Horizontal">
<Label Content="{DynamicResource flowlaucnher_plugin_websearch_set_browser_path}" Margin="0 0 10 0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<TextBox x:Name="browserPathBox" HorizontalAlignment="Left" Margin="0,0,0,0" TextChanged="OnBrowserPathTextChanged"
Width="250" Style="{StaticResource BrowserPathBoxStyle}"/>
<Button x:Name="viewButton" HorizontalAlignment="Left" Margin="10,0,0,0"
Click="OnChooseClick" FontSize="13" Content="{DynamicResource flowlauncher_plugin_websearch_choose}" Width="80"/>
<StackPanel
Grid.Row="1"
Margin="14,3,0,0"
HorizontalAlignment="Left"
Orientation="Horizontal">
<Label
Margin="0,0,10,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{DynamicResource flowlaucnher_plugin_websearch_set_browser_path}" />
<TextBox
x:Name="browserPathBox"
Width="250"
Margin="0,0,0,0"
HorizontalAlignment="Left"
Style="{StaticResource BrowserPathBoxStyle}"
TextChanged="OnBrowserPathTextChanged" />
<Button
x:Name="viewButton"
Width="80"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Click="OnChooseClick"
Content="{DynamicResource flowlauncher_plugin_websearch_choose}"
FontSize="13" />
</StackPanel>
<ListView Margin="0 18 0 0" ItemsSource="{Binding Settings.SearchSources}"
SelectedItem="{Binding Settings.SelectedSearchSource}"
x:Name="SearchSourcesListView"
Grid.Row="2"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}"
BorderBrush="DarkGray"
BorderThickness="1"
GridViewColumnHeader.Click="SortByColumn"
MouseDoubleClick="MouseDoubleClickItem">
<ListView
x:Name="SearchSourcesListView"
Grid.Row="2"
Margin="0,18,0,0"
BorderBrush="DarkGray"
BorderThickness="1"
GridViewColumnHeader.Click="SortByColumn"
ItemsSource="{Binding Settings.SearchSources}"
MouseDoubleClick="MouseDoubleClickItem"
SelectedItem="{Binding Settings.SelectedSearchSource}"
Style="{StaticResource {x:Static GridView.GridViewStyleKey}}">
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Path=IconPath}" Width="20" Height="20" Margin="6 0 0 0"/>
<Image
Width="20"
Height="20"
Margin="6,0,0,0"
Source="{Binding Path=IconPath}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{DynamicResource flowlauncher_plugin_websearch_action_keyword}"
DisplayMemberBinding="{Binding ActionKeyword}"
Width="130">
<GridViewColumn
Width="130"
DisplayMemberBinding="{Binding ActionKeyword}"
Header="{DynamicResource flowlauncher_plugin_websearch_action_keyword}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ActionKeyword}"/>
<TextBlock Text="{Binding ActionKeyword}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{DynamicResource flowlauncher_plugin_websearch_title}"
DisplayMemberBinding="{Binding Title}" Width="350">
<GridViewColumn
Width="350"
DisplayMemberBinding="{Binding Title}"
Header="{DynamicResource flowlauncher_plugin_websearch_title}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="{DynamicResource flowlauncher_plugin_websearch_enable}"
DisplayMemberBinding="{Binding Enabled}"
Width="80">
<GridViewColumn
Width="80"
DisplayMemberBinding="{Binding Enabled}"
Header="{DynamicResource flowlauncher_plugin_websearch_enable}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Enabled}"/>
<TextBlock Text="{Binding Enabled}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<StackPanel Grid.Row="3" HorizontalAlignment="Right" Orientation="Horizontal">
<Button Click="OnDeleteSearchSearchClick" Width="100" Margin="10"
Content="{DynamicResource flowlauncher_plugin_websearch_delete}" />
<Button Click="OnEditSearchSourceClick" Width="100" Margin="10"
Content="{DynamicResource flowlauncher_plugin_websearch_edit}" />
<Button Click="OnAddSearchSearchClick" Width="100" Margin="10 10 0 10"
Content="{DynamicResource flowlauncher_plugin_websearch_add}" />
<StackPanel
Grid.Row="3"
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button
Width="100"
Margin="10"
Click="OnDeleteSearchSearchClick"
Content="{DynamicResource flowlauncher_plugin_websearch_delete}" />
<Button
Width="100"
Margin="10"
Click="OnEditSearchSourceClick"
Content="{DynamicResource flowlauncher_plugin_websearch_edit}" />
<Button
Width="100"
Margin="10,10,0,10"
Click="OnAddSearchSearchClick"
Content="{DynamicResource flowlauncher_plugin_websearch_add}" />
</StackPanel>
<Border BorderThickness="0 1 0 0" Grid.Row="4" Margin="0 0 0 0" BorderBrush="#cecece" HorizontalAlignment="Stretch">
<DockPanel HorizontalAlignment="Right" Margin="0 14 0 0">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Right">
<Label Content="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion_provider}" Margin="14 0 10 0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding Settings.Suggestions}" VerticalAlignment="Center"
SelectedItem="{Binding Settings.SelectedSuggestion}"
IsEnabled="{Binding ElementName=EnableSuggestion, Path=IsChecked}" Margin="0 0 20 0" FontSize="11" Height="30"/>
<Label Content="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion}" Margin="0 0 10 0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<CheckBox IsChecked="{Binding Settings.EnableSuggestion}"
Margin="0 0 0 0"
Name="EnableSuggestion"/>
<Border
Grid.Row="4"
Margin="0,0,0,0"
HorizontalAlignment="Stretch"
BorderBrush="#cecece"
BorderThickness="0,1,0,0">
<DockPanel Margin="0,14,0,0" HorizontalAlignment="Right">
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
<Label
Margin="14,0,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Content="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion_provider}" />
<ComboBox
Height="30"
Margin="0,0,20,0"
VerticalAlignment="Center"
FontSize="11"
IsEnabled="{Binding ElementName=EnableSuggestion, Path=IsChecked}"
ItemsSource="{Binding Settings.Suggestions}"
SelectedItem="{Binding Settings.SelectedSuggestion}" />
<Label
Margin="0,0,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Content="{DynamicResource flowlauncher_plugin_websearch_enable_suggestion}" />
<CheckBox
Name="EnableSuggestion"
Margin="0,0,0,0"
IsChecked="{Binding Settings.EnableSuggestion}" />
</StackPanel>
<!-- Not sure why binding IsEnabled directly to Settings.EnableWebSaerchSuggestion is not working -->
</DockPanel>
<!-- Not sure why binding IsEnabled directly to Settings.EnableWebSaerchSuggestion is not working -->
</DockPanel>
</Border>
</Grid>
</UserControl>

View file

@ -0,0 +1,78 @@
using System.Collections.Generic;
namespace Flow.Launcher.Plugin.WindowsSettings.Classes
{
/// <summary>
/// A windows setting
/// </summary>
internal record WindowsSetting
{
/// <summary>
/// Initializes a new instance of the <see cref="WindowsSetting"/> class.
/// </summary>
public WindowsSetting()
{
Name = string.Empty;
Area = string.Empty;
Command = string.Empty;
Type = string.Empty;
}
/// <summary>
/// Gets or sets the name of this setting.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the area of this setting.
/// </summary>
public string Area { get; set; }
/// <summary>
/// Gets or sets the command of this setting.
/// </summary>
public string Command { get; set; }
private string type = string.Empty;
/// <summary>
/// Gets or sets the type of the windows setting.
/// </summary>
public string Type { get; set; }
/// <summary>
/// Gets or sets the type display name of this setting.
/// </summary>
public string? DisplayType { get; set; }
/// <summary>
/// Gets or sets the alternative names of this setting.
/// </summary>
public IEnumerable<string>? AltNames { get; set; }
/// <summary>
/// Gets or sets the Keywords names of this task link.
/// </summary>
public IEnumerable<IEnumerable<string>>? Keywords { get; set; }
/// <summary>
/// Gets or sets the Glyph of this setting
/// </summary>
public string? glyph { get; set; }
/// <summary>
/// Gets or sets a additional note of this settings.
/// <para>(e.g. why is not supported on your system)</para>
/// </summary>
public string? Note { get; set; }
/// <summary>
/// Gets or sets the minimum need Windows build for this setting.
/// </summary>
public uint? IntroducedInBuild { get; set; }
/// <summary>
/// Gets or sets the Windows build since this settings is not longer present.
/// </summary>
public uint? DeprecatedInBuild { get; set; }
}
}

View file

@ -0,0 +1,76 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppDesignerFolder>Properties</AppDesignerFolder>
<ErrorReport>prompt</ErrorReport>
<NeutralLanguage>en-US</NeutralLanguage>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.WindowsSettings</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<Optimize>false</Optimize>
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>..\..\Output\Release\Plugins\Flow.Launcher.Plugin.WindowsSettings</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>portable</DebugType>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<None Remove="WindowsSettings.json" />
</ItemGroup>
<ItemGroup>
<None Include="plugin.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="WindowsSettings.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="Images\*.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Windows;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.WindowsSettings.Classes;
using Flow.Launcher.Plugin.WindowsSettings.Properties;
namespace Flow.Launcher.Plugin.WindowsSettings.Helper
{
/// <summary>
/// Helper class to easier work with context menu entries
/// </summary>
internal static class ContextMenuHelper
{
/// <summary>
/// Return a list with all context menu entries for the given <see cref="Result"/>
/// <para>Symbols taken from <see href="https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font"/></para>
/// </summary>
/// <param name="result">The result for the context menu entires</param>
/// <param name="assemblyName">The name of the this assembly</param>
/// <returns>A list with context menu entries</returns>
internal static List<Result> GetContextMenu(in Result result, in string assemblyName)
{
if (result?.ContextData is not WindowsSetting entry)
{
return new List<Result>(0);
}
var list = new List<Result>(1)
{
new()
{
Action = _ => TryToCopyToClipBoard(entry.Command),
Title = $"{Resources.CopyCommand} (Ctrl+C)",
},
};
return list;
}
/// <summary>
/// Copy the given text to the clipboard
/// </summary>
/// <param name="text">The text to copy to the clipboard</param>
/// <returns><see langword="true"/>The text successful copy to the clipboard, otherwise <see langword="false"/></returns>
private static bool TryToCopyToClipBoard(in string text)
{
try
{
Clipboard.Clear();
Clipboard.SetText(text);
return true;
}
catch (Exception exception)
{
Log.Exception("Can't copy to clipboard", exception, typeof(Main));
return false;
}
}
}
}

View file

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Flow.Launcher.Plugin.WindowsSettings.Classes;
namespace Flow.Launcher.Plugin.WindowsSettings.Helper
{
/// <summary>
/// Helper class to easier work with the JSON file that contains all Windows settings
/// </summary>
internal static class JsonSettingsListHelper
{
/// <summary>
/// The name of the file that contains all settings for the query
/// </summary>
private const string _settingsFile = "WindowsSettings.json";
/// <summary>
/// Read all possible Windows settings.
/// </summary>
/// <returns>A list with all possible windows settings.</returns>
internal static IEnumerable<WindowsSetting> ReadAllPossibleSettings()
{
var assembly = Assembly.GetExecutingAssembly();
var type = assembly.GetTypes().FirstOrDefault(x => x.Name == nameof(Main));
IEnumerable<WindowsSetting>? settingsList = null;
try
{
var resourceName = $"{type?.Namespace}.{_settingsFile}";
using var stream = assembly.GetManifestResourceStream(resourceName);
if (stream is null)
{
throw new Exception("stream is null");
}
var options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverter());
using var reader = new StreamReader(stream);
var text = reader.ReadToEnd();
settingsList = JsonSerializer.Deserialize<IEnumerable<WindowsSetting>>(text, options);
}
catch (Exception exception)
{
Log.Exception("Error loading settings JSON file", exception, typeof(Main));
}
return settingsList ?? Enumerable.Empty<WindowsSetting>();
}
}
}

View file

@ -0,0 +1,189 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.WindowsSettings.Classes;
using Flow.Launcher.Plugin.WindowsSettings.Properties;
namespace Flow.Launcher.Plugin.WindowsSettings.Helper
{
/// <summary>
/// Helper class to easier work with results
/// </summary>
internal static class ResultHelper
{
private static IPublicAPI? _api;
public static void Init(IPublicAPI api) => _api = api;
/// <summary>
/// Return a list with <see cref="Result"/>s, based on the given list.
/// </summary>
/// <param name="list">The original result list to convert.</param>
/// <param name="query">Query for specific result List</param>
/// <param name="windowsSettingIconPath">The path to the icon of each entry.</param>
/// <returns>A list with <see cref="Result"/>.</returns>
internal static List<Result> GetResultList(
in IEnumerable<WindowsSetting> list,
Query query,
string windowsSettingIconPath,
string controlPanelIconPath)
{
var resultList = new List<Result>();
foreach (var entry in list)
{
const int highScore = 20;
const int midScore = 10;
Result? result;
Debug.Assert(_api != null, nameof(_api) + " != null");
var nameMatch = _api.FuzzySearch(query.Search, entry.Name);
if (nameMatch.IsSearchPrecisionScoreMet())
{
var settingResult = NewSettingResult(nameMatch.Score + highScore, entry.Type);
settingResult.TitleHighlightData = nameMatch.MatchData;
result = settingResult;
}
else
{
var areaMatch = _api.FuzzySearch(query.Search, entry.Area);
if (areaMatch.IsSearchPrecisionScoreMet())
{
var settingResult = NewSettingResult(areaMatch.Score + midScore, entry.Type);
settingResult.SubTitleHighlightData = areaMatch.MatchData.Select(x => x + 6).ToList();
result = settingResult;
}
else
{
result = entry.AltNames?
.Select(altName => _api.FuzzySearch(query.Search, altName))
.Where(match => match.IsSearchPrecisionScoreMet())
.Select(altNameMatch => NewSettingResult(altNameMatch.Score + midScore, entry.Type))
.FirstOrDefault();
}
if (result is null && entry.Keywords is not null)
{
string[] searchKeywords = query.SearchTerms;
if (searchKeywords
.All(x => entry
.Keywords
.SelectMany(x => x)
.Contains(x, StringComparer.CurrentCultureIgnoreCase))
)
result = NewSettingResult(midScore, entry.Type);
}
}
if (result is null)
continue;
AddOptionalToolTip(entry, result);
resultList.Add(result);
Result NewSettingResult(int score, string type) => new()
{
Action = _ => DoOpenSettingsAction(entry),
IcoPath = type == "AppSettingsApp" ? windowsSettingIconPath : controlPanelIconPath,
SubTitle = GetSubtitle(entry.Area, type),
Title = entry.Name + entry.glyph,
ContextData = entry,
Score = score
};
}
return resultList;
}
private static string GetSubtitle(string section, string entryType)
{
var settingType = entryType == "AppSettingsApp" ? "System settings" : "Control Panel";
return $"{settingType} > {section}";
}
/// <summary>
/// Add a tool-tip to the given <see cref="Result"/>, based o the given <see cref="IWindowsSetting"/>.
/// </summary>
/// <param name="entry">The <see cref="WindowsSetting"/> that contain informations for the tool-tip.</param>
/// <param name="result">The <see cref="Result"/> that need a tool-tip.</param>
private static void AddOptionalToolTip(WindowsSetting entry, Result result)
{
var toolTipText = new StringBuilder();
var settingType = entry.Type == "AppSettingsApp" ? "System settings" : "Control Panel";
toolTipText.AppendLine($"{Resources.Application}: {settingType}");
toolTipText.AppendLine($"{Resources.Area}: {entry.Area}");
if (entry.AltNames != null && entry.AltNames.Any())
{
var altList = entry.AltNames.Aggregate((current, next) => $"{current}, {next}");
toolTipText.AppendLine($"{Resources.AlternativeName}: {altList}");
}
toolTipText.Append($"{Resources.Command}: {entry.Command}");
if (!string.IsNullOrEmpty(entry.Note))
{
toolTipText.AppendLine(string.Empty);
toolTipText.AppendLine(string.Empty);
toolTipText.Append($"{Resources.Note}: {entry.Note}");
}
result.TitleToolTip = toolTipText.ToString();
result.SubTitleToolTip = result.TitleToolTip;
}
/// <summary>
/// Open the settings page of the given <see cref="IWindowsSetting"/>.
/// </summary>
/// <param name="entry">The <see cref="WindowsSetting"/> that contain the information to open the setting on command level.</param>
/// <returns><see langword="true"/> if the settings could be opened, otherwise <see langword="false"/>.</returns>
private static bool DoOpenSettingsAction(WindowsSetting entry)
{
ProcessStartInfo processStartInfo;
var command = entry.Command;
command = Environment.ExpandEnvironmentVariables(command);
if (command.Contains(' '))
{
var commandSplit = command.Split(' ');
var file = commandSplit.First();
var arguments = command[file.Length..].TrimStart();
processStartInfo = new ProcessStartInfo(file, arguments)
{
UseShellExecute = false,
};
}
else
{
processStartInfo = new ProcessStartInfo(command)
{
UseShellExecute = true,
};
}
try
{
Process.Start(processStartInfo);
return true;
}
catch (Exception exception)
{
Log.Exception("can't open settings", exception, typeof(ResultHelper));
return false;
}
}
}
}

View file

@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Flow.Launcher.Plugin.WindowsSettings.Classes;
using Flow.Launcher.Plugin.WindowsSettings.Properties;
namespace Flow.Launcher.Plugin.WindowsSettings.Helper
{
/// <summary>
/// Helper class to easier work with translations.
/// </summary>
internal static class TranslationHelper
{
/// <summary>
/// Translate all settings of the given list with <see cref="WindowsSetting"/>.
/// </summary>
/// <param name="settingsList">The list that contains <see cref="WindowsSetting"/> to translate.</param>
internal static IEnumerable<WindowsSetting> TranslateAllSettings(in IEnumerable<WindowsSetting>? settingsList)
{
var translatedSettings = new List<WindowsSetting>();
if (settingsList is null)
return new List<WindowsSetting>();
foreach (var settings in settingsList)
{
var area = Resources.ResourceManager.GetString($"Area{settings.Area}");
var name = Resources.ResourceManager.GetString(settings.Name);
var type = Resources.ResourceManager.GetString(settings.Type);
if (string.IsNullOrEmpty(area))
{
Log.Warn($"Resource string for [Area{settings.Area}] not found", typeof(Main));
}
if (string.IsNullOrEmpty(name))
{
Log.Warn($"Resource string for [{settings.Name}] not found", typeof(Main));
}
if (string.IsNullOrEmpty(type))
{
Log.Warn($"Resource string for [{settings.Name}] not found", typeof(Main));
}
if (!string.IsNullOrEmpty(settings.Note))
{
var note = Resources.ResourceManager.GetString(settings.Note);
if (string.IsNullOrEmpty(note))
{
Log.Warn($"Resource string for [{settings.Note}] not found", typeof(Main));
}
settings.Note = note ?? settings.Note ?? string.Empty;
}
List<string>? translatedAltNames = null;
if (settings.AltNames is not null && settings.AltNames.Any())
{
translatedAltNames = new List<string>();
foreach (var altName in settings.AltNames)
{
if (string.IsNullOrWhiteSpace(altName))
{
continue;
}
var translatedAltName = Resources.ResourceManager.GetString(altName);
if (string.IsNullOrEmpty(translatedAltName))
{
Log.Warn($"Resource string for [{altName}] not found", typeof(Main));
}
translatedAltNames.Add(translatedAltName ?? altName);
}
}
var translatedSetting = settings with
{
Area = area ?? settings.Area,
Name = name ?? settings.Name,
DisplayType = type ?? settings.Type,
AltNames = translatedAltNames
};
translatedSettings.Add(translatedSetting);
}
return translatedSettings;
}
}
}

View file

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Flow.Launcher.Plugin.WindowsSettings.Classes;
namespace Flow.Launcher.Plugin.WindowsSettings.Helper
{
/// <summary>
/// Helper class to easier work with the version of the Windows OS
/// </summary>
internal static class UnsupportedSettingsHelper
{
private const string _keyPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
private const string _keyNameBuild = "CurrentBuild";
private const string _keyNameBuildNumber = "CurrentBuildNumber";
/// <summary>
/// Remove all <see cref="WindowsSetting"/> of the given list that are not present on the current used Windows build.
/// </summary>
/// <param name="settingsList">The list with <see cref="WindowsSetting"/> to filter.</param>
/// <returns>A new list with <see cref="WindowsSetting"/> that only contain present Windows settings for this OS.</returns>
internal static IEnumerable<WindowsSetting> FilterByBuild(in IEnumerable<WindowsSetting>? settingsList)
{
if (settingsList is null)
{
return Enumerable.Empty<WindowsSetting>();
}
var currentBuild = GetNumericRegistryValue(_keyPath, _keyNameBuild);
var currentBuildNumber = GetNumericRegistryValue(_keyPath, _keyNameBuildNumber);
if (currentBuild != currentBuildNumber)
{
var usedValueName = currentBuild != uint.MinValue ? _keyNameBuild : _keyNameBuildNumber;
var warningMessage =
$"Detecting the Windows version in registry ({_keyPath}) leads to an inconclusive"
+ $" result ({_keyNameBuild}={currentBuild}, {_keyNameBuildNumber}={currentBuildNumber})!"
+ $" For resolving the conflict we use the value of '{usedValueName}'.";
Log.Warn(warningMessage, typeof(UnsupportedSettingsHelper));
}
var currentWindowsBuild = currentBuild != uint.MinValue
? currentBuild
: currentBuildNumber;
var filteredSettingsList = settingsList.Where(found
=> (found.DeprecatedInBuild == null || currentWindowsBuild < found.DeprecatedInBuild)
&& (found.IntroducedInBuild == null || currentWindowsBuild >= found.IntroducedInBuild));
filteredSettingsList = filteredSettingsList.OrderBy(found => found.Name);
return filteredSettingsList;
}
/// <summary>
/// Return a unsigned numeric value from given registry value name inside the given registry key.
/// </summary>
/// <param name="registryKey">The registry key.</param>
/// <param name="valueName">The name of the registry value.</param>
/// <returns>A registry value or <see cref="uint.MinValue"/> on error.</returns>
private static uint GetNumericRegistryValue(in string registryKey, in string valueName)
{
object? registryValueData;
try
{
registryValueData = Microsoft.Win32.Registry.GetValue(registryKey, valueName, uint.MinValue);
}
catch (Exception exception)
{
Log.Exception(
$"Can't get registry value for '{valueName}'",
exception,
typeof(UnsupportedSettingsHelper));
return uint.MinValue;
}
return uint.TryParse(registryValueData as string, out var buildNumber)
? buildNumber
: uint.MinValue;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,24 @@
using System;
using System.Runtime.CompilerServices;
using Flow.Launcher.Plugin;
namespace Flow.Launcher.Plugin.WindowsSettings
{
public static class Log
{
private static IPublicAPI? _api;
public static void Init(IPublicAPI api)
{
_api = api;
}
public static void Exception(string message, Exception exception, Type type, [CallerMemberName] string methodName = "")
{
_api?.LogException(type.FullName, message, exception, methodName);
}
public static void Warn(string message, Type type, [CallerMemberName] string methodName = "")
{
_api?.LogWarn(type.FullName, message, methodName);
}
}
}

Some files were not shown because too many files have changed in this diff Show more