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

This commit is contained in:
Jeremy Wu 2020-06-28 12:17:57 +10:00
commit 2ff4ffdf91
63 changed files with 4993 additions and 369 deletions

BIN
Doc/Logo/app_error.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
Doc/Logo/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
Doc/Logo/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

1
Doc/Logo/logo.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 382.6 382.5"><defs><linearGradient id="a" x2="249.9" y1="191.3" y2="191.3" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#1b9de2"/><stop offset=".2" stop-color="#1595df"/><stop offset=".7" stop-color="#0680d7"/><stop offset="1" stop-color="#0078d4"/></linearGradient><linearGradient id="b" x1="697.3" x2="809.9" y1="499.2" y2="499.2" gradientTransform="rotate(49.2 809.6 -269.1)" xlink:href="#a"/><linearGradient id="c" x1="143.6" x2="393.5" y1="249.8" y2="249.8" gradientTransform="rotate(180 263.1 220.5)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0c59a4"/><stop offset="1" stop-color="#114a8b"/></linearGradient></defs><path fill="url(#a)" d="M117 382.5H0v-189C0 90.7 84 0 186.9 0h63v120.4h-54.6c-46.8 0-78 31.2-78 78l-.1 184.1z"/><path fill="url(#b)" d="M249.9 182.6l.2-46.8h-54.7c-39 0-62.4 23.4-62.4 62.4l-.2 47 54.6-.1c39 0 62.5-23.4 62.5-62.5z"/><path fill="url(#c)" d="M265.5 0h117v189c0 102.8-84 193.5-186.8 193.5h-63V262.1h54.6c46.9 0 78.1-31.2 78.1-78L265.5 0z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
Doc/Logo/logo128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
Doc/Logo/logo16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

BIN
Doc/Logo/logo256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
Doc/Logo/logo32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

BIN
Doc/Logo/logo48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,019 B

BIN
Doc/Logo/logo512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Doc/Logo/logo64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -32,10 +32,9 @@ namespace Flow.Launcher.Core.Configuration
try try
{ {
MoveUserDataFolder(DataLocation.PortableDataPath, DataLocation.RoamingDataPath); MoveUserDataFolder(DataLocation.PortableDataPath, DataLocation.RoamingDataPath);
#if DEBUG #if !DEBUG
// Create shortcuts and uninstaller are not required in debug mode, // Create shortcuts and uninstaller are not required in debug mode,
// otherwise will repoint the path of the actual installed production version to the debug version // otherwise will repoint the path of the actual installed production version to the debug version
#else
CreateShortcuts(); CreateShortcuts();
CreateUninstallerEntry(); CreateUninstallerEntry();
#endif #endif
@ -48,10 +47,7 @@ namespace Flow.Launcher.Core.Configuration
} }
catch (Exception e) catch (Exception e)
{ {
#if !DEBUG Log.Exception("|Portable.DisablePortableMode|Error occured while disabling portable mode", e);
Log.Exception("Portable", "Error occured while disabling portable mode", e);
#endif
throw;
} }
} }
@ -60,10 +56,9 @@ namespace Flow.Launcher.Core.Configuration
try try
{ {
MoveUserDataFolder(DataLocation.RoamingDataPath, DataLocation.PortableDataPath); MoveUserDataFolder(DataLocation.RoamingDataPath, DataLocation.PortableDataPath);
#if DEBUG #if !DEBUG
// Remove shortcuts and uninstaller are not required in debug mode, // Remove shortcuts and uninstaller are not required in debug mode,
// otherwise will delete the actual installed production version // otherwise will delete the actual installed production version
#else
RemoveShortcuts(); RemoveShortcuts();
RemoveUninstallerEntry(); RemoveUninstallerEntry();
#endif #endif
@ -76,10 +71,7 @@ namespace Flow.Launcher.Core.Configuration
} }
catch (Exception e) catch (Exception e)
{ {
#if !DEBUG Log.Exception("|Portable.EnablePortableMode|Error occured while enabling portable mode", e);
Log.Exception("Portable", "Error occured while enabling portable mode", e);
#endif
throw;
} }
} }
@ -125,14 +117,13 @@ namespace Flow.Launcher.Core.Configuration
public void CreateUninstallerEntry() public void CreateUninstallerEntry()
{ {
var uninstallRegSubKey = @"Software\Microsoft\Windows\CurrentVersion\Uninstall"; var uninstallRegSubKey = @"Software\Microsoft\Windows\CurrentVersion\Uninstall";
// NB: Sometimes the Uninstall key doesn't exist
using (var parentKey =
RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default)
.CreateSubKey("Uninstall", RegistryKeyPermissionCheck.ReadWriteSubTree)) {; }
var key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default) using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default))
.CreateSubKey(uninstallRegSubKey + "\\" + Constant.FlowLauncher, RegistryKeyPermissionCheck.ReadWriteSubTree); using (var subKey1 = baseKey.CreateSubKey(uninstallRegSubKey, RegistryKeyPermissionCheck.ReadWriteSubTree))
key.SetValue("DisplayIcon", Constant.ApplicationDirectory + "\\app.ico", RegistryValueKind.String); using (var subKey2 = subKey1.CreateSubKey(Constant.FlowLauncher, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
subKey2.SetValue("DisplayIcon", Path.Combine(Constant.ApplicationDirectory, "app.ico"), RegistryValueKind.String);
}
using (var portabilityUpdater = NewUpdateManager()) using (var portabilityUpdater = NewUpdateManager())
{ {
@ -142,7 +133,10 @@ namespace Flow.Launcher.Core.Configuration
internal void IndicateDeletion(string filePathTodelete) internal void IndicateDeletion(string filePathTodelete)
{ {
using (StreamWriter sw = File.CreateText(filePathTodelete + "\\" + DataLocation.DeletionIndicatorFile)){} var deleteFilePath = Path.Combine(filePathTodelete, DataLocation.DeletionIndicatorFile);
using (var _ = File.CreateText(deleteFilePath))
{
}
} }
///<summary> ///<summary>
@ -152,21 +146,18 @@ namespace Flow.Launcher.Core.Configuration
public void PreStartCleanUpAfterPortabilityUpdate() public void PreStartCleanUpAfterPortabilityUpdate()
{ {
// Specify here so this method does not rely on other environment variables to initialise // Specify here so this method does not rely on other environment variables to initialise
var portableDataPath = Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location.NonNull()).ToString(), "UserData"); var portableDataDir = Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location.NonNull()).ToString(), "UserData");
var roamingDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FlowLauncher"); var roamingDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FlowLauncher");
bool DataLocationPortableDeleteRequired = false; // Get full path to the .dead files for each case
bool DataLocationRoamingDeleteRequired = false; var portableDataDeleteFilePath = Path.Combine(portableDataDir, DataLocation.DeletionIndicatorFile);
var roamingDataDeleteFilePath = Path.Combine(roamingDataDir, DataLocation.DeletionIndicatorFile);
if ((roamingDataPath + "\\" + DataLocation.DeletionIndicatorFile).FileExits()) // If the data folder in %appdata% is marked for deletion,
DataLocationRoamingDeleteRequired = true; // delete it and prompt the user to pick the portable data location
if (File.Exists(roamingDataDeleteFilePath))
if ((portableDataPath + "\\" + DataLocation.DeletionIndicatorFile).FileExits())
DataLocationPortableDeleteRequired = true;
if (DataLocationRoamingDeleteRequired)
{ {
FilesFolders.RemoveFolderIfExists(roamingDataPath); FilesFolders.RemoveFolderIfExists(roamingDataDir);
if (MessageBox.Show("Flow Launcher has detected you enabled portable mode, " + if (MessageBox.Show("Flow Launcher has detected you enabled portable mode, " +
"would you like to move it to a different location?", string.Empty, "would you like to move it to a different location?", string.Empty,
@ -176,18 +167,15 @@ namespace Flow.Launcher.Core.Configuration
Environment.Exit(0); Environment.Exit(0);
} }
return;
} }
// Otherwise, if the portable data folder is marked for deletion,
if(DataLocationPortableDeleteRequired) // delete it and notify the user about it.
else if (File.Exists(portableDataDeleteFilePath))
{ {
FilesFolders.RemoveFolderIfExists(portableDataPath); FilesFolders.RemoveFolderIfExists(portableDataDir);
MessageBox.Show("Flow Launcher has detected you disabled portable mode, " + MessageBox.Show("Flow Launcher has detected you disabled portable mode, " +
"the relevant shortcuts and uninstaller entry have been created"); "the relevant shortcuts and uninstaller entry have been created");
return;
} }
} }
@ -196,7 +184,7 @@ namespace Flow.Launcher.Core.Configuration
var roamingLocationExists = DataLocation.RoamingDataPath.LocationExists(); var roamingLocationExists = DataLocation.RoamingDataPath.LocationExists();
var portableLocationExists = DataLocation.PortableDataPath.LocationExists(); var portableLocationExists = DataLocation.PortableDataPath.LocationExists();
if(roamingLocationExists && portableLocationExists) if (roamingLocationExists && portableLocationExists)
{ {
MessageBox.Show(string.Format("Flow Launcher detected your user data exists both in {0} and " + MessageBox.Show(string.Format("Flow Launcher detected your user data exists both in {0} and " +
"{1}. {2}{2}Please delete {1} in order to proceed. No changes have occured.", "{1}. {2}{2}Please delete {1} in order to proceed. No changes have occured.",

View file

@ -2,9 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.IO; using System.IO;
using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Flow.Launcher.Infrastructure.Exception; using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
@ -13,24 +12,16 @@ namespace Flow.Launcher.Core.Plugin
internal abstract class PluginConfig internal abstract class PluginConfig
{ {
private const string PluginConfigName = "plugin.json";
private static readonly List<PluginMetadata> PluginMetadatas = new List<PluginMetadata>();
/// <summary> /// <summary>
/// Parse plugin metadata in giving directories /// Parse plugin metadata in the given directories
/// </summary> /// </summary>
/// <param name="pluginDirectories"></param> /// <param name="pluginDirectories"></param>
/// <returns></returns> /// <returns></returns>
public static List<PluginMetadata> Parse(string[] pluginDirectories) public static List<PluginMetadata> Parse(string[] pluginDirectories)
{ {
PluginMetadatas.Clear(); var allPluginMetadata = new List<PluginMetadata>();
var directories = pluginDirectories.SelectMany(Directory.GetDirectories); var directories = pluginDirectories.SelectMany(Directory.GetDirectories);
ParsePluginConfigs(directories);
return PluginMetadatas;
}
private static void ParsePluginConfigs(IEnumerable<string> directories)
{
// todo use linq when diable plugin is implmented since parallel.foreach + list is not thread saft // todo use linq when diable plugin is implmented since parallel.foreach + list is not thread saft
foreach (var directory in directories) foreach (var directory in directories)
{ {
@ -50,15 +41,17 @@ namespace Flow.Launcher.Core.Plugin
PluginMetadata metadata = GetPluginMetadata(directory); PluginMetadata metadata = GetPluginMetadata(directory);
if (metadata != null) if (metadata != null)
{ {
PluginMetadatas.Add(metadata); allPluginMetadata.Add(metadata);
} }
} }
} }
return allPluginMetadata;
} }
private static PluginMetadata GetPluginMetadata(string pluginDirectory) private static PluginMetadata GetPluginMetadata(string pluginDirectory)
{ {
string configPath = Path.Combine(pluginDirectory, PluginConfigName); string configPath = Path.Combine(pluginDirectory, Constant.PluginMetadataFileName);
if (!File.Exists(configPath)) if (!File.Exists(configPath))
{ {
Log.Error($"|PluginConfig.GetPluginMetadata|Didn't find config file <{configPath}>"); Log.Error($"|PluginConfig.GetPluginMetadata|Didn't find config file <{configPath}>");
@ -81,7 +74,6 @@ namespace Flow.Launcher.Core.Plugin
return null; return null;
} }
if (!AllowedLanguage.IsAllowed(metadata.Language)) if (!AllowedLanguage.IsAllowed(metadata.Language))
{ {
Log.Error($"|PluginConfig.GetPluginMetadata|Invalid language <{metadata.Language}> for config <{configPath}>"); Log.Error($"|PluginConfig.GetPluginMetadata|Invalid language <{metadata.Language}> for config <{configPath}>");

View file

@ -1,9 +1,11 @@
using System; using System;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json; using Newtonsoft.Json;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger;
namespace Flow.Launcher.Core.Plugin namespace Flow.Launcher.Core.Plugin
{ {
@ -13,28 +15,28 @@ namespace Flow.Launcher.Core.Plugin
{ {
if (File.Exists(path)) if (File.Exists(path))
{ {
string tempFoler = Path.Combine(Path.GetTempPath(), "flowlauncher\\plugins"); string tempFolder = Path.Combine(Path.GetTempPath(), "flowlauncher", "plugins");
if (Directory.Exists(tempFoler)) if (Directory.Exists(tempFolder))
{ {
Directory.Delete(tempFoler, true); Directory.Delete(tempFolder, true);
} }
UnZip(path, tempFoler, true); UnZip(path, tempFolder, true);
string iniPath = Path.Combine(tempFoler, "plugin.json"); string jsonPath = Path.Combine(tempFolder, Constant.PluginMetadataFileName);
if (!File.Exists(iniPath)) if (!File.Exists(jsonPath))
{ {
MessageBox.Show("Install failed: plugin config is missing"); MessageBox.Show("Install failed: plugin config is missing");
return; return;
} }
PluginMetadata plugin = GetMetadataFromJson(tempFoler); PluginMetadata plugin = GetMetadataFromJson(tempFolder);
if (plugin == null || plugin.Name == null) if (plugin == null || plugin.Name == null)
{ {
MessageBox.Show("Install failed: plugin config is invalid"); MessageBox.Show("Install failed: plugin config is invalid");
return; return;
} }
string pluginFolerPath = Infrastructure.UserSettings.DataLocation.PluginsDirectory; string pluginFolderPath = Infrastructure.UserSettings.DataLocation.PluginsDirectory;
string newPluginName = plugin.Name string newPluginName = plugin.Name
.Replace("/", "_") .Replace("/", "_")
@ -46,7 +48,9 @@ namespace Flow.Launcher.Core.Plugin
.Replace("*", "_") .Replace("*", "_")
.Replace("|", "_") .Replace("|", "_")
+ "-" + Guid.NewGuid(); + "-" + Guid.NewGuid();
string newPluginPath = Path.Combine(pluginFolerPath, newPluginName);
string newPluginPath = Path.Combine(pluginFolderPath, newPluginName);
string content = $"Do you want to install following plugin?{Environment.NewLine}{Environment.NewLine}" + string content = $"Do you want to install following plugin?{Environment.NewLine}{Environment.NewLine}" +
$"Name: {plugin.Name}{Environment.NewLine}" + $"Name: {plugin.Name}{Environment.NewLine}" +
$"Version: {plugin.Version}{Environment.NewLine}" + $"Version: {plugin.Version}{Environment.NewLine}" +
@ -71,8 +75,7 @@ namespace Flow.Launcher.Core.Plugin
File.Create(Path.Combine(existingPlugin.Metadata.PluginDirectory, "NeedDelete.txt")).Close(); File.Create(Path.Combine(existingPlugin.Metadata.PluginDirectory, "NeedDelete.txt")).Close();
} }
UnZip(path, newPluginPath, true); Directory.Move(tempFolder, newPluginPath);
Directory.Delete(tempFoler, true);
//exsiting plugins may be has loaded by application, //exsiting plugins may be has loaded by application,
//if we try to delelte those kind of plugins, we will get a error that indicate the //if we try to delelte those kind of plugins, we will get a error that indicate the
@ -94,7 +97,7 @@ namespace Flow.Launcher.Core.Plugin
private static PluginMetadata GetMetadataFromJson(string pluginDirectory) private static PluginMetadata GetMetadataFromJson(string pluginDirectory)
{ {
string configPath = Path.Combine(pluginDirectory, "plugin.json"); string configPath = Path.Combine(pluginDirectory, Constant.PluginMetadataFileName);
PluginMetadata metadata; PluginMetadata metadata;
if (!File.Exists(configPath)) if (!File.Exists(configPath))
@ -107,36 +110,20 @@ namespace Flow.Launcher.Core.Plugin
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath)); metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginDirectory = pluginDirectory; metadata.PluginDirectory = pluginDirectory;
} }
catch (Exception) catch (Exception e)
{ {
string error = $"Parse plugin config {configPath} failed: json format is not valid"; Log.Exception($"|PluginInstaller.GetMetadataFromJson|plugin config {configPath} failed: invalid json format", e);
#if (DEBUG)
{
throw new Exception(error);
}
#endif
return null; return null;
} }
if (!AllowedLanguage.IsAllowed(metadata.Language)) if (!AllowedLanguage.IsAllowed(metadata.Language))
{ {
string error = $"Parse plugin config {configPath} failed: invalid language {metadata.Language}"; Log.Error($"|PluginInstaller.GetMetadataFromJson|plugin config {configPath} failed: invalid language {metadata.Language}");
#if (DEBUG)
{
throw new Exception(error);
}
#endif
return null; return null;
} }
if (!File.Exists(metadata.ExecuteFilePath)) if (!File.Exists(metadata.ExecuteFilePath))
{ {
string error = $"Parse plugin config {configPath} failed: ExecuteFile {metadata.ExecuteFilePath} didn't exist"; Log.Error($"|PluginInstaller.GetMetadataFromJson|plugin config {configPath} failed: file {metadata.ExecuteFilePath} doesn't exist");
#if (DEBUG)
{
throw new Exception(error);
}
#endif
return null; return null;
} }
@ -144,58 +131,38 @@ namespace Flow.Launcher.Core.Plugin
} }
/// <summary> /// <summary>
/// unzip /// unzip plugin contents to the given directory.
/// </summary> /// </summary>
/// <param name="zipedFile">The ziped file.</param> /// <param name="zipFile">The path to the zip file.</param>
/// <param name="strDirectory">The STR directory.</param> /// <param name="strDirectory">The output directory.</param>
/// <param name="overWrite">overwirte</param> /// <param name="overWrite">overwirte</param>
private static void UnZip(string zipedFile, string strDirectory, bool overWrite) private static void UnZip(string zipFile, string strDirectory, bool overWrite)
{ {
if (strDirectory == "") if (strDirectory == "")
strDirectory = Directory.GetCurrentDirectory(); strDirectory = Directory.GetCurrentDirectory();
if (!strDirectory.EndsWith("\\"))
strDirectory = strDirectory + "\\";
using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipedFile))) using (ZipInputStream zipStream = new ZipInputStream(File.OpenRead(zipFile)))
{ {
ZipEntry theEntry; ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null) while ((theEntry = zipStream.GetNextEntry()) != null)
{ {
string directoryName = ""; var pathToZip = theEntry.Name;
string pathToZip = ""; var directoryName = String.IsNullOrEmpty(pathToZip) ? "" : Path.GetDirectoryName(pathToZip);
pathToZip = theEntry.Name; var fileName = Path.GetFileName(pathToZip);
var destinationDir = Path.Combine(strDirectory, directoryName);
var destinationFile = Path.Combine(destinationDir, fileName);
if (pathToZip != "") Directory.CreateDirectory(destinationDir);
directoryName = Path.GetDirectoryName(pathToZip) + "\\";
string fileName = Path.GetFileName(pathToZip); if (String.IsNullOrEmpty(fileName) || (File.Exists(destinationFile) && !overWrite))
continue;
Directory.CreateDirectory(strDirectory + directoryName); using (FileStream streamWriter = File.Create(destinationFile))
if (fileName != "")
{ {
if ((File.Exists(strDirectory + directoryName + fileName) && overWrite) || (!File.Exists(strDirectory + directoryName + fileName))) zipStream.CopyTo(streamWriter);
{
using (FileStream streamWriter = File.Create(strDirectory + directoryName + fileName))
{
byte[] data = new byte[2048];
while (true)
{
int size = s.Read(data, 0, data.Length);
if (size > 0)
streamWriter.Write(data, 0, size);
else
break;
}
streamWriter.Close();
}
}
} }
} }
s.Close();
} }
} }
} }

View file

@ -19,10 +19,6 @@ namespace Flow.Launcher.Core.Plugin
{ {
private static IEnumerable<PluginPair> _contextMenuPlugins; private static IEnumerable<PluginPair> _contextMenuPlugins;
/// <summary>
/// Directories that will hold Flow Launcher plugin directory
/// </summary>
public static List<PluginPair> AllPlugins { get; private set; } public static List<PluginPair> AllPlugins { get; private set; }
public static readonly List<PluginPair> GlobalPlugins = new List<PluginPair>(); public static readonly List<PluginPair> GlobalPlugins = new List<PluginPair>();
public static readonly Dictionary<string, PluginPair> NonGlobalPlugins = new Dictionary<string, PluginPair>(); public static readonly Dictionary<string, PluginPair> NonGlobalPlugins = new Dictionary<string, PluginPair>();
@ -32,27 +28,18 @@ namespace Flow.Launcher.Core.Plugin
// todo happlebao, this should not be public, the indicator function should be embeded // todo happlebao, this should not be public, the indicator function should be embeded
public static PluginsSettings Settings; public static PluginsSettings Settings;
private static List<PluginMetadata> _metadatas; private static List<PluginMetadata> _metadatas;
private static readonly string[] Directories = { Constant.PreinstalledDirectory, DataLocation.PluginsDirectory };
private static void ValidateUserDirectory() /// <summary>
{ /// Directories that will hold Flow Launcher plugin directory
if (!Directory.Exists(DataLocation.PluginsDirectory)) /// </summary>
{ private static readonly string[] Directories = { Constant.PreinstalledDirectory, DataLocation.PluginsDirectory };
Directory.CreateDirectory(DataLocation.PluginsDirectory);
}
}
private static void DeletePythonBinding() private static void DeletePythonBinding()
{ {
const string binding = "flowlauncher.py"; const string binding = "flowlauncher.py";
var directory = DataLocation.PluginsDirectory; foreach (var subDirectory in Directory.GetDirectories(DataLocation.PluginsDirectory))
foreach (var subDirectory in Directory.GetDirectories(directory))
{ {
var path = Path.Combine(subDirectory, binding); File.Delete(Path.Combine(subDirectory, binding));
if (File.Exists(path))
{
File.Delete(path);
}
} }
} }
@ -76,7 +63,8 @@ namespace Flow.Launcher.Core.Plugin
static PluginManager() static PluginManager()
{ {
ValidateUserDirectory(); // validate user directory
Directory.CreateDirectory(DataLocation.PluginsDirectory);
// force old plugins use new python binding // force old plugins use new python binding
DeletePythonBinding(); DeletePythonBinding();
} }
@ -132,9 +120,10 @@ namespace Flow.Launcher.Core.Plugin
GlobalPlugins.Add(plugin); GlobalPlugins.Add(plugin);
// Plugins may have multiple ActionKeywords, eg. WebSearch // Plugins may have multiple ActionKeywords, eg. WebSearch
plugin.Metadata.ActionKeywords.Where(x => x != Query.GlobalPluginWildcardSign) plugin.Metadata.ActionKeywords
.ToList() .Where(x => x != Query.GlobalPluginWildcardSign)
.ForEach(x => NonGlobalPlugins[x] = plugin); .ToList()
.ForEach(x => NonGlobalPlugins[x] = plugin);
} }
if (failedPlugins.Any()) if (failedPlugins.Any())
@ -164,9 +153,9 @@ namespace Flow.Launcher.Core.Plugin
public static List<Result> QueryForPlugin(PluginPair pair, Query query) public static List<Result> QueryForPlugin(PluginPair pair, Query query)
{ {
var results = new List<Result>();
try try
{ {
List<Result> results = null;
var metadata = pair.Metadata; var metadata = pair.Metadata;
var milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", () => var milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", () =>
{ {
@ -175,13 +164,12 @@ namespace Flow.Launcher.Core.Plugin
}); });
metadata.QueryCount += 1; metadata.QueryCount += 1;
metadata.AvgQueryTime = metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2; metadata.AvgQueryTime = metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
return results;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e); Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e);
return new List<Result>();
} }
return results;
} }
public static void UpdatePluginMetadata(List<Result> results, PluginMetadata metadata, Query query) public static void UpdatePluginMetadata(List<Result> results, PluginMetadata metadata, Query query)
@ -221,47 +209,34 @@ namespace Flow.Launcher.Core.Plugin
public static List<Result> GetContextMenusForPlugin(Result result) public static List<Result> GetContextMenusForPlugin(Result result)
{ {
var results = new List<Result>();
var pluginPair = _contextMenuPlugins.FirstOrDefault(o => o.Metadata.ID == result.PluginID); var pluginPair = _contextMenuPlugins.FirstOrDefault(o => o.Metadata.ID == result.PluginID);
if (pluginPair != null) if (pluginPair != null)
{ {
var metadata = pluginPair.Metadata;
var plugin = (IContextMenu)pluginPair.Plugin; var plugin = (IContextMenu)pluginPair.Plugin;
try try
{ {
var results = plugin.LoadContextMenus(result); results = plugin.LoadContextMenus(result);
foreach (var r in results) foreach (var r in results)
{ {
r.PluginDirectory = metadata.PluginDirectory; r.PluginDirectory = pluginPair.Metadata.PluginDirectory;
r.PluginID = metadata.ID; r.PluginID = pluginPair.Metadata.ID;
r.OriginQuery = result.OriginQuery; r.OriginQuery = result.OriginQuery;
} }
return results;
} }
catch (Exception e) catch (Exception e)
{ {
Log.Exception($"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{metadata.Name}>", e); Log.Exception($"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>", e);
return new List<Result>();
} }
} }
else return results;
{
return new List<Result>();
}
} }
public static bool ActionKeywordRegistered(string actionKeyword) public static bool ActionKeywordRegistered(string actionKeyword)
{ {
if (actionKeyword != Query.GlobalPluginWildcardSign && return actionKeyword != Query.GlobalPluginWildcardSign
NonGlobalPlugins.ContainsKey(actionKeyword)) && NonGlobalPlugins.ContainsKey(actionKeyword);
{
return true;
}
else
{
return false;
}
} }
/// <summary> /// <summary>
@ -299,7 +274,7 @@ namespace Flow.Launcher.Core.Plugin
GlobalPlugins.Remove(plugin); GlobalPlugins.Remove(plugin);
} }
if(oldActionkeyword != Query.GlobalPluginWildcardSign) if (oldActionkeyword != Query.GlobalPluginWildcardSign)
NonGlobalPlugins.Remove(oldActionkeyword); NonGlobalPlugins.Remove(oldActionkeyword);

View file

@ -21,7 +21,7 @@ namespace Flow.Launcher.Core.Plugin
public static List<PluginPair> Plugins(List<PluginMetadata> metadatas, PluginsSettings settings) public static List<PluginPair> Plugins(List<PluginMetadata> metadatas, PluginsSettings settings)
{ {
var dotnetPlugins = DotNetPlugins(metadatas).ToList(); var dotnetPlugins = DotNetPlugins(metadatas);
var pythonPlugins = PythonPlugins(metadatas, settings.PythonDirectory); var pythonPlugins = PythonPlugins(metadatas, settings.PythonDirectory);
var executablePlugins = ExecutablePlugins(metadatas); var executablePlugins = ExecutablePlugins(metadatas);
var plugins = dotnetPlugins.Concat(pythonPlugins).Concat(executablePlugins).ToList(); var plugins = dotnetPlugins.Concat(pythonPlugins).Concat(executablePlugins).ToList();
@ -46,75 +46,58 @@ namespace Flow.Launcher.Core.Plugin
var type = types.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IPlugin))); var type = types.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IPlugin)));
var plugin = (IPlugin)Activator.CreateInstance(type); var plugin = (IPlugin)Activator.CreateInstance(type);
#else #else
Assembly assembly; Assembly assembly = null;
IPlugin plugin = null;
try try
{ {
assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(metadata.ExecuteFilePath); assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(metadata.ExecuteFilePath);
}
catch (Exception e)
{
erroredPlugins.Add(metadata.Name);
Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
return;
}
Type type;
try
{
var types = assembly.GetTypes(); var types = assembly.GetTypes();
var type = types.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IPlugin)));
type = types.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(typeof(IPlugin))); plugin = (IPlugin)Activator.CreateInstance(type);
}
catch (Exception e) when (assembly == null)
{
Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e);
} }
catch (InvalidOperationException e) catch (InvalidOperationException e)
{ {
erroredPlugins.Add(metadata.Name);
Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e); Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e);
return;
} }
catch (ReflectionTypeLoadException e) catch (ReflectionTypeLoadException e)
{ {
erroredPlugins.Add(metadata.Name);
Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e); Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e);
return;
}
IPlugin plugin;
try
{
plugin = (IPlugin)Activator.CreateInstance(type);
} }
catch (Exception e) catch (Exception e)
{ {
erroredPlugins.Add(metadata.Name);
Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e); Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e);
}
if (plugin == null)
{
erroredPlugins.Add(metadata.Name);
return; return;
} }
#endif #endif
PluginPair pair = new PluginPair plugins.Add(new PluginPair
{ {
Plugin = plugin, Plugin = plugin,
Metadata = metadata Metadata = metadata
}; });
plugins.Add(pair);
}); });
metadata.InitTime += milliseconds; metadata.InitTime += milliseconds;
} }
if (erroredPlugins.Count > 0) if (erroredPlugins.Count > 0)
{ {
var errorPluginString = ""; var errorPluginString = String.Join(Environment.NewLine, erroredPlugins);
var errorMessage = "The following " var errorMessage = "The following "
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ") + (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
+ "errored and cannot be loaded:"; + "errored and cannot be loaded:";
erroredPlugins.ForEach(x => errorPluginString += x + Environment.NewLine);
Task.Run(() => Task.Run(() =>
{ {
MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" +
@ -127,65 +110,74 @@ namespace Flow.Launcher.Core.Plugin
return plugins; return plugins;
} }
public static IEnumerable<PluginPair> PythonPlugins(List<PluginMetadata> source, string pythonDirecotry) public static IEnumerable<PluginPair> PythonPlugins(List<PluginMetadata> source, string pythonDirectory)
{ {
var metadatas = source.Where(o => o.Language.ToUpper() == AllowedLanguage.Python); // try to set Constant.PythonPath, either from
string filename; // PATH or from the given pythonDirectory
if (string.IsNullOrEmpty(pythonDirectory))
if (string.IsNullOrEmpty(pythonDirecotry))
{ {
var paths = Environment.GetEnvironmentVariable(PATH); var paths = Environment.GetEnvironmentVariable(PATH);
if (paths != null) if (paths != null)
{ {
var pythonPaths = paths.Split(';').Where(p => p.ToLower().Contains(Python)); var pythonInPath = paths
if (pythonPaths.Any()) .Split(';')
.Where(p => p.ToLower().Contains(Python))
.Any();
if (pythonInPath)
{ {
filename = PythonExecutable; Constant.PythonPath = PythonExecutable;
} }
else else
{ {
Log.Error("|PluginsLoader.PythonPlugins|Python can't be found in PATH."); Log.Error("|PluginsLoader.PythonPlugins|Python can't be found in PATH.");
return new List<PluginPair>();
} }
} }
else else
{ {
Log.Error("|PluginsLoader.PythonPlugins|PATH environment variable is not set."); Log.Error("|PluginsLoader.PythonPlugins|PATH environment variable is not set.");
return new List<PluginPair>();
} }
} }
else else
{ {
var path = Path.Combine(pythonDirecotry, PythonExecutable); var path = Path.Combine(pythonDirectory, PythonExecutable);
if (File.Exists(path)) if (File.Exists(path))
{ {
filename = path; Constant.PythonPath = path;
} }
else else
{ {
Log.Error("|PluginsLoader.PythonPlugins|Can't find python executable in <b "); Log.Error($"|PluginsLoader.PythonPlugins|Can't find python executable in {path}");
return new List<PluginPair>();
} }
} }
Constant.PythonPath = filename;
var plugins = metadatas.Select(metadata => new PluginPair // if we have a path to the python executable,
// load every python plugin pair.
if (String.IsNullOrEmpty(Constant.PythonPath))
{ {
Plugin = new PythonPlugin(filename), return new List<PluginPair>();
Metadata = metadata }
}); else
return plugins; {
return source
.Where(o => o.Language.ToUpper() == AllowedLanguage.Python)
.Select(metadata => new PluginPair
{
Plugin = new PythonPlugin(Constant.PythonPath),
Metadata = metadata
});
}
} }
public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source) public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source)
{ {
var metadatas = source.Where(o => o.Language.ToUpper() == AllowedLanguage.Executable); return source
.Where(o => o.Language.ToUpper() == AllowedLanguage.Executable)
var plugins = metadatas.Select(metadata => new PluginPair .Select(metadata => new PluginPair
{ {
Plugin = new ExecutablePlugin(metadata.ExecuteFilePath), Plugin = new ExecutablePlugin(metadata.ExecuteFilePath),
Metadata = metadata Metadata = metadata
}); });
return plugins;
} }
} }

View file

@ -86,8 +86,8 @@ namespace Flow.Launcher.Core
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}";
FilesFolders.Copy(DataLocation.PortableDataPath, targetDestination); FilesFolders.Copy(DataLocation.PortableDataPath, targetDestination);
if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination)) if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination))
MessageBox.Show(string.Format("Flow Launcher was not able to move your user profile data to the new update version. Please manually" + MessageBox.Show("Flow Launcher 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}", DataLocation.PortableDataPath, targetDestination)); $"move your profile data folder from {DataLocation.PortableDataPath} to {targetDestination}");
} }
else else
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -8,6 +8,7 @@ namespace Flow.Launcher.Infrastructure
{ {
public const string FlowLauncher = "Flow.Launcher"; public const string FlowLauncher = "Flow.Launcher";
public const string Plugins = "Plugins"; public const string Plugins = "Plugins";
public const string PluginMetadataFileName = "plugin.json";
public const string ApplicationFileName = FlowLauncher + ".exe"; public const string ApplicationFileName = FlowLauncher + ".exe";

View file

@ -1,4 +1,4 @@
<Window x:Class="Flow.Launcher.ActionKeywords" <Window x:Class="Flow.Launcher.ActionKeywords"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ActionKeywords" Title="ActionKeywords"
@ -6,38 +6,36 @@
ResizeMode="NoResize" ResizeMode="NoResize"
Loaded="ActionKeyword_OnLoaded" Loaded="ActionKeyword_OnLoaded"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Height="200" Width="600"> Height="250" Width="500">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition Height="60"/>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="170" /> <ColumnDefinition Width="150" />
<ColumnDefinition /> <ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Margin="10" FontSize="14" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" <TextBlock FontSize="14" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Right" Text="{DynamicResource oldActionKeyword}" /> HorizontalAlignment="Left" Text="{DynamicResource currentActionKeywords}" />
<TextBlock x:Name="tbOldActionKeyword" Margin="10" FontSize="14" Grid.Row="0" Grid.Column="1" <TextBlock x:Name="tbOldActionKeyword" Grid.Row="0" Grid.Column="1" Margin="170 10 10 10" FontSize="14"
VerticalAlignment="Center" HorizontalAlignment="Left"> VerticalAlignment="Center" HorizontalAlignment="Left" />
Old ActionKeywords:
</TextBlock>
<TextBlock Margin="10" FontSize="14" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" <TextBlock FontSize="14" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center"
HorizontalAlignment="Right" Text="{DynamicResource newActionKeyword}" /> HorizontalAlignment="Left" Text="{DynamicResource newActionKeyword}" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Grid.Column="1"> <StackPanel Grid.Row="1" Orientation="Horizontal" Grid.Column="1">
<TextBox x:Name="tbAction" Margin="10" Width="400" VerticalAlignment="Center" HorizontalAlignment="Left" /> <TextBox x:Name="tbAction" Margin="170 10 15 10" Width="105" VerticalAlignment="Center" HorizontalAlignment="Left" />
</StackPanel> </StackPanel>
<TextBlock Grid.Row="2" Grid.ColumnSpan="1" Grid.Column="1" Padding="5" Foreground="Gray" <TextBlock Grid.Row="2" Grid.ColumnSpan="1" Grid.Column="1" Foreground="Gray"
Text="{DynamicResource actionkeyword_tips}" /> Text="{DynamicResource actionkeyword_tips}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="3" Grid.Column="1"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="3" Grid.Column="1">
<Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 10 0" Width="80" Height="25" <Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 10 0" Width="80" Height="30"
Content="{DynamicResource cancel}" /> Content="{DynamicResource cancel}" />
<Button x:Name="btnDone" Margin="10 0 10 0" Width="80" Height="25" Click="btnDone_OnClick"> <Button x:Name="btnDone" Margin="10 0 10 0" Width="80" Height="30" Click="btnDone_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" /> <TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button> </Button>
</StackPanel> </StackPanel>

View file

@ -4,30 +4,33 @@ using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure.Exception; using Flow.Launcher.Infrastructure.Exception;
using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.ViewModel;
namespace Flow.Launcher namespace Flow.Launcher
{ {
public partial class ActionKeywords : Window public partial class ActionKeywords : Window
{ {
private PluginPair _plugin; private readonly PluginPair plugin;
private Settings _settings; private Settings settings;
private readonly Internationalization _translater = InternationalizationManager.Instance; private readonly Internationalization translater = InternationalizationManager.Instance;
private readonly PluginViewModel pluginViewModel;
public ActionKeywords(string pluginId, Settings settings) public ActionKeywords(string pluginId, Settings settings, PluginViewModel pluginViewModel)
{ {
InitializeComponent(); InitializeComponent();
_plugin = PluginManager.GetPluginForId(pluginId); plugin = PluginManager.GetPluginForId(pluginId);
_settings = settings; this.settings = settings;
if (_plugin == null) this.pluginViewModel = pluginViewModel;
if (plugin == null)
{ {
MessageBox.Show(_translater.GetTranslation("cannotFindSpecifiedPlugin")); MessageBox.Show(translater.GetTranslation("cannotFindSpecifiedPlugin"));
Close(); Close();
} }
} }
private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e) private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e)
{ {
tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeperater, _plugin.Metadata.ActionKeywords.ToArray()); tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeperater, plugin.Metadata.ActionKeywords.ToArray());
tbAction.Focus(); tbAction.Focus();
} }
@ -38,19 +41,17 @@ namespace Flow.Launcher
private void btnDone_OnClick(object sender, RoutedEventArgs _) private void btnDone_OnClick(object sender, RoutedEventArgs _)
{ {
var oldActionKeyword = _plugin.Metadata.ActionKeywords[0]; var oldActionKeyword = plugin.Metadata.ActionKeywords[0];
var newActionKeyword = tbAction.Text.Trim(); var newActionKeyword = tbAction.Text.Trim();
newActionKeyword = newActionKeyword.Length > 0 ? newActionKeyword : "*"; newActionKeyword = newActionKeyword.Length > 0 ? newActionKeyword : "*";
if (!PluginManager.ActionKeywordRegistered(newActionKeyword)) if (!pluginViewModel.IsActionKeywordRegistered(newActionKeyword))
{ {
var id = _plugin.Metadata.ID; pluginViewModel.ChangeActionKeyword(newActionKeyword, oldActionKeyword);
PluginManager.ReplaceActionKeyword(id, oldActionKeyword, newActionKeyword);
MessageBox.Show(_translater.GetTranslation("success"));
Close(); Close();
} }
else else
{ {
string msg = _translater.GetTranslation("newActionKeywordsHasBeenAssigned"); string msg = translater.GetTranslation("newActionKeywordsHasBeenAssigned");
MessageBox.Show(msg); MessageBox.Show(msg);
} }
} }

View file

@ -1,4 +1,4 @@
<Window x:Class="Flow.Launcher.CustomQueryHotkeySetting" <Window x:Class="Flow.Launcher.CustomQueryHotkeySetting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:flowlauncher="clr-namespace:Flow.Launcher" xmlns:flowlauncher="clr-namespace:Flow.Launcher"
@ -6,6 +6,12 @@
ResizeMode="NoResize" ResizeMode="NoResize"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Title="Custom Plugin Hotkey" Height="200" Width="674.766"> Title="Custom Plugin Hotkey" Height="200" Width="674.766">
<Window.InputBindings>
<KeyBinding Key="Escape" Command="Close"/>
</Window.InputBindings>
<Window.CommandBindings>
<CommandBinding Command="Close" Executed="cmdEsc_OnPress"/>
</Window.CommandBindings>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
@ -18,7 +24,7 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Margin="10" FontSize="14" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" <TextBlock Margin="10" FontSize="14" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Right" Text="{DynamicResource hotkey}" /> HorizontalAlignment="Right" Text="{DynamicResource hotkey}" />
<flowlauncher:HotkeyControl x:Name="ctlHotkey" Margin="10" Grid.Column="1" /> <flowlauncher:HotkeyControl x:Name="ctlHotkey" Margin="10,0,10,0" Grid.Column="1" VerticalAlignment="Center" Height="32" />
<TextBlock Margin="10" FontSize="14" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" <TextBlock Margin="10" FontSize="14" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Right" Text="{DynamicResource actionKeyword}" /> HorizontalAlignment="Right" Text="{DynamicResource actionKeyword}" />
@ -29,9 +35,9 @@
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="2" Grid.Column="1">
<Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 10 0" Width="80" Height="25" <Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 10 0" Width="80" Height="32"
Content="{DynamicResource cancel}" /> Content="{DynamicResource cancel}" />
<Button x:Name="btnAdd" Margin="10 0 10 0" Width="80" Height="25" Click="btnAdd_OnClick"> <Button x:Name="btnAdd" Margin="10 0 10 0" Width="80" Height="32" Click="btnAdd_OnClick">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" /> <TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button> </Button>
</StackPanel> </StackPanel>

View file

@ -1,13 +1,13 @@
using System; using Flow.Launcher.Core.Resource;
using System.Collections.Generic; using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
using NHotkey;
using NHotkey.Wpf;
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using NHotkey; using System.Windows.Input;
using NHotkey.Wpf;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
namespace Flow.Launcher namespace Flow.Launcher
{ {
@ -125,5 +125,10 @@ namespace Flow.Launcher
MessageBox.Show(errorMsg); MessageBox.Show(errorMsg);
} }
} }
private void cmdEsc_OnPress(object sender, ExecutedRoutedEventArgs e)
{
Close();
}
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">Nøgleord</system:String> <system:String x:Key="actionKeywords">Nøgleord</system:String>
<system:String x:Key="pluginDirectory">Plugin bibliotek</system:String> <system:String x:Key="pluginDirectory">Plugin bibliotek</system:String>
<system:String x:Key="author">Forfatter</system:String> <system:String x:Key="author">Forfatter</system:String>
<system:String x:Key="plugin_init_time">Initaliseringstid: {0}ms</system:String> <system:String x:Key="plugin_init_time">Initaliseringstid:</system:String>
<system:String x:Key="plugin_query_time">Søgetid: {0}ms</system:String> <system:String x:Key="plugin_query_time">Søgetid:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Tema</system:String> <system:String x:Key="theme">Tema</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">Aktionsschlüsselwörter</system:String> <system:String x:Key="actionKeywords">Aktionsschlüsselwörter</system:String>
<system:String x:Key="pluginDirectory">Pluginordner</system:String> <system:String x:Key="pluginDirectory">Pluginordner</system:String>
<system:String x:Key="author">Autor</system:String> <system:String x:Key="author">Autor</system:String>
<system:String x:Key="plugin_init_time">Initialisierungszeit: {0}ms</system:String> <system:String x:Key="plugin_init_time">Initialisierungszeit:</system:String>
<system:String x:Key="plugin_query_time">Abfragezeit: {0}ms</system:String> <system:String x:Key="plugin_query_time">Abfragezeit:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Theme</system:String> <system:String x:Key="theme">Theme</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -40,11 +40,13 @@
<system:String x:Key="plugin">Plugin</system:String> <system:String x:Key="plugin">Plugin</system:String>
<system:String x:Key="browserMorePlugins">Find more plugins</system:String> <system:String x:Key="browserMorePlugins">Find more plugins</system:String>
<system:String x:Key="disable">Disable</system:String> <system:String x:Key="disable">Disable</system:String>
<system:String x:Key="actionKeywords">Action keywords</system:String> <system:String x:Key="actionKeywords">Action keyword:</system:String>
<system:String x:Key="currentActionKeywords">Current action keyword:</system:String>
<system:String x:Key="newActionKeyword">New action keyword:</system:String>
<system:String x:Key="pluginDirectory">Plugin Directory</system:String> <system:String x:Key="pluginDirectory">Plugin Directory</system:String>
<system:String x:Key="author">Author</system:String> <system:String x:Key="author">Author</system:String>
<system:String x:Key="plugin_init_time">Init time: {0}ms</system:String> <system:String x:Key="plugin_init_time">Init time:</system:String>
<system:String x:Key="plugin_query_time">Query time: {0}ms</system:String> <system:String x:Key="plugin_query_time">Query time:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Theme</system:String> <system:String x:Key="theme">Theme</system:String>

View file

@ -40,8 +40,8 @@
<system:String x:Key="actionKeywords">Mot-clé d'action :</system:String> <system:String x:Key="actionKeywords">Mot-clé d'action :</system:String>
<system:String x:Key="pluginDirectory">Répertoire</system:String> <system:String x:Key="pluginDirectory">Répertoire</system:String>
<system:String x:Key="author">Auteur </system:String> <system:String x:Key="author">Auteur </system:String>
<system:String x:Key="plugin_init_time">Chargement : {0}ms</system:String> <system:String x:Key="plugin_init_time">Chargement :</system:String>
<system:String x:Key="plugin_query_time">Utilisation : {0}ms</system:String> <system:String x:Key="plugin_query_time">Utilisation :</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Thèmes</system:String> <system:String x:Key="theme">Thèmes</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -40,8 +40,8 @@
<system:String x:Key="actionKeywords">Parole chiave</system:String> <system:String x:Key="actionKeywords">Parole chiave</system:String>
<system:String x:Key="pluginDirectory">Cartella Plugin</system:String> <system:String x:Key="pluginDirectory">Cartella Plugin</system:String>
<system:String x:Key="author">Autore</system:String> <system:String x:Key="author">Autore</system:String>
<system:String x:Key="plugin_init_time">Tempo di avvio: {0}ms</system:String> <system:String x:Key="plugin_init_time">Tempo di avvio:</system:String>
<system:String x:Key="plugin_query_time">Tempo ricerca: {0}ms</system:String> <system:String x:Key="plugin_query_time">Tempo ricerca:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Tema</system:String> <system:String x:Key="theme">Tema</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -41,8 +41,8 @@
<system:String x:Key="actionKeywords">キーワード</system:String> <system:String x:Key="actionKeywords">キーワード</system:String>
<system:String x:Key="pluginDirectory">プラグイン・ディレクトリ</system:String> <system:String x:Key="pluginDirectory">プラグイン・ディレクトリ</system:String>
<system:String x:Key="author">作者</system:String> <system:String x:Key="author">作者</system:String>
<system:String x:Key="plugin_init_time">初期化時間: {0}ms</system:String> <system:String x:Key="plugin_init_time">初期化時間:</system:String>
<system:String x:Key="plugin_query_time">クエリ時間: {0}ms</system:String> <system:String x:Key="plugin_query_time">クエリ時間:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">テーマ</system:String> <system:String x:Key="theme">テーマ</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -40,8 +40,8 @@
<system:String x:Key="actionKeywords">액션 키워드</system:String> <system:String x:Key="actionKeywords">액션 키워드</system:String>
<system:String x:Key="pluginDirectory">플러그인 디렉토리</system:String> <system:String x:Key="pluginDirectory">플러그인 디렉토리</system:String>
<system:String x:Key="author">저자</system:String> <system:String x:Key="author">저자</system:String>
<system:String x:Key="plugin_init_time">초기화 시간: {0}ms</system:String> <system:String x:Key="plugin_init_time">초기화 시간:</system:String>
<system:String x:Key="plugin_query_time">쿼리 시간: {0}ms</system:String> <system:String x:Key="plugin_query_time">쿼리 시간:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">테마</system:String> <system:String x:Key="theme">테마</system:String>

View file

@ -40,8 +40,8 @@
<system:String x:Key="actionKeywords">Handlingsnøkkelord</system:String> <system:String x:Key="actionKeywords">Handlingsnøkkelord</system:String>
<system:String x:Key="pluginDirectory">Utvidelseskatalog</system:String> <system:String x:Key="pluginDirectory">Utvidelseskatalog</system:String>
<system:String x:Key="author">Forfatter</system:String> <system:String x:Key="author">Forfatter</system:String>
<system:String x:Key="plugin_init_time">Oppstartstid: {0}ms</system:String> <system:String x:Key="plugin_init_time">Oppstartstid:</system:String>
<system:String x:Key="plugin_query_time">Spørringstid: {0}ms</system:String> <system:String x:Key="plugin_query_time">Spørringstid:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Tema</system:String> <system:String x:Key="theme">Tema</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">Action terfwoorden</system:String> <system:String x:Key="actionKeywords">Action terfwoorden</system:String>
<system:String x:Key="pluginDirectory">Plugin map</system:String> <system:String x:Key="pluginDirectory">Plugin map</system:String>
<system:String x:Key="author">Auteur</system:String> <system:String x:Key="author">Auteur</system:String>
<system:String x:Key="plugin_init_time">Init tijd: {0}ms</system:String> <system:String x:Key="plugin_init_time">Init tijd:</system:String>
<system:String x:Key="plugin_query_time">Query tijd: {0}ms</system:String> <system:String x:Key="plugin_query_time">Query tijd:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Thema</system:String> <system:String x:Key="theme">Thema</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">Wyzwalacze</system:String> <system:String x:Key="actionKeywords">Wyzwalacze</system:String>
<system:String x:Key="pluginDirectory">Folder wtyczki</system:String> <system:String x:Key="pluginDirectory">Folder wtyczki</system:String>
<system:String x:Key="author">Autor</system:String> <system:String x:Key="author">Autor</system:String>
<system:String x:Key="plugin_init_time">Czas ładowania: {0}ms</system:String> <system:String x:Key="plugin_init_time">Czas ładowania:</system:String>
<system:String x:Key="plugin_query_time">Czas zapytania: {0}ms</system:String> <system:String x:Key="plugin_query_time">Czas zapytania:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Skórka</system:String> <system:String x:Key="theme">Skórka</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -40,8 +40,8 @@
<system:String x:Key="actionKeywords">Palavras-chave de ação</system:String> <system:String x:Key="actionKeywords">Palavras-chave de ação</system:String>
<system:String x:Key="pluginDirectory">Diretório de Plugins</system:String> <system:String x:Key="pluginDirectory">Diretório de Plugins</system:String>
<system:String x:Key="author">Autor</system:String> <system:String x:Key="author">Autor</system:String>
<system:String x:Key="plugin_init_time">Tempo de inicialização: {0}ms</system:String> <system:String x:Key="plugin_init_time">Tempo de inicialização:</system:String>
<system:String x:Key="plugin_query_time">Tempo de consulta: {0}ms</system:String> <system:String x:Key="plugin_query_time">Tempo de consulta:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Tema</system:String> <system:String x:Key="theme">Tema</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">Ключевое слово</system:String> <system:String x:Key="actionKeywords">Ключевое слово</system:String>
<system:String x:Key="pluginDirectory">Папка</system:String> <system:String x:Key="pluginDirectory">Папка</system:String>
<system:String x:Key="author">Автор</system:String> <system:String x:Key="author">Автор</system:String>
<system:String x:Key="plugin_init_time">Инициализация: {0}ms</system:String> <system:String x:Key="plugin_init_time">Инициализация:</system:String>
<system:String x:Key="plugin_query_time">Запрос: {0}ms</system:String> <system:String x:Key="plugin_query_time">Запрос:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Темы</system:String> <system:String x:Key="theme">Темы</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -41,8 +41,8 @@
<system:String x:Key="actionKeywords">Skratka akcie</system:String> <system:String x:Key="actionKeywords">Skratka akcie</system:String>
<system:String x:Key="pluginDirectory">Priečinok s pluginmy</system:String> <system:String x:Key="pluginDirectory">Priečinok s pluginmy</system:String>
<system:String x:Key="author">Autor</system:String> <system:String x:Key="author">Autor</system:String>
<system:String x:Key="plugin_init_time">Čas inic.: {0}ms</system:String> <system:String x:Key="plugin_init_time">Čas inic.:</system:String>
<system:String x:Key="plugin_query_time">Čas dopytu: {0}ms</system:String> <system:String x:Key="plugin_query_time">Čas dopytu:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Motív</system:String> <system:String x:Key="theme">Motív</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -40,8 +40,8 @@
<system:String x:Key="actionKeywords">Ključne reči</system:String> <system:String x:Key="actionKeywords">Ključne reči</system:String>
<system:String x:Key="pluginDirectory">Plugin direktorijum</system:String> <system:String x:Key="pluginDirectory">Plugin direktorijum</system:String>
<system:String x:Key="author">Autor</system:String> <system:String x:Key="author">Autor</system:String>
<system:String x:Key="plugin_init_time">Vreme inicijalizacije: {0}ms</system:String> <system:String x:Key="plugin_init_time">Vreme inicijalizacije:</system:String>
<system:String x:Key="plugin_query_time">Vreme upita: {0}ms</system:String> <system:String x:Key="plugin_query_time">Vreme upita:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Tema</system:String> <system:String x:Key="theme">Tema</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -42,8 +42,8 @@
<system:String x:Key="actionKeywords">Anahtar Kelimeler</system:String> <system:String x:Key="actionKeywords">Anahtar Kelimeler</system:String>
<system:String x:Key="pluginDirectory">Eklenti Klasörü</system:String> <system:String x:Key="pluginDirectory">Eklenti Klasörü</system:String>
<system:String x:Key="author">Yapımcı</system:String> <system:String x:Key="author">Yapımcı</system:String>
<system:String x:Key="plugin_init_time">Açılış Süresi: {0}ms</system:String> <system:String x:Key="plugin_init_time">Açılış Süresi:</system:String>
<system:String x:Key="plugin_query_time">Sorgu Süresi: {0}ms</system:String> <system:String x:Key="plugin_query_time">Sorgu Süresi:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Temalar</system:String> <system:String x:Key="theme">Temalar</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--MainWindow--> <!--MainWindow-->
@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">Ключове слово</system:String> <system:String x:Key="actionKeywords">Ключове слово</system:String>
<system:String x:Key="pluginDirectory">Директорія плагіну</system:String> <system:String x:Key="pluginDirectory">Директорія плагіну</system:String>
<system:String x:Key="author">Автор</system:String> <system:String x:Key="author">Автор</system:String>
<system:String x:Key="plugin_init_time">Ініціалізація: {0}ms</system:String> <system:String x:Key="plugin_init_time">Ініціалізація:</system:String>
<system:String x:Key="plugin_query_time">Запит: {0}ms</system:String> <system:String x:Key="plugin_query_time">Запит:</system:String>
<!--Setting Theme--> <!--Setting Theme-->
<system:String x:Key="theme">Теми</system:String> <system:String x:Key="theme">Теми</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--主窗体--> <!--主窗体-->
@ -41,8 +41,8 @@
<system:String x:Key="actionKeywords">触发关键字</system:String> <system:String x:Key="actionKeywords">触发关键字</system:String>
<system:String x:Key="pluginDirectory">插件目录</system:String> <system:String x:Key="pluginDirectory">插件目录</system:String>
<system:String x:Key="author">作者</system:String> <system:String x:Key="author">作者</system:String>
<system:String x:Key="plugin_init_time">加载耗时 {0}ms</system:String> <system:String x:Key="plugin_init_time">加载耗时</system:String>
<system:String x:Key="plugin_query_time">查询耗时 {0}ms</system:String> <system:String x:Key="plugin_query_time">查询耗时</system:String>
<!--设置,主题--> <!--设置,主题-->
<system:String x:Key="theme">主题</system:String> <system:String x:Key="theme">主题</system:String>

View file

@ -1,4 +1,4 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"> xmlns:system="clr-namespace:System;assembly=mscorlib">
<!--主視窗--> <!--主視窗-->
@ -36,8 +36,8 @@
<system:String x:Key="actionKeywords">觸發關鍵字</system:String> <system:String x:Key="actionKeywords">觸發關鍵字</system:String>
<system:String x:Key="pluginDirectory">外掛資料夾</system:String> <system:String x:Key="pluginDirectory">外掛資料夾</system:String>
<system:String x:Key="author">作者</system:String> <system:String x:Key="author">作者</system:String>
<system:String x:Key="plugin_init_time">載入耗時:{0}ms</system:String> <system:String x:Key="plugin_init_time">載入耗時:</system:String>
<system:String x:Key="plugin_query_time">查詢耗時:{0}ms</system:String> <system:String x:Key="plugin_query_time">查詢耗時:</system:String>
<!--設定,主題--> <!--設定,主題-->
<system:String x:Key="theme">主題</system:String> <system:String x:Key="theme">主題</system:String>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View file

@ -175,14 +175,16 @@
<TextBlock Text="{DynamicResource actionKeywords}" <TextBlock Text="{DynamicResource actionKeywords}"
Visibility="{Binding ActionKeywordsVisibility}" Visibility="{Binding ActionKeywordsVisibility}"
Margin="20 0 0 0" MaxWidth="100"/> Margin="20 0 0 0"/>
<TextBlock Text="{Binding ActionKeywordsText}" <TextBlock Text="{Binding ActionKeywordsText}"
Visibility="{Binding ActionKeywordsVisibility}" Visibility="{Binding ActionKeywordsVisibility}"
ToolTip="Change Action Keywords" ToolTip="Change Action Keywords"
Margin="5 0 0 0" Cursor="Hand" Foreground="Blue" Margin="5 0 0 0" Cursor="Hand" Foreground="Blue"
MouseUp="OnPluginActionKeywordsClick" MaxWidth="100" /> MouseUp="OnPluginActionKeywordsClick" MaxWidth="100" />
<TextBlock Text="{Binding InitilizaTime}" Margin="10 0 0 0" MaxWidth="100"/> <TextBlock Text="{DynamicResource plugin_init_time}" Margin="10 0 0 0" MaxWidth="100"/>
<TextBlock Text="{Binding QueryTime}" Margin="10 0 0 0" MaxWidth="100"/> <TextBlock Text="{Binding InitilizaTime}" Margin="5 0 0 0" MaxWidth="100"/>
<TextBlock Text="{DynamicResource plugin_query_time}" Margin="10 0 0 0" MaxWidth="100"/>
<TextBlock Text="{Binding QueryTime}" Margin="5 0 0 0" MaxWidth="100"/>
<TextBlock Text="{DynamicResource pluginDirectory}" <TextBlock Text="{DynamicResource pluginDirectory}"
MaxWidth="100" Cursor="Hand" Margin="40 0 0 0" MaxWidth="100" Cursor="Hand" Margin="40 0 0 0"
MouseUp="OnPluginDirecotyClick" Foreground="Blue" /> MouseUp="OnPluginDirecotyClick" Foreground="Blue" />

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
@ -21,17 +20,17 @@ namespace Flow.Launcher
{ {
private const string StartupPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; private const string StartupPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
public readonly IPublicAPI _api; public readonly IPublicAPI API;
private Settings _settings; private Settings settings;
private SettingWindowViewModel _viewModel; private SettingWindowViewModel viewModel;
public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel)
{ {
InitializeComponent(); InitializeComponent();
_settings = viewModel.Settings; settings = viewModel.Settings;
DataContext = viewModel; DataContext = viewModel;
_viewModel = viewModel; this.viewModel = viewModel;
_api = api; API = api;
} }
#region General #region General
@ -94,7 +93,7 @@ namespace Flow.Launcher
var pythonPath = Path.Combine(pythonDirectory, PluginsLoader.PythonExecutable); var pythonPath = Path.Combine(pythonDirectory, PluginsLoader.PythonExecutable);
if (File.Exists(pythonPath)) if (File.Exists(pythonPath))
{ {
_settings.PluginSettings.PythonDirectory = pythonDirectory; settings.PluginSettings.PythonDirectory = pythonDirectory;
MessageBox.Show("Remember to restart Flow Launcher use new Python path"); MessageBox.Show("Remember to restart Flow Launcher use new Python path");
} }
else else
@ -111,7 +110,7 @@ namespace Flow.Launcher
private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e) private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e)
{ {
HotkeyControl.SetHotkey(_viewModel.Settings.Hotkey, false); HotkeyControl.SetHotkey(viewModel.Settings.Hotkey, false);
} }
void OnHotkeyChanged(object sender, EventArgs e) void OnHotkeyChanged(object sender, EventArgs e)
@ -129,8 +128,8 @@ namespace Flow.Launcher
Application.Current.MainWindow.Visibility = Visibility.Hidden; Application.Current.MainWindow.Visibility = Visibility.Hidden;
} }
}); });
RemoveHotkey(_settings.Hotkey); RemoveHotkey(settings.Hotkey);
_settings.Hotkey = HotkeyControl.CurrentHotkey.ToString(); settings.Hotkey = HotkeyControl.CurrentHotkey.ToString();
} }
} }
@ -159,7 +158,7 @@ namespace Flow.Launcher
private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e) private void OnDeleteCustomHotkeyClick(object sender, RoutedEventArgs e)
{ {
var item = _viewModel.SelectedCustomPluginHotkey; var item = viewModel.SelectedCustomPluginHotkey;
if (item == null) if (item == null)
{ {
MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); MessageBox.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem"));
@ -173,17 +172,17 @@ namespace Flow.Launcher
MessageBox.Show(deleteWarning, InternationalizationManager.Instance.GetTranslation("delete"), MessageBox.Show(deleteWarning, InternationalizationManager.Instance.GetTranslation("delete"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes) MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{ {
_settings.CustomPluginHotkeys.Remove(item); settings.CustomPluginHotkeys.Remove(item);
RemoveHotkey(item.Hotkey); RemoveHotkey(item.Hotkey);
} }
} }
private void OnnEditCustomHotkeyClick(object sender, RoutedEventArgs e) private void OnnEditCustomHotkeyClick(object sender, RoutedEventArgs e)
{ {
var item = _viewModel.SelectedCustomPluginHotkey; var item = viewModel.SelectedCustomPluginHotkey;
if (item != null) if (item != null)
{ {
CustomQueryHotkeySetting window = new CustomQueryHotkeySetting(this, _settings); CustomQueryHotkeySetting window = new CustomQueryHotkeySetting(this, settings);
window.UpdateItem(item); window.UpdateItem(item);
window.ShowDialog(); window.ShowDialog();
} }
@ -195,7 +194,7 @@ namespace Flow.Launcher
private void OnAddCustomeHotkeyClick(object sender, RoutedEventArgs e) private void OnAddCustomeHotkeyClick(object sender, RoutedEventArgs e)
{ {
new CustomQueryHotkeySetting(this, _settings).ShowDialog(); new CustomQueryHotkeySetting(this, settings).ShowDialog();
} }
#endregion #endregion
@ -204,17 +203,17 @@ namespace Flow.Launcher
private void OnPluginToggled(object sender, RoutedEventArgs e) private void OnPluginToggled(object sender, RoutedEventArgs e)
{ {
var id = _viewModel.SelectedPlugin.PluginPair.Metadata.ID; var id = viewModel.SelectedPlugin.PluginPair.Metadata.ID;
// used to sync the current status from the plugin manager into the setting to keep consistency after save // 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; settings.PluginSettings.Plugins[id].Disabled = viewModel.SelectedPlugin.PluginPair.Metadata.Disabled;
} }
private void OnPluginActionKeywordsClick(object sender, MouseButtonEventArgs e) private void OnPluginActionKeywordsClick(object sender, MouseButtonEventArgs e)
{ {
if (e.ChangedButton == MouseButton.Left) if (e.ChangedButton == MouseButton.Left)
{ {
var id = _viewModel.SelectedPlugin.PluginPair.Metadata.ID; var id = viewModel.SelectedPlugin.PluginPair.Metadata.ID;
ActionKeywords changeKeywordsWindow = new ActionKeywords(id, _settings); ActionKeywords changeKeywordsWindow = new ActionKeywords(id, settings, viewModel.SelectedPlugin);
changeKeywordsWindow.ShowDialog(); changeKeywordsWindow.ShowDialog();
} }
} }
@ -223,7 +222,7 @@ namespace Flow.Launcher
{ {
if (e.ChangedButton == MouseButton.Left) if (e.ChangedButton == MouseButton.Left)
{ {
var website = _viewModel.SelectedPlugin.PluginPair.Metadata.Website; var website = viewModel.SelectedPlugin.PluginPair.Metadata.Website;
if (!string.IsNullOrEmpty(website)) if (!string.IsNullOrEmpty(website))
{ {
var uri = new Uri(website); var uri = new Uri(website);
@ -239,7 +238,7 @@ namespace Flow.Launcher
{ {
if (e.ChangedButton == MouseButton.Left) if (e.ChangedButton == MouseButton.Left)
{ {
var directory = _viewModel.SelectedPlugin.PluginPair.Metadata.PluginDirectory; var directory = viewModel.SelectedPlugin.PluginPair.Metadata.PluginDirectory;
if (!string.IsNullOrEmpty(directory)) if (!string.IsNullOrEmpty(directory))
FilesFolders.OpenPath(directory); FilesFolders.OpenPath(directory);
} }
@ -250,7 +249,7 @@ namespace Flow.Launcher
private void OnTestProxyClick(object sender, RoutedEventArgs e) private void OnTestProxyClick(object sender, RoutedEventArgs e)
{ // TODO: change to command { // TODO: change to command
var msg = _viewModel.TestProxy(); var msg = viewModel.TestProxy();
MessageBox.Show(msg); // TODO: add message box service MessageBox.Show(msg); // TODO: add message box service
} }
@ -258,7 +257,7 @@ namespace Flow.Launcher
private async void OnCheckUpdates(object sender, RoutedEventArgs e) private async void OnCheckUpdates(object sender, RoutedEventArgs e)
{ {
_viewModel.UpdateApp(); // TODO: change to command viewModel.UpdateApp(); // TODO: change to command
} }
private void OnRequestNavigate(object sender, RequestNavigateEventArgs e) private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
@ -269,7 +268,7 @@ namespace Flow.Launcher
private void OnClosed(object sender, EventArgs e) private void OnClosed(object sender, EventArgs e)
{ {
_viewModel.Save(); viewModel.Save();
} }
private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e) private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e)

View file

@ -1,8 +1,9 @@
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using Flow.Launcher.Core.Resource; using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Core.Plugin;
namespace Flow.Launcher.ViewModel namespace Flow.Launcher.ViewModel
{ {
@ -22,8 +23,17 @@ namespace Flow.Launcher.ViewModel
} }
} }
public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count > 1 ? Visibility.Collapsed : Visibility.Visible; public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count > 1 ? Visibility.Collapsed : Visibility.Visible;
public string InitilizaTime => string.Format(_translator.GetTranslation("plugin_init_time"), PluginPair.Metadata.InitTime); public string InitilizaTime => PluginPair.Metadata.InitTime.ToString() + "ms";
public string QueryTime => string.Format(_translator.GetTranslation("plugin_query_time"), PluginPair.Metadata.AvgQueryTime); public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms";
public string ActionKeywordsText => string.Join(Query.ActionKeywordSeperater, PluginPair.Metadata.ActionKeywords); public string ActionKeywordsText => string.Join(Query.ActionKeywordSeperater, PluginPair.Metadata.ActionKeywords);
public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword)
{
PluginManager.ReplaceActionKeyword(PluginPair.Metadata.ID, oldActionKeyword, newActionKeyword);
OnPropertyChanged(nameof(ActionKeywordsText));
}
public bool IsActionKeywordRegistered(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword);
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -17,7 +17,6 @@ namespace Flow.Launcher.Plugin.PluginManagement
public class Main : IPlugin, IPluginI18n public class Main : IPlugin, IPluginI18n
{ {
private static string APIBASE = "http://api.wox.one"; private static string APIBASE = "http://api.wox.one";
private static string PluginConfigName = "plugin.json";
private static string pluginSearchUrl = APIBASE + "/plugin/search/"; private static string pluginSearchUrl = APIBASE + "/plugin/search/";
private const string ListCommand = "list"; private const string ListCommand = "list";
private const string InstallCommand = "install"; private const string InstallCommand = "install";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -1,5 +1,6 @@
Flow Launcher <p align="center">
============= <img width="500px" src="https://github.com/Flow-Launcher/Flow.Launcher/blob/5ba4514f31e624c679628d4dfe89036c0e24006c/Doc/Logo/resources/flow-header-square-transparent.png">
</p>
![Maintenance](https://img.shields.io/maintenance/yes/2020) ![Maintenance](https://img.shields.io/maintenance/yes/2020)
[![Build status](https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true&retina=true)](https://ci.appveyor.com/project/JohnTheGr8/flow-launcher/branch/dev) [![Build status](https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true&retina=true)](https://ci.appveyor.com/project/JohnTheGr8/flow-launcher/branch/dev)