mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into add_enable_portablemode_setting
This commit is contained in:
commit
dbc52f56c8
36 changed files with 714 additions and 164 deletions
24
Plugins/Wox.Plugin.Calculator/DecimalSeparator.cs
Normal file
24
Plugins/Wox.Plugin.Calculator/DecimalSeparator.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Wox.Core;
|
||||
|
||||
namespace Wox.Plugin.Caculator
|
||||
{
|
||||
[TypeConverter(typeof(LocalizationConverter))]
|
||||
public enum DecimalSeparator
|
||||
{
|
||||
[LocalizedDescription("wox_plugin_calculator_decimal_seperator_use_system_locale")]
|
||||
UseSystemLocale,
|
||||
|
||||
[LocalizedDescription("wox_plugin_calculator_decimal_seperator_dot")]
|
||||
Dot,
|
||||
|
||||
[LocalizedDescription("wox_plugin_calculator_decimal_seperator_comma")]
|
||||
Comma
|
||||
}
|
||||
}
|
||||
|
|
@ -7,4 +7,10 @@
|
|||
<system:String x:Key="wox_plugin_calculator_not_a_number">Keine Zahl (NaN)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_expression_not_complete">Ausdruck falsch oder nicht vollständig (Klammern vergessen?)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_copy_number_to_clipboard">Diese Zahl in die Zwischenablage kopieren</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_output_decimal_seperator">Dezimaltrennzeichen</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_output_decimal_seperator_help">Das Dezimaltrennzeichen, welches bei der Ausgabe verwendet werden soll.</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_decimal_seperator_use_system_locale">Systemeinstellung nutzen</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_decimal_seperator_comma">Komma (,)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_decimal_seperator_dot">Punkt (.)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_max_decimal_places">Max. Nachkommastellen</system:String>
|
||||
</ResourceDictionary>
|
||||
|
|
@ -7,4 +7,10 @@
|
|||
<system:String x:Key="wox_plugin_calculator_not_a_number">Not a number (NaN)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_expression_not_complete">Expression wrong or incomplete (Did you forget some parentheses?)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_copy_number_to_clipboard">Copy this number to the clipboard</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_output_decimal_seperator">Decimal separator</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_output_decimal_seperator_help">The decimal separator to be used in the output.</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_decimal_seperator_use_system_locale">Use system locale</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_decimal_seperator_comma">Comma (,)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_decimal_seperator_dot">Dot (.)</system:String>
|
||||
<system:String x:Key="wox_plugin_calculator_max_decimal_places">Max. decimal places</system:String>
|
||||
</ResourceDictionary>
|
||||
|
|
@ -1,12 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using Mages.Core;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Plugin.Caculator.ViewModels;
|
||||
using Wox.Plugin.Caculator.Views;
|
||||
|
||||
namespace Wox.Plugin.Caculator
|
||||
{
|
||||
public class Main : IPlugin, IPluginI18n
|
||||
public class Main : IPlugin, IPluginI18n, ISavable, ISettingProvider
|
||||
{
|
||||
private static readonly Regex RegValidExpressChar = new Regex(
|
||||
@"^(" +
|
||||
|
|
@ -21,20 +27,33 @@ namespace Wox.Plugin.Caculator
|
|||
private static readonly Engine MagesEngine;
|
||||
private PluginInitContext Context { get; set; }
|
||||
|
||||
private static Settings _settings;
|
||||
private static SettingsViewModel _viewModel;
|
||||
|
||||
static Main()
|
||||
{
|
||||
MagesEngine = new Engine();
|
||||
MagesEngine = new Engine();
|
||||
}
|
||||
|
||||
public void Init(PluginInitContext context)
|
||||
{
|
||||
Context = context;
|
||||
|
||||
_viewModel = new SettingsViewModel();
|
||||
_settings = _viewModel.Settings;
|
||||
}
|
||||
|
||||
public List<Result> Query(Query query)
|
||||
{
|
||||
if (query.Search.Length <= 2 // don't affect when user only input "e" or "i" keyword
|
||||
|| !RegValidExpressChar.IsMatch(query.Search)
|
||||
|| !IsBracketComplete(query.Search)) return new List<Result>();
|
||||
if (!CanCalculate(query))
|
||||
{
|
||||
return new List<Result>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var result = MagesEngine.Interpret(query.Search);
|
||||
var expression = query.Search.Replace(",", ".");
|
||||
var result = MagesEngine.Interpret(expression);
|
||||
|
||||
if (result.ToString() == "NaN")
|
||||
result = Context.API.GetTranslation("wox_plugin_calculator_not_a_number");
|
||||
|
|
@ -42,14 +61,16 @@ namespace Wox.Plugin.Caculator
|
|||
if (result is Function)
|
||||
result = Context.API.GetTranslation("wox_plugin_calculator_expression_not_complete");
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(result?.ToString()))
|
||||
{
|
||||
decimal roundedResult = Math.Round(Convert.ToDecimal(result), _settings.MaxDecimalPlaces, MidpointRounding.AwayFromZero);
|
||||
string newResult = ChangeDecimalSeparator(roundedResult, GetDecimalSeparator());
|
||||
|
||||
return new List<Result>
|
||||
{
|
||||
new Result
|
||||
{
|
||||
Title = result.ToString(),
|
||||
Title = newResult,
|
||||
IcoPath = "Images/calculator.png",
|
||||
Score = 300,
|
||||
SubTitle = Context.API.GetTranslation("wox_plugin_calculator_copy_number_to_clipboard"),
|
||||
|
|
@ -57,7 +78,7 @@ namespace Wox.Plugin.Caculator
|
|||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(result.ToString());
|
||||
Clipboard.SetText(newResult);
|
||||
return true;
|
||||
}
|
||||
catch (ExternalException)
|
||||
|
|
@ -78,6 +99,53 @@ namespace Wox.Plugin.Caculator
|
|||
return new List<Result>();
|
||||
}
|
||||
|
||||
private bool CanCalculate(Query query)
|
||||
{
|
||||
// Don't execute when user only input "e" or "i" keyword
|
||||
if (query.Search.Length < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RegValidExpressChar.IsMatch(query.Search))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsBracketComplete(query.Search))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private string ChangeDecimalSeparator(decimal value, string newDecimalSeparator)
|
||||
{
|
||||
if (String.IsNullOrEmpty(newDecimalSeparator))
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
var numberFormatInfo = new NumberFormatInfo
|
||||
{
|
||||
NumberDecimalSeparator = newDecimalSeparator
|
||||
};
|
||||
return value.ToString(numberFormatInfo);
|
||||
}
|
||||
|
||||
private string GetDecimalSeparator()
|
||||
{
|
||||
string systemDecimalSeperator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
||||
switch (_settings.DecimalSeparator)
|
||||
{
|
||||
case DecimalSeparator.UseSystemLocale: return systemDecimalSeperator;
|
||||
case DecimalSeparator.Dot: return ".";
|
||||
case DecimalSeparator.Comma: return ",";
|
||||
default: return systemDecimalSeperator;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsBracketComplete(string query)
|
||||
{
|
||||
var matchs = RegBrackets.Matches(query);
|
||||
|
|
@ -96,12 +164,7 @@ namespace Wox.Plugin.Caculator
|
|||
|
||||
return leftBracketCount == 0;
|
||||
}
|
||||
|
||||
public void Init(PluginInitContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
{
|
||||
return Context.API.GetTranslation("wox_plugin_caculator_plugin_name");
|
||||
|
|
@ -111,5 +174,15 @@ namespace Wox.Plugin.Caculator
|
|||
{
|
||||
return Context.API.GetTranslation("wox_plugin_caculator_plugin_description");
|
||||
}
|
||||
|
||||
public Control CreateSettingPanel()
|
||||
{
|
||||
return new CalculatorSettings(_viewModel);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_viewModel.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
Plugins/Wox.Plugin.Calculator/Settings.cs
Normal file
14
Plugins/Wox.Plugin.Calculator/Settings.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wox.Plugin.Caculator
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
public DecimalSeparator DecimalSeparator { get; set; } = DecimalSeparator.UseSystemLocale;
|
||||
public int MaxDecimalPlaces { get; set; } = 10;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Wox.Infrastructure.Storage;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
|
||||
namespace Wox.Plugin.Caculator.ViewModels
|
||||
{
|
||||
public class SettingsViewModel : BaseModel, ISavable
|
||||
{
|
||||
private readonly PluginJsonStorage<Settings> _storage;
|
||||
|
||||
public SettingsViewModel()
|
||||
{
|
||||
_storage = new PluginJsonStorage<Settings>();
|
||||
Settings = _storage.Load();
|
||||
}
|
||||
|
||||
public Settings Settings { get; set; }
|
||||
|
||||
public IEnumerable<int> MaxDecimalPlacesRange => Enumerable.Range(1, 20);
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_storage.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
56
Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml
Normal file
56
Plugins/Wox.Plugin.Calculator/Views/CalculatorSettings.xaml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<UserControl x:Class="Wox.Plugin.Caculator.Views.CalculatorSettings"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:ui="clr-namespace:Wox.Infrastructure.UI;assembly=Wox.Infrastructure"
|
||||
xmlns:calculator="clr-namespace:Wox.Plugin.Caculator"
|
||||
xmlns:core="clr-namespace:Wox.Core;assembly=Wox.Core"
|
||||
xmlns:viewModels="clr-namespace:Wox.Plugin.Caculator.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
Loaded="CalculatorSettings_Loaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
|
||||
<UserControl.Resources>
|
||||
<core:LocalizationConverter x:Key="LocalizationConverter"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border BorderBrush="Gray" Margin="10" BorderThickness="1">
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0" Grid.Row="0" Text="{DynamicResource wox_plugin_calculator_output_decimal_seperator}" VerticalAlignment="Center" />
|
||||
<ComboBox x:Name="DecimalSeparatorComboBox"
|
||||
Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Margin="0 5 0 5"
|
||||
HorizontalAlignment="Left"
|
||||
SelectedItem="{Binding Settings.DecimalSeparator}"
|
||||
ItemsSource="{Binding Source={ui:EnumBindingSource {x:Type calculator:DecimalSeparator}}}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={StaticResource LocalizationConverter}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" Text="{DynamicResource wox_plugin_calculator_max_decimal_places}" VerticalAlignment="Center" />
|
||||
<ComboBox x:Name="MaxDecimalPlaces"
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Margin="0 5 0 5"
|
||||
HorizontalAlignment="Left"
|
||||
SelectedItem="{Binding Settings.MaxDecimalPlaces}"
|
||||
ItemsSource="{Binding MaxDecimalPlacesRange}">
|
||||
</ComboBox>
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Wox.Plugin.Caculator.ViewModels;
|
||||
|
||||
namespace Wox.Plugin.Caculator.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for CalculatorSettings.xaml
|
||||
/// </summary>
|
||||
public partial class CalculatorSettings : UserControl
|
||||
{
|
||||
private readonly SettingsViewModel _viewModel;
|
||||
private readonly Settings _settings;
|
||||
|
||||
public CalculatorSettings(SettingsViewModel viewModel)
|
||||
{
|
||||
_viewModel = viewModel;
|
||||
_settings = viewModel.Settings;
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void CalculatorSettings_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DecimalSeparatorComboBox.SelectedItem = _settings.DecimalSeparator;
|
||||
MaxDecimalPlaces.SelectedItem = _settings.MaxDecimalPlaces;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -46,14 +46,22 @@
|
|||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xaml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\SolutionAssemblyInfo.cs">
|
||||
<Link>Properties\SolutionAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="DecimalSeparator.cs" />
|
||||
<Compile Include="NumberTranslator.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Settings.cs" />
|
||||
<Compile Include="ViewModels\SettingsViewModel.cs" />
|
||||
<Compile Include="Views\CalculatorSettings.xaml.cs">
|
||||
<DependentUpon>CalculatorSettings.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="plugin.json">
|
||||
|
|
@ -61,6 +69,10 @@
|
|||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Wox.Core\Wox.Core.csproj">
|
||||
<Project>{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}</Project>
|
||||
<Name>Wox.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Wox.Infrastructure\Wox.Infrastructure.csproj">
|
||||
<Project>{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}</Project>
|
||||
<Name>Wox.Infrastructure</Name>
|
||||
|
|
@ -122,12 +134,18 @@
|
|||
<Version>10.3.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Mages">
|
||||
<Version>1.5.0</Version>
|
||||
<Version>1.6.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Runtime">
|
||||
<Version>4.0.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="Views\CalculatorSettings.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ namespace Wox.Plugin.PluginIndicator
|
|||
var results = from keyword in PluginManager.NonGlobalPlugins.Keys
|
||||
where keyword.StartsWith(query.Terms[0])
|
||||
let metadata = PluginManager.NonGlobalPlugins[keyword].Metadata
|
||||
let disabled = PluginManager.Settings.Plugins[metadata.ID].Disabled
|
||||
where !disabled
|
||||
where !metadata.Disabled
|
||||
select new Result
|
||||
{
|
||||
Title = keyword,
|
||||
|
|
|
|||
BIN
Plugins/Wox.Plugin.Sys/Images/checkupdate.png
Normal file
BIN
Plugins/Wox.Plugin.Sys/Images/checkupdate.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
|
|
@ -234,6 +234,20 @@ namespace Wox.Plugin.Sys
|
|||
context.API.GetTranslation("wox_plugin_sys_dlgtext_all_applicableplugins_reloaded"));
|
||||
return true;
|
||||
}
|
||||
},
|
||||
new Result
|
||||
{
|
||||
Title = "Check For Update",
|
||||
SubTitle = "Check for new Wox update",
|
||||
IcoPath = "Images\\checkupdate.png",
|
||||
Action = c =>
|
||||
{
|
||||
Application.Current.MainWindow.Hide();
|
||||
context.API.CheckForNewUpdate();
|
||||
context.API.ShowMsg("Please wait...",
|
||||
"Checking for new update");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return results;
|
||||
|
|
|
|||
|
|
@ -71,9 +71,15 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Images\checkupdate.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Images\recyclebin.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Images\shutdown.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Content Include="Images\sleep.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
|
|||
19
README.md
19
README.md
|
|
@ -19,11 +19,22 @@ Features
|
|||
- Search for everything—applications, **uwp**, folders, files and more.
|
||||
- Use *pinyin* to search for programs / 支持用 **拼音** 搜索程序
|
||||
- wyy / wangyiyun → 网易云音乐
|
||||
- Keyword plugin search
|
||||
- search google with `g search_term`
|
||||
- Keyword plugin search `g search_term`
|
||||
- Search youtube, google, twitter and many more
|
||||
- Build custom themes at http://www.wox.one/theme/builder
|
||||
- Install plugins from http://www.wox.one/plugin
|
||||
|
||||
**New from this fork:**
|
||||
- Portable mode
|
||||
- Drastically improved search experience
|
||||
- Search all subfolders and files
|
||||
- Option to always run CMD or Powershell as administrator
|
||||
- Run CMD, Powershell and programs as a different user
|
||||
- Manage what programs should be loaded
|
||||
- Highlighting of how results are matched during query search
|
||||
- Open web search result as a tab or a new window
|
||||
- Automatic update
|
||||
- Reload/update plugin data
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
|
@ -42,8 +53,8 @@ Versions marked as **pre-release** are unstable pre-release versions.
|
|||
|
||||
- Requirements:
|
||||
- .net >= 4.5.2
|
||||
- [everything](https://www.voidtools.com/): `.exe` installer + use x64 if your windows is x64 + everything service is running
|
||||
- [python3](https://www.python.org/downloads/): `.exe` installer + add it to `%PATH%` or set it in WoX settings
|
||||
- If you want to integrate with [everything](https://www.voidtools.com/): `.exe` installer + use x64 if your windows is x64 + everything service is running. Supported version is 1.3.4.686
|
||||
- If you use python plugins, install [python3](https://www.python.org/downloads/): `.exe` installer + add it to `%PATH%` or set it in WoX settings
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
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)
|
||||
|
|
@ -128,35 +149,6 @@ namespace Wox.Core.Plugin
|
|||
PluginInstaller.Install(path);
|
||||
}
|
||||
|
||||
public static Query QueryInit(string text) //todo is that possible to move it into type Query?
|
||||
{
|
||||
// replace multiple white spaces with one white space
|
||||
var terms = text.Split(new[] { Query.TermSeperater }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var rawQuery = string.Join(Query.TermSeperater, terms);
|
||||
var actionKeyword = string.Empty;
|
||||
var search = rawQuery;
|
||||
var actionParameters = terms.ToList();
|
||||
if (terms.Length == 0) return null;
|
||||
if (NonGlobalPlugins.ContainsKey(terms[0]) &&
|
||||
!Settings.Plugins[NonGlobalPlugins[terms[0]].Metadata.ID].Disabled)
|
||||
{
|
||||
actionKeyword = terms[0];
|
||||
actionParameters = terms.Skip(1).ToList();
|
||||
search = string.Join(Query.TermSeperater, actionParameters.ToArray());
|
||||
}
|
||||
var query = new Query
|
||||
{
|
||||
Terms = terms,
|
||||
RawQuery = rawQuery,
|
||||
ActionKeyword = actionKeyword,
|
||||
Search = search,
|
||||
// Obsolete value initialisation
|
||||
ActionName = actionKeyword,
|
||||
ActionParameters = actionParameters
|
||||
};
|
||||
return query;
|
||||
}
|
||||
|
||||
public static List<PluginPair> ValidPluginsForQuery(Query query)
|
||||
{
|
||||
if (NonGlobalPlugins.ContainsKey(query.ActionKeyword))
|
||||
|
|
|
|||
50
Wox.Core/Plugin/QueryBuilder.cs
Normal file
50
Wox.Core/Plugin/QueryBuilder.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Wox.Plugin;
|
||||
|
||||
namespace Wox.Core.Plugin
|
||||
{
|
||||
public static class QueryBuilder
|
||||
{
|
||||
public static Query Build(string text, Dictionary<string, PluginPair> nonGlobalPlugins)
|
||||
{
|
||||
// replace multiple white spaces with one white space
|
||||
var terms = text.Split(new[] { Query.TermSeperater }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (terms.Length == 0)
|
||||
{ // nothing was typed
|
||||
return null;
|
||||
}
|
||||
|
||||
var rawQuery = string.Join(Query.TermSeperater, terms);
|
||||
string actionKeyword, search;
|
||||
string possibleActionKeyword = terms[0];
|
||||
List<string> actionParameters;
|
||||
if (nonGlobalPlugins.TryGetValue(possibleActionKeyword, out var pluginPair) && !pluginPair.Metadata.Disabled)
|
||||
{ // use non global plugin for query
|
||||
actionKeyword = possibleActionKeyword;
|
||||
actionParameters = terms.Skip(1).ToList();
|
||||
search = actionParameters.Count > 0 ? rawQuery.Substring(actionKeyword.Length + 1) : string.Empty;
|
||||
}
|
||||
else
|
||||
{ // non action keyword
|
||||
actionKeyword = string.Empty;
|
||||
actionParameters = terms.ToList();
|
||||
search = rawQuery;
|
||||
}
|
||||
|
||||
var query = new Query
|
||||
{
|
||||
Terms = terms,
|
||||
RawQuery = rawQuery,
|
||||
ActionKeyword = actionKeyword,
|
||||
Search = search,
|
||||
// Obsolete value initialisation
|
||||
ActionName = actionKeyword,
|
||||
ActionParameters = actionParameters
|
||||
};
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
Wox.Core/Resource/LocalizationConverter.cs
Normal file
37
Wox.Core/Resource/LocalizationConverter.cs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Wox.Core
|
||||
{
|
||||
public class LocalizationConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (targetType == typeof(string) && value != null)
|
||||
{
|
||||
FieldInfo fi = value.GetType().GetField(value.ToString());
|
||||
if (fi != null)
|
||||
{
|
||||
string localizedDescription = string.Empty;
|
||||
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
if ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description)))
|
||||
{
|
||||
localizedDescription = attributes[0].Description;
|
||||
}
|
||||
|
||||
return (!String.IsNullOrEmpty(localizedDescription)) ? localizedDescription : value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Wox.Core/Resource/LocalizedDescriptionAttribute.cs
Normal file
27
Wox.Core/Resource/LocalizedDescriptionAttribute.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System.ComponentModel;
|
||||
using Wox.Core.Resource;
|
||||
|
||||
namespace Wox.Core
|
||||
{
|
||||
public class LocalizedDescriptionAttribute : DescriptionAttribute
|
||||
{
|
||||
private readonly Internationalization _translator;
|
||||
private readonly string _resourceKey;
|
||||
|
||||
public LocalizedDescriptionAttribute(string resourceKey)
|
||||
{
|
||||
_translator = InternationalizationManager.Instance;
|
||||
_resourceKey = resourceKey;
|
||||
}
|
||||
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
string description = _translator.GetTranslation(_resourceKey);
|
||||
return string.IsNullOrWhiteSpace(description) ?
|
||||
string.Format("[[{0}]]", _resourceKey) : description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
|
|
@ -10,9 +10,11 @@ using JetBrains.Annotations;
|
|||
using Squirrel;
|
||||
using Newtonsoft.Json;
|
||||
using Wox.Core.Resource;
|
||||
using Wox.Plugin.SharedCommands;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Http;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using System.IO;
|
||||
|
||||
namespace Wox.Core
|
||||
{
|
||||
|
|
@ -25,14 +27,14 @@ namespace Wox.Core
|
|||
GitHubRepository = gitHubRepository;
|
||||
}
|
||||
|
||||
public async Task UpdateApp()
|
||||
public async Task UpdateApp(bool silentIfLatestVersion = true)
|
||||
{
|
||||
UpdateManager m;
|
||||
UpdateInfo u;
|
||||
UpdateManager updateManager;
|
||||
UpdateInfo newUpdateInfo;
|
||||
|
||||
try
|
||||
{
|
||||
m = await GitHubUpdateManager(GitHubRepository);
|
||||
updateManager = await GitHubUpdateManager(GitHubRepository);
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
|
||||
{
|
||||
|
|
@ -43,42 +45,61 @@ namespace Wox.Core
|
|||
try
|
||||
{
|
||||
// UpdateApp CheckForUpdate will return value only if the app is squirrel installed
|
||||
u = await m.CheckForUpdate().NonNull();
|
||||
newUpdateInfo = await updateManager.CheckForUpdate().NonNull();
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
|
||||
{
|
||||
Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to api.github.com.", e);
|
||||
m.Dispose();
|
||||
updateManager.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
var fr = u.FutureReleaseEntry;
|
||||
var cr = u.CurrentlyInstalledVersion;
|
||||
Log.Info($"|Updater.UpdateApp|Future Release <{fr.Formatted()}>");
|
||||
if (fr.Version > cr.Version)
|
||||
var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString());
|
||||
var currentVersion = Version.Parse(Constant.Version);
|
||||
|
||||
Log.Info($"|Updater.UpdateApp|Future Release <{newUpdateInfo.FutureReleaseEntry.Formatted()}>");
|
||||
|
||||
if (newReleaseVersion <= currentVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
await m.DownloadReleases(u.ReleasesToApply);
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
|
||||
{
|
||||
Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
|
||||
m.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
await m.ApplyReleases(u);
|
||||
await m.CreateUninstallerRegistryEntry();
|
||||
|
||||
var newVersionTips = this.NewVersinoTips(fr.Version.ToString());
|
||||
|
||||
MessageBox.Show(newVersionTips);
|
||||
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
|
||||
if (!silentIfLatestVersion)
|
||||
MessageBox.Show("You already have the latest Wox version");
|
||||
updateManager.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply);
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException)
|
||||
{
|
||||
Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e);
|
||||
updateManager.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
await updateManager.ApplyReleases(newUpdateInfo);
|
||||
|
||||
if (Constant.IsPortableMode)
|
||||
{
|
||||
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{Constant.PortableFolderName}";
|
||||
FilesFolders.Copy(Constant.PortableDataPath, targetDestination);
|
||||
if (!FilesFolders.VerifyBothFolderFilesEqual(Constant.PortableDataPath, targetDestination))
|
||||
MessageBox.Show(string.Format("Wox was not able to move your user profile data to the new update version. Please manually" +
|
||||
"move your profile data folder from {0} to {1}", Constant.PortableDataPath, targetDestination));
|
||||
}
|
||||
else
|
||||
{
|
||||
await updateManager.CreateUninstallerRegistryEntry();
|
||||
}
|
||||
|
||||
var newVersionTips = NewVersinoTips(newReleaseVersion.ToString());
|
||||
|
||||
MessageBox.Show(newVersionTips);
|
||||
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
|
||||
|
||||
// always dispose UpdateManager
|
||||
m.Dispose();
|
||||
updateManager.Dispose();
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@
|
|||
<Compile Include="Configuration\Portable.cs" />
|
||||
<Compile Include="Plugin\ExecutablePlugin.cs" />
|
||||
<Compile Include="Plugin\PluginsLoader.cs" />
|
||||
<Compile Include="Resource\LocalizationConverter.cs" />
|
||||
<Compile Include="Resource\LocalizedDescriptionAttribute.cs" />
|
||||
<Compile Include="Plugin\QueryBuilder.cs" />
|
||||
<Compile Include="Updater.cs" />
|
||||
<Compile Include="Resource\AvailableLanguages.cs" />
|
||||
<Compile Include="Resource\Internationalization.cs" />
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Wox.Infrastructure.Logger
|
|||
{
|
||||
public const string DirectoryName = "Logs";
|
||||
|
||||
public static string CurrentLogDirectory { get; private set; }
|
||||
public static string CurrentLogDirectory { get; }
|
||||
|
||||
static Log()
|
||||
{
|
||||
|
|
@ -53,6 +53,14 @@ namespace Wox.Infrastructure.Logger
|
|||
|
||||
[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))
|
||||
{
|
||||
|
|
@ -60,16 +68,17 @@ namespace Wox.Infrastructure.Logger
|
|||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(message))
|
||||
{ // todo: not sure we really need that
|
||||
{
|
||||
// todo: not sure we really need that
|
||||
LogFaultyFormat($"Fail to specify a message during logging");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(methodName))
|
||||
{
|
||||
className += "." + methodName;
|
||||
return className + "." + methodName;
|
||||
}
|
||||
|
||||
ExceptionInternal(className, message, exception);
|
||||
return className;
|
||||
}
|
||||
|
||||
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
|
||||
|
|
@ -140,18 +149,48 @@ namespace Wox.Infrastructure.Logger
|
|||
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)
|
||||
{
|
||||
LogInternal(message, LogLevel.Debug);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
LogInternal(message, LogLevel.Info);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
57
Wox.Infrastructure/UI/EnumBindingSource.cs
Normal file
57
Wox.Infrastructure/UI/EnumBindingSource.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Wox.Infrastructure.UI
|
||||
{
|
||||
public class EnumBindingSourceExtension : MarkupExtension
|
||||
{
|
||||
private Type _enumType;
|
||||
public Type EnumType
|
||||
{
|
||||
get { return _enumType; }
|
||||
set
|
||||
{
|
||||
if (value != _enumType)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
Type enumType = Nullable.GetUnderlyingType(value) ?? value;
|
||||
if (!enumType.IsEnum)
|
||||
{
|
||||
throw new ArgumentException("Type must represent an enum.");
|
||||
}
|
||||
}
|
||||
|
||||
_enumType = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EnumBindingSourceExtension() { }
|
||||
|
||||
public EnumBindingSourceExtension(Type enumType)
|
||||
{
|
||||
EnumType = enumType;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
if (_enumType == null)
|
||||
{
|
||||
throw new InvalidOperationException("The EnumType must be specified.");
|
||||
}
|
||||
|
||||
Type actualEnumType = Nullable.GetUnderlyingType(_enumType) ?? _enumType;
|
||||
Array enumValues = Enum.GetValues(actualEnumType);
|
||||
|
||||
if (actualEnumType == _enumType)
|
||||
{
|
||||
return enumValues;
|
||||
}
|
||||
|
||||
Array tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1);
|
||||
enumValues.CopyTo(tempArray, 1);
|
||||
return tempArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ namespace Wox.Infrastructure.UserSettings
|
|||
{
|
||||
ID = metadata.ID,
|
||||
Name = metadata.Name,
|
||||
ActionKeywords = metadata.ActionKeywords,
|
||||
ActionKeywords = metadata.ActionKeywords,
|
||||
Disabled = metadata.Disabled
|
||||
};
|
||||
}
|
||||
|
|
@ -39,7 +39,11 @@ namespace Wox.Infrastructure.UserSettings
|
|||
{
|
||||
public string ID { get; set; }
|
||||
public string Name { get; set; }
|
||||
public List<string> ActionKeywords { get; set; }
|
||||
public List<string> ActionKeywords { get; set; } // a reference of the action keywords from plugin manager
|
||||
|
||||
/// <summary>
|
||||
/// Used only to save the state of the plugin in settings
|
||||
/// </summary>
|
||||
public bool Disabled { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@
|
|||
<Compile Include="Hotkey\HotkeyModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Alphabet.cs" />
|
||||
<Compile Include="UI\EnumBindingSource.cs" />
|
||||
<Compile Include="UserSettings\HttpProxy.cs" />
|
||||
<Compile Include="UserSettings\PluginHotkey.cs" />
|
||||
<Compile Include="UserSettings\PluginSettings.cs" />
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ namespace Wox.Infrastructure
|
|||
public static readonly string ApplicationDirectory = Directory.GetParent(ProgramDirectory).ToString();
|
||||
public static readonly string RootDirectory = Directory.GetParent(ApplicationDirectory).ToString();
|
||||
|
||||
public static bool IsPortableMode;
|
||||
public const string PortableFolderName = "UserData";
|
||||
public static string PortableDataPath = Path.Combine(ProgramDirectory, PortableFolderName);
|
||||
public static string RoamingDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Wox);
|
||||
|
|
@ -23,6 +24,7 @@ namespace Wox.Infrastructure
|
|||
{
|
||||
if (Directory.Exists(PortableDataPath))
|
||||
{
|
||||
IsPortableMode = true;
|
||||
return PortableDataPath;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -70,13 +70,18 @@ namespace Wox.Plugin
|
|||
/// </summary>
|
||||
void ReloadAllPluginData();
|
||||
|
||||
/// <summary>
|
||||
/// Check for new Wox update
|
||||
/// </summary>
|
||||
void CheckForNewUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// Show message box
|
||||
/// </summary>
|
||||
/// <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
|
||||
|
|
|
|||
|
|
@ -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,7 +42,7 @@ namespace Wox.Plugin.SharedCommands
|
|||
Copy(subdir.FullName, temppath);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
throw e;
|
||||
|
|
@ -69,7 +69,7 @@ namespace Wox.Plugin.SharedCommands
|
|||
|
||||
return true;
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
throw e;
|
||||
|
|
@ -88,7 +88,7 @@ namespace Wox.Plugin.SharedCommands
|
|||
if (Directory.Exists(path))
|
||||
Directory.Delete(path, true);
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
throw e;
|
||||
|
|
|
|||
51
Wox.Test/QueryBuilderTest.cs
Normal file
51
Wox.Test/QueryBuilderTest.cs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Plugin;
|
||||
|
||||
namespace Wox.Test
|
||||
{
|
||||
public class QueryBuilderTest
|
||||
{
|
||||
[Test]
|
||||
public void ExclusivePluginQueryTest()
|
||||
{
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{">", new PluginPair {Metadata = new PluginMetadata {ActionKeywords = new List<string> {">"}}}}
|
||||
};
|
||||
|
||||
Query q = QueryBuilder.Build("> file.txt file2 file3", nonGlobalPlugins);
|
||||
|
||||
Assert.AreEqual("file.txt file2 file3", q.Search);
|
||||
Assert.AreEqual(">", q.ActionKeyword);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExclusivePluginQueryIgnoreDisabledTest()
|
||||
{
|
||||
var nonGlobalPlugins = new Dictionary<string, PluginPair>
|
||||
{
|
||||
{">", new PluginPair {Metadata = new PluginMetadata {ActionKeywords = new List<string> {">"}, Disabled = true}}}
|
||||
};
|
||||
|
||||
Query q = QueryBuilder.Build("> file.txt file2 file3", nonGlobalPlugins);
|
||||
|
||||
Assert.AreEqual("> file.txt file2 file3", q.Search);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GenericPluginQueryTest()
|
||||
{
|
||||
Query q = QueryBuilder.Build("file.txt file2 file3", new Dictionary<string, PluginPair>());
|
||||
|
||||
Assert.AreEqual("file.txt file2 file3", q.Search);
|
||||
Assert.AreEqual("", q.ActionKeyword);
|
||||
|
||||
Assert.AreEqual("file.txt", q.FirstSearch);
|
||||
Assert.AreEqual("file2", q.SecondSearch);
|
||||
Assert.AreEqual("file3", q.ThirdSearch);
|
||||
Assert.AreEqual("file2 file3", q.SecondToEndSearch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
using NUnit.Framework;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Plugin;
|
||||
|
||||
namespace Wox.Test
|
||||
{
|
||||
public class QueryTest
|
||||
{
|
||||
[Test]
|
||||
[Ignore("Current query is tightly integrated with GUI, can't be tested.")]
|
||||
public void ExclusivePluginQueryTest()
|
||||
{
|
||||
Query q = PluginManager.QueryInit("> file.txt file2 file3");
|
||||
|
||||
Assert.AreEqual(q.FirstSearch, "file.txt");
|
||||
Assert.AreEqual(q.SecondSearch, "file2");
|
||||
Assert.AreEqual(q.ThirdSearch, "file3");
|
||||
Assert.AreEqual(q.SecondToEndSearch, "file2 file3");
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Current query is tightly integrated with GUI, can't be tested.")]
|
||||
public void GenericPluginQueryTest()
|
||||
{
|
||||
Query q = PluginManager.QueryInit("file.txt file2 file3");
|
||||
|
||||
Assert.AreEqual(q.FirstSearch, "file.txt");
|
||||
Assert.AreEqual(q.SecondSearch, "file2");
|
||||
Assert.AreEqual(q.ThirdSearch, "file3");
|
||||
Assert.AreEqual(q.SecondToEndSearch, "file2 file3");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
</Compile>
|
||||
<Compile Include="FuzzyMatcherTest.cs" />
|
||||
<Compile Include="Plugins\PluginInitTest.cs" />
|
||||
<Compile Include="QueryTest.cs" />
|
||||
<Compile Include="QueryBuilderTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UrlPluginTest.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Net;
|
|||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Squirrel;
|
||||
using Wox.Core;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Core.Resource;
|
||||
using Wox.Helper;
|
||||
|
|
@ -65,6 +66,11 @@ namespace Wox
|
|||
UpdateManager.RestartApp();
|
||||
}
|
||||
|
||||
public void CheckForNewUpdate()
|
||||
{
|
||||
_settingsVM.UpdateApp();
|
||||
}
|
||||
|
||||
public void SaveAppAllSettings()
|
||||
{
|
||||
_mainVM.Save();
|
||||
|
|
@ -91,12 +97,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@
|
|||
<TabControl Height="auto" SelectedIndex="0">
|
||||
<TabItem Header="{DynamicResource general}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<CheckBox IsChecked="{Binding Settings.StartWoxOnSystemStartup}" Margin="10">
|
||||
<CheckBox Margin="10" IsChecked="{Binding Settings.StartWoxOnSystemStartup}"
|
||||
Checked="OnAutoStartupChecked" Unchecked="OnAutoStartupUncheck">
|
||||
<TextBlock Text="{DynamicResource startWoxOnSystemStartup}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="10" IsChecked="{Binding Settings.HideOnStartup}">
|
||||
|
|
@ -51,8 +52,7 @@
|
|||
<CheckBox Margin="10" IsChecked="{Binding Settings.IgnoreHotkeysOnFullscreen}">
|
||||
<TextBlock Text="{DynamicResource ignoreHotkeysOnFullscreen}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="10" IsChecked="{Binding Settings.AutoUpdates}"
|
||||
Checked="OnAutoStartupChecked" Unchecked="OnAutoStartupUncheck">
|
||||
<CheckBox Margin="10" IsChecked="{Binding Settings.AutoUpdates}">
|
||||
<TextBlock Text="{DynamicResource autoUpdates}" />
|
||||
</CheckBox>
|
||||
<CheckBox Margin="10" IsChecked="{Binding Settings.ShouldUsePinyin}">
|
||||
|
|
|
|||
|
|
@ -215,7 +215,8 @@ namespace Wox
|
|||
private void OnPluginToggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var id = _viewModel.SelectedPlugin.PluginPair.Metadata.ID;
|
||||
_settings.PluginSettings.Plugins[id].Disabled = _viewModel.SelectedPlugin.PluginPair.Metadata.Disabled;
|
||||
// used to sync the current status from the plugin manager into the setting to keep consistency after save
|
||||
_settings.PluginSettings.Plugins[id].Disabled = _viewModel.SelectedPlugin.PluginPair.Metadata.Disabled;
|
||||
}
|
||||
|
||||
private void OnPluginActionKeywordsClick(object sender, MouseButtonEventArgs e)
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ namespace Wox.ViewModel
|
|||
|
||||
ProgressBarVisibility = Visibility.Hidden;
|
||||
_isQueryRunning = true;
|
||||
var query = PluginManager.QueryInit(QueryText.Trim());
|
||||
var query = QueryBuilder.Build(QueryText.Trim(), PluginManager.NonGlobalPlugins);
|
||||
if (query != null)
|
||||
{
|
||||
// handle the exclusiveness of plugin using action keyword
|
||||
|
|
@ -401,8 +401,7 @@ namespace Wox.ViewModel
|
|||
{
|
||||
Parallel.ForEach(plugins, parallelOptions, plugin =>
|
||||
{
|
||||
var config = _settings.PluginSettings.Plugins[plugin.Metadata.ID];
|
||||
if (!config.Disabled)
|
||||
if (!plugin.Metadata.Disabled)
|
||||
{
|
||||
var results = PluginManager.QueryForPlugin(plugin, query);
|
||||
UpdateResultView(results, plugin.Metadata, query);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Wox.ViewModel
|
|||
|
||||
public async void UpdateApp()
|
||||
{
|
||||
await _updater.UpdateApp();
|
||||
await _updater.UpdateApp(false);
|
||||
}
|
||||
|
||||
public void EnablePortableMode()
|
||||
|
|
@ -163,26 +163,11 @@ namespace Wox.ViewModel
|
|||
{
|
||||
get
|
||||
{
|
||||
var plugins = PluginManager.AllPlugins;
|
||||
var settings = Settings.PluginSettings.Plugins;
|
||||
plugins.Sort((a, b) =>
|
||||
{
|
||||
var d1 = settings[a.Metadata.ID].Disabled;
|
||||
var d2 = settings[b.Metadata.ID].Disabled;
|
||||
if (d1 == d2)
|
||||
{
|
||||
return string.Compare(a.Metadata.Name, b.Metadata.Name, StringComparison.CurrentCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
return d1.CompareTo(d2);
|
||||
}
|
||||
});
|
||||
|
||||
var metadatas = plugins.Select(p => new PluginViewModel
|
||||
{
|
||||
PluginPair = p,
|
||||
}).ToList();
|
||||
var metadatas = PluginManager.AllPlugins
|
||||
.OrderBy(x => x.Metadata.Disabled)
|
||||
.ThenBy(y => y.Metadata.Name)
|
||||
.Select(p => new PluginViewModel { PluginPair = p})
|
||||
.ToList();
|
||||
return metadatas;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue