use %APPDATA%

1. Fix can't find Result.ctor bug for plugin introduced in
c0889de1f9ae460b2cc189eb59e5bd90ddb7d17e
2. use %APPDATA% for all data, part of #389
3. MISC
This commit is contained in:
bao-qian
2016-04-27 02:15:53 +01:00
parent e96bd5a0e7
commit dc3b01dc15
22 changed files with 157 additions and 159 deletions

View File

@@ -51,8 +51,11 @@ namespace Wox.Plugin.Folder
x => x.Nickname.StartsWith(input, StringComparison.OrdinalIgnoreCase)).ToList();
List<Result> results =
userFolderLinks.Select(
item => new Result(item.Nickname, "Images/folder.png", "Ctrl + Enter to open the directory")
item => new Result()
{
Title = item.Nickname,
IcoPath = "Images/folder.png",
SubTitle = "Ctrl + Enter to open the directory",
Action = c =>
{
if (c.SpecialKeyState.CtrlPressed)
@@ -128,8 +131,10 @@ namespace Wox.Plugin.Folder
string firstResult = "Open current directory";
if (incompleteName.Length > 0)
firstResult = "Open " + rawQuery;
results.Add(new Result(firstResult, "Images/folder.png")
results.Add(new Result
{
Title = firstResult,
IcoPath = "Images/folder.png",
Score = 10000,
Action = c =>
{
@@ -147,8 +152,11 @@ namespace Wox.Plugin.Folder
if (incompleteName.Length != 0 && !dir.Name.ToLower().StartsWith(incompleteName))
continue;
DirectoryInfo dirCopy = dir;
var result = new Result(dir.Name, "Images/folder.png", "Ctrl + Enter to open the directory")
var result = new Result
{
Title = dir.Name,
IcoPath = "Images/folder.png",
SubTitle = "Ctrl + Enter to open the directory",
Action = c =>
{
if (c.SpecialKeyState.CtrlPressed)
@@ -180,8 +188,10 @@ namespace Wox.Plugin.Folder
if (incompleteName.Length != 0 && !file.Name.ToLower().StartsWith(incompleteName))
continue;
string filePath = file.FullName;
var result = new Result(Path.GetFileName(filePath), "Images/file.png")
var result = new Result
{
Title = Path.GetFileName(filePath),
IcoPath = "Images/file.png",
Action = c =>
{
try

View File

@@ -153,7 +153,6 @@ namespace Wox.Plugin.PluginManagement
string pluginUrl = APIBASE + "/media/" + r1.plugin_file;
Client.DownloadFile(pluginUrl, filePath);
context.API.InstallPlugin(filePath);
context.API.ReloadPlugins();
}
catch (Exception exception)
{

View File

@@ -19,7 +19,7 @@ namespace Wox.Core.Plugin
/// </summary>
/// <param name="pluginDirectories"></param>
/// <returns></returns>
public static List<PluginMetadata> Parse(List<string> pluginDirectories)
public static List<PluginMetadata> Parse(string[] pluginDirectories)
{
pluginMetadatas.Clear();
foreach (string pluginDirectory in pluginDirectories)

View File

@@ -34,7 +34,7 @@ namespace Wox.Core.Plugin
return;
}
string pluginFolerPath = PluginManager.PluginDirectory;
string pluginFolerPath = PluginManager.UserDirectory;
string newPluginName = plugin.Name
.Replace("/", "_")

View File

@@ -17,13 +17,11 @@ namespace Wox.Core.Plugin
/// </summary>
public static class PluginManager
{
public const string DirectoryName = "Plugins";
private static IEnumerable<PluginPair> _contextMenuPlugins;
/// <summary>
/// Directories that will hold Wox plugin directory
/// </summary>
private static readonly List<string> PluginDirectories = new List<string>();
public static List<PluginPair> AllPlugins { get; private set; }
@@ -34,47 +32,31 @@ namespace Wox.Core.Plugin
private static IEnumerable<PluginPair> InstantQueryPlugins { get; set; }
public static IPublicAPI API { private set; get; }
public static readonly string PluginDirectory = Path.Combine(WoxDirectroy.Executable, DirectoryName);
public const string DirectoryName = "Plugins";
public static readonly string PreinstalledDirectory = Path.Combine(Infrastructure.Wox.ProgramPath, DirectoryName);
public static readonly string UserDirectory = Path.Combine(Infrastructure.Wox.DataPath, DirectoryName);
private static readonly string[] Directories = { PreinstalledDirectory, UserDirectory };
private static void SetupPluginDirectories()
private static void ValidateUserDirectory()
{
PluginDirectories.Add(PluginDirectory);
MakesurePluginDirectoriesExist();
}
private static void MakesurePluginDirectoriesExist()
{
foreach (string pluginDirectory in PluginDirectories)
if (!Directory.Exists(UserDirectory))
{
if (!Directory.Exists(pluginDirectory))
{
try
{
Directory.CreateDirectory(pluginDirectory);
}
catch (Exception e)
{
Log.Error(e);
}
}
Directory.CreateDirectory(UserDirectory);
}
}
/// <summary>
/// Load and init all Wox plugins
/// </summary>
///
public static void Initialize()
static PluginManager()
{
SetupPluginDirectories();
var metadatas = PluginConfig.Parse(PluginDirectories);
AllPlugins = new CSharpPluginLoader().LoadPlugin(metadatas).Concat(
new JsonRPCPluginLoader<PythonPlugin>().LoadPlugin(metadatas)).ToList();
ValidateUserDirectory();
}
public static void InitializePlugins(IPublicAPI api)
{
var metadatas = PluginConfig.Parse(Directories);
var plugins1 = new CSharpPluginLoader().LoadPlugin(metadatas);
var plugins2 = new JsonRPCPluginLoader<PythonPlugin>().LoadPlugin(metadatas);
AllPlugins = plugins1.Concat(plugins2).ToList();
//load plugin i18n languages
ResourceMerger.UpdatePluginLanguages();
@@ -228,14 +210,6 @@ namespace Wox.Core.Plugin
return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign);
}
private static bool IsInstantQueryPlugin(PluginPair plugin)
{
//any plugin that takes more than 200ms for AvgQueryTime won't be treated as IInstantQuery plugin anymore.
return plugin.AvgQueryTime < 200 &&
plugin.Plugin is IInstantQuery &&
InstantQueryPlugins.Any(p => p.Metadata.ID == plugin.Metadata.ID);
}
/// <summary>
/// get specified plugin, return null if not found
/// </summary>

View File

@@ -8,7 +8,7 @@ namespace Wox.Core.Plugin
{
internal class PythonPlugin : JsonRPCPlugin
{
private static readonly string PythonHome = Path.Combine(WoxDirectroy.Executable, "PythonHome");
private static readonly string PythonHome = Path.Combine(Infrastructure.Wox.ProgramPath, "PythonHome");
private readonly ProcessStartInfo _startInfo;
public override string SupportedLanguage => AllowedLanguage.Python;

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using Wox.Core.UserSettings;
using Wox.Infrastructure.Exception;
using Wox.Infrastructure.Logger;
using Wox.Plugin;

View File

@@ -8,7 +8,7 @@ namespace Wox.Core.Resource
{
public string DirectoryName { get; protected set; }
protected string DirectoryPath => Path.Combine(WoxDirectroy.Executable, DirectoryName);
protected string DirectoryPath => Path.Combine(Infrastructure.Wox.ProgramPath, DirectoryName);
public abstract ResourceDictionary GetResourceDictionary();
}

View File

@@ -94,7 +94,7 @@ namespace Wox.Infrastructure.Image
ImageSource image = null;
if (string.IsNullOrEmpty(path))
{
path = Path.Combine(WoxDirectroy.Executable, "Images", "app.png");
path = Path.Combine(Wox.ProgramPath, "Images", "app.png");
image = new BitmapImage(new Uri(path));
return image;
}
@@ -131,14 +131,14 @@ namespace Wox.Infrastructure.Image
}
else
{
path = Path.Combine(WoxDirectroy.Executable, "Images", Path.GetFileName(path));
path = Path.Combine(Wox.ProgramPath, "Images", Path.GetFileName(path));
if (File.Exists(path))
{
image = new BitmapImage(new Uri(path));
}
else
{
path = Path.Combine(WoxDirectroy.Executable, "Images", "app.png");
path = Path.Combine(Wox.ProgramPath, "Images", "app.png");
image = new BitmapImage(new Uri(path));
}
}

View File

@@ -13,30 +13,20 @@ namespace Wox.Infrastructure.Storage
/// Normally, it has better performance, but not readable
/// You MUST mark implement class as Serializable
/// </summary>
public class BinaryStorage<T> where T : class, new()
public class BinaryStorage<T> : Storage<T> where T : new()
{
private T _binary;
private string FilePath { get; }
private string FileName { get; }
private const string FileSuffix = ".dat";
private string DirectoryPath { get; }
private const string DirectoryName = "Config";
public BinaryStorage()
{
FileName = typeof(T).Name;
DirectoryPath = Path.Combine(WoxDirectroy.Executable, DirectoryName);
FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix); ;
FileSuffix = ".dat";
DirectoryName = "Cache";
DirectoryPath = Path.Combine(DirectoryPath, DirectoryName);
FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix);
ValidateDirectory();
}
public T Load()
public override T Load()
{
if (!Directory.Exists(DirectoryPath))
{
Directory.CreateDirectory(DirectoryPath);
}
if (File.Exists(FilePath))
{
using (var stream = new FileStream(FilePath, FileMode.Open))
@@ -55,7 +45,7 @@ namespace Wox.Infrastructure.Storage
{
LoadDefault();
}
return _binary;
return Data;
}
private void Deserialize(FileStream stream)
@@ -69,17 +59,17 @@ namespace Wox.Infrastructure.Storage
try
{
_binary = (T)binaryFormatter.Deserialize(stream);
Data = (T)binaryFormatter.Deserialize(stream);
}
catch (SerializationException e)
{
LoadDefault();
Log.Error(e);
LoadDefault();
}
catch (InvalidCastException e)
{
LoadDefault();
Log.Error(e);
LoadDefault();
}
finally
{
@@ -87,9 +77,10 @@ namespace Wox.Infrastructure.Storage
}
}
private void LoadDefault()
public override void LoadDefault()
{
_binary = new T();
Data = new T();
Save();
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
@@ -108,7 +99,7 @@ namespace Wox.Infrastructure.Storage
return ayResult;
}
public void Save()
public override void Save()
{
using (var stream = new FileStream(FilePath, FileMode.Create))
{
@@ -119,7 +110,7 @@ namespace Wox.Infrastructure.Storage
try
{
binaryFormatter.Serialize(stream, _binary);
binaryFormatter.Serialize(stream, Data);
}
catch (SerializationException e)
{

View File

@@ -7,23 +7,19 @@ namespace Wox.Infrastructure.Storage
/// <summary>
/// Serialize object using json format.
/// </summary>
public class JsonStrorage<T> where T : new()
public class JsonStrorage<T> : Storage<T> where T : new()
{
private T _json;
private readonly JsonSerializerSettings _serializerSettings;
protected string FileName { get; set; }
protected string FilePath { get; set; }
protected const string FileSuffix = ".json";
protected string DirectoryPath { get; set; }
protected const string DirectoryName = "Config";
internal JsonStrorage()
{
FileName = typeof(T).Name;
DirectoryPath = Path.Combine(WoxDirectroy.Executable, DirectoryName);
FileSuffix = ".json";
DirectoryName = "Settings";
DirectoryPath = Path.Combine(DirectoryPath, DirectoryName);
FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix);
ValidateDirectory();
// use property initialization instead of DefaultValueAttribute
// easier and flexible for default value of object
_serializerSettings = new JsonSerializerSettings
@@ -33,13 +29,8 @@ namespace Wox.Infrastructure.Storage
};
}
public T Load()
public override T Load()
{
if (!Directory.Exists(DirectoryPath))
{
Directory.CreateDirectory(DirectoryPath);
}
if (File.Exists(FilePath))
{
var searlized = File.ReadAllText(FilePath);
@@ -56,33 +47,31 @@ namespace Wox.Infrastructure.Storage
{
LoadDefault();
}
return _json;
return Data;
}
private void Deserialize(string searlized)
{
try
{
_json = JsonConvert.DeserializeObject<T>(searlized, _serializerSettings);
Data = JsonConvert.DeserializeObject<T>(searlized, _serializerSettings);
}
catch (JsonSerializationException e)
{
LoadDefault();
Log.Error(e);
}
}
private void LoadDefault()
public override void LoadDefault()
{
_json = JsonConvert.DeserializeObject<T>("{}", _serializerSettings);
Data = JsonConvert.DeserializeObject<T>("{}", _serializerSettings);
Save();
}
public void Save()
public override void Save()
{
string serialized = JsonConvert.SerializeObject(_json, Formatting.Indented);
string serialized = JsonConvert.SerializeObject(Data, Formatting.Indented);
File.WriteAllText(FilePath, serialized);
}
}

View File

@@ -6,15 +6,14 @@ namespace Wox.Infrastructure.Storage
{
public PluginJsonStorage()
{
var pluginDirectoryName = "Plugins";
DirectoryName = "Plugins";
// C# releated, add python releated below
var type = typeof (T);
FileName = type.Name;
var assemblyName = type.Assembly.GetName().Name;
DirectoryPath = Path.Combine(WoxDirectroy.Executable, DirectoryName, pluginDirectoryName, assemblyName);
var assemblyName = DataType.Assembly.GetName().Name;
DirectoryPath = Path.Combine(DirectoryPath, DirectoryName, assemblyName);
FilePath = Path.Combine(DirectoryPath, FileName + FileSuffix);
ValidateDirectory();
}
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.IO;
namespace Wox.Infrastructure.Storage
{
public class Storage<T>
{
protected T Data;
protected Type DataType { get; }
public string FileName { get; }
public string FilePath { get; set; }
public string FileSuffix { get; set; }
public string DirectoryPath { get; set; }
public string DirectoryName { get; set; }
public virtual T Load()
{
throw new NotImplementedException();
}
public virtual void Save()
{
throw new NotImplementedException();
}
public virtual void LoadDefault()
{
throw new NotImplementedException();
}
protected Storage()
{
DataType = typeof (T);
FileName = DataType.Name;
DirectoryPath = Wox.DataPath;
}
protected void ValidateDirectory()
{
if (!Directory.Exists(DirectoryPath))
{
Directory.CreateDirectory(DirectoryPath);
}
}
}
}

View File

@@ -78,8 +78,8 @@
<Compile Include="Image\ImageLoader.cs" />
<Compile Include="Logger\Log.cs" />
<Compile Include="Storage\PluginSettingsStorage.cs" />
<Compile Include="Storage\Storage.cs" />
<Compile Include="SyntaxSuger.cs" />
<Compile Include="WoxDirectroy.cs" />
<Compile Include="Stopwatch.cs" />
<Compile Include="Storage\BinaryStorage.cs" />
<Compile Include="Storage\JsonStorage.cs" />
@@ -90,6 +90,7 @@
<Compile Include="Hotkey\HotkeyModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Alphabet.cs" />
<Compile Include="Wox.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wox.Plugin\Wox.Plugin.csproj">

13
Wox.Infrastructure/Wox.cs Normal file
View File

@@ -0,0 +1,13 @@
using System;
using System.IO;
using System.Reflection;
namespace Wox.Infrastructure
{
public static class Wox
{
public const string Name = "Wox";
public static readonly string ProgramPath = Directory.GetParent(Assembly.GetExecutingAssembly().Location).ToString();
public static readonly string DataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Name);
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Wox.Infrastructure
{
public static class WoxDirectroy
{
public static string Executable { get; internal set; }
}
}

View File

@@ -82,11 +82,6 @@ namespace Wox.Plugin
/// <param name="path">Plugin path (ends with .wox)</param>
void InstallPlugin(string path);
/// <summary>
/// Reload all plugins
/// </summary>
void ReloadPlugins();
/// <summary>
/// Get translation of current language
/// You need to implement IPluginI18n if you want to support multiple languages for your plugin

View File

@@ -60,7 +60,7 @@ namespace Wox.Plugin
public override int GetHashCode()
{
var hashcode = (Title?.GetHashCode() ?? 0) ^
(SubTitle?.GetHashCode() ?? 0) ;
(SubTitle?.GetHashCode() ?? 0);
return hashcode;
}
@@ -69,18 +69,21 @@ namespace Wox.Plugin
return Title + SubTitle;
}
public Result(string Title = null, string IcoPath = null, string SubTitle = null)
[Obsolete("Use IContextMenu instead")]
/// <summary>
/// Context menus associate with this result
/// </summary>
public List<Result> ContextMenu { get; set; }
[Obsolete("Use Object initializers instead")]
public Result(string Titles, string IcoPath, string SubTitle = null)
{
this.Title = Title;
this.IcoPath = IcoPath;
this.SubTitle = SubTitle;
}
[Obsolete("Use IContextMenu instead")]
/// <summary>
/// Context menus associate with this result
/// </summary>
public List<Result> ContextMenu { get; set; }
public Result() { }
/// <summary>
/// Additional data associate with this result

View File

@@ -1,16 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Wox.CommandArgs;
using Wox.Core.Plugin;
using Wox.Helper;
using Wox.Infrastructure;
using Wox.Infrastructure.Image;
using Wox.ViewModel;
using Stopwatch = Wox.Infrastructure.Stopwatch;
@@ -40,11 +36,9 @@ namespace Wox
Stopwatch.Debug("Startup Time", () =>
{
base.OnStartup(e);
WoxDirectroy.Executable = Directory.GetParent(Assembly.GetExecutingAssembly().Location).ToString();
RegisterUnhandledException();
Task.Factory.StartNew(ImageLoader.PreloadImages);
PluginManager.Initialize();
MainViewModel mainVM = new MainViewModel();
API = new PublicAPIInstance(mainVM, mainVM._settings);

View File

@@ -38,7 +38,7 @@ namespace Wox
Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(TopProperty));
fadeOutStoryboard.Children.Add(fadeOutAnimation);
imgClose.Source = ImageLoader.Load(Path.Combine(WoxDirectroy.Executable, "Images\\close.png"));
imgClose.Source = ImageLoader.Load(Path.Combine(Infrastructure.Wox.ProgramPath, "Images\\close.png"));
imgClose.MouseUp += imgClose_MouseUp;
}
@@ -66,7 +66,7 @@ namespace Wox
}
if (!File.Exists(iconPath))
{
imgIco.Source = ImageLoader.Load(Path.Combine(WoxDirectroy.Executable, "Images\\app.png"));
imgIco.Source = ImageLoader.Load(Path.Combine(Infrastructure.Wox.ProgramPath, "Images\\app.png"));
}
else {
imgIco.Source = ImageLoader.Load(iconPath);

View File

@@ -118,15 +118,6 @@ namespace Wox
Application.Current.Dispatcher.Invoke(() => PluginManager.InstallPlugin(path));
}
public void ReloadPlugins()
{
Application.Current.Dispatcher.Invoke(() =>
{
PluginManager.Initialize();
PluginManager.InitializePlugins(this);
});
}
public string GetTranslation(string key)
{
return InternationalizationManager.Instance.GetTranslation(key);

View File

@@ -496,7 +496,7 @@ namespace Wox.ViewModel
Title = string.Format(executeQueryHistoryTitle,history.Query),
SubTitle = string.Format(lastExecuteTime,history.ExecutedDateTime),
IcoPath = "Images\\history.png",
PluginDirectory = WoxDirectroy.Executable,
PluginDirectory = Infrastructure.Wox.ProgramPath,
Action = _ =>{
QueryText = history.Query;
OnTextBoxSelected();
@@ -511,9 +511,11 @@ namespace Wox.ViewModel
Result menu;
if (_topMostRecord.IsTopMost(result))
{
menu = new Result(InternationalizationManager.Instance.GetTranslation("cancelTopMostInThisQuery"), "Images\\down.png")
menu = new Result
{
PluginDirectory = WoxDirectroy.Executable,
Title = InternationalizationManager.Instance.GetTranslation("cancelTopMostInThisQuery"),
IcoPath = "Images\\down.png",
PluginDirectory = Infrastructure.Wox.ProgramPath,
Action = _ =>
{
_topMostRecord.Remove(result);
@@ -524,9 +526,11 @@ namespace Wox.ViewModel
}
else
{
menu = new Result(InternationalizationManager.Instance.GetTranslation("setAsTopMostInThisQuery"), "Images\\up.png")
menu = new Result
{
PluginDirectory = WoxDirectroy.Executable,
Title = InternationalizationManager.Instance.GetTranslation("setAsTopMostInThisQuery"),
IcoPath = "Images\\up.png",
PluginDirectory = Infrastructure.Wox.ProgramPath,
Action = _ =>
{
_topMostRecord.AddOrUpdate(result);
@@ -551,8 +555,11 @@ namespace Wox.ViewModel
var icon = metadata.IcoPath;
var subtitle = $"{author}: {metadata.Author}, {website}: {metadata.Website} {version}: {metadata.Version}";
var menu = new Result(title, icon, subtitle)
var menu = new Result
{
Title = title,
IcoPath = icon,
SubTitle = subtitle,
PluginDirectory = metadata.PluginDirectory,
Action = _ => false
};