mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge "dev" into "improve-calculator"
This commit is contained in:
commit
ec2aaa8457
98 changed files with 2216 additions and 1216 deletions
|
|
@ -37,32 +37,13 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Data.SQLite, Version=1.0.111.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Data.SQLite.Core.1.0.111.0\lib\net451\System.Data.SQLite.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SQLite.EF6, Version=1.0.111.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Data.SQLite.EF6.1.0.111.0\lib\net451\System.Data.SQLite.EF6.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SQLite.Linq, Version=1.0.111.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Data.SQLite.Linq.1.0.111.0\lib\net451\System.Data.SQLite.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="UnidecodeSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\UnidecodeSharp.1.0.0.0\lib\net35\UnidecodeSharp.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -79,7 +60,6 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -123,16 +103,19 @@
|
|||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Data.SQLite">
|
||||
<Version>1.0.111</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Data.SQLite.Core">
|
||||
<Version>1.0.111</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="UnidecodeSharp">
|
||||
<Version>1.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
|
||||
<Import Project="..\..\packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets" Condition="Exists('..\..\packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\System.Data.SQLite.Core.1.0.111.0\build\net451\System.Data.SQLite.Core.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
|
||||
|
||||
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</configSections>
|
||||
<startup>
|
||||
|
|
@ -18,10 +18,5 @@
|
|||
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
|
||||
</providers>
|
||||
</entityFramework>
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="System.Data.SQLite.EF6" />
|
||||
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
|
||||
<remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
|
||||
</system.data>
|
||||
|
||||
</configuration>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="EntityFramework" version="6.2.0" targetFramework="net452" />
|
||||
<package id="System.Data.SQLite" version="1.0.111.0" targetFramework="net452" />
|
||||
<package id="System.Data.SQLite.Core" version="1.0.111.0" targetFramework="net452" />
|
||||
<package id="System.Data.SQLite.EF6" version="1.0.111.0" targetFramework="net452" />
|
||||
<package id="System.Data.SQLite.Linq" version="1.0.111.0" targetFramework="net452" />
|
||||
<package id="UnidecodeSharp" version="1.0.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -64,7 +64,6 @@
|
|||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -130,6 +129,17 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mages">
|
||||
<Version>1.5.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="Views\CalculatorSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Mages" version="1.5.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -55,7 +55,6 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -112,6 +111,14 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -27,7 +27,6 @@ namespace Wox.Plugin.ControlPanel
|
|||
Directory.CreateDirectory(iconFolder);
|
||||
}
|
||||
|
||||
|
||||
foreach (ControlPanelItem item in controlPanelItems)
|
||||
{
|
||||
if (!File.Exists(iconFolder + item.GUID + fileType) && item.Icon != null)
|
||||
|
|
@ -43,7 +42,10 @@ namespace Wox.Plugin.ControlPanel
|
|||
|
||||
foreach (var item in controlPanelItems)
|
||||
{
|
||||
item.Score = Score(item, query.Search);
|
||||
var titleMatch = StringMatcher.FuzzySearch(query.Search, item.LocalizedString);
|
||||
var subTitleMatch = StringMatcher.FuzzySearch(query.Search, item.InfoTip);
|
||||
|
||||
item.Score = Math.Max(titleMatch.Score, subTitleMatch.Score);
|
||||
if (item.Score > 0)
|
||||
{
|
||||
var result = new Result
|
||||
|
|
@ -66,6 +68,16 @@ namespace Wox.Plugin.ControlPanel
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (item.Score == titleMatch.Score)
|
||||
{
|
||||
result.TitleHighlightData = titleMatch.MatchData;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SubTitleHighlightData = subTitleMatch.MatchData;
|
||||
}
|
||||
|
||||
results.Add(result);
|
||||
}
|
||||
}
|
||||
|
|
@ -74,26 +86,6 @@ namespace Wox.Plugin.ControlPanel
|
|||
return panelItems;
|
||||
}
|
||||
|
||||
private int Score(ControlPanelItem item, string query)
|
||||
{
|
||||
var scores = new List<int> {0};
|
||||
if (!string.IsNullOrEmpty(item.LocalizedString))
|
||||
{
|
||||
var score1 = StringMatcher.FuzzySearch(query, item.LocalizedString).ScoreAfterSearchPrecisionFilter();
|
||||
var score2 = StringMatcher.ScoreForPinyin(item.LocalizedString, query);
|
||||
scores.Add(score1);
|
||||
scores.Add(score2);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(item.InfoTip))
|
||||
{
|
||||
var score1 = StringMatcher.FuzzySearch(query, item.InfoTip).ScoreAfterSearchPrecisionFilter();
|
||||
var score2 = StringMatcher.ScoreForPinyin(item.InfoTip, query);
|
||||
scores.Add(score1);
|
||||
scores.Add(score2);
|
||||
}
|
||||
return scores.Max();
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
{
|
||||
return context.API.GetTranslation("wox_plugin_controlpanel_plugin_name");
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -114,6 +113,14 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -2,76 +2,36 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Plugin.Everything.Everything.Exceptions;
|
||||
|
||||
namespace Wox.Plugin.Everything.Everything
|
||||
{
|
||||
public sealed class EverythingAPI
|
||||
public interface IEverythingApi
|
||||
{
|
||||
#region DllImport
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
private static extern int Everything_SetSearchW(string lpSearchString);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SetMatchPath(bool bEnable);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SetMatchCase(bool bEnable);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SetMatchWholeWord(bool bEnable);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SetRegex(bool bEnable);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SetMax(int dwMax);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SetOffset(int dwOffset);
|
||||
/// <summary>
|
||||
/// Searches the specified key word.
|
||||
/// </summary>
|
||||
/// <param name="keyWord">The key word.</param>
|
||||
/// <param name="token">token that allow cancellation</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="maxCount">The max count.</param>
|
||||
/// <returns></returns>
|
||||
List<SearchResult> Search(string keyWord, CancellationToken token, int offset = 0, int maxCount = 100);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_GetMatchPath();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_GetMatchCase();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_GetMatchWholeWord();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_GetRegex();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern UInt32 Everything_GetMax();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern UInt32 Everything_GetOffset();
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
private static extern string Everything_GetSearchW();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern StateCode Everything_GetLastError();
|
||||
void Load(string sdkPath);
|
||||
}
|
||||
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
private static extern bool Everything_QueryW(bool bWait);
|
||||
public sealed class EverythingApi : IEverythingApi
|
||||
{
|
||||
private const int BufferSize = 4096;
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_SortResultsByPath();
|
||||
private readonly object _syncObject = new object();
|
||||
// cached buffer to remove redundant allocations.
|
||||
private readonly StringBuilder _buffer = new StringBuilder(BufferSize);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern int Everything_GetNumFileResults();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern int Everything_GetNumFolderResults();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern int Everything_GetNumResults();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern int Everything_GetTotFileResults();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern int Everything_GetTotFolderResults();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern int Everything_GetTotResults();
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_IsVolumeResult(int nIndex);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_IsFolderResult(int nIndex);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern bool Everything_IsFileResult(int nIndex);
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
private static extern void Everything_GetResultFullPathNameW(int nIndex, StringBuilder lpString, int nMaxCount);
|
||||
[DllImport(Main.DLL)]
|
||||
private static extern void Everything_Reset();
|
||||
#endregion
|
||||
|
||||
enum StateCode
|
||||
public enum StateCode
|
||||
{
|
||||
OK,
|
||||
MemoryError,
|
||||
|
|
@ -87,15 +47,15 @@ namespace Wox.Plugin.Everything.Everything
|
|||
/// Gets or sets a value indicating whether [match path].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [match path]; otherwise, <c>false</c>.</value>
|
||||
public Boolean MatchPath
|
||||
public bool MatchPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Everything_GetMatchPath();
|
||||
return EverythingApiDllImport.Everything_GetMatchPath();
|
||||
}
|
||||
set
|
||||
{
|
||||
Everything_SetMatchPath(value);
|
||||
EverythingApiDllImport.Everything_SetMatchPath(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -103,15 +63,15 @@ namespace Wox.Plugin.Everything.Everything
|
|||
/// Gets or sets a value indicating whether [match case].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [match case]; otherwise, <c>false</c>.</value>
|
||||
public Boolean MatchCase
|
||||
public bool MatchCase
|
||||
{
|
||||
get
|
||||
{
|
||||
return Everything_GetMatchCase();
|
||||
return EverythingApiDllImport.Everything_GetMatchCase();
|
||||
}
|
||||
set
|
||||
{
|
||||
Everything_SetMatchCase(value);
|
||||
EverythingApiDllImport.Everything_SetMatchCase(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,15 +79,15 @@ namespace Wox.Plugin.Everything.Everything
|
|||
/// Gets or sets a value indicating whether [match whole word].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [match whole word]; otherwise, <c>false</c>.</value>
|
||||
public Boolean MatchWholeWord
|
||||
public bool MatchWholeWord
|
||||
{
|
||||
get
|
||||
{
|
||||
return Everything_GetMatchWholeWord();
|
||||
return EverythingApiDllImport.Everything_GetMatchWholeWord();
|
||||
}
|
||||
set
|
||||
{
|
||||
Everything_SetMatchWholeWord(value);
|
||||
EverythingApiDllImport.Everything_SetMatchWholeWord(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,15 +95,15 @@ namespace Wox.Plugin.Everything.Everything
|
|||
/// Gets or sets a value indicating whether [enable regex].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [enable regex]; otherwise, <c>false</c>.</value>
|
||||
public Boolean EnableRegex
|
||||
public bool EnableRegex
|
||||
{
|
||||
get
|
||||
{
|
||||
return Everything_GetRegex();
|
||||
return EverythingApiDllImport.Everything_GetRegex();
|
||||
}
|
||||
set
|
||||
{
|
||||
Everything_SetRegex(value);
|
||||
EverythingApiDllImport.Everything_SetRegex(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,12 +112,91 @@ namespace Wox.Plugin.Everything.Everything
|
|||
/// </summary>
|
||||
public void Reset()
|
||||
{
|
||||
Everything_Reset();
|
||||
lock (_syncObject)
|
||||
{
|
||||
EverythingApiDllImport.Everything_Reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void no()
|
||||
/// <summary>
|
||||
/// Searches the specified key word and reset the everything API afterwards
|
||||
/// </summary>
|
||||
/// <param name="keyWord">The key word.</param>
|
||||
/// <param name="token">when cancelled the current search will stop and exit (and would not reset)</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="maxCount">The max count.</param>
|
||||
/// <returns></returns>
|
||||
public List<SearchResult> Search(string keyWord, CancellationToken token, int offset = 0, int maxCount = 100)
|
||||
{
|
||||
switch (Everything_GetLastError())
|
||||
if (string.IsNullOrEmpty(keyWord))
|
||||
throw new ArgumentNullException(nameof(keyWord));
|
||||
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
|
||||
if (maxCount < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(maxCount));
|
||||
|
||||
lock (_syncObject)
|
||||
{
|
||||
if (keyWord.StartsWith("@"))
|
||||
{
|
||||
EverythingApiDllImport.Everything_SetRegex(true);
|
||||
keyWord = keyWord.Substring(1);
|
||||
}
|
||||
|
||||
EverythingApiDllImport.Everything_SetSearchW(keyWord);
|
||||
EverythingApiDllImport.Everything_SetOffset(offset);
|
||||
EverythingApiDllImport.Everything_SetMax(maxCount);
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (!EverythingApiDllImport.Everything_QueryW(true))
|
||||
{
|
||||
CheckAndThrowExceptionOnError();
|
||||
return null;
|
||||
}
|
||||
|
||||
var results = new List<SearchResult>();
|
||||
for (int idx = 0; idx < EverythingApiDllImport.Everything_GetNumResults(); ++idx)
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
EverythingApiDllImport.Everything_GetResultFullPathNameW(idx, _buffer, BufferSize);
|
||||
|
||||
var result = new SearchResult { FullPath = _buffer.ToString() };
|
||||
if (EverythingApiDllImport.Everything_IsFolderResult(idx))
|
||||
result.Type = ResultType.Folder;
|
||||
else if (EverythingApiDllImport.Everything_IsFileResult(idx))
|
||||
result.Type = ResultType.File;
|
||||
|
||||
results.Add(result);
|
||||
}
|
||||
|
||||
Reset();
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern int LoadLibrary(string name);
|
||||
|
||||
public void Load(string sdkPath)
|
||||
{
|
||||
LoadLibrary(sdkPath);
|
||||
}
|
||||
|
||||
private static void CheckAndThrowExceptionOnError()
|
||||
{
|
||||
switch (EverythingApiDllImport.Everything_GetLastError())
|
||||
{
|
||||
case StateCode.CreateThreadError:
|
||||
throw new CreateThreadException();
|
||||
|
|
@ -175,71 +214,5 @@ namespace Wox.Plugin.Everything.Everything
|
|||
throw new RegisterClassExException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches the specified key word.
|
||||
/// </summary>
|
||||
/// <param name="keyWord">The key word.</param>
|
||||
/// <param name="offset">The offset.</param>
|
||||
/// <param name="maxCount">The max count.</param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<SearchResult> Search(string keyWord, int offset = 0, int maxCount = 100)
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyWord))
|
||||
throw new ArgumentNullException("keyWord");
|
||||
|
||||
if (offset < 0)
|
||||
throw new ArgumentOutOfRangeException("offset");
|
||||
|
||||
if (maxCount < 0)
|
||||
throw new ArgumentOutOfRangeException("maxCount");
|
||||
|
||||
if (keyWord.StartsWith("@"))
|
||||
{
|
||||
Everything_SetRegex(true);
|
||||
keyWord = keyWord.Substring(1);
|
||||
}
|
||||
Everything_SetSearchW(keyWord);
|
||||
Everything_SetOffset(offset);
|
||||
Everything_SetMax(maxCount);
|
||||
|
||||
|
||||
if (!Everything_QueryW(true))
|
||||
{
|
||||
switch (Everything_GetLastError())
|
||||
{
|
||||
case StateCode.CreateThreadError:
|
||||
throw new CreateThreadException();
|
||||
case StateCode.CreateWindowError:
|
||||
throw new CreateWindowException();
|
||||
case StateCode.InvalidCallError:
|
||||
throw new InvalidCallException();
|
||||
case StateCode.InvalidIndexError:
|
||||
throw new InvalidIndexException();
|
||||
case StateCode.IPCError:
|
||||
throw new IPCErrorException();
|
||||
case StateCode.MemoryError:
|
||||
throw new MemoryErrorException();
|
||||
case StateCode.RegisterClassExError:
|
||||
throw new RegisterClassExException();
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
const int bufferSize = 4096;
|
||||
StringBuilder buffer = new StringBuilder(bufferSize);
|
||||
for (int idx = 0; idx < Everything_GetNumResults(); ++idx)
|
||||
{
|
||||
Everything_GetResultFullPathNameW(idx, buffer, bufferSize);
|
||||
|
||||
var result = new SearchResult { FullPath = buffer.ToString() };
|
||||
if (Everything_IsFolderResult(idx))
|
||||
result.Type = ResultType.Folder;
|
||||
else if (Everything_IsFileResult(idx))
|
||||
result.Type = ResultType.File;
|
||||
|
||||
yield return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Wox.Plugin.Everything.Everything
|
||||
{
|
||||
public sealed class EverythingApiDllImport
|
||||
{
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
internal static extern int Everything_SetSearchW(string lpSearchString);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SetMatchPath(bool bEnable);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SetMatchCase(bool bEnable);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SetMatchWholeWord(bool bEnable);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SetRegex(bool bEnable);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SetMax(int dwMax);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SetOffset(int dwOffset);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_GetMatchPath();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_GetMatchCase();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_GetMatchWholeWord();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_GetRegex();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern uint Everything_GetMax();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern uint Everything_GetOffset();
|
||||
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
internal static extern string Everything_GetSearchW();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern EverythingApi.StateCode Everything_GetLastError();
|
||||
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
internal static extern bool Everything_QueryW(bool bWait);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_SortResultsByPath();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern int Everything_GetNumFileResults();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern int Everything_GetNumFolderResults();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern int Everything_GetNumResults();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern int Everything_GetTotFileResults();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern int Everything_GetTotFolderResults();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern int Everything_GetTotResults();
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_IsVolumeResult(int nIndex);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_IsFolderResult(int nIndex);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern bool Everything_IsFileResult(int nIndex);
|
||||
|
||||
[DllImport(Main.DLL, CharSet = CharSet.Unicode)]
|
||||
internal static extern void Everything_GetResultFullPathNameW(int nIndex, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport(Main.DLL)]
|
||||
internal static extern void Everything_Reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,11 +3,12 @@ using System.Collections.Generic;
|
|||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Plugin.Everything.Everything;
|
||||
|
||||
|
|
@ -15,14 +16,16 @@ namespace Wox.Plugin.Everything
|
|||
{
|
||||
public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu, ISavable
|
||||
{
|
||||
private readonly EverythingAPI _api = new EverythingAPI();
|
||||
|
||||
public const string DLL = "Everything.dll";
|
||||
private readonly IEverythingApi _api = new EverythingApi();
|
||||
|
||||
|
||||
|
||||
private PluginInitContext _context;
|
||||
|
||||
private Settings _settings;
|
||||
private PluginJsonStorage<Settings> _storage;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
|
||||
public void Save()
|
||||
{
|
||||
|
|
@ -31,53 +34,24 @@ namespace Wox.Plugin.Everything
|
|||
|
||||
public List<Result> Query(Query query)
|
||||
{
|
||||
_cancellationTokenSource?.Cancel(); // cancel if already exist
|
||||
var cts = _cancellationTokenSource = new CancellationTokenSource();
|
||||
var results = new List<Result>();
|
||||
if (!string.IsNullOrEmpty(query.Search))
|
||||
{
|
||||
var keyword = query.Search;
|
||||
if (_settings.MaxSearchCount <= 0)
|
||||
{
|
||||
_settings.MaxSearchCount = 50;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
var searchList = _api.Search(keyword, maxCount: _settings.MaxSearchCount).ToList();
|
||||
foreach (var s in searchList)
|
||||
var searchList = _api.Search(keyword, cts.Token, maxCount: _settings.MaxSearchCount);
|
||||
if (searchList == null)
|
||||
{
|
||||
var path = s.FullPath;
|
||||
return results;
|
||||
}
|
||||
|
||||
string workingDir = null;
|
||||
if (_settings.UseLocationAsWorkingDir)
|
||||
workingDir = Path.GetDirectoryName(path);
|
||||
|
||||
Result r = new Result();
|
||||
r.Title = Path.GetFileName(path);
|
||||
r.SubTitle = path;
|
||||
r.IcoPath = path;
|
||||
r.Action = c =>
|
||||
{
|
||||
bool hide;
|
||||
try
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = path,
|
||||
UseShellExecute = true,
|
||||
WorkingDirectory = workingDir
|
||||
});
|
||||
hide = true;
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
var name = $"Plugin: {_context.CurrentPluginMetadata.Name}";
|
||||
var message = "Can't open this file";
|
||||
_context.API.ShowMsg(name, message, string.Empty);
|
||||
hide = false;
|
||||
}
|
||||
return hide;
|
||||
};
|
||||
r.ContextData = s;
|
||||
foreach (var searchResult in searchList)
|
||||
{
|
||||
var r = CreateResult(keyword, searchResult);
|
||||
results.Add(r);
|
||||
}
|
||||
}
|
||||
|
|
@ -91,6 +65,7 @@ namespace Wox.Plugin.Everything
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception("EverythingPlugin", "Query Error", e);
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = _context.API.GetTranslation("wox_plugin_everything_query_error"),
|
||||
|
|
@ -106,13 +81,51 @@ namespace Wox.Plugin.Everything
|
|||
}
|
||||
}
|
||||
|
||||
_api.Reset();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern int LoadLibrary(string name);
|
||||
private Result CreateResult(string keyword, SearchResult searchResult)
|
||||
{
|
||||
var path = searchResult.FullPath;
|
||||
|
||||
string workingDir = null;
|
||||
if (_settings.UseLocationAsWorkingDir)
|
||||
workingDir = Path.GetDirectoryName(path);
|
||||
|
||||
var r = new Result
|
||||
{
|
||||
Title = Path.GetFileName(path),
|
||||
SubTitle = path,
|
||||
IcoPath = path,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(keyword, Path.GetFileName(path)).MatchData,
|
||||
Action = c =>
|
||||
{
|
||||
bool hide;
|
||||
try
|
||||
{
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = path, UseShellExecute = true, WorkingDirectory = workingDir
|
||||
});
|
||||
hide = true;
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
var name = $"Plugin: {_context.CurrentPluginMetadata.Name}";
|
||||
var message = "Can't open this file";
|
||||
_context.API.ShowMsg(name, message, string.Empty);
|
||||
hide = false;
|
||||
}
|
||||
|
||||
return hide;
|
||||
},
|
||||
ContextData = searchResult,
|
||||
SubTitleHighlightData = StringMatcher.FuzzySearch(keyword, path).MatchData
|
||||
};
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<ContextMenu> GetDefaultContextMenu()
|
||||
{
|
||||
|
|
@ -147,6 +160,10 @@ namespace Wox.Plugin.Everything
|
|||
_context = context;
|
||||
_storage = new PluginJsonStorage<Settings>();
|
||||
_settings = _storage.Load();
|
||||
if (_settings.MaxSearchCount <= 0)
|
||||
{
|
||||
_settings.MaxSearchCount = Settings.DefaultMaxSearchCount;
|
||||
}
|
||||
|
||||
var pluginDirectory = context.CurrentPluginMetadata.PluginDirectory;
|
||||
const string sdk = "EverythingSDK";
|
||||
|
|
@ -156,7 +173,7 @@ namespace Wox.Plugin.Everything
|
|||
|
||||
var sdkPath = Path.Combine(sdkDirectory, DLL);
|
||||
Constant.EverythingSDKPath = sdkPath;
|
||||
LoadLibrary(sdkPath);
|
||||
_api.Load(sdkPath);
|
||||
}
|
||||
|
||||
private static string CpuType()
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ namespace Wox.Plugin.Everything
|
|||
{
|
||||
public class Settings
|
||||
{
|
||||
public const int DefaultMaxSearchCount = 50;
|
||||
|
||||
public string EditorPath { get; set; } = "";
|
||||
|
||||
public List<ContextMenu> ContextMenus = new List<ContextMenu>();
|
||||
|
||||
public int MaxSearchCount { get; set; } = 100;
|
||||
public int MaxSearchCount { get; set; } = DefaultMaxSearchCount;
|
||||
|
||||
public bool UseLocationAsWorkingDir { get; set; } = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
<Compile Include="EverythingSettings.xaml.cs">
|
||||
<DependentUpon>EverythingSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Everything\EverythingApiDllImport.cs" />
|
||||
<Compile Include="Everything\Exceptions\CreateThreadException.cs" />
|
||||
<Compile Include="Everything\Exceptions\CreateWindowException.cs" />
|
||||
<Compile Include="Everything\EverythingAPI.cs" />
|
||||
|
|
@ -100,7 +101,6 @@
|
|||
<Content Include="Images\warning.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="plugin.json">
|
||||
|
|
@ -163,6 +163,17 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
218
Plugins/Wox.Plugin.Folder/ContextMenuLoader.cs
Normal file
218
Plugins/Wox.Plugin.Folder/ContextMenuLoader.cs
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.Image;
|
||||
using Wox.Plugin.SharedCommands;
|
||||
|
||||
namespace Wox.Plugin.Folder
|
||||
{
|
||||
internal class ContextMenuLoader : IContextMenu
|
||||
{
|
||||
private readonly PluginInitContext _context;
|
||||
|
||||
public ContextMenuLoader(PluginInitContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public List<Result> LoadContextMenus(Result selectedResult)
|
||||
{
|
||||
var contextMenus = new List<Result>();
|
||||
if (selectedResult.ContextData is SearchResult record)
|
||||
{
|
||||
if (record.Type == ResultType.File)
|
||||
{
|
||||
contextMenus.Add(CreateOpenWithEditorResult(record));
|
||||
contextMenus.Add(CreateOpenContainingFolderResult(record));
|
||||
}
|
||||
|
||||
var icoPath = (record.Type == ResultType.File) ? Main.FileImagePath : Main.FolderImagePath;
|
||||
var fileOrFolder = (record.Type == ResultType.File) ? "file" : "folder";
|
||||
contextMenus.Add(new Result
|
||||
{
|
||||
Title = "Copy path",
|
||||
SubTitle = $"Copy the current {fileOrFolder} path to clipboard",
|
||||
Action = (context) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(record.FullPath);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var message = "Fail to set text in clipboard";
|
||||
LogException(message, e);
|
||||
_context.API.ShowMsg(message);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
IcoPath = Main.CopyImagePath
|
||||
});
|
||||
|
||||
contextMenus.Add(new Result
|
||||
{
|
||||
Title = $"Copy {fileOrFolder}",
|
||||
SubTitle = $"Copy the {fileOrFolder} to clipboard",
|
||||
Action = (context) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetFileDropList(new System.Collections.Specialized.StringCollection { record.FullPath });
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var message = $"Fail to set {fileOrFolder} in clipboard";
|
||||
LogException(message, e);
|
||||
_context.API.ShowMsg(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
},
|
||||
IcoPath = icoPath
|
||||
});
|
||||
|
||||
if (record.Type == ResultType.File || record.Type == ResultType.Folder)
|
||||
contextMenus.Add(new Result
|
||||
{
|
||||
Title = $"Delete {fileOrFolder}",
|
||||
SubTitle = $"Delete the selected {fileOrFolder}",
|
||||
Action = (context) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (record.Type == ResultType.File)
|
||||
File.Delete(record.FullPath);
|
||||
else
|
||||
Directory.Delete(record.FullPath);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
var message = $"Fail to delete {fileOrFolder} at {record.FullPath}";
|
||||
LogException(message, e);
|
||||
_context.API.ShowMsg(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
IcoPath = Main.DeleteFileFolderImagePath
|
||||
});
|
||||
|
||||
if (record.Type == ResultType.File && CanRunAsDifferentUser(record.FullPath))
|
||||
contextMenus.Add(new Result
|
||||
{
|
||||
Title = "Run as different user",
|
||||
Action = (context) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Task.Run(()=> ShellCommand.RunAsDifferentUser(record.FullPath.SetProcessStartInfo()));
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
var name = "Plugin: Folder";
|
||||
var message = $"File not found: {e.Message}";
|
||||
_context.API.ShowMsg(name, message);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
IcoPath = "Images/user.png"
|
||||
});
|
||||
}
|
||||
|
||||
return contextMenus;
|
||||
}
|
||||
|
||||
private Result CreateOpenContainingFolderResult(SearchResult record)
|
||||
{
|
||||
return new Result
|
||||
{
|
||||
Title = "Open containing folder",
|
||||
Action = _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start("explorer.exe", $" /select,\"{record.FullPath}\"");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
var message = $"Fail to open file at {record.FullPath}";
|
||||
LogException(message, e);
|
||||
_context.API.ShowMsg(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
IcoPath = Main.FolderImagePath
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private Result CreateOpenWithEditorResult(SearchResult record)
|
||||
{
|
||||
string editorPath = "notepad.exe"; // TODO add the ability to create a custom editor
|
||||
|
||||
var name = "Open With Editor: " + Path.GetFileNameWithoutExtension(editorPath);
|
||||
return new Result
|
||||
{
|
||||
Title = name,
|
||||
Action = _ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start(editorPath, record.FullPath);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var message = $"Fail to editor for file at {record.FullPath}";
|
||||
LogException(message, e);
|
||||
_context.API.ShowMsg(message);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
IcoPath = editorPath
|
||||
};
|
||||
}
|
||||
|
||||
public void LogException(string message, Exception e)
|
||||
{
|
||||
Log.Exception($"|Wox.Plugin.Folder.ContextMenu|{message}", e);
|
||||
}
|
||||
|
||||
private bool CanRunAsDifferentUser(string path)
|
||||
{
|
||||
switch(Path.GetExtension(path))
|
||||
{
|
||||
case ".exe":
|
||||
case ".bat":
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SearchResult
|
||||
{
|
||||
public string FullPath { get; set; }
|
||||
public ResultType Type { get; set; }
|
||||
}
|
||||
|
||||
public enum ResultType
|
||||
{
|
||||
Volume,
|
||||
Folder,
|
||||
File
|
||||
}
|
||||
}
|
||||
BIN
Plugins/Wox.Plugin.Folder/Images/deletefilefolder.png
Normal file
BIN
Plugins/Wox.Plugin.Folder/Images/deletefilefolder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
Plugins/Wox.Plugin.Folder/Images/file.png
Normal file
BIN
Plugins/Wox.Plugin.Folder/Images/file.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 290 B |
BIN
Plugins/Wox.Plugin.Folder/Images/user.png
Normal file
BIN
Plugins/Wox.Plugin.Folder/Images/user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
|
|
@ -5,17 +5,26 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Storage;
|
||||
|
||||
namespace Wox.Plugin.Folder
|
||||
{
|
||||
public class Main : IPlugin, ISettingProvider, IPluginI18n, ISavable
|
||||
public class Main : IPlugin, ISettingProvider, IPluginI18n, ISavable, IContextMenu
|
||||
{
|
||||
public const string FolderImagePath = "Images\\folder.png";
|
||||
public const string FileImagePath = "Images\\file.png";
|
||||
public const string DeleteFileFolderImagePath = "Images\\deletefilefolder.png";
|
||||
public const string CopyImagePath = "Images\\copy.png";
|
||||
|
||||
private string DefaultFolderSubtitleString = "Ctrl + Enter to open the directory";
|
||||
|
||||
private static List<string> _driverNames;
|
||||
private PluginInitContext _context;
|
||||
|
||||
private readonly Settings _settings;
|
||||
private readonly PluginJsonStorage<Settings> _storage;
|
||||
private IContextMenu _contextMenuLoader;
|
||||
|
||||
public Main()
|
||||
{
|
||||
|
|
@ -36,6 +45,7 @@ namespace Wox.Plugin.Folder
|
|||
public void Init(PluginInitContext context)
|
||||
{
|
||||
_context = context;
|
||||
_contextMenuLoader = new ContextMenuLoader(context);
|
||||
InitialDriverList();
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +54,7 @@ namespace Wox.Plugin.Folder
|
|||
var results = GetUserFolderResults(query);
|
||||
|
||||
string search = query.Search.ToLower();
|
||||
if (_driverNames != null && !_driverNames.Any(search.StartsWith))
|
||||
if (!IsDriveOrSharedFolder(search))
|
||||
return results;
|
||||
|
||||
results.AddRange(QueryInternal_Directory_Exists(query));
|
||||
|
|
@ -58,13 +68,34 @@ namespace Wox.Plugin.Folder
|
|||
return results;
|
||||
}
|
||||
|
||||
private Result CreateFolderResult(string title, string path, string queryActionKeyword)
|
||||
private static bool IsDriveOrSharedFolder(string search)
|
||||
{
|
||||
if (search.StartsWith(@"\\"))
|
||||
{ // share folder
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_driverNames != null && _driverNames.Any(search.StartsWith))
|
||||
{ // normal drive letter
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_driverNames == null && search.Length > 2 && char.IsLetter(search[0]) && search[1] == ':')
|
||||
{ // when we don't have the drive letters we can try...
|
||||
return true; // we don't know so let's give it the possibility
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Result CreateFolderResult(string title, string subtitle, string path, Query query)
|
||||
{
|
||||
return new Result
|
||||
{
|
||||
Title = title,
|
||||
IcoPath = path,
|
||||
SubTitle = "Ctrl + Enter to open the directory",
|
||||
SubTitle = subtitle,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(query.Search, title).MatchData,
|
||||
Action = c =>
|
||||
{
|
||||
if (c.SpecialKeyState.CtrlPressed)
|
||||
|
|
@ -82,9 +113,12 @@ namespace Wox.Plugin.Folder
|
|||
}
|
||||
|
||||
string changeTo = path.EndsWith("\\") ? path : path + "\\";
|
||||
_context.API.ChangeQuery(string.IsNullOrEmpty(queryActionKeyword)? changeTo : queryActionKeyword + " " + changeTo);
|
||||
_context.API.ChangeQuery(string.IsNullOrEmpty(query.ActionKeyword) ?
|
||||
changeTo :
|
||||
query.ActionKeyword + " " + changeTo);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = path }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -93,8 +127,8 @@ namespace Wox.Plugin.Folder
|
|||
string search = query.Search.ToLower();
|
||||
var userFolderLinks = _settings.FolderLinks.Where(
|
||||
x => x.Nickname.StartsWith(search, StringComparison.OrdinalIgnoreCase));
|
||||
var results = userFolderLinks.Select(item => CreateFolderResult(item.Nickname, item.Path, query.ActionKeyword))
|
||||
.ToList();
|
||||
var results = userFolderLinks.Select(item =>
|
||||
CreateFolderResult(item.Nickname, DefaultFolderSubtitleString, item.Path, query)).ToList();
|
||||
return results;
|
||||
}
|
||||
|
||||
|
|
@ -132,48 +166,67 @@ namespace Wox.Plugin.Folder
|
|||
incompleteName = search.Substring(index + 1).ToLower();
|
||||
search = search.Substring(0, index + 1);
|
||||
if (!Directory.Exists(search))
|
||||
{
|
||||
return results;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return results;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // folder exist, add \ at the end of doesn't exist
|
||||
{
|
||||
// folder exist, add \ at the end of doesn't exist
|
||||
if (!search.EndsWith("\\"))
|
||||
{
|
||||
search += "\\";
|
||||
}
|
||||
}
|
||||
|
||||
results.Add(CreateOpenCurrentFolderResult(incompleteName, search));
|
||||
|
||||
|
||||
var directoryInfo = new DirectoryInfo(search);
|
||||
|
||||
var searchOption= SearchOption.TopDirectoryOnly;
|
||||
var searchOption = SearchOption.TopDirectoryOnly;
|
||||
incompleteName += "*";
|
||||
|
||||
if (incompleteName.StartsWith(">")) // give the ability to search all folder when starting with >
|
||||
// give the ability to search all folder when starting with >
|
||||
if (incompleteName.StartsWith(">"))
|
||||
{
|
||||
searchOption = SearchOption.AllDirectories;
|
||||
incompleteName = incompleteName.Substring(1);
|
||||
|
||||
// match everything before and after search term using supported wildcard '*', ie. *searchterm*
|
||||
incompleteName = "*" + incompleteName.Substring(1);
|
||||
}
|
||||
|
||||
var folderList = new List<Result>();
|
||||
var fileList = new List<Result>();
|
||||
|
||||
var folderSubtitleString = DefaultFolderSubtitleString;
|
||||
|
||||
try
|
||||
{
|
||||
// search folder and add results
|
||||
var directoryInfo = new DirectoryInfo(search);
|
||||
var fileSystemInfos = directoryInfo.GetFileSystemInfos(incompleteName, searchOption);
|
||||
|
||||
foreach (var fileSystemInfo in fileSystemInfos)
|
||||
{
|
||||
if ((fileSystemInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) continue;
|
||||
|
||||
var result =
|
||||
fileSystemInfo is DirectoryInfo
|
||||
? CreateFolderResult(fileSystemInfo.Name, fileSystemInfo.FullName, query.ActionKeyword)
|
||||
: CreateFileResult(fileSystemInfo.FullName);
|
||||
results.Add(result);
|
||||
if(fileSystemInfo is DirectoryInfo)
|
||||
{
|
||||
if (searchOption == SearchOption.AllDirectories)
|
||||
folderSubtitleString = fileSystemInfo.FullName;
|
||||
|
||||
folderList.Add(CreateFolderResult(fileSystemInfo.Name, folderSubtitleString, fileSystemInfo.FullName, query));
|
||||
}
|
||||
else
|
||||
{
|
||||
fileList.Add(CreateFileResult(fileSystemInfo.FullName, query));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e is UnauthorizedAccessException || e is ArgumentException)
|
||||
{
|
||||
|
|
@ -185,15 +238,18 @@ namespace Wox.Plugin.Folder
|
|||
throw;
|
||||
}
|
||||
|
||||
return results;
|
||||
// Intial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
|
||||
return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList();
|
||||
}
|
||||
|
||||
private static Result CreateFileResult(string filePath)
|
||||
private static Result CreateFileResult(string filePath, Query query)
|
||||
{
|
||||
var result = new Result
|
||||
{
|
||||
Title = Path.GetFileName(filePath),
|
||||
SubTitle = filePath,
|
||||
IcoPath = filePath,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(query.Search, Path.GetFileName(filePath)).MatchData,
|
||||
Action = c =>
|
||||
{
|
||||
try
|
||||
|
|
@ -206,7 +262,8 @@ namespace Wox.Plugin.Folder
|
|||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
ContextData = new SearchResult { Type = ResultType.File, FullPath = filePath}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
|
@ -243,5 +300,10 @@ namespace Wox.Plugin.Folder
|
|||
{
|
||||
return _context.API.GetTranslation("wox_plugin_folder_plugin_description");
|
||||
}
|
||||
|
||||
public List<Result> LoadContextMenus(Result selectedResult)
|
||||
{
|
||||
return _contextMenuLoader.LoadContextMenus(selectedResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
<Compile Include="..\..\SolutionAssemblyInfo.cs">
|
||||
<Link>Properties\SolutionAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="ContextMenuLoader.cs" />
|
||||
<Compile Include="FolderLink.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="FolderPluginSettings.xaml.cs">
|
||||
|
|
@ -67,7 +68,6 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -80,6 +80,15 @@
|
|||
<None Include="Images\copy.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Images\deletefilefolder.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Images\file.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Images\user.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Languages\en.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
|
@ -126,6 +135,17 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -33,10 +33,6 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
|
@ -49,7 +45,6 @@
|
|||
<Compile Include="Main.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -115,6 +110,14 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -8,6 +8,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Newtonsoft.Json;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Http;
|
||||
using Wox.Infrastructure.Logger;
|
||||
|
||||
|
|
@ -142,6 +143,8 @@ namespace Wox.Plugin.PluginManagement
|
|||
Title = r.name,
|
||||
SubTitle = r.description,
|
||||
IcoPath = "Images\\plugin.png",
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(query.SecondSearch, r.name).MatchData,
|
||||
SubTitleHighlightData = StringMatcher.FuzzySearch(query.SecondSearch, r.description).MatchData,
|
||||
Action = c =>
|
||||
{
|
||||
MessageBoxResult result = MessageBox.Show("Are you sure you wish to install the \'" + r.name + "\' plugin",
|
||||
|
|
@ -191,6 +194,8 @@ namespace Wox.Plugin.PluginManagement
|
|||
Title = plugin.Name,
|
||||
SubTitle = plugin.Description,
|
||||
IcoPath = plugin.IcoPath,
|
||||
TitleHighlightData = StringMatcher.FuzzySearch(query.SecondSearch, plugin.Name).MatchData,
|
||||
SubTitleHighlightData = StringMatcher.FuzzySearch(query.SecondSearch, plugin.Description).MatchData,
|
||||
Action = e =>
|
||||
{
|
||||
UnInstallPlugin(plugin);
|
||||
|
|
|
|||
|
|
@ -34,14 +34,6 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
|
@ -68,7 +60,6 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -120,6 +111,17 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
BIN
Plugins/Wox.Plugin.Program/Images/user.png
Normal file
BIN
Plugins/Wox.Plugin.Program/Images/user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
|
|
@ -31,6 +31,7 @@
|
|||
<system:String x:Key="wox_plugin_program_update_file_suffixes">Successfully updated file suffixes</system:String>
|
||||
<system:String x:Key="wox_plugin_program_suffixes_cannot_empty">File suffixes can't be empty</system:String>
|
||||
|
||||
<system:String x:Key="wox_plugin_program_run_as_different_user">Run As Different User</system:String>
|
||||
<system:String x:Key="wox_plugin_program_run_as_administrator">Run As Administrator</system:String>
|
||||
<system:String x:Key="wox_plugin_program_open_containing_folder">Open containing folder</system:String>
|
||||
<system:String x:Key="wox_plugin_program_disable_program">Disable this program from displaying</system:String>
|
||||
|
|
|
|||
|
|
@ -78,8 +78,8 @@ namespace Wox.Plugin.Program
|
|||
}
|
||||
|
||||
var results1 = win32.AsParallel()
|
||||
.Where(p => p.Enabled)
|
||||
.Select(p => p.Result(query.Search, _context.API));
|
||||
.Where(p => p.Enabled)
|
||||
.Select(p => p.Result(query.Search, _context.API));
|
||||
|
||||
var results2 = uwps.AsParallel()
|
||||
.Where(p => p.Enabled)
|
||||
|
|
@ -191,22 +191,19 @@ namespace Wox.Plugin.Program
|
|||
);
|
||||
}
|
||||
|
||||
public static bool StartProcess(ProcessStartInfo info)
|
||||
public static void StartProcess(Func<ProcessStartInfo, Process> runProcess, ProcessStartInfo info)
|
||||
{
|
||||
bool hide;
|
||||
try
|
||||
{
|
||||
Process.Start(info);
|
||||
hide = true;
|
||||
runProcess(info);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
var name = "Plugin: Program";
|
||||
var message = $"Can't start: {info.FileName}";
|
||||
var message = $"Unable to start: {info.FileName}";
|
||||
_context.API.ShowMsg(name, message, string.Empty);
|
||||
hide = false;
|
||||
}
|
||||
return hide;
|
||||
}
|
||||
|
||||
public void ReloadData()
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ namespace Wox.Plugin.Program.Programs
|
|||
|
||||
public UWP(Package package)
|
||||
{
|
||||
|
||||
Location = package.InstalledLocation.Path;
|
||||
Name = package.Id.Name;
|
||||
FullName = package.Id.FullName;
|
||||
|
|
@ -266,11 +265,9 @@ namespace Wox.Plugin.Program.Programs
|
|||
|
||||
private int Score(string query)
|
||||
{
|
||||
var score1 = StringMatcher.FuzzySearch(query, DisplayName).ScoreAfterSearchPrecisionFilter();
|
||||
var score2 = StringMatcher.ScoreForPinyin(DisplayName, query);
|
||||
var score3 = StringMatcher.FuzzySearch(query, Description).ScoreAfterSearchPrecisionFilter();
|
||||
var score4 = StringMatcher.ScoreForPinyin(Description, query);
|
||||
var score = new[] { score1, score2, score3, score4 }.Max();
|
||||
var displayNameMatch = StringMatcher.FuzzySearch(query, DisplayName);
|
||||
var descriptionMatch = StringMatcher.FuzzySearch(query, Description);
|
||||
var score = new[] { displayNameMatch.Score, descriptionMatch.Score }.Max();
|
||||
return score;
|
||||
}
|
||||
|
||||
|
|
@ -299,14 +296,18 @@ namespace Wox.Plugin.Program.Programs
|
|||
Description.Substring(0, DisplayName.Length) == DisplayName)
|
||||
{
|
||||
result.Title = Description;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Description).MatchData;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(Description))
|
||||
{
|
||||
result.Title = $"{DisplayName}: {Description}";
|
||||
var title = $"{DisplayName}: {Description}";
|
||||
result.Title = title;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, title).MatchData;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Title = DisplayName;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, DisplayName).MatchData;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -318,11 +319,14 @@ namespace Wox.Plugin.Program.Programs
|
|||
new Result
|
||||
{
|
||||
Title = api.GetTranslation("wox_plugin_program_open_containing_folder"),
|
||||
|
||||
Action = _ =>
|
||||
{
|
||||
var hide = Main.StartProcess(new ProcessStartInfo(Package.Location));
|
||||
return hide;
|
||||
Main.StartProcess(Process.Start, new ProcessStartInfo(Package.Location));
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
IcoPath = "Images/folder.png"
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ using System.Linq;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
using Shell;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Plugin.Program.Logger;
|
||||
using Wox.Plugin.SharedCommands;
|
||||
|
||||
namespace Wox.Plugin.Program.Programs
|
||||
{
|
||||
|
|
@ -33,12 +35,10 @@ namespace Wox.Plugin.Program.Programs
|
|||
|
||||
private int Score(string query)
|
||||
{
|
||||
var score1 = StringMatcher.FuzzySearch(query, Name).ScoreAfterSearchPrecisionFilter();
|
||||
var score2 = StringMatcher.ScoreForPinyin(Name, query);
|
||||
var score3 = StringMatcher.FuzzySearch(query, Description).ScoreAfterSearchPrecisionFilter();
|
||||
var score4 = StringMatcher.ScoreForPinyin(Description, query);
|
||||
var score5 = StringMatcher.FuzzySearch(query, ExecutableName).ScoreAfterSearchPrecisionFilter();
|
||||
var score = new[] { score1, score2, score3, score4, score5 }.Max();
|
||||
var nameMatch = StringMatcher.FuzzySearch(query, Name);
|
||||
var descriptionMatch = StringMatcher.FuzzySearch(query, Description);
|
||||
var executableNameMatch = StringMatcher.FuzzySearch(query, ExecutableName);
|
||||
var score = new[] { nameMatch.Score, descriptionMatch.Score, executableNameMatch.Score }.Max();
|
||||
return score;
|
||||
}
|
||||
|
||||
|
|
@ -64,8 +64,10 @@ namespace Wox.Plugin.Program.Programs
|
|||
FileName = FullPath,
|
||||
WorkingDirectory = ParentDirectory
|
||||
};
|
||||
var hide = Main.StartProcess(info);
|
||||
return hide;
|
||||
|
||||
Main.StartProcess(Process.Start, info);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -73,14 +75,18 @@ namespace Wox.Plugin.Program.Programs
|
|||
Description.Substring(0, Name.Length) == Name)
|
||||
{
|
||||
result.Title = Description;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Description).MatchData;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(Description))
|
||||
{
|
||||
result.Title = $"{Name}: {Description}";
|
||||
var title = $"{Name}: {Description}";
|
||||
result.Title = title;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, title).MatchData;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Title = Name;
|
||||
result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -91,6 +97,19 @@ namespace Wox.Plugin.Program.Programs
|
|||
{
|
||||
var contextMenus = new List<Result>
|
||||
{
|
||||
new Result
|
||||
{
|
||||
Title = api.GetTranslation("wox_plugin_program_run_as_different_user"),
|
||||
Action = _ =>
|
||||
{
|
||||
var info = FullPath.SetProcessStartInfo(ParentDirectory);
|
||||
|
||||
Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info));
|
||||
|
||||
return true;
|
||||
},
|
||||
IcoPath = "Images/user.png"
|
||||
},
|
||||
new Result
|
||||
{
|
||||
Title = api.GetTranslation("wox_plugin_program_run_as_administrator"),
|
||||
|
|
@ -102,8 +121,10 @@ namespace Wox.Plugin.Program.Programs
|
|||
WorkingDirectory = ParentDirectory,
|
||||
Verb = "runas"
|
||||
};
|
||||
var hide = Main.StartProcess(info);
|
||||
return hide;
|
||||
|
||||
Task.Run(() => Main.StartProcess(Process.Start, info));
|
||||
|
||||
return true;
|
||||
},
|
||||
IcoPath = "Images/cmd.png"
|
||||
},
|
||||
|
|
@ -112,8 +133,9 @@ namespace Wox.Plugin.Program.Programs
|
|||
Title = api.GetTranslation("wox_plugin_program_open_containing_folder"),
|
||||
Action = _ =>
|
||||
{
|
||||
var hide = Main.StartProcess(new ProcessStartInfo(ParentDirectory));
|
||||
return hide;
|
||||
Main.StartProcess(Process.Start, new ProcessStartInfo(ParentDirectory));
|
||||
|
||||
return true;
|
||||
},
|
||||
IcoPath = "Images/folder.png"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,18 +40,7 @@
|
|||
<HintPath>.\AppxPackagingTlb.dll</HintPath>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</Reference>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NLog.4.2.0\lib\net45\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="ShObjIdlTlb">
|
||||
|
|
@ -94,7 +83,6 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -112,6 +100,9 @@
|
|||
<None Include="Images\disable.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="Images\user.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Languages\en.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
|
@ -163,14 +154,24 @@
|
|||
<Name>Wox.Plugin</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NLog">
|
||||
<Version>4.2.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="UwpDesktop">
|
||||
<Version>10.0.14393.3</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\..\packages\UwpDesktop.10.0.14393.3\build\portable-net45+uap\UwpDesktop.targets" Condition="Exists('..\..\packages\UwpDesktop.10.0.14393.3\build\portable-net45+uap\UwpDesktop.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\packages\UwpDesktop.10.0.14393.3\build\portable-net45+uap\UwpDesktop.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\UwpDesktop.10.0.14393.3\build\portable-net45+uap\UwpDesktop.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="NLog" version="4.2.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
<package id="UwpDesktop" version="10.0.14393.3" targetFramework="net452" />
|
||||
</packages>
|
||||
BIN
Plugins/Wox.Plugin.Shell/Images/user.png
Normal file
BIN
Plugins/Wox.Plugin.Shell/Images/user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
<system:String x:Key="wox_plugin_cmd_relace_winr">Replace Win+R</system:String>
|
||||
<system:String x:Key="wox_plugin_cmd_leave_cmd_open">Do not close Command Prompt after command execution</system:String>
|
||||
<system:String x:Key="wox_plugin_cmd_always_run_as_administrator">Always run as administrator</system:String>
|
||||
<system:String x:Key="wox_plugin_cmd_run_as_different_user">Run as different user</system:String>
|
||||
<system:String x:Key="wox_plugin_cmd_plugin_name">Shell</system:String>
|
||||
<system:String x:Key="wox_plugin_cmd_plugin_description">Allows to execute system commands from Wox. Commands should start with ></system:String>
|
||||
<system:String x:Key="wox_plugin_cmd_cmd_has_been_executed_times">this command has been executed {0} times</system:String>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using WindowsInput;
|
||||
using WindowsInput.Native;
|
||||
using Wox.Infrastructure.Hotkey;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Plugin.SharedCommands;
|
||||
using Application = System.Windows.Application;
|
||||
using Control = System.Windows.Controls.Control;
|
||||
using Keys = System.Windows.Forms.Keys;
|
||||
|
|
@ -83,7 +86,7 @@ namespace Wox.Plugin.Shell
|
|||
IcoPath = Image,
|
||||
Action = c =>
|
||||
{
|
||||
Execute(m);
|
||||
Execute(Process.Start, PrepareProcessStartInfo(m));
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
|
|
@ -116,7 +119,7 @@ namespace Wox.Plugin.Shell
|
|||
IcoPath = Image,
|
||||
Action = c =>
|
||||
{
|
||||
Execute(m.Key);
|
||||
Execute(Process.Start, PrepareProcessStartInfo(m.Key));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -135,7 +138,7 @@ namespace Wox.Plugin.Shell
|
|||
IcoPath = Image,
|
||||
Action = c =>
|
||||
{
|
||||
Execute(cmd);
|
||||
Execute(Process.Start, PrepareProcessStartInfo(cmd));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -153,27 +156,26 @@ namespace Wox.Plugin.Shell
|
|||
IcoPath = Image,
|
||||
Action = c =>
|
||||
{
|
||||
Execute(m.Key);
|
||||
Execute(Process.Start, PrepareProcessStartInfo(m.Key));
|
||||
return true;
|
||||
}
|
||||
}).Take(5);
|
||||
return history.ToList();
|
||||
}
|
||||
|
||||
private void Execute(string command, bool runAsAdministrator = false)
|
||||
private ProcessStartInfo PrepareProcessStartInfo(string command, bool runAsAdministrator = false)
|
||||
{
|
||||
command = command.Trim();
|
||||
command = Environment.ExpandEnvironmentVariables(command);
|
||||
var workingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
var runAsAdministratorArg = !runAsAdministrator && !_settings.RunAsAdministrator ? "" : "runas";
|
||||
|
||||
ProcessStartInfo info;
|
||||
if (_settings.Shell == Shell.Cmd)
|
||||
{
|
||||
var arguments = _settings.LeaveShellOpen ? $"/k \"{command}\"" : $"/c \"{command}\" & pause";
|
||||
info = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = arguments,
|
||||
};
|
||||
|
||||
info = ShellCommand.SetProcessStartInfo("cmd.exe", workingDirectory, arguments, runAsAdministratorArg);
|
||||
}
|
||||
else if (_settings.Shell == Shell.Powershell)
|
||||
{
|
||||
|
|
@ -186,11 +188,8 @@ namespace Wox.Plugin.Shell
|
|||
{
|
||||
arguments = $"\"{command} ; Read-Host -Prompt \\\"Press Enter to continue\\\"\"";
|
||||
}
|
||||
info = new ProcessStartInfo
|
||||
{
|
||||
FileName = "powershell.exe",
|
||||
Arguments = arguments
|
||||
};
|
||||
|
||||
info = ShellCommand.SetProcessStartInfo("powershell.exe", workingDirectory, arguments, runAsAdministratorArg);
|
||||
}
|
||||
else if (_settings.Shell == Shell.RunCommand)
|
||||
{
|
||||
|
|
@ -200,41 +199,48 @@ namespace Wox.Plugin.Shell
|
|||
var filename = parts[0];
|
||||
if (ExistInPath(filename))
|
||||
{
|
||||
var arguemtns = parts[1];
|
||||
info = new ProcessStartInfo
|
||||
{
|
||||
FileName = filename,
|
||||
Arguments = arguemtns
|
||||
};
|
||||
var arguments = parts[1];
|
||||
info = ShellCommand.SetProcessStartInfo(filename, workingDirectory, arguments, runAsAdministratorArg);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = new ProcessStartInfo(command);
|
||||
info = ShellCommand.SetProcessStartInfo(command, verb: runAsAdministratorArg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
info = new ProcessStartInfo(command);
|
||||
info = ShellCommand.SetProcessStartInfo(command, verb: runAsAdministratorArg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
info.UseShellExecute = true;
|
||||
info.WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
info.Verb = runAsAdministrator ? "runas" : "";
|
||||
|
||||
_settings.AddCmdHistory(command);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private void Execute(Func<ProcessStartInfo, Process> startProcess,ProcessStartInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process.Start(info);
|
||||
_settings.AddCmdHistory(command);
|
||||
startProcess(info);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
MessageBox.Show($"Command not found: {e.Message}");
|
||||
var name = "Plugin: Shell";
|
||||
var message = $"Command not found: {e.Message}";
|
||||
_context.API.ShowMsg(name, message);
|
||||
}
|
||||
catch(Win32Exception e)
|
||||
{
|
||||
var name = "Plugin: Shell";
|
||||
var message = $"Error running the command: {e.Message}";
|
||||
_context.API.ShowMsg(name, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,19 +322,31 @@ namespace Wox.Plugin.Shell
|
|||
|
||||
public List<Result> LoadContextMenus(Result selectedResult)
|
||||
{
|
||||
return new List<Result>
|
||||
var resultlist = new List<Result>
|
||||
{
|
||||
new Result
|
||||
{
|
||||
Title = _context.API.GetTranslation("wox_plugin_cmd_run_as_administrator"),
|
||||
Action = c =>
|
||||
{
|
||||
Execute(selectedResult.Title, true);
|
||||
return true;
|
||||
},
|
||||
IcoPath = Image
|
||||
}
|
||||
};
|
||||
new Result
|
||||
{
|
||||
Title = _context.API.GetTranslation("wox_plugin_cmd_run_as_different_user"),
|
||||
Action = c =>
|
||||
{
|
||||
Task.Run(() =>Execute(ShellCommand.RunAsDifferentUser, PrepareProcessStartInfo(selectedResult.Title)));
|
||||
return true;
|
||||
},
|
||||
IcoPath = "Images/user.png"
|
||||
},
|
||||
new Result
|
||||
{
|
||||
Title = _context.API.GetTranslation("wox_plugin_cmd_run_as_administrator"),
|
||||
Action = c =>
|
||||
{
|
||||
Execute(Process.Start, PrepareProcessStartInfo(selectedResult.Title, true));
|
||||
return true;
|
||||
},
|
||||
IcoPath = Image
|
||||
}
|
||||
};
|
||||
|
||||
return resultlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ namespace Wox.Plugin.Shell
|
|||
public Shell Shell { get; set; } = Shell.Cmd;
|
||||
public bool ReplaceWinR { get; set; } = true;
|
||||
public bool LeaveShellOpen { get; set; }
|
||||
public bool RunAsAdministrator { get; set; } = true;
|
||||
|
||||
public Dictionary<string, int> Count = new Dictionary<string, int>();
|
||||
|
||||
public void AddCmdHistory(string cmdName)
|
||||
|
|
|
|||
|
|
@ -12,10 +12,12 @@
|
|||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<CheckBox Grid.Row="0" x:Name="ReplaceWinR" Content="{DynamicResource wox_plugin_cmd_relace_winr}" Margin="10" HorizontalAlignment="Left"/>
|
||||
<CheckBox Grid.Row="1" x:Name="LeaveShellOpen" Content="{DynamicResource wox_plugin_cmd_leave_cmd_open}" Margin="10" HorizontalAlignment="Left"/>
|
||||
<ComboBox Grid.Row="2" x:Name="ShellComboBox" Margin="10" HorizontalAlignment="Left" >
|
||||
<CheckBox Grid.Row="2" x:Name="AlwaysRunAsAdministrator" Content="{DynamicResource wox_plugin_cmd_always_run_as_administrator}" Margin="10" HorizontalAlignment="Left"/>
|
||||
<ComboBox Grid.Row="3" x:Name="ShellComboBox" Margin="10" HorizontalAlignment="Left" >
|
||||
<ComboBoxItem>CMD</ComboBoxItem>
|
||||
<ComboBoxItem>PowerShell</ComboBoxItem>
|
||||
<ComboBoxItem>RunCommand</ComboBoxItem>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace Wox.Plugin.Shell
|
|||
{
|
||||
ReplaceWinR.IsChecked = _settings.ReplaceWinR;
|
||||
LeaveShellOpen.IsChecked = _settings.LeaveShellOpen;
|
||||
AlwaysRunAsAdministrator.IsChecked = _settings.RunAsAdministrator;
|
||||
LeaveShellOpen.IsEnabled = _settings.Shell != Shell.RunCommand;
|
||||
|
||||
LeaveShellOpen.Checked += (o, e) =>
|
||||
|
|
@ -29,6 +30,16 @@ namespace Wox.Plugin.Shell
|
|||
_settings.LeaveShellOpen = false;
|
||||
};
|
||||
|
||||
AlwaysRunAsAdministrator.Checked += (o, e) =>
|
||||
{
|
||||
_settings.RunAsAdministrator = true;
|
||||
};
|
||||
|
||||
AlwaysRunAsAdministrator.Unchecked += (o, e) =>
|
||||
{
|
||||
_settings.RunAsAdministrator = false;
|
||||
};
|
||||
|
||||
ReplaceWinR.Checked += (o, e) =>
|
||||
{
|
||||
_settings.ReplaceWinR = true;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@
|
|||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Images\user.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Languages\en.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
|
@ -102,7 +105,6 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -128,6 +130,20 @@
|
|||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="InputSimulator">
|
||||
<Version>1.0.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="InputSimulator" version="1.0.4.0" targetFramework="net452" />
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -56,12 +56,21 @@ namespace Wox.Plugin.Sys
|
|||
var results = new List<Result>();
|
||||
foreach (var c in commands)
|
||||
{
|
||||
var titleScore = StringMatcher.FuzzySearch(query.Search, c.Title).ScoreAfterSearchPrecisionFilter();
|
||||
var subTitleScore = StringMatcher.FuzzySearch(query.Search, c.SubTitle).ScoreAfterSearchPrecisionFilter();
|
||||
var score = Math.Max(titleScore, subTitleScore);
|
||||
var titleMatch = StringMatcher.FuzzySearch(query.Search, c.Title);
|
||||
var subTitleMatch = StringMatcher.FuzzySearch(query.Search, c.SubTitle);
|
||||
|
||||
var score = Math.Max(titleMatch.Score, subTitleMatch.Score);
|
||||
if (score > 0)
|
||||
{
|
||||
c.Score = score;
|
||||
if (score == titleMatch.Score)
|
||||
{
|
||||
c.TitleHighlightData = titleMatch.MatchData;
|
||||
}
|
||||
else
|
||||
{
|
||||
c.SubTitleHighlightData = subTitleMatch.MatchData;
|
||||
}
|
||||
results.Add(c);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@
|
|||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -146,6 +145,14 @@
|
|||
<ItemGroup>
|
||||
<Folder Include="Images\Images\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -56,7 +56,6 @@
|
|||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -122,6 +121,14 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -34,14 +34,6 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
|
|
@ -183,7 +175,6 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="plugin.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
@ -193,6 +184,17 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
WoX
|
||||
===
|
||||
|
||||

|
||||

|
||||
[](https://github.com/jjw24/Wox/releases/latest)
|
||||

|
||||

|
||||
[](https://ci.appveyor.com/project/happlebao/wox/branch/master)
|
||||
[](https://github.com/Wox-launcher/Wox/releases)
|
||||
[](https://dev.azure.com/Wox-Launcher/Wox/_build/latest?definitionId=1&branchName=master)
|
||||
[](https://github.com/jjw24/Wox/releases)
|
||||
[](https://github.com/LunaGao/BlessYourCodeTag)
|
||||
|
||||
**WoX** is a launcher for Windows that simply works. It's an alternative to [Alfred](https://www.alfredapp.com/) and [Launchy](http://www.launchy.net/). You can call it Windows omni-eXecutor if you want a long name.
|
||||
|
|
@ -49,6 +49,8 @@ Usage
|
|||
-----
|
||||
|
||||
- Launch: <kbd>Alt</kbd>+<kbd>Space</kbd>
|
||||
- Context Menu: <kbd>Ctrl</kbd>+<kbd>O</kbd>
|
||||
- Cancel/Return: <kbd>Esc</kbd>
|
||||
- Install/Uninstall plugin: type `wpm install/uninstall`
|
||||
- Reset: delete `%APPDATA%\Wox`
|
||||
- Log: `%APPDATA%\Wox\Logs`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
|
@ -92,21 +93,36 @@ namespace Wox.Core.Plugin
|
|||
Settings.UpdatePluginSettings(_metadatas);
|
||||
AllPlugins = PluginsLoader.Plugins(_metadatas, Settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call initialize for all plugins
|
||||
/// </summary>
|
||||
/// <returns>return the list of failed to init plugins or null for none</returns>
|
||||
public static void InitializePlugins(IPublicAPI api)
|
||||
{
|
||||
API = api;
|
||||
var failedPlugins = new ConcurrentQueue<PluginPair>();
|
||||
Parallel.ForEach(AllPlugins, pair =>
|
||||
{
|
||||
var milliseconds = Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", () =>
|
||||
try
|
||||
{
|
||||
pair.Plugin.Init(new PluginInitContext
|
||||
var milliseconds = Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", () =>
|
||||
{
|
||||
CurrentPluginMetadata = pair.Metadata,
|
||||
API = API
|
||||
pair.Plugin.Init(new PluginInitContext
|
||||
{
|
||||
CurrentPluginMetadata = pair.Metadata,
|
||||
API = API
|
||||
});
|
||||
});
|
||||
});
|
||||
pair.Metadata.InitTime += milliseconds;
|
||||
Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
|
||||
pair.Metadata.InitTime += milliseconds;
|
||||
Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception(nameof(PluginManager), $"Fail to Init plugin: {pair.Metadata.Name}", e);
|
||||
pair.Metadata.Disabled = true; // TODO: not sure this really disable it later on
|
||||
failedPlugins.Enqueue(pair);
|
||||
}
|
||||
});
|
||||
|
||||
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
|
||||
|
|
@ -121,6 +137,11 @@ namespace Wox.Core.Plugin
|
|||
.ForEach(x => NonGlobalPlugins[x] = plugin);
|
||||
}
|
||||
|
||||
if (failedPlugins.Any())
|
||||
{
|
||||
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
|
||||
API.ShowMsg($"Fail to Init Plugins", $"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help", "", false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InstallPlugin(string path)
|
||||
|
|
|
|||
|
|
@ -16,18 +16,23 @@ using Wox.Infrastructure.Logger;
|
|||
|
||||
namespace Wox.Core
|
||||
{
|
||||
public static class Updater
|
||||
public class Updater
|
||||
{
|
||||
private static readonly Internationalization Translater = InternationalizationManager.Instance;
|
||||
public string GitHubRepository { get; }
|
||||
|
||||
public static async Task UpdateApp()
|
||||
public Updater(string gitHubRepository)
|
||||
{
|
||||
GitHubRepository = gitHubRepository;
|
||||
}
|
||||
|
||||
public async Task UpdateApp()
|
||||
{
|
||||
UpdateManager m;
|
||||
UpdateInfo u;
|
||||
|
||||
try
|
||||
{
|
||||
m = await GitHubUpdateManager(Constant.Repository);
|
||||
m = await GitHubUpdateManager(GitHubRepository);
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
|
||||
{
|
||||
|
|
@ -66,8 +71,8 @@ namespace Wox.Core
|
|||
await m.ApplyReleases(u);
|
||||
await m.CreateUninstallerRegistryEntry();
|
||||
|
||||
var newVersionTips = Translater.GetTranslation("newVersionTips");
|
||||
newVersionTips = string.Format(newVersionTips, fr.Version);
|
||||
var newVersionTips = this.NewVersinoTips(fr.Version.ToString());
|
||||
|
||||
MessageBox.Show(newVersionTips);
|
||||
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
|
||||
}
|
||||
|
|
@ -90,7 +95,7 @@ namespace Wox.Core
|
|||
}
|
||||
|
||||
/// https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/UpdateManager.Factory.cs
|
||||
private static async Task<UpdateManager> GitHubUpdateManager(string repository)
|
||||
private async Task<UpdateManager> GitHubUpdateManager(string repository)
|
||||
{
|
||||
var uri = new Uri(repository);
|
||||
var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases";
|
||||
|
|
@ -109,7 +114,7 @@ namespace Wox.Core
|
|||
return manager;
|
||||
}
|
||||
|
||||
public static string NewVersinoTips(string version)
|
||||
public string NewVersinoTips(string version)
|
||||
{
|
||||
var translater = InternationalizationManager.Instance;
|
||||
var tips = string.Format(translater.GetTranslation("newVersionTips"), version);
|
||||
|
|
|
|||
|
|
@ -36,64 +36,8 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DeltaCompressionDotNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="DeltaCompressionDotNet.MsDelta, Version=1.0.0.0, Culture=neutral, PublicKeyToken=46b2138a390abf55, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.MsDelta.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="DeltaCompressionDotNet.PatchApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3e8888ee913ed789, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.PatchApi.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="PropertyChanged, Version=1.51.0.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\PropertyChanged.Fody.1.51.0\lib\dotnet\PropertyChanged.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Squirrel, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
|
|
@ -128,7 +72,6 @@
|
|||
<Compile Include="Resource\Theme.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Plugin\README.md" />
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
|
|
@ -145,14 +88,31 @@
|
|||
<ItemGroup>
|
||||
<Content Include="FodyWeavers.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fody">
|
||||
<Version>1.29.2</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="PropertyChanged.Fody">
|
||||
<Version>1.51.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="squirrel.windows">
|
||||
<Version>1.5.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\packages\Fody.1.29.2\build\dotnet\Fody.targets" Condition="Exists('..\packages\Fody.1.29.2\build\dotnet\Fody.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Fody.1.29.2\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.29.2\build\dotnet\Fody.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="DeltaCompressionDotNet" version="1.0.0" targetFramework="net452" />
|
||||
<package id="Fody" version="1.29.2" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Mono.Cecil" version="0.9.6.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="PropertyChanged.Fody" version="1.51.0" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net452" />
|
||||
<package id="Splat" version="1.6.2" targetFramework="net452" />
|
||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -2,49 +2,95 @@
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using hyjiacan.util.p4n;
|
||||
using hyjiacan.util.p4n.format;
|
||||
using JetBrains.Annotations;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
|
||||
namespace Wox.Infrastructure
|
||||
{
|
||||
public static class Alphabet
|
||||
public interface IAlphabet
|
||||
{
|
||||
private static readonly HanyuPinyinOutputFormat Format = new HanyuPinyinOutputFormat();
|
||||
private static ConcurrentDictionary<string, string[][]> PinyinCache;
|
||||
private static BinaryStorage<ConcurrentDictionary<string, string[][]>> _pinyinStorage;
|
||||
private static Settings _settings;
|
||||
string Translate(string stringToTranslate);
|
||||
}
|
||||
|
||||
public static void Initialize(Settings settings)
|
||||
public class Alphabet : IAlphabet
|
||||
{
|
||||
private readonly HanyuPinyinOutputFormat Format = new HanyuPinyinOutputFormat();
|
||||
private ConcurrentDictionary<string, string[][]> PinyinCache;
|
||||
private BinaryStorage<ConcurrentDictionary<string, string[][]>> _pinyinStorage;
|
||||
private Settings _settings;
|
||||
|
||||
public void Initialize([NotNull] Settings settings)
|
||||
{
|
||||
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
InitializePinyinHelpers();
|
||||
}
|
||||
|
||||
private void InitializePinyinHelpers()
|
||||
{
|
||||
_settings = settings;
|
||||
Format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
|
||||
Stopwatch.Normal("|Wox.Infrastructure.Alphabet.Initialize|Preload pinyin cache", () =>
|
||||
{
|
||||
_pinyinStorage = new BinaryStorage<ConcurrentDictionary<string, string[][]>>("Pinyin");
|
||||
PinyinCache = _pinyinStorage.TryLoad(new ConcurrentDictionary<string, string[][]>());
|
||||
|
||||
// force pinyin library static constructor initialize
|
||||
PinyinHelper.toHanyuPinyinStringArray('T', Format);
|
||||
});
|
||||
Log.Info($"|Wox.Infrastructure.Alphabet.Initialize|Number of preload pinyin combination<{PinyinCache.Count}>");
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
public string Translate(string str)
|
||||
{
|
||||
return ConvertChineseCharactersToPinyin(str);
|
||||
}
|
||||
|
||||
public string ConvertChineseCharactersToPinyin(string source)
|
||||
{
|
||||
if (!_settings.ShouldUsePinyin)
|
||||
return source;
|
||||
|
||||
if (string.IsNullOrEmpty(source))
|
||||
return source;
|
||||
|
||||
if (!ContainsChinese(source))
|
||||
return source;
|
||||
|
||||
var combination = PinyinCombination(source);
|
||||
|
||||
var pinyinArray=combination.Select(x => string.Join("", x));
|
||||
var acronymArray = combination.Select(Acronym).Distinct();
|
||||
|
||||
var joinedSingleStringCombination = new StringBuilder();
|
||||
var all = acronymArray.Concat(pinyinArray);
|
||||
all.ToList().ForEach(x => joinedSingleStringCombination.Append(x));
|
||||
|
||||
return joinedSingleStringCombination.ToString();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (!_settings.ShouldUsePinyin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_pinyinStorage.Save(PinyinCache);
|
||||
}
|
||||
|
||||
private static string[] EmptyStringArray = new string[0];
|
||||
private static string[][] Empty2DStringArray = new string[0][];
|
||||
|
||||
[Obsolete("Not accurate, eg 音乐 will not return yinyue but returns yinle ")]
|
||||
/// <summary>
|
||||
/// replace chinese character with pinyin, non chinese character won't be modified
|
||||
/// <param name="word"> should be word or sentence, instead of single character. e.g. 微软 </param>
|
||||
/// </summary>
|
||||
public static string[] Pinyin(string word)
|
||||
public string[] Pinyin(string word)
|
||||
{
|
||||
if (!_settings.ShouldUsePinyin)
|
||||
{
|
||||
|
|
@ -66,51 +112,48 @@ namespace Wox.Infrastructure
|
|||
/// e.g. 音乐 will return yinyue and yinle
|
||||
/// <param name="characters"> should be word or sentence, instead of single character. e.g. 微软 </param>
|
||||
/// </summmary>
|
||||
public static string[][] PinyinComination(string characters)
|
||||
public string[][] PinyinCombination(string characters)
|
||||
{
|
||||
if (_settings.ShouldUsePinyin && !string.IsNullOrEmpty(characters))
|
||||
{
|
||||
if (!PinyinCache.ContainsKey(characters))
|
||||
{
|
||||
|
||||
var allPinyins = new List<string[]>();
|
||||
foreach (var c in characters)
|
||||
{
|
||||
var pinyins = PinyinHelper.toHanyuPinyinStringArray(c, Format);
|
||||
if (pinyins != null)
|
||||
{
|
||||
var r = pinyins.Distinct().ToArray();
|
||||
allPinyins.Add(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
var r = new[] { c.ToString() };
|
||||
allPinyins.Add(r);
|
||||
}
|
||||
}
|
||||
|
||||
var combination = allPinyins.Aggregate(Combination).Select(c => c.Split(';')).ToArray();
|
||||
PinyinCache[characters] = combination;
|
||||
return combination;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PinyinCache[characters];
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!_settings.ShouldUsePinyin || string.IsNullOrEmpty(characters))
|
||||
{
|
||||
return Empty2DStringArray;
|
||||
}
|
||||
|
||||
if (!PinyinCache.ContainsKey(characters))
|
||||
{
|
||||
var allPinyins = new List<string[]>();
|
||||
foreach (var c in characters)
|
||||
{
|
||||
var pinyins = PinyinHelper.toHanyuPinyinStringArray(c, Format);
|
||||
if (pinyins != null)
|
||||
{
|
||||
var r = pinyins.Distinct().ToArray();
|
||||
allPinyins.Add(r);
|
||||
}
|
||||
else
|
||||
{
|
||||
var r = new[] { c.ToString() };
|
||||
allPinyins.Add(r);
|
||||
}
|
||||
}
|
||||
|
||||
var combination = allPinyins.Aggregate(Combination).Select(c => c.Split(';')).ToArray();
|
||||
PinyinCache[characters] = combination;
|
||||
return combination;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PinyinCache[characters];
|
||||
}
|
||||
}
|
||||
|
||||
public static string Acronym(string[] pinyin)
|
||||
public string Acronym(string[] pinyin)
|
||||
{
|
||||
var acronym = string.Join("", pinyin.Select(p => p[0]));
|
||||
return acronym;
|
||||
}
|
||||
|
||||
public static bool ContainsChinese(string word)
|
||||
public bool ContainsChinese(string word)
|
||||
{
|
||||
if (!_settings.ShouldUsePinyin)
|
||||
{
|
||||
|
|
@ -128,7 +171,7 @@ namespace Wox.Infrastructure
|
|||
return chinese;
|
||||
}
|
||||
|
||||
private static string[] Combination(string[] array1, string[] array2)
|
||||
private string[] Combination(string[] array1, string[] array2)
|
||||
{
|
||||
if (!_settings.ShouldUsePinyin)
|
||||
{
|
||||
|
|
@ -142,7 +185,5 @@ namespace Wox.Infrastructure
|
|||
).ToArray();
|
||||
return combination;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Wox.Infrastructure
|
|||
|
||||
public static FuzzyMatcher Create(string query)
|
||||
{
|
||||
return new FuzzyMatcher(query, StringMatcher.DefaultMatchOption);
|
||||
return new FuzzyMatcher(query, new MatchOption());
|
||||
}
|
||||
|
||||
public static FuzzyMatcher Create(string query, MatchOption opt)
|
||||
|
|
@ -26,7 +26,7 @@ namespace Wox.Infrastructure
|
|||
|
||||
public MatchResult Evaluate(string str)
|
||||
{
|
||||
return StringMatcher.FuzzySearch(query, str, opt);
|
||||
return StringMatcher.Instance.FuzzyMatch(query, str, opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ namespace Wox.Infrastructure
|
|||
|
||||
public static void ValidateDataDirectory(string bundledDataDirectory, string dataDirectory)
|
||||
{
|
||||
|
||||
if (!Directory.Exists(dataDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(dataDirectory);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,16 @@ namespace Wox.Infrastructure.Http
|
|||
{
|
||||
private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko";
|
||||
|
||||
static Http()
|
||||
{
|
||||
// need to be added so it would work on a win10 machine
|
||||
ServicePointManager.Expect100Continue = true;
|
||||
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls
|
||||
| SecurityProtocolType.Tls11
|
||||
| SecurityProtocolType.Tls12
|
||||
| SecurityProtocolType.Ssl3;
|
||||
}
|
||||
|
||||
public static HttpProxy Proxy { private get; set; }
|
||||
public static IWebProxy WebProxy()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,6 +39,19 @@ namespace Wox.Infrastructure.Image
|
|||
var contains = _data.ContainsKey(key);
|
||||
return contains;
|
||||
}
|
||||
|
||||
public int CacheSize()
|
||||
{
|
||||
return _data.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// return the number of unique images in the cache (by reference not by checking images content)
|
||||
/// </summary>
|
||||
public int UniqueImagesInCache()
|
||||
{
|
||||
return _data.Values.Distinct().Count();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
49
Wox.Infrastructure/Image/ImageHashGenerator.cs
Normal file
49
Wox.Infrastructure/Image/ImageHashGenerator.cs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace Wox.Infrastructure.Image
|
||||
{
|
||||
public interface IImageHashGenerator
|
||||
{
|
||||
string GetHashFromImage(ImageSource image);
|
||||
}
|
||||
public class ImageHashGenerator : IImageHashGenerator
|
||||
{
|
||||
public string GetHashFromImage(ImageSource imageSource)
|
||||
{
|
||||
if (!(imageSource is BitmapSource image))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var outStream = new MemoryStream())
|
||||
{
|
||||
// PngBitmapEncoder enc2 = new PngBitmapEncoder();
|
||||
// enc2.Frames.Add(BitmapFrame.Create(tt));
|
||||
|
||||
var enc = new JpegBitmapEncoder();
|
||||
var bitmapFrame = BitmapFrame.Create(image);
|
||||
bitmapFrame.Freeze();
|
||||
enc.Frames.Add(bitmapFrame);
|
||||
enc.Save(outStream);
|
||||
var byteArray = outStream.GetBuffer();
|
||||
using (var sha1 = new SHA1CryptoServiceProvider())
|
||||
{
|
||||
var hash = Convert.ToBase64String(sha1.ComputeHash(byteArray));
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@ namespace Wox.Infrastructure.Image
|
|||
{
|
||||
private static readonly ImageCache ImageCache = new ImageCache();
|
||||
private static BinaryStorage<ConcurrentDictionary<string, int>> _storage;
|
||||
private static readonly ConcurrentDictionary<string, string> GuidToKey = new ConcurrentDictionary<string, string>();
|
||||
private static IImageHashGenerator _hashGenerator;
|
||||
|
||||
|
||||
private static readonly string[] ImageExtensions =
|
||||
|
|
@ -30,7 +32,8 @@ namespace Wox.Infrastructure.Image
|
|||
|
||||
public static void Initialize()
|
||||
{
|
||||
_storage = new BinaryStorage<ConcurrentDictionary<string, int>> ("Image");
|
||||
_storage = new BinaryStorage<ConcurrentDictionary<string, int>>("Image");
|
||||
_hashGenerator = new ImageHashGenerator();
|
||||
ImageCache.Usage = _storage.TryLoad(new ConcurrentDictionary<string, int>());
|
||||
|
||||
foreach (var icon in new[] { Constant.DefaultIcon, Constant.ErrorIcon })
|
||||
|
|
@ -43,16 +46,12 @@ namespace Wox.Infrastructure.Image
|
|||
{
|
||||
Stopwatch.Normal("|ImageLoader.Initialize|Preload images cost", () =>
|
||||
{
|
||||
ImageCache.Usage.AsParallel().Where(i => !ImageCache.ContainsKey(i.Key)).ForAll(i =>
|
||||
ImageCache.Usage.AsParallel().ForAll(x =>
|
||||
{
|
||||
var img = Load(i.Key);
|
||||
if (img != null)
|
||||
{
|
||||
ImageCache[i.Key] = img;
|
||||
}
|
||||
Load(x.Key);
|
||||
});
|
||||
});
|
||||
Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.Usage.Count}>");
|
||||
Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.Usage.Count}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -61,31 +60,56 @@ namespace Wox.Infrastructure.Image
|
|||
ImageCache.Cleanup();
|
||||
_storage.Save(ImageCache.Usage);
|
||||
}
|
||||
|
||||
public static ImageSource Load(string path, bool loadFullImage = false)
|
||||
|
||||
private class ImageResult
|
||||
{
|
||||
public ImageResult(ImageSource imageSource, ImageType imageType)
|
||||
{
|
||||
ImageSource = imageSource;
|
||||
ImageType = imageType;
|
||||
}
|
||||
|
||||
public ImageType ImageType { get; }
|
||||
public ImageSource ImageSource { get; }
|
||||
}
|
||||
|
||||
private enum ImageType
|
||||
{
|
||||
File,
|
||||
Folder,
|
||||
Data,
|
||||
ImageFile,
|
||||
Error,
|
||||
Cache
|
||||
}
|
||||
|
||||
private static ImageResult LoadInternal(string path, bool loadFullImage = false)
|
||||
{
|
||||
ImageSource image;
|
||||
ImageType type = ImageType.Error;
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return ImageCache[Constant.ErrorIcon];
|
||||
return new ImageResult(ImageCache[Constant.ErrorIcon], ImageType.Error);
|
||||
}
|
||||
if (ImageCache.ContainsKey(path))
|
||||
{
|
||||
return ImageCache[path];
|
||||
return new ImageResult(ImageCache[path], ImageType.Cache);
|
||||
}
|
||||
|
||||
|
||||
if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new BitmapImage(new Uri(path));
|
||||
var imageSource = new BitmapImage(new Uri(path));
|
||||
imageSource.Freeze();
|
||||
return new ImageResult(imageSource, ImageType.Data);
|
||||
}
|
||||
|
||||
if (!Path.IsPathRooted(path))
|
||||
{
|
||||
path = Path.Combine(Constant.ProgramDirectory, "Images", Path.GetFileName(path));
|
||||
}
|
||||
|
||||
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
/* Directories can also have thumbnails instead of shell icons.
|
||||
|
|
@ -94,14 +118,17 @@ namespace Wox.Infrastructure.Image
|
|||
* Wox responsibility.
|
||||
* - Solution: just load the icon
|
||||
*/
|
||||
type = ImageType.Folder;
|
||||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize,
|
||||
Constant.ThumbnailSize, ThumbnailOptions.IconOnly);
|
||||
|
||||
}
|
||||
else if (File.Exists(path))
|
||||
{
|
||||
var extension = Path.GetExtension(path).ToLower();
|
||||
if (ImageExtensions.Contains(extension))
|
||||
{
|
||||
type = ImageType.ImageFile;
|
||||
if (loadFullImage)
|
||||
{
|
||||
image = LoadFullImage(path);
|
||||
|
|
@ -119,6 +146,7 @@ namespace Wox.Infrastructure.Image
|
|||
}
|
||||
else
|
||||
{
|
||||
type = ImageType.File;
|
||||
image = WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize,
|
||||
Constant.ThumbnailSize, ThumbnailOptions.None);
|
||||
}
|
||||
|
|
@ -128,17 +156,50 @@ namespace Wox.Infrastructure.Image
|
|||
image = ImageCache[Constant.ErrorIcon];
|
||||
path = Constant.ErrorIcon;
|
||||
}
|
||||
ImageCache[path] = image;
|
||||
image.Freeze();
|
||||
|
||||
if (type != ImageType.Error)
|
||||
{
|
||||
image.Freeze();
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path}", e);
|
||||
|
||||
type = ImageType.Error;
|
||||
image = ImageCache[Constant.ErrorIcon];
|
||||
ImageCache[path] = image;
|
||||
}
|
||||
return image;
|
||||
return new ImageResult(image, type);
|
||||
}
|
||||
|
||||
private static bool EnableImageHash = true;
|
||||
|
||||
public static ImageSource Load(string path, bool loadFullImage = false)
|
||||
{
|
||||
var imageResult = LoadInternal(path, loadFullImage);
|
||||
|
||||
var img = imageResult.ImageSource;
|
||||
if (imageResult.ImageType != ImageType.Error && imageResult.ImageType != ImageType.Cache)
|
||||
{ // we need to get image hash
|
||||
string hash = EnableImageHash ? _hashGenerator.GetHashFromImage(img) : null;
|
||||
if (hash != null)
|
||||
{
|
||||
if (GuidToKey.TryGetValue(hash, out string key))
|
||||
{ // image already exists
|
||||
img = ImageCache[key];
|
||||
}
|
||||
else
|
||||
{ // new guid
|
||||
GuidToKey[hash] = path;
|
||||
}
|
||||
}
|
||||
|
||||
// update cache
|
||||
ImageCache[path] = img;
|
||||
}
|
||||
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
private static BitmapImage LoadFullImage(string path)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,6 @@ namespace Wox.Infrastructure.Image
|
|||
|
||||
try
|
||||
{
|
||||
|
||||
return Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
|
|
@ -11,18 +11,20 @@ namespace Wox.Infrastructure.Logger
|
|||
{
|
||||
public const string DirectoryName = "Logs";
|
||||
|
||||
public static string CurrentLogDirectory { get; }
|
||||
|
||||
static Log()
|
||||
{
|
||||
var path = Path.Combine(Constant.DataDirectory, DirectoryName, Constant.Version);
|
||||
if (!Directory.Exists(path))
|
||||
CurrentLogDirectory = Path.Combine(Constant.DataDirectory, DirectoryName, Constant.Version);
|
||||
if (!Directory.Exists(CurrentLogDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
Directory.CreateDirectory(CurrentLogDirectory);
|
||||
}
|
||||
|
||||
var configuration = new LoggingConfiguration();
|
||||
var target = new FileTarget();
|
||||
configuration.AddTarget("file", target);
|
||||
target.FileName = path.Replace(@"\", "/") + "/${shortdate}.txt";
|
||||
target.FileName = CurrentLogDirectory.Replace(@"\", "/") + "/${shortdate}.txt";
|
||||
#if DEBUG
|
||||
var rule = new LoggingRule("*", LogLevel.Debug, target);
|
||||
#else
|
||||
|
|
@ -47,8 +49,62 @@ namespace Wox.Infrastructure.Logger
|
|||
return valid;
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Error(string message)
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
var classNameWithMethod = CheckClassAndMessageAndReturnFullClassWithMethod(className, message, methodName);
|
||||
|
||||
ExceptionInternal(classNameWithMethod, message, exception);
|
||||
}
|
||||
|
||||
private static string CheckClassAndMessageAndReturnFullClassWithMethod(string className, string message,
|
||||
string methodName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(className))
|
||||
{
|
||||
LogFaultyFormat($"Fail to specify a class name during logging of message: {message ?? "no message entered"}");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{
|
||||
// todo: not sure we really need that
|
||||
LogFaultyFormat($"Fail to specify a message during logging");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(methodName))
|
||||
{
|
||||
return className + "." + methodName;
|
||||
}
|
||||
|
||||
return className;
|
||||
}
|
||||
|
||||
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
|
||||
{
|
||||
var logger = LogManager.GetLogger(classAndMethod);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
|
||||
|
||||
logger.Error("-------------------------- Begin exception --------------------------");
|
||||
logger.Error(message);
|
||||
|
||||
do
|
||||
{
|
||||
logger.Error($"Exception full name:\n <{e.GetType().FullName}>");
|
||||
logger.Error($"Exception message:\n <{e.Message}>");
|
||||
logger.Error($"Exception stack trace:\n <{e.StackTrace}>");
|
||||
logger.Error($"Exception source:\n <{e.Source}>");
|
||||
logger.Error($"Exception target site:\n <{e.TargetSite}>");
|
||||
logger.Error($"Exception HResult:\n <{e.HResult}>");
|
||||
e = e.InnerException;
|
||||
} while (e != null);
|
||||
|
||||
logger.Error("-------------------------- End exception --------------------------");
|
||||
}
|
||||
|
||||
private static void LogInternal(string message, LogLevel level)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
|
|
@ -57,8 +113,8 @@ namespace Wox.Infrastructure.Logger
|
|||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
|
||||
logger.Error(unprefixed);
|
||||
System.Diagnostics.Debug.WriteLine($"{level.Name}|{message}");
|
||||
logger.Log(level, unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -78,25 +134,7 @@ namespace Wox.Infrastructure.Logger
|
|||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
|
||||
|
||||
logger.Error("-------------------------- Begin exception --------------------------");
|
||||
logger.Error(unprefixed);
|
||||
|
||||
do
|
||||
{
|
||||
logger.Error($"Exception fulle name:\n <{e.GetType().FullName}>");
|
||||
logger.Error($"Exception message:\n <{e.Message}>");
|
||||
logger.Error($"Exception stack trace:\n <{e.StackTrace}>");
|
||||
logger.Error($"Exception source:\n <{e.Source}>");
|
||||
logger.Error($"Exception target site:\n <{e.TargetSite}>");
|
||||
logger.Error($"Exception HResult:\n <{e.HResult}>");
|
||||
e = e.InnerException;
|
||||
} while (e != null);
|
||||
|
||||
logger.Error("-------------------------- End exception --------------------------");
|
||||
ExceptionInternal(prefix, unprefixed, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -104,62 +142,59 @@ namespace Wox.Infrastructure.Logger
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Error(string message)
|
||||
{
|
||||
LogInternal(message, LogLevel.Error);
|
||||
}
|
||||
|
||||
public static void Error(string className, string message, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
LogInternal(LogLevel.Error, className, message, methodName);
|
||||
}
|
||||
|
||||
private static void LogInternal(LogLevel level, string className, string message, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
var classNameWithMethod = CheckClassAndMessageAndReturnFullClassWithMethod(className, message, methodName);
|
||||
|
||||
var logger = LogManager.GetLogger(classNameWithMethod);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"{level.Name}|{message}");
|
||||
logger.Log(level, message);
|
||||
}
|
||||
|
||||
public static void Debug(string className, string message, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
LogInternal(LogLevel.Debug, className, message, methodName);
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Debug(string message)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
LogInternal(message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"DEBUG|{message}");
|
||||
logger.Debug(unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFaultyFormat(message);
|
||||
}
|
||||
public static void Info(string className, string message, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
LogInternal(LogLevel.Info, className, message, methodName);
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Info(string message)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
LogInternal(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"INFO|{message}");
|
||||
logger.Info(unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFaultyFormat(message);
|
||||
}
|
||||
public static void Warn(string className, string message, [CallerMemberName] string methodName = "")
|
||||
{
|
||||
LogInternal(LogLevel.Warn, className, message, methodName);
|
||||
}
|
||||
|
||||
/// <param name="message">example: "|prefix|unprefixed" </param>
|
||||
public static void Warn(string message)
|
||||
{
|
||||
if (FormatValid(message))
|
||||
{
|
||||
var parts = message.Split('|');
|
||||
var prefix = parts[1];
|
||||
var unprefixed = parts[2];
|
||||
var logger = LogManager.GetLogger(prefix);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"WARN|{message}");
|
||||
logger.Warn(unprefixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFaultyFormat(message);
|
||||
}
|
||||
LogInternal(message, LogLevel.Warn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,108 +1,220 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
using static Wox.Infrastructure.StringMatcher;
|
||||
|
||||
namespace Wox.Infrastructure
|
||||
{
|
||||
public static class StringMatcher
|
||||
public class StringMatcher
|
||||
{
|
||||
public static MatchOption DefaultMatchOption = new MatchOption();
|
||||
private readonly MatchOption _defaultMatchOption = new MatchOption();
|
||||
|
||||
public static string UserSettingSearchPrecision { get; set; }
|
||||
public SearchPrecisionScore UserSettingSearchPrecision { get; set; }
|
||||
|
||||
private readonly IAlphabet _alphabet;
|
||||
|
||||
public StringMatcher(IAlphabet alphabet = null)
|
||||
{
|
||||
_alphabet = alphabet;
|
||||
}
|
||||
|
||||
public static StringMatcher Instance { get; internal set; }
|
||||
|
||||
[Obsolete("This method is obsolete and should not be used. Please use the static function StringMatcher.FuzzySearch")]
|
||||
public static int Score(string source, string target)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(source) && !string.IsNullOrEmpty(target))
|
||||
{
|
||||
return FuzzySearch(target, source, DefaultMatchOption).Score;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return FuzzySearch(target, source).Score;
|
||||
}
|
||||
|
||||
[Obsolete("This method is obsolete and should not be used. Please use the static function StringMatcher.FuzzySearch")]
|
||||
public static bool IsMatch(string source, string target)
|
||||
{
|
||||
return FuzzySearch(target, source, DefaultMatchOption).Score > 0;
|
||||
return Score(source, target) > 0;
|
||||
}
|
||||
|
||||
public static MatchResult FuzzySearch(string query, string stringToCompare)
|
||||
{
|
||||
return FuzzySearch(query, stringToCompare, DefaultMatchOption);
|
||||
return Instance.FuzzyMatch(query, stringToCompare);
|
||||
}
|
||||
|
||||
public MatchResult FuzzyMatch(string query, string stringToCompare)
|
||||
{
|
||||
return FuzzyMatch(query, stringToCompare, _defaultMatchOption);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// refer to https://github.com/mattyork/fuzzy
|
||||
/// Current method:
|
||||
/// Character matching + substring matching;
|
||||
/// 1. Query search string is split into substrings, separator is whitespace.
|
||||
/// 2. Check each query substring's characters against full compare string,
|
||||
/// 3. if a character in the substring is matched, loop back to verify the previous character.
|
||||
/// 4. If previous character also matches, and is the start of the substring, update list.
|
||||
/// 5. Once the previous character is verified, move on to the next character in the query substring.
|
||||
/// 6. Move onto the next substring's characters until all substrings are checked.
|
||||
/// 7. Consider success and move onto scoring if every char or substring without whitespaces matched
|
||||
/// </summary>
|
||||
public static MatchResult FuzzySearch(string query, string stringToCompare, MatchOption opt)
|
||||
public MatchResult FuzzyMatch(string query, string stringToCompare, MatchOption opt)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query)) return new MatchResult { Success = false };
|
||||
|
||||
if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query)) return new MatchResult (false, UserSettingSearchPrecision);
|
||||
|
||||
query = query.Trim();
|
||||
|
||||
var len = stringToCompare.Length;
|
||||
var compareString = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
|
||||
var pattern = opt.IgnoreCase ? query.ToLower() : query;
|
||||
if (_alphabet != null)
|
||||
{
|
||||
query = _alphabet.Translate(query);
|
||||
stringToCompare = _alphabet.Translate(stringToCompare);
|
||||
}
|
||||
|
||||
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
|
||||
|
||||
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
|
||||
|
||||
var querySubstrings = queryWithoutCase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int currentQuerySubstringIndex = 0;
|
||||
var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
|
||||
var currentQuerySubstringCharacterIndex = 0;
|
||||
|
||||
var sb = new StringBuilder(stringToCompare.Length + (query.Length * (opt.Prefix.Length + opt.Suffix.Length)));
|
||||
var patternIdx = 0;
|
||||
var firstMatchIndex = -1;
|
||||
var firstMatchIndexInWord = -1;
|
||||
var lastMatchIndex = 0;
|
||||
char ch;
|
||||
for (var idx = 0; idx < len; idx++)
|
||||
bool allQuerySubstringsMatched = false;
|
||||
bool matchFoundInPreviousLoop = false;
|
||||
bool allSubstringsContainedInCompareString = true;
|
||||
|
||||
var indexList = new List<int>();
|
||||
|
||||
for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
|
||||
{
|
||||
ch = stringToCompare[idx];
|
||||
if (compareString[idx] == pattern[patternIdx])
|
||||
if (fullStringToCompareWithoutCase[compareStringIndex] != currentQuerySubstring[currentQuerySubstringCharacterIndex])
|
||||
{
|
||||
if (firstMatchIndex < 0)
|
||||
firstMatchIndex = idx;
|
||||
lastMatchIndex = idx + 1;
|
||||
|
||||
sb.Append(opt.Prefix + ch + opt.Suffix);
|
||||
patternIdx += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(ch);
|
||||
matchFoundInPreviousLoop = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// match success, append remain char
|
||||
if (patternIdx == pattern.Length && (idx + 1) != compareString.Length)
|
||||
if (firstMatchIndex < 0)
|
||||
{
|
||||
sb.Append(stringToCompare.Substring(idx + 1));
|
||||
break;
|
||||
// first matched char will become the start of the compared string
|
||||
firstMatchIndex = compareStringIndex;
|
||||
}
|
||||
|
||||
if (currentQuerySubstringCharacterIndex == 0)
|
||||
{
|
||||
// first letter of current word
|
||||
matchFoundInPreviousLoop = true;
|
||||
firstMatchIndexInWord = compareStringIndex;
|
||||
}
|
||||
else if (!matchFoundInPreviousLoop)
|
||||
{
|
||||
// we want to verify that there is not a better match if this is not a full word
|
||||
// in order to do so we need to verify all previous chars are part of the pattern
|
||||
var startIndexToVerify = compareStringIndex - currentQuerySubstringCharacterIndex;
|
||||
|
||||
if (AllPreviousCharsMatched(startIndexToVerify, currentQuerySubstringCharacterIndex, fullStringToCompareWithoutCase, currentQuerySubstring))
|
||||
{
|
||||
matchFoundInPreviousLoop = true;
|
||||
|
||||
// if it's the beginning character of the first query substring that is matched then we need to update start index
|
||||
firstMatchIndex = currentQuerySubstringIndex == 0 ? startIndexToVerify : firstMatchIndex;
|
||||
|
||||
indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex, firstMatchIndexInWord, indexList);
|
||||
}
|
||||
}
|
||||
|
||||
lastMatchIndex = compareStringIndex + 1;
|
||||
indexList.Add(compareStringIndex);
|
||||
|
||||
currentQuerySubstringCharacterIndex++;
|
||||
|
||||
// if finished looping through every character in the current substring
|
||||
if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
|
||||
{
|
||||
// if any of the substrings was not matched then consider as all are not matched
|
||||
allSubstringsContainedInCompareString = matchFoundInPreviousLoop && allSubstringsContainedInCompareString;
|
||||
|
||||
currentQuerySubstringIndex++;
|
||||
|
||||
allQuerySubstringsMatched = AllQuerySubstringsMatched(currentQuerySubstringIndex, querySubstrings.Length);
|
||||
if (allQuerySubstringsMatched)
|
||||
break;
|
||||
|
||||
// otherwise move to the next query substring
|
||||
currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
|
||||
currentQuerySubstringCharacterIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// return rendered string if we have a match for every char
|
||||
if (patternIdx == pattern.Length)
|
||||
|
||||
// proceed to calculate score if every char or substring without whitespaces matched
|
||||
if (allQuerySubstringsMatched)
|
||||
{
|
||||
return new MatchResult
|
||||
{
|
||||
Success = true,
|
||||
Value = sb.ToString(),
|
||||
Score = CalScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex)
|
||||
};
|
||||
var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, allSubstringsContainedInCompareString);
|
||||
|
||||
return new MatchResult(true, UserSettingSearchPrecision, indexList, score);
|
||||
}
|
||||
|
||||
return new MatchResult { Success = false };
|
||||
return new MatchResult (false, UserSettingSearchPrecision);
|
||||
}
|
||||
|
||||
private static int CalScore(string query, string stringToCompare, int firstIndex, int matchLen)
|
||||
private static bool AllPreviousCharsMatched(int startIndexToVerify, int currentQuerySubstringCharacterIndex,
|
||||
string fullStringToCompareWithoutCase, string currentQuerySubstring)
|
||||
{
|
||||
//a match found near the beginning of a string is scored more than a match found near the end
|
||||
//a match is scored more if the characters in the patterns are closer to each other, while the score is lower if they are more spread out
|
||||
var allMatch = true;
|
||||
for (int indexToCheck = 0; indexToCheck < currentQuerySubstringCharacterIndex; indexToCheck++)
|
||||
{
|
||||
if (fullStringToCompareWithoutCase[startIndexToVerify + indexToCheck] !=
|
||||
currentQuerySubstring[indexToCheck])
|
||||
{
|
||||
allMatch = false;
|
||||
}
|
||||
}
|
||||
|
||||
return allMatch;
|
||||
}
|
||||
|
||||
private static List<int> GetUpdatedIndexList(int startIndexToVerify, int currentQuerySubstringCharacterIndex, int firstMatchIndexInWord, List<int> indexList)
|
||||
{
|
||||
var updatedList = new List<int>();
|
||||
|
||||
indexList.RemoveAll(x => x >= firstMatchIndexInWord);
|
||||
|
||||
updatedList.AddRange(indexList);
|
||||
|
||||
for (int indexToCheck = 0; indexToCheck < currentQuerySubstringCharacterIndex; indexToCheck++)
|
||||
{
|
||||
updatedList.Add(startIndexToVerify + indexToCheck);
|
||||
}
|
||||
|
||||
return updatedList;
|
||||
}
|
||||
|
||||
private static bool AllQuerySubstringsMatched(int currentQuerySubstringIndex, int querySubstringsLength)
|
||||
{
|
||||
return currentQuerySubstringIndex >= querySubstringsLength;
|
||||
}
|
||||
|
||||
private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen, bool allSubstringsContainedInCompareString)
|
||||
{
|
||||
// A match found near the beginning of a string is scored more than a match found near the end
|
||||
// A match is scored more if the characters in the patterns are closer to each other,
|
||||
// while the score is lower if they are more spread out
|
||||
var score = 100 * (query.Length + 1) / ((1 + firstIndex) + (matchLen + 1));
|
||||
//a match with less characters assigning more weights
|
||||
|
||||
// A match with less characters assigning more weights
|
||||
if (stringToCompare.Length - query.Length < 5)
|
||||
{
|
||||
score += 20;
|
||||
}
|
||||
else if (stringToCompare.Length - query.Length < 10)
|
||||
{
|
||||
score += 10;
|
||||
}
|
||||
|
||||
if (allSubstringsContainedInCompareString)
|
||||
{
|
||||
int count = query.Count(c => !char.IsWhiteSpace(c));
|
||||
int factor = count < 4 ? 10 : 5;
|
||||
score += factor * count;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
|
@ -113,77 +225,83 @@ namespace Wox.Infrastructure
|
|||
Low = 20,
|
||||
None = 0
|
||||
}
|
||||
|
||||
public static bool IsSearchPrecisionScoreMet(this MatchResult matchResult)
|
||||
{
|
||||
var precisionScore = (SearchPrecisionScore)Enum.Parse(typeof(SearchPrecisionScore),
|
||||
UserSettingSearchPrecision ?? SearchPrecisionScore.Regular.ToString());
|
||||
return matchResult.Score >= (int)precisionScore;
|
||||
}
|
||||
|
||||
public static int ScoreAfterSearchPrecisionFilter(this MatchResult matchResult)
|
||||
{
|
||||
return matchResult.IsSearchPrecisionScoreMet() ? matchResult.Score : 0;
|
||||
|
||||
}
|
||||
|
||||
public static int ScoreForPinyin(string source, string target)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(source) && !string.IsNullOrEmpty(target))
|
||||
{
|
||||
if (Alphabet.ContainsChinese(source))
|
||||
{
|
||||
var combination = Alphabet.PinyinComination(source);
|
||||
var pinyinScore = combination
|
||||
.Select(pinyin => FuzzySearch(target, string.Join("", pinyin)).Score)
|
||||
.Max();
|
||||
var acronymScore = combination.Select(Alphabet.Acronym)
|
||||
.Select(pinyin => FuzzySearch(target, pinyin).Score)
|
||||
.Max();
|
||||
var score = Math.Max(pinyinScore, acronymScore);
|
||||
return score;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchResult
|
||||
{
|
||||
public MatchResult(bool success, SearchPrecisionScore searchPrecision)
|
||||
{
|
||||
Success = success;
|
||||
SearchPrecision = searchPrecision;
|
||||
}
|
||||
|
||||
public MatchResult(bool success, SearchPrecisionScore searchPrecision, List<int> matchData, int rawScore)
|
||||
{
|
||||
Success = success;
|
||||
SearchPrecision = searchPrecision;
|
||||
MatchData = matchData;
|
||||
RawScore = rawScore;
|
||||
}
|
||||
|
||||
public bool Success { get; set; }
|
||||
public int Score { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// highlight string
|
||||
/// The final score of the match result with search precision filters applied.
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
public int Score { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The raw calculated search score without any search precision filtering applied.
|
||||
/// </summary>
|
||||
private int _rawScore;
|
||||
|
||||
public int RawScore
|
||||
{
|
||||
get { return _rawScore; }
|
||||
set
|
||||
{
|
||||
_rawScore = value;
|
||||
Score = ScoreAfterSearchPrecisionFilter(_rawScore);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Matched data to highlight.
|
||||
/// </summary>
|
||||
public List<int> MatchData { get; set; }
|
||||
|
||||
public SearchPrecisionScore SearchPrecision { get; set; }
|
||||
|
||||
public bool IsSearchPrecisionScoreMet()
|
||||
{
|
||||
return IsSearchPrecisionScoreMet(_rawScore);
|
||||
}
|
||||
|
||||
private bool IsSearchPrecisionScoreMet(int rawScore)
|
||||
{
|
||||
return rawScore >= (int)SearchPrecision;
|
||||
}
|
||||
|
||||
private int ScoreAfterSearchPrecisionFilter(int rawScore)
|
||||
{
|
||||
return IsSearchPrecisionScoreMet(rawScore) ? rawScore : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class MatchOption
|
||||
{
|
||||
public MatchOption()
|
||||
{
|
||||
Prefix = "";
|
||||
Suffix = "";
|
||||
IgnoreCase = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// prefix of match char, use for hightlight
|
||||
/// </summary>
|
||||
public string Prefix { get; set; }
|
||||
[Obsolete("this is never used")]
|
||||
public string Prefix { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// suffix of match char, use for hightlight
|
||||
/// </summary>
|
||||
public string Suffix { get; set; }
|
||||
[Obsolete("this is never used")]
|
||||
public string Suffix { get; set; } = "";
|
||||
|
||||
public bool IgnoreCase { get; set; }
|
||||
public bool IgnoreCase { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,19 +21,38 @@ namespace Wox.Infrastructure.UserSettings
|
|||
public string ResultFontWeight { get; set; }
|
||||
public string ResultFontStretch { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// when false Alphabet static service will always return empty results
|
||||
/// </summary>
|
||||
public bool ShouldUsePinyin { get; set; } = true;
|
||||
|
||||
private string _querySearchPrecision { get; set; } = StringMatcher.SearchPrecisionScore.Regular.ToString();
|
||||
public string QuerySearchPrecision
|
||||
|
||||
internal StringMatcher.SearchPrecisionScore QuerySearchPrecision { get; private set; } = StringMatcher.SearchPrecisionScore.Regular;
|
||||
|
||||
[JsonIgnore]
|
||||
public string QuerySearchPrecisionString
|
||||
{
|
||||
get { return _querySearchPrecision; }
|
||||
get { return QuerySearchPrecision.ToString(); }
|
||||
set
|
||||
{
|
||||
_querySearchPrecision = value;
|
||||
StringMatcher.UserSettingSearchPrecision = value;
|
||||
try
|
||||
{
|
||||
var precisionScore = (StringMatcher.SearchPrecisionScore)Enum
|
||||
.Parse(typeof(StringMatcher.SearchPrecisionScore), value);
|
||||
|
||||
QuerySearchPrecision = precisionScore;
|
||||
StringMatcher.Instance.UserSettingSearchPrecision = precisionScore;
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
Logger.Log.Exception(nameof(Settings), "Failed to load QuerySearchPrecisionString value from Settings file", e);
|
||||
|
||||
QuerySearchPrecision = StringMatcher.SearchPrecisionScore.Regular;
|
||||
StringMatcher.Instance.UserSettingSearchPrecision = StringMatcher.SearchPrecisionScore.Regular;
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,22 +36,6 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.2.0\lib\net45\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Pinyin4Net, Version=2016.4.24.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Pinyin4DotNet.2016.4.23.4\lib\net452\Pinyin4Net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
|
|
@ -71,6 +55,7 @@
|
|||
<Compile Include="Hotkey\InterceptKeys.cs" />
|
||||
<Compile Include="Hotkey\KeyEvent.cs" />
|
||||
<Compile Include="Image\ImageCache.cs" />
|
||||
<Compile Include="Image\ImageHashGenerator.cs" />
|
||||
<Compile Include="Image\ImageLoader.cs" />
|
||||
<Compile Include="Image\ThumbnailReader.cs" />
|
||||
<Compile Include="Logger\Log.cs" />
|
||||
|
|
@ -101,14 +86,31 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NLog">
|
||||
<Version>4.2.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NLog.Schema" GeneratePathProperty="true">
|
||||
<Version>4.2.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Pinyin4DotNet" GeneratePathProperty="true">
|
||||
<Version>2016.4.23.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>cd $(SolutionDir)packages\Pinyin4DotNet*\pinyindb\
|
||||
xcopy /Y unicode_to_hanyu_pinyin.txt $(TargetDir)pinyindb\
|
||||
cd $(SolutionDir)packages\NLog.Schema*\content\
|
||||
xcopy /Y NLog.xsd $(TargetDir)</PreBuildEvent>
|
||||
<PreBuildEvent>
|
||||
xcopy /Y $(PkgPinyin4DotNet)\pinyindb\unicode_to_hanyu_pinyin.txt $(TargetDir)pinyindb\
|
||||
xcopy /Y $(PkgNLog_Schema)\content\NLog.xsd $(TargetDir)
|
||||
</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ namespace Wox.Infrastructure
|
|||
public static readonly string DataDirectory = DetermineDataDirectory();
|
||||
public static readonly string PluginsDirectory = Path.Combine(DataDirectory, Plugins);
|
||||
public static readonly string PreinstalledDirectory = Path.Combine(ProgramDirectory, Plugins);
|
||||
public const string Repository = "https://github.com/Wox-launcher/Wox";
|
||||
public const string Issue = "https://github.com/Wox-launcher/Wox/issues/new";
|
||||
public static readonly string Version = FileVersionInfo.GetVersionInfo(Assembly.Location.NonNull()).ProductVersion;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="NLog" version="4.2.0" targetFramework="net452" />
|
||||
<package id="NLog.Schema" version="4.2.0" targetFramework="net452" />
|
||||
<package id="Pinyin4DotNet" version="2016.4.23.4" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -1,11 +1,9 @@
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using JetBrains.Annotations;
|
||||
using PropertyChanged;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
[ImplementPropertyChanged]
|
||||
public class BaseModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace Wox.Plugin
|
|||
/// <param name="title">Message title</param>
|
||||
/// <param name="subTitle">Message subtitle</param>
|
||||
/// <param name="iconPath">Message icon path (relative path to your plugin folder)</param>
|
||||
void ShowMsg(string title, string subTitle = "", string iconPath = "");
|
||||
void ShowMsg(string title, string subTitle = "", string iconPath = "", bool useMainWindowAsOwner = true);
|
||||
|
||||
/// <summary>
|
||||
/// Open setting dialog
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using PropertyChanged;
|
||||
|
||||
namespace Wox.Plugin
|
||||
{
|
||||
[JsonObject(MemberSerialization.OptOut)]
|
||||
|
|
@ -46,6 +46,9 @@ namespace Wox.Plugin
|
|||
[Obsolete("Use IcoPath")]
|
||||
public string FullIcoPath => IcoPath;
|
||||
|
||||
/// <summary>
|
||||
/// Init time include both plugin load time and init time
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public long InitTime { get; set; }
|
||||
[JsonIgnore]
|
||||
|
|
|
|||
|
|
@ -42,6 +42,16 @@ namespace Wox.Plugin
|
|||
|
||||
public int Score { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of indexes for the characters to be highlighted in Title
|
||||
/// </summary>
|
||||
public IList<int> TitleHighlightData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of indexes for the characters to be highlighted in SubTitle
|
||||
/// </summary>
|
||||
public IList<int> SubTitleHighlightData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only resulsts that originQuery match with curren query will be displayed in the panel
|
||||
/// </summary>
|
||||
|
|
@ -69,7 +79,9 @@ namespace Wox.Plugin
|
|||
|
||||
var equality = string.Equals(r?.Title, Title) &&
|
||||
string.Equals(r?.SubTitle, SubTitle) &&
|
||||
string.Equals(r?.IcoPath, IcoPath);
|
||||
string.Equals(r?.IcoPath, IcoPath) &&
|
||||
TitleHighlightData == r.TitleHighlightData &&
|
||||
SubTitleHighlightData == r.SubTitleHighlightData;
|
||||
|
||||
return equality;
|
||||
}
|
||||
|
|
|
|||
76
Wox.Plugin/SharedCommands/ShellCommand.cs
Normal file
76
Wox.Plugin/SharedCommands/ShellCommand.cs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wox.Plugin.SharedCommands
|
||||
{
|
||||
public static class ShellCommand
|
||||
{
|
||||
public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);
|
||||
[DllImport("user32.dll")] static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam);
|
||||
[DllImport("user32.dll")] static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
|
||||
[DllImport("user32.dll")] static extern int GetWindowTextLength(IntPtr hwnd);
|
||||
|
||||
private static bool containsSecurityWindow;
|
||||
|
||||
public static Process RunAsDifferentUser(ProcessStartInfo processStartInfo)
|
||||
{
|
||||
processStartInfo.Verb = "RunAsUser";
|
||||
var process = Process.Start(processStartInfo);
|
||||
|
||||
containsSecurityWindow = false;
|
||||
while (!containsSecurityWindow) // wait for windows to bring up the "Windows Security" dialog
|
||||
{
|
||||
CheckSecurityWindow();
|
||||
Thread.Sleep(25);
|
||||
}
|
||||
while (containsSecurityWindow) // while this process contains a "Windows Security" dialog, stay open
|
||||
{
|
||||
containsSecurityWindow = false;
|
||||
CheckSecurityWindow();
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
private static void CheckSecurityWindow()
|
||||
{
|
||||
ProcessThreadCollection ptc = Process.GetCurrentProcess().Threads;
|
||||
for (int i = 0; i < ptc.Count; i++)
|
||||
EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero);
|
||||
}
|
||||
|
||||
private static bool CheckSecurityThread(IntPtr hwnd, IntPtr lParam)
|
||||
{
|
||||
if (GetWindowTitle(hwnd) == "Windows Security")
|
||||
containsSecurityWindow = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string GetWindowTitle(IntPtr hwnd)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(GetWindowTextLength(hwnd) + 1);
|
||||
GetWindowText(hwnd, sb, sb.Capacity);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "")
|
||||
{
|
||||
var info = new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
WorkingDirectory = workingDirectory,
|
||||
Arguments = arguments,
|
||||
Verb = verb
|
||||
};
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,20 +36,8 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="JetBrains.Annotations, Version=10.3.0.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\JetBrains.Annotations.10.3.0\lib\net\JetBrains.Annotations.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="PropertyChanged, Version=1.51.0.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\PropertyChanged.Fody.1.51.0\lib\dotnet\PropertyChanged.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xaml" />
|
||||
|
|
@ -78,23 +66,39 @@
|
|||
<Compile Include="Result.cs" />
|
||||
<Compile Include="ActionContext.cs" />
|
||||
<Compile Include="SharedCommands\SearchWeb.cs" />
|
||||
<Compile Include="SharedCommands\ShellCommand.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="README.md" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="FodyWeavers.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fody">
|
||||
<Version>1.29.2</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mono.Cecil">
|
||||
<Version>0.9.6.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="PropertyChanged.Fody">
|
||||
<Version>1.51.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="..\packages\Fody.1.29.2\build\dotnet\Fody.targets" Condition="Exists('..\packages\Fody.1.29.2\build\dotnet\Fody.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Fody.1.29.2\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.29.2\build\dotnet\Fody.targets'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Fody" version="1.29.2" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="PropertyChanged.Fody" version="1.51.0" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -11,17 +11,25 @@ namespace Wox.Test
|
|||
[TestFixture]
|
||||
public class FuzzyMatcherTest
|
||||
{
|
||||
public List<string> GetSearchStrings()
|
||||
private const string Chrome = "Chrome";
|
||||
private const string CandyCrushSagaFromKing = "Candy Crush Saga from King";
|
||||
private const string HelpCureHopeRaiseOnMindEntityChrome = "Help cure hope raise on mind entity Chrome";
|
||||
private const string UninstallOrChangeProgramsOnYourComputer = "Uninstall or change programs on your computer";
|
||||
private const string LastIsChrome = "Last is chrome";
|
||||
private const string OneOneOneOne = "1111";
|
||||
private const string MicrosoftSqlServerManagementStudio = "Microsoft SQL Server Management Studio";
|
||||
|
||||
public List<string> GetSearchStrings()
|
||||
=> new List<string>
|
||||
{
|
||||
"Chrome",
|
||||
Chrome,
|
||||
"Choose which programs you want Windows to use for activities like web browsing, editing photos, sending e-mail, and playing music.",
|
||||
"Help cure hope raise on mind entity Chrome ",
|
||||
"Candy Crush Saga from King",
|
||||
"Uninstall or change programs on your computer",
|
||||
HelpCureHopeRaiseOnMindEntityChrome,
|
||||
CandyCrushSagaFromKing,
|
||||
UninstallOrChangeProgramsOnYourComputer,
|
||||
"Add, change, and manage fonts on your computer",
|
||||
"Last is chrome",
|
||||
"1111"
|
||||
LastIsChrome,
|
||||
OneOneOneOne
|
||||
};
|
||||
|
||||
public List<int> GetPrecisionScores()
|
||||
|
|
@ -48,14 +56,14 @@ namespace Wox.Test
|
|||
"aac"
|
||||
};
|
||||
|
||||
|
||||
var results = new List<Result>();
|
||||
var matcher = new StringMatcher();
|
||||
foreach (var str in sources)
|
||||
{
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = str,
|
||||
Score = StringMatcher.FuzzySearch("inst", str).Score
|
||||
Score = matcher.FuzzyMatch("inst", str).RawScore
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -71,30 +79,30 @@ namespace Wox.Test
|
|||
public void WhenGivenNotAllCharactersFoundInSearchStringThenShouldReturnZeroScore(string searchString)
|
||||
{
|
||||
var compareString = "Can have rum only in my glass";
|
||||
|
||||
var scoreResult = StringMatcher.FuzzySearch(searchString, compareString).Score;
|
||||
var matcher = new StringMatcher();
|
||||
var scoreResult = matcher.FuzzyMatch(searchString, compareString).RawScore;
|
||||
|
||||
Assert.True(scoreResult == 0);
|
||||
}
|
||||
|
||||
|
||||
[TestCase("chr")]
|
||||
[TestCase("chrom")]
|
||||
[TestCase("chrome")]
|
||||
[TestCase("chrome")]
|
||||
[TestCase("cand")]
|
||||
[TestCase("cpywa")]
|
||||
[TestCase("ccs")]
|
||||
public void WhenGivenStringsAndAppliedPrecisionFilteringThenShouldReturnGreaterThanPrecisionScoreResults(string searchTerm)
|
||||
{
|
||||
var results = new List<Result>();
|
||||
|
||||
var matcher = new StringMatcher();
|
||||
foreach (var str in GetSearchStrings())
|
||||
{
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = str,
|
||||
Score = StringMatcher.FuzzySearch(searchTerm, str).Score
|
||||
Score = matcher.FuzzyMatch(searchTerm, str).Score
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var precisionScore in GetPrecisionScores())
|
||||
{
|
||||
|
|
@ -114,76 +122,104 @@ namespace Wox.Test
|
|||
}
|
||||
}
|
||||
|
||||
[TestCase("chrome")]
|
||||
public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring(string searchTerm)
|
||||
[TestCase(Chrome, Chrome, 137)]
|
||||
[TestCase(Chrome, LastIsChrome, 83)]
|
||||
[TestCase(Chrome, HelpCureHopeRaiseOnMindEntityChrome, 21)]
|
||||
[TestCase(Chrome, UninstallOrChangeProgramsOnYourComputer, 15)]
|
||||
[TestCase(Chrome, CandyCrushSagaFromKing, 0)]
|
||||
[TestCase("sql", MicrosoftSqlServerManagementStudio, 56)]
|
||||
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, 79)]//double spacing intended
|
||||
public void WhenGivenQueryStringThenShouldReturnCurrentScoring(string queryString, string compareString, int expectedScore)
|
||||
{
|
||||
var searchStrings = new List<string>
|
||||
{
|
||||
"Chrome",//SCORE: 107
|
||||
"Last is chrome",//SCORE: 53
|
||||
"Help cure hope raise on mind entity Chrome",//SCORE: 21
|
||||
"Uninstall or change programs on your computer", //SCORE: 15
|
||||
"Candy Crush Saga from King"//SCORE: 0
|
||||
}
|
||||
.OrderByDescending(x => x)
|
||||
.ToList();
|
||||
// When, Given
|
||||
var matcher = new StringMatcher();
|
||||
var rawScore = matcher.FuzzyMatch(queryString, compareString).RawScore;
|
||||
|
||||
var results = new List<Result>();
|
||||
|
||||
foreach (var str in searchStrings)
|
||||
{
|
||||
results.Add(new Result
|
||||
{
|
||||
Title = str,
|
||||
Score = StringMatcher.FuzzySearch(searchTerm, str).Score
|
||||
});
|
||||
}
|
||||
|
||||
var orderedResults = results.OrderByDescending(x => x.Title).ToList();
|
||||
|
||||
Debug.WriteLine("");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("SEARCHTERM: " + searchTerm);
|
||||
foreach (var item in orderedResults)
|
||||
{
|
||||
Debug.WriteLine("SCORE: " + item.Score.ToString() + ", FoundString: " + item.Title);
|
||||
}
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("");
|
||||
|
||||
Assert.IsTrue(orderedResults[0].Score == 15 && orderedResults[0].Title == searchStrings[0]);
|
||||
Assert.IsTrue(orderedResults[1].Score == 53 && orderedResults[1].Title == searchStrings[1]);
|
||||
Assert.IsTrue(orderedResults[2].Score == 21 && orderedResults[2].Title == searchStrings[2]);
|
||||
Assert.IsTrue(orderedResults[3].Score == 107 && orderedResults[3].Title == searchStrings[3]);
|
||||
Assert.IsTrue(orderedResults[4].Score == 0 && orderedResults[4].Title == searchStrings[4]);
|
||||
// Should
|
||||
Assert.AreEqual(expectedScore, rawScore, $"Expected score for compare string '{compareString}': {expectedScore}, Actual: {rawScore}");
|
||||
}
|
||||
|
||||
[TestCase("goo", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("chr", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Low, true)]
|
||||
[TestCase("chr", "Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("chr", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("chr", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Low, true)]
|
||||
[TestCase("chr", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("chr", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.None, true)]
|
||||
[TestCase("ccs", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Low, true)]
|
||||
[TestCase("cand", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("cand", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
public void WhenGivenDesiredPrecisionThenShouldReturnAllResultsGreaterOrEqual(string queryString, string compareString,
|
||||
int expectedPrecisionScore, bool expectedPrecisionResult)
|
||||
[TestCase("goo", "Google Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("chr", "Google Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
|
||||
[TestCase("chr", "Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
|
||||
[TestCase("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.None, true)]
|
||||
[TestCase("ccs", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Low, true)]
|
||||
[TestCase("cand", "Candy Crush Saga from King",StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("cand", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
public void WhenGivenDesiredPrecisionThenShouldReturnAllResultsGreaterOrEqual(
|
||||
string queryString,
|
||||
string compareString,
|
||||
StringMatcher.SearchPrecisionScore expectedPrecisionScore,
|
||||
bool expectedPrecisionResult)
|
||||
{
|
||||
var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
|
||||
StringMatcher.UserSettingSearchPrecision = expectedPrecisionString.ToString();
|
||||
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
|
||||
// When
|
||||
var matcher = new StringMatcher {UserSettingSearchPrecision = expectedPrecisionScore};
|
||||
|
||||
// Given
|
||||
var matchResult = matcher.FuzzyMatch(queryString, compareString);
|
||||
|
||||
Debug.WriteLine("");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine($"SearchTerm: {queryString} PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
|
||||
Debug.WriteLine($"SCORE: {matchResult.Score.ToString()}, ComparedString: {compareString}");
|
||||
Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
|
||||
Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionScore} ({(int)expectedPrecisionScore})");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("");
|
||||
|
||||
var matchPrecisionResult = matchResult.IsSearchPrecisionScoreMet();
|
||||
Assert.IsTrue(matchPrecisionResult == expectedPrecisionResult);
|
||||
// Should
|
||||
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
|
||||
$"Query:{queryString}{Environment.NewLine} " +
|
||||
$"Compare:{compareString}{Environment.NewLine}" +
|
||||
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
|
||||
$"Precision Score: {(int)expectedPrecisionScore}");
|
||||
}
|
||||
|
||||
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("term", "Windows Terminal (Preview)", StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sqlserv", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("sql servman", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("sql serv man", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("sql studio", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("mic", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("chr", "Shutdown", StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("mssms", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, false)]
|
||||
[TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("a test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
[TestCase("test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
|
||||
public void WhenGivenQueryShouldReturnResultsContainingAllQuerySubstrings(
|
||||
string queryString,
|
||||
string compareString,
|
||||
StringMatcher.SearchPrecisionScore expectedPrecisionScore,
|
||||
bool expectedPrecisionResult)
|
||||
{
|
||||
// When
|
||||
var matcher = new StringMatcher { UserSettingSearchPrecision = expectedPrecisionScore };
|
||||
|
||||
// Given
|
||||
var matchResult = matcher.FuzzyMatch(queryString, compareString);
|
||||
|
||||
Debug.WriteLine("");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
|
||||
Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionScore} ({(int)expectedPrecisionScore})");
|
||||
Debug.WriteLine("###############################################");
|
||||
Debug.WriteLine("");
|
||||
|
||||
// Should
|
||||
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
|
||||
$"Query:{queryString}{Environment.NewLine} " +
|
||||
$"Compare:{compareString}{Environment.NewLine}" +
|
||||
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
|
||||
$"Precision Score: {(int)expectedPrecisionScore}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\NUnit3TestAdapter.3.15.1\build\net35\NUnit3TestAdapter.props" Condition="Exists('..\packages\NUnit3TestAdapter.3.15.1\build\net35\NUnit3TestAdapter.props')" />
|
||||
<Import Project="..\packages\NUnit.3.12.0\build\NUnit.props" Condition="Exists('..\packages\NUnit.3.12.0\build\NUnit.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
|
|
@ -38,13 +36,6 @@
|
|||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Moq, Version=4.2.1409.1722, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=3.12.0.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
|
|
@ -77,16 +68,17 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<PackageReference Include="Moq">
|
||||
<Version>4.2.1409.1722</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit">
|
||||
<Version>3.12.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit3TestAdapter">
|
||||
<Version>3.15.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\NUnit.3.12.0\build\NUnit.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit.3.12.0\build\NUnit.props'))" />
|
||||
<Error Condition="!Exists('..\packages\NUnit3TestAdapter.3.15.1\build\net35\NUnit3TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NUnit3TestAdapter.3.15.1\build\net35\NUnit3TestAdapter.props'))" />
|
||||
</Target>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Moq" version="4.2.1409.1722" targetFramework="net452" />
|
||||
<package id="NUnit" version="3.12.0" targetFramework="net452" />
|
||||
<package id="NUnit3TestAdapter" version="3.15.1" targetFramework="net452" />
|
||||
</packages>
|
||||
|
|
@ -1,7 +1,19 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<!--https://msdn.microsoft.com/en-us/library/dd409252(v=vs.110).aspx-->
|
||||
<configSections>
|
||||
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="Wox.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<runtime>
|
||||
<loadFromRemoteSources enabled="true"/>
|
||||
</runtime>
|
||||
<applicationSettings>
|
||||
<Wox.Properties.Settings>
|
||||
<setting name="GithubRepo" serializeAs="String">
|
||||
<value>https://github.com/Wox-launcher/Wox</value>
|
||||
</setting>
|
||||
</Wox.Properties.Settings>
|
||||
</applicationSettings>
|
||||
</configuration>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
|
|
@ -25,6 +25,9 @@ namespace Wox
|
|||
private Settings _settings;
|
||||
private MainViewModel _mainVM;
|
||||
private SettingWindowViewModel _settingsVM;
|
||||
private readonly Updater _updater = new Updater(Wox.Properties.Settings.Default.GithubRepo);
|
||||
private readonly Alphabet _alphabet = new Alphabet();
|
||||
private StringMatcher _stringMatcher;
|
||||
|
||||
[STAThread]
|
||||
public static void Main()
|
||||
|
|
@ -50,17 +53,18 @@ namespace Wox
|
|||
|
||||
ImageLoader.Initialize();
|
||||
|
||||
_settingsVM = new SettingWindowViewModel();
|
||||
_settingsVM = new SettingWindowViewModel(_updater);
|
||||
_settings = _settingsVM.Settings;
|
||||
|
||||
Alphabet.Initialize(_settings);
|
||||
|
||||
StringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
|
||||
_alphabet.Initialize(_settings);
|
||||
_stringMatcher = new StringMatcher(_alphabet);
|
||||
StringMatcher.Instance = _stringMatcher;
|
||||
_stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
|
||||
|
||||
PluginManager.LoadPlugins(_settings.PluginSettings);
|
||||
_mainVM = new MainViewModel(_settings);
|
||||
var window = new MainWindow(_settings, _mainVM);
|
||||
API = new PublicAPIInstance(_settingsVM, _mainVM);
|
||||
API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet);
|
||||
PluginManager.InitializePlugins(API);
|
||||
Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}");
|
||||
|
||||
|
|
@ -110,12 +114,12 @@ namespace Wox
|
|||
var timer = new Timer(1000 * 60 * 60 * 5);
|
||||
timer.Elapsed += async (s, e) =>
|
||||
{
|
||||
await Updater.UpdateApp();
|
||||
await _updater.UpdateApp();
|
||||
};
|
||||
timer.Start();
|
||||
|
||||
// check updates on startup
|
||||
await Updater.UpdateApp();
|
||||
await _updater.UpdateApp();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -144,10 +148,6 @@ namespace Wox
|
|||
private static void RegisterAppDomainExceptions()
|
||||
{
|
||||
AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle;
|
||||
AppDomain.CurrentDomain.FirstChanceException += (_, e) =>
|
||||
{
|
||||
Log.Exception("|App.RegisterAppDomainExceptions|First Chance Exception:", e.Exception);
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -156,13 +156,7 @@ namespace Wox
|
|||
// but if sessionending is not called, exit won't be called when log off / shutdown
|
||||
if (!_disposed)
|
||||
{
|
||||
_mainVM.Save();
|
||||
_settingsVM.Save();
|
||||
|
||||
PluginManager.Save();
|
||||
ImageLoader.Save();
|
||||
Alphabet.Save();
|
||||
|
||||
API.SaveAppAllSettings();
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
Wox/Converters/HighlightTextConverter.cs
Normal file
53
Wox/Converters/HighlightTextConverter.cs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace Wox.Converters
|
||||
{
|
||||
public class HighlightTextConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] value, Type targetType, object parameter, CultureInfo cultureInfo)
|
||||
{
|
||||
var text = value[0] as string;
|
||||
var highlightData = value[1] as List<int>;
|
||||
|
||||
var textBlock = new Span();
|
||||
|
||||
if (highlightData == null || !highlightData.Any())
|
||||
{
|
||||
// No highlight data, just return the text
|
||||
return new Run(text);
|
||||
}
|
||||
|
||||
for (var i = 0; i < text.Length; i++)
|
||||
{
|
||||
var currentCharacter = text.Substring(i, 1);
|
||||
if (this.ShouldHighlight(highlightData, i))
|
||||
{
|
||||
textBlock.Inlines.Add(new Bold(new Run(currentCharacter)));
|
||||
}
|
||||
else
|
||||
{
|
||||
textBlock.Inlines.Add(new Run(currentCharacter));
|
||||
}
|
||||
}
|
||||
return textBlock;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return new[] { DependencyProperty.UnsetValue, DependencyProperty.UnsetValue };
|
||||
}
|
||||
|
||||
private bool ShouldHighlight(List<int> highlightData, int index)
|
||||
{
|
||||
return highlightData.Contains(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -87,4 +87,4 @@
|
|||
</ContentControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Window>
|
||||
</Window>
|
||||
|
|
|
|||
11
Wox/Properties/Settings.Designer.cs
generated
11
Wox/Properties/Settings.Designer.cs
generated
|
|
@ -12,7 +12,7 @@ namespace Wox.Properties {
|
|||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
|
@ -22,5 +22,14 @@ namespace Wox.Properties {
|
|||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("https://github.com/Wox-launcher/Wox")]
|
||||
public string GithubRepo {
|
||||
get {
|
||||
return ((string)(this["GithubRepo"]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:_settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Wox.Properties" GeneratedClassName="Settings">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="GithubRepo" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">https://github.com/Wox-launcher/Wox</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
|
|
@ -20,16 +20,17 @@ namespace Wox
|
|||
{
|
||||
private readonly SettingWindowViewModel _settingsVM;
|
||||
private readonly MainViewModel _mainVM;
|
||||
private readonly Alphabet _alphabet;
|
||||
|
||||
#region Constructor
|
||||
|
||||
public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM)
|
||||
public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, Alphabet alphabet)
|
||||
{
|
||||
_settingsVM = settingsVM;
|
||||
_mainVM = mainVM;
|
||||
_alphabet = alphabet;
|
||||
GlobalHotkey.Instance.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
||||
WebRequest.RegisterPrefix("data", new DataWebRequestFactory());
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
@ -70,7 +71,7 @@ namespace Wox
|
|||
_settingsVM.Save();
|
||||
PluginManager.Save();
|
||||
ImageLoader.Save();
|
||||
Alphabet.Save();
|
||||
_alphabet.Save();
|
||||
}
|
||||
|
||||
public void ReloadAllPluginData()
|
||||
|
|
@ -90,12 +91,12 @@ namespace Wox
|
|||
_mainVM.MainWindowVisibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
public void ShowMsg(string title, string subTitle = "", string iconPath = "")
|
||||
public void ShowMsg(string title, string subTitle = "", string iconPath = "", bool useMainWindowAsOwner = true)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
var m = new Msg { Owner = Application.Current.MainWindow };
|
||||
m.Show(title, subTitle, iconPath);
|
||||
var msg = useMainWindowAsOwner ? new Msg {Owner = Application.Current.MainWindow} : new Msg();
|
||||
msg.Show(title, subTitle, iconPath);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Wox
|
|||
|
||||
private void SetException(Exception exception)
|
||||
{
|
||||
string path = Path.Combine(Constant.DataDirectory, Log.DirectoryName, Constant.Version);
|
||||
string path = Log.CurrentLogDirectory;
|
||||
var directory = new DirectoryInfo(path);
|
||||
var log = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:vm="clr-namespace:Wox.ViewModel"
|
||||
xmlns:converter="clr-namespace:Wox.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="100" d:DesignHeight="100"
|
||||
d:DataContext="{d:DesignInstance vm:ResultsViewModel}"
|
||||
MaxHeight="{Binding MaxHeight}"
|
||||
|
|
@ -30,6 +31,9 @@
|
|||
<Button.Content>
|
||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5"
|
||||
Cursor="Hand" UseLayoutRounding="False">
|
||||
<Grid.Resources>
|
||||
<converter:HighlightTextConverter x:Key="HighlightTextConverter"/>
|
||||
</Grid.Resources>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition />
|
||||
|
|
@ -44,9 +48,23 @@
|
|||
</Grid.RowDefinitions>
|
||||
<TextBlock Style="{DynamicResource ItemTitleStyle}" DockPanel.Dock="Left"
|
||||
VerticalAlignment="Center" ToolTip="{Binding Result.Title}" x:Name="Title"
|
||||
Text="{Binding Result.Title}" />
|
||||
Text="{Binding Result.Title}">
|
||||
<vm:ResultsViewModel.FormattedText>
|
||||
<MultiBinding Converter="{StaticResource HighlightTextConverter}">
|
||||
<Binding Path="Result.Title" />
|
||||
<Binding Path="Result.TitleHighlightData" />
|
||||
</MultiBinding>
|
||||
</vm:ResultsViewModel.FormattedText>
|
||||
</TextBlock>
|
||||
<TextBlock Style="{DynamicResource ItemSubTitleStyle}" ToolTip="{Binding Result.SubTitle}"
|
||||
Grid.Row="1" x:Name="SubTitle" Text="{Binding Result.SubTitle}" />
|
||||
Grid.Row="1" x:Name="SubTitle" Text="{Binding Result.SubTitle}">
|
||||
<vm:ResultsViewModel.FormattedText>
|
||||
<MultiBinding Converter="{StaticResource HighlightTextConverter}">
|
||||
<Binding Path="Result.SubTitle" />
|
||||
<Binding Path="Result.SubTitleHighlightData" />
|
||||
</MultiBinding>
|
||||
</vm:ResultsViewModel.FormattedText>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Button.Content>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
<TextBlock Text="{DynamicResource querySearchPrecision}" />
|
||||
<ComboBox Margin="10 0 0 0" Width="120"
|
||||
ItemsSource="{Binding QuerySearchPrecisionStrings}"
|
||||
SelectedItem="{Binding Settings.QuerySearchPrecision}" />
|
||||
SelectedItem="{Binding Settings.QuerySearchPrecisionString}" />
|
||||
</StackPanel>
|
||||
<StackPanel Margin="10" Orientation="Horizontal">
|
||||
<TextBlock Text="{DynamicResource lastQueryMode}" />
|
||||
|
|
|
|||
|
|
@ -260,53 +260,16 @@ namespace Wox
|
|||
#region Proxy
|
||||
|
||||
private void OnTestProxyClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_settings.Proxy.Server))
|
||||
{
|
||||
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("serverCantBeEmpty"));
|
||||
return;
|
||||
}
|
||||
if (_settings.Proxy.Port <= 0)
|
||||
{
|
||||
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("portCantBeEmpty"));
|
||||
return;
|
||||
}
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Infrastructure.Constant.Repository);
|
||||
if (string.IsNullOrEmpty(_settings.Proxy.UserName) || string.IsNullOrEmpty(_settings.Proxy.Password))
|
||||
{
|
||||
request.Proxy = new WebProxy(_settings.Proxy.Server, _settings.Proxy.Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Proxy = new WebProxy(_settings.Proxy.Server, _settings.Proxy.Port)
|
||||
{
|
||||
Credentials = new NetworkCredential(_settings.Proxy.UserName, _settings.Proxy.Password)
|
||||
};
|
||||
}
|
||||
try
|
||||
{
|
||||
var response = (HttpWebResponse)request.GetResponse();
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("proxyIsCorrect"));
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("proxyConnectFailed"));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("proxyConnectFailed"));
|
||||
}
|
||||
{ // TODO: change to command
|
||||
var msg = _viewModel.TestProxy();
|
||||
MessageBox.Show(msg); // TODO: add message box service
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async void OnCheckUpdates(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await Updater.UpdateApp();
|
||||
_viewModel.UpdateApp(); // TODO: change to command
|
||||
}
|
||||
|
||||
private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
|
||||
|
|
|
|||
28
Wox/Settings.cs
Normal file
28
Wox/Settings.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
namespace Wox.Properties {
|
||||
|
||||
|
||||
// This class allows you to handle specific events on the settings class:
|
||||
// The SettingChanging event is raised before a setting's value is changed.
|
||||
// The PropertyChanged event is raised after a setting's value is changed.
|
||||
// The SettingsLoaded event is raised after the setting values are loaded.
|
||||
// The SettingsSaving event is raised before the setting values are saved.
|
||||
internal sealed partial class Settings {
|
||||
|
||||
public Settings() {
|
||||
// // To add event handlers for saving and changing settings, uncomment the lines below:
|
||||
//
|
||||
// this.SettingChanging += this.SettingChangingEventHandler;
|
||||
//
|
||||
// this.SettingsSaving += this.SettingsSavingEventHandler;
|
||||
//
|
||||
}
|
||||
|
||||
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
|
||||
// Add code to handle the SettingChangingEvent event here.
|
||||
}
|
||||
|
||||
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
|
||||
// Add code to handle the SettingsSaving event here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ using Wox.Core.Resource;
|
|||
using Wox.Helper;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Hotkey;
|
||||
using Wox.Infrastructure.Image;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
using Wox.Plugin;
|
||||
|
|
@ -25,7 +24,7 @@ namespace Wox.ViewModel
|
|||
{
|
||||
#region Private Fields
|
||||
|
||||
private bool _queryHasReturn;
|
||||
private bool _isQueryRunning;
|
||||
private Query _lastQuery;
|
||||
private string _queryTextBeforeLeaveResults;
|
||||
|
||||
|
|
@ -41,7 +40,7 @@ namespace Wox.ViewModel
|
|||
private CancellationToken _updateToken;
|
||||
private bool _saved;
|
||||
|
||||
private Internationalization _translator = InternationalizationManager.Instance;
|
||||
private readonly Internationalization _translator = InternationalizationManager.Instance;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
@ -312,7 +311,7 @@ namespace Wox.ViewModel
|
|||
{
|
||||
var filtered = results.Where
|
||||
(
|
||||
r => StringMatcher.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet()
|
||||
r => StringMatcher.FuzzySearch(query, r.Title).IsSearchPrecisionScoreMet()
|
||||
|| StringMatcher.FuzzySearch(query, r.SubTitle).IsSearchPrecisionScoreMet()
|
||||
).ToList();
|
||||
ContextMenu.AddResults(filtered, id);
|
||||
|
|
@ -371,63 +370,59 @@ namespace Wox.ViewModel
|
|||
if (!string.IsNullOrEmpty(QueryText))
|
||||
{
|
||||
_updateSource?.Cancel();
|
||||
_updateSource = new CancellationTokenSource();
|
||||
_updateToken = _updateSource.Token;
|
||||
var currentUpdateSource = new CancellationTokenSource();
|
||||
_updateSource = currentUpdateSource;
|
||||
var currentCancellationToken = _updateSource.Token;
|
||||
_updateToken = currentCancellationToken;
|
||||
|
||||
ProgressBarVisibility = Visibility.Hidden;
|
||||
_queryHasReturn = false;
|
||||
_isQueryRunning = true;
|
||||
var query = PluginManager.QueryInit(QueryText.Trim());
|
||||
if (query != null)
|
||||
{
|
||||
// handle the exclusiveness of plugin using action keyword
|
||||
string lastKeyword = _lastQuery.ActionKeyword;
|
||||
string keyword = query.ActionKeyword;
|
||||
if (string.IsNullOrEmpty(lastKeyword))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(keyword))
|
||||
{
|
||||
Results.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyword))
|
||||
{
|
||||
Results.RemoveResultsFor(PluginManager.NonGlobalPlugins[lastKeyword].Metadata);
|
||||
}
|
||||
else if (lastKeyword != keyword)
|
||||
{
|
||||
Results.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata);
|
||||
}
|
||||
}
|
||||
RemoveOldQueryResults(query);
|
||||
|
||||
_lastQuery = query;
|
||||
Task.Delay(200, _updateToken).ContinueWith(_ =>
|
||||
{
|
||||
if (query.RawQuery == _lastQuery.RawQuery && !_queryHasReturn)
|
||||
Task.Delay(200, currentCancellationToken).ContinueWith(_ =>
|
||||
{ // start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet
|
||||
if (currentUpdateSource == _updateSource && _isQueryRunning)
|
||||
{
|
||||
ProgressBarVisibility = Visibility.Visible;
|
||||
}
|
||||
}, _updateToken);
|
||||
}, currentCancellationToken);
|
||||
|
||||
var plugins = PluginManager.ValidPluginsForQuery(query);
|
||||
Task.Run(() =>
|
||||
{
|
||||
Parallel.ForEach(plugins, plugin =>
|
||||
// so looping will stop once it was cancelled
|
||||
var parallelOptions = new ParallelOptions { CancellationToken = currentCancellationToken };
|
||||
try
|
||||
{
|
||||
var config = _settings.PluginSettings.Plugins[plugin.Metadata.ID];
|
||||
if (!config.Disabled)
|
||||
Parallel.ForEach(plugins, parallelOptions, plugin =>
|
||||
{
|
||||
var results = PluginManager.QueryForPlugin(plugin, query);
|
||||
UpdateResultView(results, plugin.Metadata, query);
|
||||
}
|
||||
});
|
||||
var config = _settings.PluginSettings.Plugins[plugin.Metadata.ID];
|
||||
if (!config.Disabled)
|
||||
{
|
||||
var results = PluginManager.QueryForPlugin(plugin, query);
|
||||
UpdateResultView(results, plugin.Metadata, query);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
|
||||
// this should happen once after all queries are done so progress bar should continue
|
||||
// until the end of all querying
|
||||
_queryHasReturn = true;
|
||||
ProgressBarVisibility = Visibility.Hidden;
|
||||
}, _updateToken);
|
||||
_isQueryRunning = false;
|
||||
if (currentUpdateSource == _updateSource)
|
||||
{ // update to hidden if this is still the current query
|
||||
ProgressBarVisibility = Visibility.Hidden;
|
||||
}
|
||||
}, currentCancellationToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -437,6 +432,30 @@ namespace Wox.ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
private void RemoveOldQueryResults(Query query)
|
||||
{
|
||||
string lastKeyword = _lastQuery.ActionKeyword;
|
||||
string keyword = query.ActionKeyword;
|
||||
if (string.IsNullOrEmpty(lastKeyword))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(keyword))
|
||||
{
|
||||
Results.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyword))
|
||||
{
|
||||
Results.RemoveResultsFor(PluginManager.NonGlobalPlugins[lastKeyword].Metadata);
|
||||
}
|
||||
else if (lastKeyword != keyword)
|
||||
{
|
||||
Results.RemoveResultsExcept(PluginManager.NonGlobalPlugins[keyword].Metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Result ContextMenuTopMost(Result result)
|
||||
{
|
||||
|
|
@ -660,4 +679,4 @@ namespace Wox.ViewModel
|
|||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ namespace Wox.ViewModel
|
|||
{
|
||||
public class RelayCommand : ICommand
|
||||
{
|
||||
|
||||
private Action<object> _action;
|
||||
|
||||
public RelayCommand(Action<object> action)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ using System.Collections.Generic;
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
using Wox.Plugin;
|
||||
|
||||
|
|
@ -154,14 +156,14 @@ namespace Wox.ViewModel
|
|||
private List<ResultViewModel> NewResults(List<Result> newRawResults, string resultId)
|
||||
{
|
||||
var results = Results.ToList();
|
||||
var newResults = newRawResults.Select(r => new ResultViewModel(r)).ToList();
|
||||
var newResults = newRawResults.Select(r => new ResultViewModel(r)).ToList();
|
||||
var oldResults = results.Where(r => r.Result.PluginID == resultId).ToList();
|
||||
|
||||
// Find the same results in A (old results) and B (new newResults)
|
||||
var sameResults = oldResults
|
||||
.Where(t1 => newResults.Any(x => x.Result.Equals(t1.Result)))
|
||||
.ToList();
|
||||
|
||||
|
||||
// remove result of relative complement of B in A
|
||||
foreach (var result in oldResults.Except(sameResults))
|
||||
{
|
||||
|
|
@ -197,8 +199,37 @@ namespace Wox.ViewModel
|
|||
|
||||
return results;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FormattedText Dependency Property
|
||||
public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
|
||||
"FormattedText",
|
||||
typeof(Inline),
|
||||
typeof(ResultsViewModel),
|
||||
new PropertyMetadata(null, FormattedTextPropertyChanged));
|
||||
|
||||
public static void SetFormattedText(DependencyObject textBlock, IList<int> value)
|
||||
{
|
||||
textBlock.SetValue(FormattedTextProperty, value);
|
||||
}
|
||||
|
||||
public static Inline GetFormattedText(DependencyObject textBlock)
|
||||
{
|
||||
return (Inline)textBlock.GetValue(FormattedTextProperty);
|
||||
}
|
||||
|
||||
private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var textBlock = d as TextBlock;
|
||||
if (textBlock == null) return;
|
||||
|
||||
var inline = (Inline)e.NewValue;
|
||||
|
||||
textBlock.Inlines.Clear();
|
||||
if (inline == null) return;
|
||||
|
||||
textBlock.Inlines.Add(inline);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public class ResultCollection : ObservableCollection<ResultViewModel>
|
||||
|
|
@ -217,6 +248,10 @@ namespace Wox.ViewModel
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the results collection with new results, try to keep identical results
|
||||
/// </summary>
|
||||
/// <param name="newItems"></param>
|
||||
public void Update(List<ResultViewModel> newItems)
|
||||
{
|
||||
int newCount = newItems.Count;
|
||||
|
|
@ -228,7 +263,7 @@ namespace Wox.ViewModel
|
|||
ResultViewModel oldResult = this[i];
|
||||
ResultViewModel newResult = newItems[i];
|
||||
if (!oldResult.Equals(newResult))
|
||||
{
|
||||
{ // result is not the same update it in the current index
|
||||
this[i] = newResult;
|
||||
}
|
||||
else if (oldResult.Result.Score != newResult.Result.Score)
|
||||
|
|
@ -255,4 +290,4 @@ namespace Wox.ViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
|
@ -20,10 +21,12 @@ namespace Wox.ViewModel
|
|||
{
|
||||
public class SettingWindowViewModel : BaseModel
|
||||
{
|
||||
private readonly Updater _updater;
|
||||
private readonly WoxJsonStorage<Settings> _storage;
|
||||
|
||||
public SettingWindowViewModel()
|
||||
public SettingWindowViewModel(Updater updater)
|
||||
{
|
||||
_updater = updater;
|
||||
_storage = new WoxJsonStorage<Settings>();
|
||||
Settings = _storage.Load();
|
||||
Settings.PropertyChanged += (s, e) =>
|
||||
|
|
@ -39,6 +42,10 @@ namespace Wox.ViewModel
|
|||
|
||||
public Settings Settings { get; set; }
|
||||
|
||||
public async void UpdateApp()
|
||||
{
|
||||
await _updater.UpdateApp();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
|
|
@ -73,7 +80,7 @@ namespace Wox.ViewModel
|
|||
public List<string> QuerySearchPrecisionStrings
|
||||
{
|
||||
get
|
||||
{
|
||||
{
|
||||
var precisionStrings = new List<string>();
|
||||
|
||||
var enumList = Enum.GetValues(typeof(StringMatcher.SearchPrecisionScore)).Cast<StringMatcher.SearchPrecisionScore>().ToList();
|
||||
|
|
@ -88,6 +95,50 @@ namespace Wox.ViewModel
|
|||
public List<Language> Languages => _translater.LoadAvailableLanguages();
|
||||
public IEnumerable<int> MaxResultsRange => Enumerable.Range(2, 16);
|
||||
|
||||
public string TestProxy()
|
||||
{
|
||||
var proxyServer = Settings.Proxy.Server;
|
||||
var proxyUserName = Settings.Proxy.UserName;
|
||||
if (string.IsNullOrEmpty(proxyServer))
|
||||
{
|
||||
return InternationalizationManager.Instance.GetTranslation("serverCantBeEmpty");
|
||||
}
|
||||
if (Settings.Proxy.Port <= 0)
|
||||
{
|
||||
return InternationalizationManager.Instance.GetTranslation("portCantBeEmpty");
|
||||
}
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_updater.GitHubRepository);
|
||||
|
||||
if (string.IsNullOrEmpty(proxyUserName) || string.IsNullOrEmpty(Settings.Proxy.Password))
|
||||
{
|
||||
request.Proxy = new WebProxy(proxyServer, Settings.Proxy.Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Proxy = new WebProxy(proxyServer, Settings.Proxy.Port)
|
||||
{
|
||||
Credentials = new NetworkCredential(proxyUserName, Settings.Proxy.Password)
|
||||
};
|
||||
}
|
||||
try
|
||||
{
|
||||
var response = (HttpWebResponse)request.GetResponse();
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
return InternationalizationManager.Instance.GetTranslation("proxyIsCorrect");
|
||||
}
|
||||
else
|
||||
{
|
||||
return InternationalizationManager.Instance.GetTranslation("proxyConnectFailed");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return InternationalizationManager.Instance.GetTranslation("proxyConnectFailed");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region plugin
|
||||
|
|
@ -220,7 +271,7 @@ namespace Wox.ViewModel
|
|||
},
|
||||
new Result
|
||||
{
|
||||
Title = $"Open Source: {Constant.Repository}",
|
||||
Title = $"Open Source: {_updater.GitHubRepository}",
|
||||
SubTitle = "Please star it!"
|
||||
}
|
||||
};
|
||||
|
|
@ -330,8 +381,8 @@ namespace Wox.ViewModel
|
|||
|
||||
#region about
|
||||
|
||||
public static string Github => Constant.Repository;
|
||||
public static string ReleaseNotes => @"https://github.com/Wox-launcher/Wox/releases/latest";
|
||||
public string Github => _updater.GitHubRepository;
|
||||
public string ReleaseNotes => _updater.GitHubRepository + @"/releases/latest";
|
||||
public static string Version => Constant.Version;
|
||||
public string ActivatedTimes => string.Format(_translater.GetTranslation("about_activate_times"), Settings.ActivateTimes);
|
||||
#endregion
|
||||
|
|
|
|||
119
Wox/Wox.csproj
119
Wox/Wox.csproj
|
|
@ -65,72 +65,8 @@
|
|||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="DeltaCompressionDotNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1d14d6e5194e7f4a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="DeltaCompressionDotNet.MsDelta, Version=1.0.0.0, Culture=neutral, PublicKeyToken=46b2138a390abf55, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.MsDelta.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="DeltaCompressionDotNet.PatchApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3e8888ee913ed789, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.PatchApi.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\squirrel.windows.1.4.0\lib\Net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mono.Cecil.0.9.6.1\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHotkey, Version=1.2.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NHotkey.1.2.1\lib\net20\NHotkey.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NHotkey.Wpf, Version=1.2.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NHotkey.Wpf.1.2.1\lib\net35\NHotkey.Wpf.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.2.0\lib\net45\NLog.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NuGet.Squirrel, Version=3.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\squirrel.windows.1.4.0\lib\Net45\NuGet.Squirrel.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="PropertyChanged, Version=1.51.0.0, Culture=neutral, PublicKeyToken=ee3ee20bcf148ddd, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\PropertyChanged.Fody.1.51.0\lib\dotnet\PropertyChanged.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="ReachFramework" />
|
||||
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Squirrel, Version=1.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\squirrel.windows.1.5.2\lib\Net45\Squirrel.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data" />
|
||||
|
|
@ -149,21 +85,19 @@
|
|||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="WindowsInput, Version=1.0.4.0, Culture=neutral, PublicKeyToken=9b287f7dc5073cad, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\InputSimulator.1.0.4.0\lib\net20\WindowsInput.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\SolutionAssemblyInfo.cs">
|
||||
<Link>Properties\SolutionAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Converters\HighlightTextConverter.cs" />
|
||||
<Compile Include="Helper\SingletonWindowOpener.cs" />
|
||||
<Compile Include="PublicAPIInstance.cs" />
|
||||
<Compile Include="ReportWindow.xaml.cs" />
|
||||
<Compile Include="ResultListBox.xaml.cs">
|
||||
<DependentUpon>ResultListBox.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="Storage\HistoryItem.cs" />
|
||||
<Compile Include="Storage\QueryHistory.cs" />
|
||||
<Compile Include="Storage\TopMostRecord.cs" />
|
||||
|
|
@ -346,9 +280,6 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Themes\Light.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
|
@ -469,7 +400,44 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Resource>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Fody">
|
||||
<Version>1.29.2</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="InputSimulator">
|
||||
<Version>1.0.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="JetBrains.Annotations">
|
||||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>9.0.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NHotkey.Wpf">
|
||||
<Version>1.2.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NLog">
|
||||
<Version>4.2.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NuGet.CommandLine">
|
||||
<Version>3.4.3</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="PropertyChanged.Fody">
|
||||
<Version>1.51.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="squirrel.windows">
|
||||
<Version>1.5.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>powershell.exe -NoProfile -ExecutionPolicy Bypass -File $(SolutionDir)Scripts\post_build.ps1 $(ConfigurationName) $(SolutionDir)</PostBuildEvent>
|
||||
|
|
@ -484,11 +452,4 @@
|
|||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
<Import Project="..\packages\Fody.1.29.2\build\dotnet\Fody.targets" Condition="Exists('..\packages\Fody.1.29.2\build\dotnet\Fody.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Fody.1.29.2\build\dotnet\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.1.29.2\build\dotnet\Fody.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="DeltaCompressionDotNet" version="1.0.0" targetFramework="net452" />
|
||||
<package id="Fody" version="1.29.2" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="InputSimulator" version="1.0.4.0" targetFramework="net452" />
|
||||
<package id="JetBrains.Annotations" version="10.3.0" targetFramework="net452" />
|
||||
<package id="Mono.Cecil" version="0.9.6.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||
<package id="NHotkey" version="1.2.1" targetFramework="net452" />
|
||||
<package id="NHotkey.Wpf" version="1.2.1" targetFramework="net452" />
|
||||
<package id="NLog" version="4.2.0" targetFramework="net452" />
|
||||
<package id="NuGet.CommandLine" version="3.4.3" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="PropertyChanged.Fody" version="1.51.0" targetFramework="net452" developmentDependency="true" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net452" />
|
||||
<package id="Splat" version="1.6.2" targetFramework="net452" />
|
||||
<package id="squirrel.windows" version="1.5.2" targetFramework="net452" />
|
||||
<package id="System.Runtime" version="4.0.0" targetFramework="net452" />
|
||||
</packages>
|
||||
34
azure-pipelines.yml
Normal file
34
azure-pipelines.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# .NET Desktop
|
||||
# Build and run tests for .NET Desktop or Windows classic desktop solutions.
|
||||
# Add steps that publish symbols, save build artifacts, and more:
|
||||
# https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net
|
||||
|
||||
trigger:
|
||||
- master
|
||||
- dev
|
||||
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016' #'due to windows SDK dependency for building UWP project'
|
||||
|
||||
variables:
|
||||
solution: '**/*.sln'
|
||||
buildPlatform: 'Any CPU'
|
||||
buildConfiguration: 'Release'
|
||||
|
||||
steps:
|
||||
- task: NuGetToolInstaller@1
|
||||
|
||||
- task: NuGetCommand@2
|
||||
inputs:
|
||||
restoreSolution: '$(solution)'
|
||||
|
||||
- task: VSBuild@1
|
||||
inputs:
|
||||
solution: '$(solution)'
|
||||
platform: '$(buildPlatform)'
|
||||
configuration: '$(buildConfiguration)'
|
||||
|
||||
- task: VSTest@2
|
||||
inputs:
|
||||
platform: '$(buildPlatform)'
|
||||
configuration: '$(buildConfiguration)'
|
||||
Loading…
Reference in a new issue