Merge remote-tracking branch 'origin/dev' into GlobalHotkeyRefactor

This commit is contained in:
Jeremy 2021-11-29 20:02:26 +11:00
commit b826090bca
57 changed files with 8874 additions and 3294 deletions

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.IO; 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) private static PluginMetadata GetPluginMetadata(string pluginDirectory)

View file

@ -35,8 +35,16 @@ namespace Flow.Launcher.Infrastructure
public const string DefaultTheme = "Win11Light"; 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 Themes = "Themes";
public const string Settings = "Settings";
public const string Logs = "Logs";
public const string Website = "https://flow-launcher.github.io"; 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"; private string language = "en";
public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}"; public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}";
public string OpenResultModifiers { get; set; } = KeyConstant.Alt; public string OpenResultModifiers { get; set; } = KeyConstant.Alt;
public string DarkMode { get; set; } = "System";
public bool ShowOpenResultHotkey { get; set; } = true; public bool ShowOpenResultHotkey { get; set; } = true;
public double WindowSize { get; set; } = 580; public double WindowSize { get; set; } = 580;
@ -82,6 +83,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
} }
}; };
public bool UseAnimation { get; set; } = true;
public bool UseSound { get; set; } = true;
/// <summary> /// <summary>
/// when false Alphabet static service will always return empty results /// when false Alphabet static service will always return empty results
@ -163,4 +166,11 @@ namespace Flow.Launcher.Infrastructure.UserSettings
Empty, Empty,
Preserved Preserved
} }
public enum DarkMode
{
System,
Light,
Dark
}
} }

View file

@ -29,6 +29,15 @@ namespace Flow.Launcher.Plugin
/// </summary> /// </summary>
void RestartApp(); 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> /// <summary>
/// Save everything, all of Flow Launcher and plugins' data and settings /// Save everything, all of Flow Launcher and plugins' data and settings
/// </summary> /// </summary>

View file

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

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -60,17 +60,39 @@ namespace Flow.Launcher.Plugin.SharedCommands
return sb.ToString(); 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 var info = new ProcessStartInfo
{ {
FileName = fileName, FileName = fileName,
WorkingDirectory = workingDirectory, WorkingDirectory = workingDirectory,
Arguments = arguments, Arguments = arguments,
Verb = verb Verb = verb,
CreateNoWindow = createNoWindow
}; };
return info; 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

@ -1,85 +1,137 @@
<Window x:Class="Flow.Launcher.ActionKeywords" <Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="Flow.Launcher.ActionKeywords"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="{DynamicResource actionKeywordsTitle}" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="Images\app.png" Title="{DynamicResource actionKeywordsTitle}"
ResizeMode="NoResize" Width="450"
Loaded="ActionKeyword_OnLoaded" Background="{DynamicResource PopuBGColor}"
WindowStartupLocation="CenterScreen" Foreground="{DynamicResource PopupTextColor}"
Height="365" Width="450" Background="#F3F3F3" BorderBrush="#cecece"> 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>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition Height="80"/> <RowDefinition Height="80" />
</Grid.RowDefinitions> </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>
<StackPanel Grid.Row="0" Margin="0 0 0 12"> <Grid>
<TextBlock Grid.Column="0" Text="{DynamicResource actionKeywordsTitle}" FontSize="20" FontWeight="SemiBold" FontFamily="Segoe UI" TextAlignment="Left" <Grid.ColumnDefinitions>
Margin="0 0 0 0" /> <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>
<StackPanel> <StackPanel>
<TextBlock <TextBlock
Text="{DynamicResource actionkeyword_tips}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left"/> FontSize="14"
Text="{DynamicResource actionkeyword_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 18 0 0"> <StackPanel Margin="0,18,0,0" Orientation="Horizontal">
<TextBlock FontSize="14" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" <TextBlock
HorizontalAlignment="Left" Text="{DynamicResource currentActionKeywords}" /> Grid.Row="0"
<TextBlock x:Name="tbOldActionKeyword" Grid.Row="0" Grid.Column="1" Margin="14 10 10 10" FontSize="14" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Left" FontWeight="SemiBold"/> 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>
<StackPanel Orientation="Horizontal"> <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<TextBlock FontSize="14" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" <TextBlock
HorizontalAlignment="Left" Text="{DynamicResource newActionKeyword}" /> Grid.Row="1"
Grid.Column="1"
<TextBox x:Name="tbAction" Margin="10 10 15 10" Width="105" VerticalAlignment="Center" HorizontalAlignment="Left" /> 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>
</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> </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>
<!--
<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> </Window>

View file

@ -1,16 +1,30 @@
<Application x:Class="Flow.Launcher.App" <Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="Flow.Launcher.App"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ShutdownMode="OnMainWindowClose" xmlns:ui="http://schemas.modernwpf.com/2019"
Startup="OnStartupAsync"> ShutdownMode="OnMainWindowClose"
Startup="OnStartupAsync">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <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 /> <ui:XamlControlsResources />
<ResourceDictionary Source="pack://application:,,,/Resources/CustomControlTemplate.xaml" /> <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 Source="pack://application:,,,/Languages/en.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>

View file

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

View file

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

View file

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

View file

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

View file

@ -77,7 +77,7 @@ namespace Flow.Launcher.Helper
if (mainViewModel.ShouldIgnoreHotkeys() || mainViewModel.GameModeStatus) if (mainViewModel.ShouldIgnoreHotkeys() || mainViewModel.GameModeStatus)
return; return;
mainViewModel.MainWindowVisibility = Visibility.Visible; mainViewModel.Show();
mainViewModel.ChangeQueryText(hotkey.ActionKeyword, true); 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)) var window = Application.Current.Windows.OfType<Window>().FirstOrDefault(x => x.GetType() == typeof(T))
?? (T)Activator.CreateInstance(typeof(T), args); ?? (T)Activator.CreateInstance(typeof(T), args);
Application.Current.MainWindow.Hide();
// Fix UI bug // Fix UI bug
// Add `window.WindowState = WindowState.Normal` // Add `window.WindowState = WindowState.Normal`

View file

@ -1,26 +1,55 @@
<UserControl x:Class="Flow.Launcher.HotkeyControl" <UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="Flow.Launcher.HotkeyControl"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore" xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Height="24" Height="24"
d:DesignHeight="300" d:DesignWidth="300"> d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/> <ColumnDefinition Width="200" />
</Grid.ColumnDefinitions> </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"> <Popup
<Border Background="#f6f6f6" BorderBrush="#cecece" BorderThickness="1" CornerRadius="6" Width="120" Height="30"> x:Name="popup"
<TextBlock x:Name="tbMsg" FontSize="13" FontWeight="SemiBold" Visibility="Visible" Margin="0 0 0 0" VerticalAlignment="Center" HorizontalAlignment="Center"> AllowDrop="True"
press key 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> </TextBlock>
</Border> </Border>
</Popup> </Popup>
<TextBox x:Name="tbHotkey" TabIndex="100" VerticalContentAlignment="Center" <TextBox
PreviewKeyDown="TbHotkey_OnPreviewKeyDown" input:InputMethod.IsInputMethodEnabled="False" Margin="0 0 18 0"> x:Name="tbHotkey"
</TextBox> Margin="0,0,18,0"
VerticalContentAlignment="Center"
input:InputMethod.IsInputMethodEnabled="False"
PreviewKeyDown="TbHotkey_OnPreviewKeyDown"
TabIndex="100" />
</Grid> </Grid>
</UserControl> </UserControl>

View file

@ -16,6 +16,7 @@
<system:String x:Key="iconTrayExit">Exit</system:String> <system:String x:Key="iconTrayExit">Exit</system:String>
<system:String x:Key="closeWindow">Close</system:String> <system:String x:Key="closeWindow">Close</system:String>
<system:String x:Key="GameMode">Game Mode</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 --> <!-- Setting General -->
<system:String x:Key="flowlauncher_settings">Flow Launcher Settings</system:String> <system:String x:Key="flowlauncher_settings">Flow Launcher Settings</system:String>
@ -55,15 +56,17 @@
<system:String x:Key="disable">Off</system:String> <system:String x:Key="disable">Off</system:String>
<system:String x:Key="actionKeywordsTitle">Action keyword Setting</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="actionKeywords">Action keyword</system:String>
<system:String x:Key="currentActionKeywords">Current 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="newActionKeyword">New action keyword</system:String>
<system:String x:Key="currentPriority">Current Priority:</system:String> <system:String x:Key="currentPriority">Current Priority</system:String>
<system:String x:Key="newPriority">New Priority:</system:String> <system:String x:Key="newPriority">New Priority</system:String>
<system:String x:Key="priority">Priority</system:String> <system:String x:Key="priority">Priority</system:String>
<system:String x:Key="pluginDirectory">Plugin Directory</system:String> <system:String x:Key="pluginDirectory">Plugin Directory</system:String>
<system:String x:Key="author">Author:</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_init_time">Init time:</system:String>
<system:String x:Key="plugin_query_time">Query 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 --> <!-- Setting Plugin Store -->
@ -84,6 +87,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="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="ThemeFolder">Theme Folder</system:String>
<system:String x:Key="OpenThemeFolder">Open Theme Folder</system:String> <system:String x:Key="OpenThemeFolder">Open Theme Folder</system:String>
<system:String x:Key="DarkMode">Dark Mode</system:String>
<system:String x:Key="DarkModeSystem">System Default</system:String>
<system:String x:Key="DarkModeLight">Light</system:String>
<system:String x:Key="DarkModeDark">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 --> <!-- Setting Hotkey -->
<system:String x:Key="hotkey">Hotkey</system:String> <system:String x:Key="hotkey">Hotkey</system:String>
@ -125,6 +136,8 @@
<!-- Setting About --> <!-- Setting About -->
<system:String x:Key="about">About</system:String> <system:String x:Key="about">About</system:String>
<system:String x:Key="website">Website</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="version">Version</system:String>
<system:String x:Key="about_activate_times">You have activated Flow Launcher {0} times</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> <system:String x:Key="checkUpdates">Check for Updates</system:String>
@ -135,7 +148,10 @@
or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually. or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually.
</system:String> </system:String>
<system:String x:Key="releaseNotes">Release Notes</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 --> <!-- FileManager Setting Dialog -->
<system:String x:Key="fileManagerWindow">Select File Manager</system:String> <system:String x:Key="fileManagerWindow">Select File Manager</system:String>

View file

@ -1,7 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<!--MainWindow--> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!-- MainWindow -->
<system:String x:Key="registerHotkeyFailed">핫키 등록 실패: {0}</system:String> <system:String x:Key="registerHotkeyFailed">핫키 등록 실패: {0}</system:String>
<system:String x:Key="couldnotStartCmd">{0}을 실행할 수 없습니다.</system:String> <system:String x:Key="couldnotStartCmd">{0}을 실행할 수 없습니다.</system:String>
<system:String x:Key="invalidFlowLauncherPluginFileFormat">Flow Launcher 플러그인 파일 형식이 유효하지 않습니다.</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="iconTrayAbout">정보</system:String>
<system:String x:Key="iconTrayExit">종료</system:String> <system:String x:Key="iconTrayExit">종료</system:String>
<system:String x:Key="closeWindow">닫기</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="flowlauncher_settings">Flow Launcher 설정</system:String>
<system:String x:Key="general">일반</system:String> <system:String x:Key="general">일반</system:String>
<system:String x:Key="portableMode">포터블 모드</system:String> <system:String x:Key="portableMode">포터블 모드</system:String>
@ -33,41 +36,48 @@
<system:String x:Key="maxShowResults">표시할 결과 수</system:String> <system:String x:Key="maxShowResults">표시할 결과 수</system:String>
<system:String x:Key="ignoreHotkeysOnFullscreen">전체화면 모드에서는 핫키 무시</system:String> <system:String x:Key="ignoreHotkeysOnFullscreen">전체화면 모드에서는 핫키 무시</system:String>
<system:String x:Key="ignoreHotkeysOnFullscreenToolTip">게이머라면 켜는 것을 추천합니다.</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="pythonDirectory">Python 디렉토리</system:String>
<system:String x:Key="autoUpdates">자동 업데이트</system:String> <system:String x:Key="autoUpdates">자동 업데이트</system:String>
<system:String x:Key="selectPythonDirectory">선택</system:String> <system:String x:Key="selectPythonDirectory">선택</system:String>
<system:String x:Key="hideOnStartup">시작 시 Flow Launcher 숨김</system:String> <system:String x:Key="hideOnStartup">시작 시 Flow Launcher 숨김</system:String>
<system:String x:Key="hideNotifyIcon">트레이 아이콘 숨기기</system:String> <system:String x:Key="hideNotifyIcon">트레이 아이콘 숨기기</system:String>
<system:String x:Key="querySearchPrecision">쿼리 검색 정도</system:String> <system:String x:Key="querySearchPrecision">쿼리 검색 정도</system:String>
<system:String x:Key="querySearchPrecisionToolTip">검색 결과가 좀 더 정확해집니다.</system:String> <system:String x:Key="querySearchPrecisionToolTip">검색 결과에 필요한 최소 매치 점수를 변경합니다.</system:String>
<system:String x:Key="ShouldUsePinyin">항상 Pinyin 사용</system:String> <system:String x:Key="ShouldUsePinyin">항상 Pinyin 사용</system:String>
<system:String x:Key="ShouldUsePinyinToolTip">Pinyin을 사용하여 검색할 수 있습니다. Pinyin(병음)은 로마자 중국어 입력 방식입니다.</system:String> <system:String x:Key="ShouldUsePinyinToolTip">Pinyin을 사용하여 검색할 수 있습니다. Pinyin(병음)은 로마자 중국어 입력 방식입니다.</system:String>
<system:String x:Key="shadowEffectNotAllowed">반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다.</system:String> <system:String x:Key="shadowEffectNotAllowed">반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다.</system:String>
<!--Setting Plugin--> <!-- Setting Plugin -->
<system:String x:Key="plugin">플러그인</system:String> <system:String x:Key="plugin">플러그인</system:String>
<system:String x:Key="browserMorePlugins">플러그인 더 찾아보기</system:String> <system:String x:Key="browserMorePlugins">플러그인 더 찾아보기</system:String>
<system:String x:Key="enable">On</system:String> <system:String x:Key="enable"></system:String>
<system:String x:Key="disable">Off</system:String> <system:String x:Key="disable"></system:String>
<system:String x:Key="actionKeywords">액션 키워드</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="currentPriority">현재 중요도:</system:String>
<system:String x:Key="newPriority">새 중요도:</system:String> <system:String x:Key="newPriority">새 중요도:</system:String>
<system:String x:Key="priority">중요도</system:String> <system:String x:Key="priority">중요도</system:String>
<system:String x:Key="pluginDirectory">플러그인 디렉토리</system:String> <system:String x:Key="pluginDirectory">플러그인 폴더</system:String>
<system:String x:Key="author">자</system:String> <system:String x:Key="author">제작자</system:String>
<system:String x:Key="plugin_init_time">초기화 시간:</system:String> <system:String x:Key="plugin_init_time">초기화 시간:</system:String>
<system:String x:Key="plugin_query_time">쿼리 시간:</system:String> <system:String x:Key="plugin_query_time">쿼리 시간:</system:String>
<system:String x:Key="plugin_query_version">| 버전</system:String>
<system:String x:Key="plugin_query_web">웹사이트</system:String>
<!--Setting Plugin Store-->
<!-- Setting Plugin Store -->
<system:String x:Key="pluginStore">플러그인 스토어</system:String> <system:String x:Key="pluginStore">플러그인 스토어</system:String>
<system:String x:Key="refresh">새로고침</system:String> <system:String x:Key="refresh">새로고침</system:String>
<system:String x:Key="install">설치</system:String> <system:String x:Key="install">설치</system:String>
<!--Setting Theme--> <!-- Setting Theme -->
<system:String x:Key="theme">테마</system:String> <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="hiThere">Hi There</system:String>
<system:String x:Key="queryBoxFont">쿼리 상자 글꼴</system:String> <system:String x:Key="queryBoxFont">쿼리 상자 글꼴</system:String>
<system:String x:Key="resultItemFont">결과 항목 글꼴</system:String> <system:String x:Key="resultItemFont">결과 항목 글꼴</system:String>
@ -77,8 +87,17 @@
<system:String x:Key="theme_load_failure_parse_error">{0} 테마 로드에 실패했습니다. 기본 테마로 변경합니다.</system:String> <system:String x:Key="theme_load_failure_parse_error">{0} 테마 로드에 실패했습니다. 기본 테마로 변경합니다.</system:String>
<system:String x:Key="ThemeFolder">테마 폴더</system:String> <system:String x:Key="ThemeFolder">테마 폴더</system:String>
<system:String x:Key="OpenThemeFolder">테마 폴더 열기</system:String> <system:String x:Key="OpenThemeFolder">테마 폴더 열기</system:String>
<system:String x:Key="DarkMode">다크 모드</system:String>
<system:String x:Key="DarkModeTip">System settings will take effect from the next run</system:String>
<system:String x:Key="DarkModeSystem">시스템 기본</system:String>
<system:String x:Key="DarkModeLight">밝게</system:String>
<system:String x:Key="DarkModeDark">어둡게</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="hotkey">핫키</system:String>
<system:String x:Key="flowlauncherHotkey">Flow Launcher 핫키</system:String> <system:String x:Key="flowlauncherHotkey">Flow Launcher 핫키</system:String>
<system:String x:Key="flowlauncherHotkeyToolTip">Flow Launcher를 열 때 사용할 단축키를 입력합니다.</system:String> <system:String x:Key="flowlauncherHotkeyToolTip">Flow Launcher를 열 때 사용할 단축키를 입력합니다.</system:String>
@ -87,7 +106,7 @@
<system:String x:Key="showOpenResultHotkey">단축키 표시</system:String> <system:String x:Key="showOpenResultHotkey">단축키 표시</system:String>
<system:String x:Key="showOpenResultHotkeyToolTip">결과창에서 결과 선택 단축키를 표시합니다.</system:String> <system:String x:Key="showOpenResultHotkeyToolTip">결과창에서 결과 선택 단축키를 표시합니다.</system:String>
<system:String x:Key="customQueryHotkey">사용자지정 쿼리 핫키</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="delete">삭제</system:String>
<system:String x:Key="edit">편집</system:String> <system:String x:Key="edit">편집</system:String>
<system:String x:Key="add">추가</system:String> <system:String x:Key="add">추가</system:String>
@ -95,10 +114,11 @@
<system:String x:Key="deleteCustomHotkeyWarning">{0} 플러그인 핫키를 삭제하시겠습니까?</system:String> <system:String x:Key="deleteCustomHotkeyWarning">{0} 플러그인 핫키를 삭제하시겠습니까?</system:String>
<system:String x:Key="queryWindowShadowEffect">그림자 효과</system:String> <system:String x:Key="queryWindowShadowEffect">그림자 효과</system:String>
<system:String x:Key="shadowEffectCPUUsage">그림자 효과는 GPU를 사용합니다. 컴퓨터 퍼포먼스가 제한적인 경우 사용을 추천하지 않습니다.</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="useGlyphUI">플루언트 아이콘 사용</system:String>
<system:String x:Key="useGlyphUIEffect">결과 및 일부 메뉴에서 플루언트 아이콘을 사용합니다.</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="proxy">HTTP 프록시</system:String>
<system:String x:Key="enableProxy">HTTP 프록시 켜기</system:String> <system:String x:Key="enableProxy">HTTP 프록시 켜기</system:String>
<system:String x:Key="server">HTTP 서버</system:String> <system:String x:Key="server">HTTP 서버</system:String>
@ -114,26 +134,41 @@
<system:String x:Key="proxyIsCorrect">프록시 설정 정상</system:String> <system:String x:Key="proxyIsCorrect">프록시 설정 정상</system:String>
<system:String x:Key="proxyConnectFailed">프록시 연결 실패</system:String> <system:String x:Key="proxyConnectFailed">프록시 연결 실패</system:String>
<!--Setting About--> <!-- Setting About -->
<system:String x:Key="about">정보</system:String> <system:String x:Key="about">정보</system:String>
<system:String x:Key="website">웹사이트</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="version">버전</system:String>
<system:String x:Key="about_activate_times">Flow Launcher를 {0}번 실행했습니다.</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="checkUpdates">업데이트 확인</system:String>
<system:String x:Key="newVersionTips">새 버전({0})이 있습니다. Flow Launcher를 재시작하세요.</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="checkUpdatesFailed">업데이트 확인을 실패했습니다. api.github.com로의 연결 또는 프록시 설정을 확인해주세요.</system:String>
<system:String x:Key="downloadUpdatesFailed"> <system:String x:Key="downloadUpdatesFailed">
업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요. 업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요.
수동 다운로드를 하려면 https://github.com/Flow-Launcher/Flow.Launcher/releases 으로 방문하세요. 수동 다운로드를 하려면 https://github.com/Flow-Launcher/Flow.Launcher/releases 으로 방문하세요.
</system:String> </system:String>
<system:String x:Key="releaseNotes">릴리즈 노트:</system:String> <system:String x:Key="releaseNotes">릴리즈 노트</system:String>
<system:String x:Key="documentation">사용 팁:</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="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> <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="oldActionKeywords">예전 액션 키워드</system:String>
<system:String x:Key="newActionKeywords">새 액션 키워드</system:String> <system:String x:Key="newActionKeywords">새 액션 키워드</system:String>
<system:String x:Key="cancel">취소</system:String> <system:String x:Key="cancel">취소</system:String>
@ -143,19 +178,20 @@
<system:String x:Key="newActionKeywordsHasBeenAssigned">새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요.</system:String> <system:String x:Key="newActionKeywordsHasBeenAssigned">새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요.</system:String>
<system:String x:Key="success">성공</system:String> <system:String x:Key="success">성공</system:String>
<system:String x:Key="completedSuccessfully">성공적으로 완료했습니다.</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="customeQueryHotkeyTitle">커스텀 플러그인 핫키</system:String>
<system:String x:Key="customeQueryHotkeyTips">단축키를 지정하여 특정 쿼리를 자동으로 입력할 수 있습니다. 사용하고 싶은 단축키를 눌러 지정한 후, 사용할 쿼리를 입력하세요.</system:String>
<system:String x:Key="preview">미리보기</system:String> <system:String x:Key="preview">미리보기</system:String>
<system:String x:Key="hotkeyIsNotUnavailable">핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요.</system:String> <system:String x:Key="hotkeyIsNotUnavailable">핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요.</system:String>
<system:String x:Key="invalidPluginHotkey">플러그인 핫키가 유효하지 않습니다.</system:String> <system:String x:Key="invalidPluginHotkey">플러그인 핫키가 유효하지 않습니다.</system:String>
<system:String x:Key="update">업데이트</system:String> <system:String x:Key="update">업데이트</system:String>
<!--Hotkey Control--> <!-- Hotkey Control -->
<system:String x:Key="hotkeyUnavailable">핫키를 사용할 수 없습니다.</system:String> <system:String x:Key="hotkeyUnavailable">핫키를 사용할 수 없습니다.</system:String>
<!--Crash Reporter--> <!-- Crash Reporter -->
<system:String x:Key="reportWindow_version">버전</system:String> <system:String x:Key="reportWindow_version">버전</system:String>
<system:String x:Key="reportWindow_time">시간</system:String> <system:String x:Key="reportWindow_time">시간</system:String>
<system:String x:Key="reportWindow_reproduce">수정을 위해 애플리케이션이 어떻게 충돌했는지 알려주세요.</system:String> <system:String x:Key="reportWindow_reproduce">수정을 위해 애플리케이션이 어떻게 충돌했는지 알려주세요.</system:String>
@ -170,17 +206,19 @@
<system:String x:Key="reportWindow_report_succeed">보고서를 정상적으로 보냈습니다.</system:String> <system:String x:Key="reportWindow_report_succeed">보고서를 정상적으로 보냈습니다.</system:String>
<system:String x:Key="reportWindow_report_failed">보고서를 보내지 못했습니다.</system:String> <system:String x:Key="reportWindow_report_failed">보고서를 보내지 못했습니다.</system:String>
<system:String x:Key="reportWindow_flowlauncher_got_an_error">Flow Launcher에 문제가 발생했습니다.</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> <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_check">새 업데이트 확인 중</system:String>
<system:String x:Key="update_flowlauncher_update_new_version_available">새 Flow Launcher 버전({0})을 사용할 수 있습니다.</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_already_on_latest">이미 가장 최신 버전의 Flow Launcher를 사용중입니다.</system:String>
<system:String x:Key="update_flowlauncher_update_found">업데이트 발견</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_updating">업데이트 중...</system:String>
<system:String x:Key="update_flowlauncher_fail_moving_portable_user_profile_data">Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다. <system:String x:Key="update_flowlauncher_fail_moving_portable_user_profile_data">
프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요. </system:String> Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다.
프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요.
</system:String>
<system:String x:Key="update_flowlauncher_new_update">새 업데이트</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_error">소프트웨어 업데이트를 설치하는 중에 오류가 발생했습니다.</system:String>
<system:String x:Key="update_flowlauncher_update">업데이트</system:String> <system:String x:Key="update_flowlauncher_update">업데이트</system:String>

View file

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

View file

@ -1,4 +1,4 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@ -11,16 +11,12 @@ using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper; using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using Microsoft.AspNetCore.Authorization;
using Application = System.Windows.Application;
using Screen = System.Windows.Forms.Screen; using Screen = System.Windows.Forms.Screen;
using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip; using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip;
using DataFormats = System.Windows.DataFormats;
using DragEventArgs = System.Windows.DragEventArgs; using DragEventArgs = System.Windows.DragEventArgs;
using KeyEventArgs = System.Windows.Input.KeyEventArgs; using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MessageBox = System.Windows.MessageBox;
using NotifyIcon = System.Windows.Forms.NotifyIcon; using NotifyIcon = System.Windows.Forms.NotifyIcon;
using System.Windows.Interop; using Flow.Launcher.Infrastructure;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -34,6 +30,7 @@ namespace Flow.Launcher
private NotifyIcon _notifyIcon; private NotifyIcon _notifyIcon;
private ContextMenu contextMenu; private ContextMenu contextMenu;
private MainViewModel _viewModel; private MainViewModel _viewModel;
private bool _animating;
#endregion #endregion
@ -43,6 +40,7 @@ namespace Flow.Launcher
_viewModel = mainVM; _viewModel = mainVM;
_settings = settings; _settings = settings;
InitializeComponent(); InitializeComponent();
InitializePosition();
} }
public MainWindow() public MainWindow()
@ -52,6 +50,8 @@ namespace Flow.Launcher
private async void OnClosing(object sender, CancelEventArgs e) private async void OnClosing(object sender, CancelEventArgs e)
{ {
_settings.WindowTop = Top;
_settings.WindowLeft = Left;
_notifyIcon.Visible = false; _notifyIcon.Visible = false;
_viewModel.Save(); _viewModel.Save();
e.Cancel = true; e.Cancel = true;
@ -65,12 +65,12 @@ namespace Flow.Launcher
private void OnLoaded(object sender, RoutedEventArgs _) private void OnLoaded(object sender, RoutedEventArgs _)
{ {
HideStartup();
// show notify icon when flowlauncher is hidden // show notify icon when flowlauncher is hidden
InitializeNotifyIcon(); InitializeNotifyIcon();
InitializeDarkMode();
WindowsInteropHelper.DisableControlBox(this); WindowsInteropHelper.DisableControlBox(this);
InitProgressbarAnimation(); InitProgressbarAnimation();
InitializePosition();
// since the default main window visibility is visible // since the default main window visibility is visible
// so we need set focus during startup // so we need set focus during startup
QueryTextBox.Focus(); QueryTextBox.Focus();
@ -79,13 +79,13 @@ namespace Flow.Launcher
{ {
switch (e.PropertyName) switch (e.PropertyName)
{ {
case nameof(MainViewModel.MainWindowVisibility): case nameof(MainViewModel.MainWindowVisibilityStatus):
{ {
if (_viewModel.MainWindowVisibility == Visibility.Visible) if (_viewModel.MainWindowVisibilityStatus)
{ {
UpdatePosition();
Activate(); Activate();
QueryTextBox.Focus(); QueryTextBox.Focus();
UpdatePosition();
_settings.ActivateTimes++; _settings.ActivateTimes++;
if (!_viewModel.LastQuerySelected) if (!_viewModel.LastQuerySelected)
{ {
@ -117,7 +117,7 @@ namespace Flow.Launcher
_progressBarStoryboard.Stop(ProgressBar); _progressBarStoryboard.Stop(ProgressBar);
isProgressBarStoryboardPaused = true; isProgressBarStoryboardPaused = true;
} }
else if (_viewModel.MainWindowVisibility == Visibility.Visible && else if (_viewModel.MainWindowVisibilityStatus &&
isProgressBarStoryboardPaused) isProgressBarStoryboardPaused)
{ {
_progressBarStoryboard.Begin(ProgressBar, true); _progressBarStoryboard.Begin(ProgressBar, true);
@ -148,16 +148,20 @@ namespace Flow.Launcher
break; break;
} }
}; };
InitializePosition();
} }
private void InitializePosition() private void InitializePosition()
{ {
Top = WindowTop(); if (_settings.RememberLastLaunchLocation)
Left = WindowLeft(); {
_settings.WindowTop = Top; Top = _settings.WindowTop;
_settings.WindowLeft = Left; Left = _settings.WindowLeft;
}
else
{
Left = WindowLeft();
Top = WindowTop();
}
} }
private void UpdateNotifyIconText() private void UpdateNotifyIconText()
@ -181,7 +185,7 @@ namespace Flow.Launcher
var header = new MenuItem var header = new MenuItem
{ {
Header = "Flow Launcher", Header = "Flow Launcher",
IsEnabled = false IsEnabled = false
}; };
var open = new MenuItem var open = new MenuItem
@ -201,12 +205,13 @@ namespace Flow.Launcher
Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit") Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit")
}; };
open.Click += (o, e) => Visibility = Visibility.Visible; open.Click += (o, e) => _viewModel.ToggleFlowLauncher();
gamemode.Click += (o, e) => ToggleGameMode(); gamemode.Click += (o, e) => ToggleGameMode();
settings.Click += (o, e) => App.API.OpenSettingDialog(); settings.Click += (o, e) => App.API.OpenSettingDialog();
exit.Click += (o, e) => Close(); exit.Click += (o, e) => Close();
contextMenu.Items.Add(header); contextMenu.Items.Add(header);
contextMenu.Items.Add(open); contextMenu.Items.Add(open);
gamemode.ToolTip = InternationalizationManager.Instance.GetTranslation("GameModeToolTip");
contextMenu.Items.Add(gamemode); contextMenu.Items.Add(gamemode);
contextMenu.Items.Add(settings); contextMenu.Items.Add(settings);
contextMenu.Items.Add(exit); contextMenu.Items.Add(exit);
@ -255,6 +260,54 @@ namespace Flow.Launcher
isProgressBarStoryboardPaused = true; 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) private void OnMouseDown(object sender, MouseButtonEventArgs e)
{ {
if (e.ChangedButton == MouseButton.Left) DragMove(); if (e.ChangedButton == MouseButton.Left) DragMove();
@ -287,22 +340,41 @@ namespace Flow.Launcher
e.Handled = true; 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(); 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() private void UpdatePosition()
{ {
if (_animating)
return;
if (_settings.RememberLastLaunchLocation) if (_settings.RememberLastLaunchLocation)
{ {
Left = _settings.WindowLeft; Left = _settings.WindowLeft;
@ -317,6 +389,8 @@ namespace Flow.Launcher
private void OnLocationChanged(object sender, EventArgs e) private void OnLocationChanged(object sender, EventArgs e)
{ {
if (_animating)
return;
if (_settings.RememberLastLaunchLocation) if (_settings.RememberLastLaunchLocation)
{ {
_settings.WindowLeft = Left; _settings.WindowLeft = Left;
@ -324,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 screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
@ -333,7 +420,7 @@ namespace Flow.Launcher
return left; return left;
} }
private double WindowTop() public double WindowTop()
{ {
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
@ -392,5 +479,17 @@ namespace Flow.Launcher
{ {
QueryTextBox.CaretIndex = QueryTextBox.Text.Length; QueryTextBox.CaretIndex = QueryTextBox.Text.Length;
} }
public void InitializeDarkMode()
{
if (_settings.DarkMode == Constant.Light)
{
ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Light;
}
else if (_settings.DarkMode == 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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{DynamicResource changePriorityWindow}" Title="{DynamicResource changePriorityWindow}"
Background="#F3F3F3" Width="350"
BorderBrush="#cecece" Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
Loaded="PriorityChangeWindow_Loaded" Loaded="PriorityChangeWindow_Loaded"
MouseDown="window_MouseDown" MouseDown="window_MouseDown"
ResizeMode="NoResize" ResizeMode="NoResize"
SizeToContent="WidthAndHeight" SizeToContent="Height"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid Width="350"> <WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition Height="80" /> <RowDefinition Height="80" />
</Grid.RowDefinitions> </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"> <StackPanel Grid.Row="0">
<TextBlock <StackPanel>
HorizontalAlignment="Right" <Grid>
VerticalAlignment="Center" <Grid.ColumnDefinitions>
FontSize="14" <ColumnDefinition Width="Auto" />
Text="{DynamicResource priority}" /> <ColumnDefinition Width="*" />
<ui:NumberBox <ColumnDefinition Width="Auto" />
x:Name="tbAction" <ColumnDefinition Width="Auto" />
Width="190" <ColumnDefinition Width="Auto" />
Height="34" </Grid.ColumnDefinitions>
Margin="10,0,15,0" <Button
HorizontalAlignment="Left" Grid.Column="4"
VerticalAlignment="Center" Click="BtnCancel_OnClick"
Minimum="0" Style="{StaticResource TitleBarCloseButtonStyle}">
SmallChange="1" <Path
SpinButtonPlacementMode="Inline" /> Width="46"
</StackPanel> 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> </StackPanel>
</Grid> <StackPanel>
</Border> <TextBlock
<StackPanel FontSize="14"
Grid.Row="1" Text="{DynamicResource priority_tips}"
HorizontalAlignment="Center" TextAlignment="Left"
Orientation="Horizontal"> TextWrapping="WrapWithOverflow" />
<Button </StackPanel>
x:Name="btnCancel"
Width="100" <StackPanel Margin="0,24,0,24" Orientation="Horizontal">
Height="30" <TextBlock
Margin="0,0,5,0" HorizontalAlignment="Right"
Click="BtnCancel_OnClick" VerticalAlignment="Center"
Content="{DynamicResource cancel}" /> FontSize="14"
<Button Text="{DynamicResource priority}" />
x:Name="btnDone" <ui:NumberBox
Width="100" x:Name="tbAction"
Height="30" Width="200"
Margin="5,0,0,0" Margin="10,0,15,0"
Click="btnDone_OnClick"> HorizontalAlignment="Left"
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" /> VerticalAlignment="Center"
</Button> CornerRadius="4"
Minimum="0"
SmallChange="1"
SpinButtonPlacementMode="Inline" />
</StackPanel>
</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> </Grid>
</Window> </Window>

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
@ -14,6 +14,7 @@ using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.Plugin.SharedModels;
using Flow.Launcher.Plugin.SharedCommands;
using System.Threading; using System.Threading;
using System.IO; using System.IO;
using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Http;
@ -55,7 +56,7 @@ namespace Flow.Launcher
public void RestartApp() public void RestartApp()
{ {
_mainVM.MainWindowVisibility = Visibility.Hidden; _mainVM.Hide();
// we must manually save // we must manually save
// UpdateManager.RestartApp() will call Environment.Exit(0) // UpdateManager.RestartApp() will call Environment.Exit(0)
@ -70,7 +71,7 @@ namespace Flow.Launcher
public void RestarApp() => RestartApp(); public void RestarApp() => RestartApp();
public void ShowMainWindow() => _mainVM.MainWindowVisibility = Visibility.Visible; public void ShowMainWindow() => _mainVM.Show();
public void CheckForNewUpdate() => _settingsVM.UpdateApp(); public void CheckForNewUpdate() => _settingsVM.UpdateApp();
@ -106,6 +107,14 @@ 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 StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible; public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible;
public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed; public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed;

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

View file

@ -7,25 +7,58 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{DynamicResource fileManagerWindow}" Title="{DynamicResource fileManagerWindow}"
Background="#f3f3f3" Width="600"
Background="{DynamicResource PopuBGColor}"
DataContext="{Binding RelativeSource={RelativeSource Self}}" DataContext="{Binding RelativeSource={RelativeSource Self}}"
Foreground="{DynamicResource PopupTextColor}"
ResizeMode="NoResize" ResizeMode="NoResize"
SizeToContent="WidthAndHeight" SizeToContent="Height"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid Width="600"> <WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition Height="80" /> <RowDefinition Height="80" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Border <Grid>
Padding="26,26,26,0" <StackPanel>
Background="#ffffff"
BorderBrush="#e5e5e5"
BorderThickness="0,0,0,1">
<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 <TextBlock
Grid.Column="0" Grid.Column="0"
Margin="0,0,0,0" Margin="0,0,0,0"
@ -38,14 +71,10 @@
<StackPanel> <StackPanel>
<TextBlock <TextBlock
FontSize="14" FontSize="14"
Foreground="#1b1b1b"
Text="{DynamicResource fileManager_tips}" Text="{DynamicResource fileManager_tips}"
TextAlignment="Left" TextAlignment="Left"
TextWrapping="WrapWithOverflow" /> TextWrapping="WrapWithOverflow" />
<TextBlock <TextBlock Margin="0,14,0,0" FontSize="14">
Margin="0,14,0,0"
FontSize="14"
Foreground="#1b1b1b">
<TextBlock Text="{DynamicResource fileManager_tips2}" TextWrapping="WrapWithOverflow" /> <TextBlock Text="{DynamicResource fileManager_tips2}" TextWrapping="WrapWithOverflow" />
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
@ -86,7 +115,7 @@
<Rectangle <Rectangle
Height="1" Height="1"
Margin="0,20,0,12" Margin="0,20,0,12"
Fill="#cecece" /> Fill="{StaticResource Color03B}" />
<StackPanel <StackPanel
Margin="0,0,0,0" Margin="0,0,0,0"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
@ -199,46 +228,48 @@
</Grid> </Grid>
</StackPanel> </StackPanel>
</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> </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> </Grid>
</Window> </Window>

File diff suppressed because it is too large Load diff

View file

@ -1,20 +1,26 @@
using System; using Flow.Launcher.Core.ExternalPlugins;
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.Plugin; using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.ViewModel; using Flow.Launcher.ViewModel;
using Flow.Launcher.Helper; using Microsoft.Win32;
using System.Windows.Controls; using ModernWpf;
using Flow.Launcher.Core.ExternalPlugins; 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 namespace Flow.Launcher
{ {
@ -39,6 +45,7 @@ namespace Flow.Launcher
#region General #region General
private void OnLoaded(object sender, RoutedEventArgs e) private void OnLoaded(object sender, RoutedEventArgs e)
{ {
RefreshMaximizeRestoreButton();
// Fix (workaround) for the window freezes after lock screen (Win+L) // Fix (workaround) for the window freezes after lock screen (Win+L)
// https://stackoverflow.com/questions/4951058/software-rendering-mode-wpf // https://stackoverflow.com/questions/4951058/software-rendering-mode-wpf
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
@ -58,39 +65,30 @@ namespace Flow.Launcher
public static void SetStartup() public static void SetStartup()
{ {
using (var key = Registry.CurrentUser.OpenSubKey(StartupPath, true)) using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
{ key?.SetValue(Constant.FlowLauncher, Constant.ExecutablePath);
key?.SetValue(Infrastructure.Constant.FlowLauncher, Infrastructure.Constant.ExecutablePath);
}
} }
private void RemoveStartup() private void RemoveStartup()
{ {
using (var key = Registry.CurrentUser.OpenSubKey(StartupPath, true)) using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true);
{ key?.DeleteValue(Constant.FlowLauncher, false);
key?.DeleteValue(Infrastructure.Constant.FlowLauncher, false);
}
} }
public static bool StartupSet() 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; return path == Constant.ExecutablePath;
if (path != null)
{
return path == Infrastructure.Constant.ExecutablePath;
}
else
{
return false;
}
} }
return false;
} }
private void OnSelectPythonDirectoryClick(object sender, RoutedEventArgs e) private void OnSelectPythonDirectoryClick(object sender, RoutedEventArgs e)
{ {
var dlg = new System.Windows.Forms.FolderBrowserDialog var dlg = new FolderBrowserDialog
{ {
SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)
}; };
@ -219,7 +217,7 @@ namespace Flow.Launcher
var uri = new Uri(website); var uri = new Uri(website);
if (Uri.CheckSchemeName(uri.Scheme)) if (Uri.CheckSchemeName(uri.Scheme))
{ {
SearchWeb.NewTabInBrowser(website); website.NewTabInBrowser();
} }
} }
} }
@ -253,7 +251,7 @@ namespace Flow.Launcher
private void OnRequestNavigate(object sender, RequestNavigateEventArgs e) private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
{ {
SearchWeb.NewTabInBrowser(e.Uri.AbsoluteUri); e.Uri.AbsoluteUri.NewTabInBrowser();
e.Handled = true; e.Handled = true;
} }
@ -267,11 +265,21 @@ namespace Flow.Launcher
Close(); Close();
} }
private void OpenPluginFolder(object sender, RoutedEventArgs e) private void OpenThemeFolder(object sender, RoutedEventArgs e)
{ {
PluginManager.API.OpenDirectory(Path.Combine(DataLocation.DataDirectory(), Constant.Themes)); 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) private void OnPluginStoreRefreshClick(object sender, RoutedEventArgs e)
{ {
_ = viewModel.RefreshExternalPluginsAsync(); _ = viewModel.RefreshExternalPluginsAsync();
@ -282,20 +290,64 @@ namespace Flow.Launcher
if(sender is Button { DataContext: UserPlugin plugin }) if(sender is Button { DataContext: UserPlugin plugin })
{ {
var pluginsManagerPlugin = PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7"); var pluginsManagerPlugin = PluginManager.GetPluginForId("9f8f9b14-2518-4907-b211-35ab6290dee7");
var actionKeywrod = pluginsManagerPlugin.Metadata.ActionKeywords.Count == 0 ? "" : pluginsManagerPlugin.Metadata.ActionKeywords[0]; var actionKeyword = pluginsManagerPlugin.Metadata.ActionKeywords.Count == 0 ? "" : pluginsManagerPlugin.Metadata.ActionKeywords[0];
API.ChangeQuery($"{actionKeywrod} install {plugin.Name}"); API.ChangeQuery($"{actionKeyword} install {plugin.Name}");
API.ShowMainWindow(); API.ShowMainWindow();
} }
} }
private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */
{ {
TextBox textBox = Keyboard.FocusedElement as TextBox; if (Keyboard.FocusedElement is not TextBox textBox)
if (textBox != null)
{ {
TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next); return;
textBox.MoveFocus(tRequest); }
var tRequest = new TraversalRequest(FocusNavigationDirection.Next);
textBox.MoveFocus(tRequest);
}
private void DarkModeSelectedIndexChanged(object sender, EventArgs e) => ThemeManager.Current.ApplicationTheme = settings.DarkMode 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" <ResourceDictionary
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" /> <ResourceDictionary Source="pack://application:,,,/Themes/Base.xaml" />
</ResourceDictionary.MergedDictionaries> </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" /> <Setter Property="Foreground" Value="#ffffff" />
</Style> </Style>
<Style x:Key="QueryBoxStyle" BasedOn="{StaticResource BaseQueryBoxStyle}" TargetType="{x:Type TextBox}"> <Style
<Setter Property="SelectionBrush" Value="#4a5459"/> x:Key="QueryBoxStyle"
BasedOn="{StaticResource BaseQueryBoxStyle}"
TargetType="{x:Type TextBox}">
<Setter Property="SelectionBrush" Value="#4a5459" />
<Setter Property="FontSize" Value="24" /> <Setter Property="FontSize" Value="24" />
<Setter Property="Background" Value="#202020" /> <Setter Property="Background" Value="#202020" />
<Setter Property="Foreground" Value="#FFFFFF" /> <Setter Property="Foreground" Value="#FFFFFF" />
<Setter Property="CaretBrush" Value="#FFFFFF" /> <Setter Property="CaretBrush" Value="#FFFFFF" />
<Setter Property="FontSize" Value="26" /> <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" /> <Setter Property="Height" Value="42" />
</Style> </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="Background" Value="#202020" />
<Setter Property="Foreground" Value="#7b7b7b" /> <Setter Property="Foreground" Value="#7b7b7b" />
<Setter Property="FontSize" Value="26" /> <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" /> <Setter Property="Height" Value="42" />
</Style> </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="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="#3f3f3f" /> <Setter Property="BorderBrush" Value="#3f3f3f" />
<Setter Property="CornerRadius" Value="5" /> <Setter Property="CornerRadius" Value="5" />
<Setter Property="Background" Value="#202020" /> <Setter Property="Background" Value="#202020" />
</Style> </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="Width" Value="576" />
<Setter Property="RenderOptions.ClearTypeHint" Value="Enabled"/> <Setter Property="RenderOptions.ClearTypeHint" Value="Enabled" />
</Style> </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" /> <Setter Property="Stroke" Value="White" />
</Style> </Style>
<!-- Item Style --> <!-- Item Style -->
<Style x:Key="ItemTitleStyle" BasedOn="{StaticResource BaseItemTitleStyle}" TargetType="{x:Type TextBlock}"> <Style
x:Key="ItemTitleStyle"
BasedOn="{StaticResource BaseItemTitleStyle}"
TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#ffffff" /> <Setter Property="Foreground" Value="#ffffff" />
</Style> </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="Foreground" Value="#7b7b7b" />
<Setter Property="FontSize" Value="13" /> <Setter Property="FontSize" Value="13" />
<Setter Property="FontWeight" Value="Regular" /> <Setter Property="FontWeight" Value="Regular" />
</Style> </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" /> <Setter Property="Foreground" Value="#ffffff" />
</Style> </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="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#ffffff" /> <Setter Property="Foreground" Value="#ffffff" />
</Style> </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="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#7b7b7b" /> <Setter Property="Foreground" Value="#7b7b7b" />
<Setter Property="FontSize" Value="13" /> <Setter Property="FontSize" Value="13" />
<Setter Property="FontWeight" Value="Regular" /> <Setter Property="FontWeight" Value="Regular" />
</Style> </Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#2d2d2d</SolidColorBrush> <SolidColorBrush x:Key="ItemSelectedBackgroundColor">#198F8F8F</SolidColorBrush>
<Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" > <Style
x:Key="ItemImageSelectedStyle"
BasedOn="{StaticResource BaseItemImageSelectedStyle}"
TargetType="{x:Type Image}">
<Setter Property="Cursor" Value="Arrow" /> <Setter Property="Cursor" Value="Arrow" />
</Style> </Style>
<Style x:Key="HighlightStyle"> <Style x:Key="HighlightStyle">
<Setter Property="Inline.FontWeight" Value="Bold" /> <Setter Property="Inline.Foreground" Value="#0078d7" />
</Style> </Style>
<Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}"> <Style x:Key="ItemHotkeyStyle" TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="13" /> <Setter Property="FontSize" Value="13" />
@ -76,29 +113,45 @@
<Setter Property="FontSize" Value="13" /> <Setter Property="FontSize" Value="13" />
<Setter Property="Foreground" Value="#7b7b7b" /> <Setter Property="Foreground" Value="#7b7b7b" />
</Style> </Style>
<!-- button style in the middle of the scrollbar --> <!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" BasedOn="{StaticResource BaseThumbStyle}" TargetType="{x:Type Thumb}"> <Style
<Setter Property="SnapsToDevicePixels" Value="True"/> x:Key="ThumbStyle"
<Setter Property="OverridesDefaultStyle" Value="true"/> BasedOn="{StaticResource BaseThumbStyle}"
<Setter Property="IsTabStop" Value="false"/> TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="2"/> <Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Focusable" Value="false"/> <Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="IsTabStop" Value="false" />
<Setter Property="Width" Value="2" />
<Setter Property="Focusable" Value="false" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}"> <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> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </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>
<Style x:Key="SeparatorStyle" BasedOn="{StaticResource BaseSeparatorStyle}" TargetType="{x:Type Rectangle}"> <Style
<Setter Property="Fill" Value="#4d4d4d"/> x:Key="SearchIconStyle"
<Setter Property="Height" Value="1"/> BasedOn="{StaticResource BaseSearchIconStyle}"
<Setter Property="Margin" Value="12 0 12 8"/> TargetType="{x:Type Path}">
</Style>
<Style x:Key="SearchIconStyle" TargetType="{x:Type Path}" BasedOn="{StaticResource BaseSearchIconStyle}">
<Setter Property="Fill" Value="#4d4d4d" /> <Setter Property="Fill" Value="#4d4d4d" />
<Setter Property="Width" Value="32" /> <Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" /> <Setter Property="Height" Value="32" />

View file

@ -57,7 +57,7 @@
<Setter Property="Cursor" Value="Arrow" /> <Setter Property="Cursor" Value="Arrow" />
<Setter Property="Foreground" Value="#72767d" /> <Setter Property="Foreground" Value="#72767d" />
</Style> </Style>
<SolidColorBrush x:Key="ItemSelectedBackgroundColor">#eaeaea</SolidColorBrush> <SolidColorBrush x:Key="ItemSelectedBackgroundColor">#198F8F8F</SolidColorBrush>
<Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" > <Style x:Key="ItemImageSelectedStyle" BasedOn="{StaticResource BaseItemImageSelectedStyle}" TargetType="{x:Type Image}" >
<Setter Property="Cursor" Value="Arrow" /> <Setter Property="Cursor" Value="Arrow" />
</Style> </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.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using System.Windows; using System.Windows;
using System.Windows.Media;
using System.Windows.Input; using System.Windows.Input;
using Flow.Launcher.Core.Plugin; using Flow.Launcher.Core.Plugin;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
@ -154,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() private void InitializeKeyCommands()
{ {
EscCommand = new RelayCommand(_ => EscCommand = new RelayCommand(_ =>
@ -212,7 +193,7 @@ namespace Flow.Launcher.ViewModel
{ {
SearchWeb.NewTabInBrowser("https://github.com/Flow-Launcher/Flow.Launcher/wiki/Flow-Launcher/"); SearchWeb.NewTabInBrowser("https://github.com/Flow-Launcher/Flow.Launcher/wiki/Flow-Launcher/");
}); });
OpenSettingCommand = new RelayCommand(_ => { App.API.OpenSettingDialog(); });
OpenResultCommand = new RelayCommand(index => OpenResultCommand = new RelayCommand(index =>
{ {
var results = SelectedResults; var results = SelectedResults;
@ -381,6 +362,11 @@ namespace Flow.Launcher.ViewModel
public Visibility ProgressBarVisibility { get; set; } public Visibility ProgressBarVisibility { get; set; }
public Visibility MainWindowVisibility { 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; public double MainWindowWidth => _settings.WindowSize;
@ -394,6 +380,7 @@ namespace Flow.Launcher.ViewModel
public ICommand LoadContextMenuCommand { get; set; } public ICommand LoadContextMenuCommand { get; set; }
public ICommand LoadHistoryCommand { get; set; } public ICommand LoadHistoryCommand { get; set; }
public ICommand OpenResultCommand { get; set; } public ICommand OpenResultCommand { get; set; }
public ICommand OpenSettingCommand { get; set; }
public ICommand ReloadPluginDataCommand { get; set; } public ICommand ReloadPluginDataCommand { get; set; }
public ICommand ClearQueryCommand { get; private set; } public ICommand ClearQueryCommand { get; private set; }
@ -709,9 +696,9 @@ namespace Flow.Launcher.ViewModel
public void ToggleFlowLauncher() public void ToggleFlowLauncher()
{ {
if (MainWindowVisibility != Visibility.Visible) if (!MainWindowVisibilityStatus)
{ {
MainWindowVisibility = Visibility.Visible; Show();
} }
else else
{ {
@ -719,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() public async void Hide()
{ {
// Trick for no delay
MainWindowOpacity = 0;
switch (_settings.LastQueryMode) switch (_settings.LastQueryMode)
{ {
case LastQueryMode.Empty: case LastQueryMode.Empty:
ChangeQueryText(string.Empty); ChangeQueryText(string.Empty);
Application.Current.MainWindow.Opacity = 0; // Trick for no delay await Task.Delay(100); //Time for change to opacity
await Task.Delay(100);
Application.Current.MainWindow.Opacity = 1;
break; break;
case LastQueryMode.Preserved: case LastQueryMode.Preserved:
if (_settings.UseAnimation)
await Task.Delay(100);
LastQuerySelected = true; LastQuerySelected = true;
break; break;
case LastQueryMode.Selected: case LastQueryMode.Selected:
if (_settings.UseAnimation)
await Task.Delay(100);
LastQuerySelected = false; LastQuerySelected = false;
break; break;
default: default:
throw new ArgumentException($"wrong LastQueryMode: <{_settings.LastQueryMode}>"); throw new ArgumentException($"wrong LastQueryMode: <{_settings.LastQueryMode}>");
} }
MainWindowVisibilityStatus = false;
MainWindowVisibility = Visibility.Collapsed; MainWindowVisibility = Visibility.Collapsed;
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -4,13 +4,16 @@
<!--Dialogues--> <!--Dialogues-->
<system:String x:Key="plugin_pluginsmanager_downloading_plugin">Downloading plugin</system:String> <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_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_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_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_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_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_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_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> <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_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_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_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--> <!--Controls-->
<!--Plugin Infos--> <!--Plugin Infos-->
<system:String x:Key="plugin_pluginsmanager_plugin_name">Plugins Manager</system:String> <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_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--> <!--Context menu items-->
<system:String x:Key="plugin_pluginsmanager_plugin_contextmenu_openwebsite_title">Open website</system:String> <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_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_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_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> </ResourceDictionary>

View file

@ -4,7 +4,6 @@
<!--Dialogues--> <!--Dialogues-->
<system:String x:Key="plugin_pluginsmanager_downloading_plugin">Sťahovanie pluginu</system:String> <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_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_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> <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--> <!--Dialogues-->
<system:String x:Key="plugin_pluginsmanager_downloading_plugin">下载插件</system:String> <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_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_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> <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) public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
{ {
var search = query.Search.ToLower(); var search = query.Search;
if (string.IsNullOrWhiteSpace(search)) if (string.IsNullOrWhiteSpace(search))
return pluginManager.GetDefaultHotKeys(); return pluginManager.GetDefaultHotKeys();
@ -70,9 +70,13 @@ namespace Flow.Launcher.Plugin.PluginsManager
return search switch return search switch
{ {
var s when s.StartsWith(Settings.HotKeyInstall) => await pluginManager.RequestInstallOrUpdate(s, token), //search could be url, no need ToLower() when passed in
var s when s.StartsWith(Settings.HotkeyUninstall) => pluginManager.RequestUninstall(s), var s when s.StartsWith(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase)
var s when s.StartsWith(Settings.HotkeyUpdate) => await pluginManager.RequestUpdate(s, token), => 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 => _ => pluginManager.GetDefaultHotKeys().Where(hotkey =>
{ {
hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score; hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score;

View file

@ -9,6 +9,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
@ -17,6 +19,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
{ {
internal class PluginsManager internal class PluginsManager
{ {
const string zip = "zip";
private PluginInitContext Context { get; set; } private PluginInitContext Context { get; set; }
private Settings Settings { get; set; } private Settings Settings { get; set; }
@ -47,7 +51,6 @@ namespace Flow.Launcher.Plugin.PluginsManager
private Task _downloadManifestTask = Task.CompletedTask; private Task _downloadManifestTask = Task.CompletedTask;
internal Task UpdateManifestAsync() internal Task UpdateManifestAsync()
{ {
if (_downloadManifestTask.Status == TaskStatus.Running) if (_downloadManifestTask.Status == TaskStatus.Running)
@ -118,7 +121,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
$"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}"); $"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}");
var mainWindow = Application.Current.MainWindow; var mainWindow = Application.Current.MainWindow;
mainWindow.Visibility = Visibility.Visible; mainWindow.Show();
mainWindow.Focus(); mainWindow.Focus();
shouldHideWindow = false; shouldHideWindow = false;
@ -138,13 +141,15 @@ namespace Flow.Launcher.Plugin.PluginsManager
MessageBoxButton.YesNo) == MessageBoxResult.No) MessageBoxButton.YesNo) == MessageBoxResult.No)
return; 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 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); await Http.DownloadAsync(plugin.UrlDownload, filePath).ConfigureAwait(false);
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"),
@ -154,7 +159,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
} }
catch (Exception e) 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"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"),
plugin.Name)); plugin.Name));
@ -163,6 +172,9 @@ namespace Flow.Launcher.Plugin.PluginsManager
return; return;
} }
Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_title"),
Context.API.GetTranslation("plugin_pluginsmanager_install_success_restart"));
Context.API.RestartApp(); Context.API.RestartApp();
} }
@ -183,7 +195,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (autocompletedResults.Any()) if (autocompletedResults.Any())
return autocompletedResults; return autocompletedResults;
var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty).TrimStart(); var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart();
var resultsForUpdate = var resultsForUpdate =
from existingPlugin in Context.API.GetAllPlugins() from existingPlugin in Context.API.GetAllPlugins()
@ -239,10 +251,6 @@ namespace Flow.Launcher.Plugin.PluginsManager
Task.Run(async delegate 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) await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath)
.ConfigureAwait(false); .ConfigureAwait(false);
@ -302,6 +310,62 @@ namespace Flow.Launcher.Plugin.PluginsManager
.ToList(); .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) internal async ValueTask<List<Result>> RequestInstallOrUpdate(string searchName, CancellationToken token)
{ {
if (!PluginsManifest.UserPlugins.Any()) if (!PluginsManifest.UserPlugins.Any())
@ -311,7 +375,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
token.ThrowIfCancellationRequested(); 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 = var results =
PluginsManifest PluginsManifest
@ -369,11 +437,26 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (string.IsNullOrEmpty(metadataJsonFilePath) || string.IsNullOrEmpty(pluginFolderPath)) if (string.IsNullOrEmpty(metadataJsonFilePath) || string.IsNullOrEmpty(pluginFolderPath))
{ {
MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile")); MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile"),
return; 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); FilesFolders.CopyAll(pluginFolderPath, newPluginPath);
@ -390,7 +473,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (autocompletedResults.Any()) if (autocompletedResults.Any())
return autocompletedResults; 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 var results = Context.API
.GetAllPlugins() .GetAllPlugins()
@ -466,5 +549,13 @@ namespace Flow.Launcher.Plugin.PluginsManager
return new List<Result>(); 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 class Settings
{ {
internal string HotKeyInstall { get; set; } = "install"; internal string HotKeyInstall { get; set; } = "install";
internal string HotkeyUninstall { get; set; } = "uninstall"; internal string HotkeyUninstall { get; set; } = "uninstall";
internal string HotkeyUpdate { get; set; } = "update"; 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; Context = context;
Settings = settings; 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:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Flow.Launcher.Plugin.PluginsManager.ViewModels"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"> 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> </Grid>
</UserControl> </UserControl>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,75 +1,365 @@
<Window x:Class="Flow.Launcher.Plugin.WebSearch.SearchSourceSettingWindow" <Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="Flow.Launcher.Plugin.WebSearch.SearchSourceSettingWindow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" ResizeMode="NoResize" xmlns:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch"
WindowStartupLocation="CenterScreen" Title="{DynamicResource flowlauncher_plugin_websearch_window_title}"
Title="{DynamicResource flowlauncher_plugin_websearch_window_title}" Height="590" Width="550" Width="550"
d:DataContext="{d:DesignInstance vm:SearchSourceViewModel}" Background="#F3F3F3" BorderBrush="#cecece"> 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>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition Height="80"/> <RowDefinition Height="80" />
</Grid.RowDefinitions> </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> <Grid>
<StackPanel> <StackPanel>
<StackPanel Grid.Row="0" Margin="0 0 0 12"> <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" <TextBlock
Margin="0 0 0 0" /> 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>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock <TextBlock
Text="{DynamicResource flowlauncher_plugin_websearch_guide_1}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left"/> FontSize="14"
<TextBlock Foreground="#1b1b1b"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_2}" FontWeight="SemiBold" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Center" Margin="0 12 0 12"/> Text="{DynamicResource flowlauncher_plugin_websearch_guide_1}"
<TextBlock TextAlignment="Left"
Text="{DynamicResource flowlauncher_plugin_websearch_guide_3}" Foreground="#1b1b1b" FontSize="14" TextWrapping="WrapWithOverflow" TextAlignment="Left" Margin="0 0 0 14"/> 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>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" VerticalAlignment="Center" Width="100" <TextBlock
HorizontalAlignment="Stretch" Text="{DynamicResource flowlauncher_plugin_websearch_title}" /> Width="100"
<TextBox Text="{Binding SearchSource.Title}" Margin="10" Width="330" Margin="10"
VerticalAlignment="Center" HorizontalAlignment="Left" /> 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>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" <TextBlock
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_icon}" Width="100" /> Grid.Row="4"
<Button Click="OnSelectIconClick" Height="35" VerticalAlignment="Center" Margin="10 0 0 0" Grid.Column="0"
Content="{DynamicResource flowlauncher_plugin_websearch_select_icon}" /> Width="100"
<Image Name="imgPreviewIcon" Width="24" Height="24" Margin="14 0 0 0" VerticalAlignment="Center"/> 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>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" VerticalAlignment="Center" Width="100" <TextBlock
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_url}" /> Width="100"
<TextBox Text="{Binding SearchSource.Url}" Margin="10" Grid.Row="1" Width="330" Grid.Column="1" Margin="10"
VerticalAlignment="Center" HorizontalAlignment="Left" /> 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>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Width="100" <TextBlock
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_action_keyword}" /> Grid.Row="2"
<TextBox Text="{Binding SearchSource.ActionKeyword}" Margin="10 0 10 0" Grid.Row="2" Width="330" Grid.Column="1" Grid.Column="0"
VerticalAlignment="Center" HorizontalAlignment="Left" /> 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>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock Margin="10" FontSize="14" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Width="100" <TextBlock
HorizontalAlignment="Left" Text="{DynamicResource flowlauncher_plugin_websearch_enable}" /> Grid.Row="3"
<CheckBox IsChecked="{Binding SearchSource.Enabled}" Margin="10" Grid.Row="3" Grid.Column="1" Grid.Column="0"
VerticalAlignment="Center" /> 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>
</StackPanel> </StackPanel>
</Grid> </Grid>
</Border> </Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="1"> <StackPanel
<Button Click="OnCancelButtonClick" Grid.Row="1"
Margin="10 0 5 0" Width="100" Height="35" HorizontalAlignment="Center"
Content="{DynamicResource flowlauncher_plugin_websearch_cancel}" /> Orientation="Horizontal">
<Button Click="OnConfirmButtonClick" <Button
Margin="5 0 10 0" Width="100" Height="35" Width="100"
Content="{DynamicResource flowlauncher_plugin_websearch_confirm}" /> 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> </StackPanel>
</Grid> </Grid>
-->
</Window> </Window>

View file

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