Merge branch 'dev'

This commit is contained in:
Jeremy Wu 2020-03-01 20:12:51 +11:00
commit 28acd466b3
24 changed files with 413 additions and 153 deletions

View file

@ -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,

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -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;

View file

@ -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>

View file

@ -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
-----

View file

@ -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))

View 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;
}
}
}

View file

@ -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]

View file

@ -53,6 +53,7 @@
</Compile>
<Compile Include="Plugin\ExecutablePlugin.cs" />
<Compile Include="Plugin\PluginsLoader.cs" />
<Compile Include="Plugin\QueryBuilder.cs" />
<Compile Include="Updater.cs" />
<Compile Include="Resource\AvailableLanguages.cs" />
<Compile Include="Resource\Internationalization.cs" />

View file

@ -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)
{

View file

@ -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; }
}
}

View file

@ -7,12 +7,22 @@ namespace Wox.Infrastructure
{
public static class Constant
{
public const string Wox = "Wox";
public const string Plugins = "Plugins";
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
public static readonly string ProgramDirectory = Directory.GetParent(Assembly.Location.NonNull()).ToString();
public static readonly string ExecutablePath = Path.Combine(ProgramDirectory, Wox + ".exe");
public static bool IsPortableMode;
public const string PortableFolderName = "UserData";
public static string PortableDataPath = Path.Combine(ProgramDirectory, PortableFolderName);
public static string DetermineDataDirectory()
{
string portableDataPath = Path.Combine(ProgramDirectory, "UserData");
if (Directory.Exists(portableDataPath))
if (Directory.Exists(PortableDataPath))
{
return portableDataPath;
IsPortableMode = true;
return PortableDataPath;
}
else
{
@ -20,12 +30,6 @@ namespace Wox.Infrastructure
}
}
public const string Wox = "Wox";
public const string Plugins = "Plugins";
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
public static readonly string ProgramDirectory = Directory.GetParent(Assembly.Location.NonNull()).ToString();
public static readonly string ExecutablePath = Path.Combine(ProgramDirectory, Wox + ".exe");
public static readonly string DataDirectory = DetermineDataDirectory();
public static readonly string PluginsDirectory = Path.Combine(DataDirectory, Plugins);
public static readonly string PreinstalledDirectory = Path.Combine(ProgramDirectory, Plugins);

View file

@ -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

View file

@ -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]

View file

@ -0,0 +1,101 @@
using System;
using System.IO;
using System.Windows;
namespace Wox.Plugin.SharedCommands
{
public static class FilesFolders
{
public static void Copy(this string sourcePath, string targetPath)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourcePath);
if (!dir.Exists)
{
throw new DirectoryNotFoundException(
"Source directory does not exist or could not be found: "
+ sourcePath);
}
try
{
DirectoryInfo[] dirs = dir.GetDirectories();
// If the destination directory doesn't exist, create it.
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
// Get the files in the directory and copy them to the new location.
FileInfo[] files = dir.GetFiles();
foreach (FileInfo file in files)
{
string temppath = Path.Combine(targetPath, file.Name);
file.CopyTo(temppath, false);
}
// Recursively copy subdirectories by calling itself on each subdirectory until there are no more to copy
foreach (DirectoryInfo subdir in dirs)
{
string temppath = Path.Combine(targetPath, subdir.Name);
Copy(subdir.FullName, temppath);
}
}
catch (Exception e)
{
#if DEBUG
throw e;
#else
MessageBox.Show(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath));
RemoveFolder(targetPath);
#endif
}
}
public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath)
{
try
{
var fromDir = new DirectoryInfo(fromPath);
var toDir = new DirectoryInfo(toPath);
if (fromDir.GetFiles("*", SearchOption.AllDirectories).Length != toDir.GetFiles("*", SearchOption.AllDirectories).Length)
return false;
if (fromDir.GetDirectories("*", SearchOption.AllDirectories).Length != toDir.GetDirectories("*", SearchOption.AllDirectories).Length)
return false;
return true;
}
catch (Exception e)
{
#if DEBUG
throw e;
#else
MessageBox.Show(string.Format("Unable to verify folders and files between {0} and {1}", fromPath, toPath));
return false;
#endif
}
}
public static void RemoveFolder(this string path)
{
try
{
if (Directory.Exists(path))
Directory.Delete(path, true);
}
catch (Exception e)
{
#if DEBUG
throw e;
#else
MessageBox.Show(string.Format("Not able to delete folder {0}, please go to the location and manually delete it", path));
#endif
}
}
}
}

View file

@ -65,6 +65,7 @@
<Compile Include="Query.cs" />
<Compile Include="Result.cs" />
<Compile Include="ActionContext.cs" />
<Compile Include="SharedCommands\FilesFolders.cs" />
<Compile Include="SharedCommands\SearchWeb.cs" />
<Compile Include="SharedCommands\ShellCommand.cs" />
</ItemGroup>

View 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);
}
}
}

View file

@ -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");
}
}
}

View file

@ -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>

View file

@ -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);
});
}

View file

@ -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}">

View file

@ -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)

View file

@ -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);

View file

@ -44,7 +44,7 @@ namespace Wox.ViewModel
public async void UpdateApp()
{
await _updater.UpdateApp();
await _updater.UpdateApp(false);
}
public void Save()
@ -150,26 +150,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;
}
}