mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into velopack
This commit is contained in:
commit
5d122dfb1f
20 changed files with 189 additions and 151 deletions
1
.github/actions/spelling/expect.txt
vendored
1
.github/actions/spelling/expect.txt
vendored
|
|
@ -106,3 +106,4 @@ alreadyexists
|
||||||
JsonRPC
|
JsonRPC
|
||||||
JsonRPCV2
|
JsonRPCV2
|
||||||
Softpedia
|
Softpedia
|
||||||
|
img
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,9 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
|
|
||||||
public ExecutablePluginV2(string filename)
|
public ExecutablePluginV2(string filename)
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo { FileName = filename };
|
||||||
{
|
|
||||||
FileName = filename,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override MessageHandlerType MessageHandler { get; } = MessageHandlerType.NewLineDelimited;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
{
|
{
|
||||||
internal abstract class JsonRPCPluginV2 : JsonRPCPluginBase, IAsyncDisposable, IAsyncReloadable, IResultUpdated
|
internal abstract class JsonRPCPluginV2 : JsonRPCPluginBase, IAsyncDisposable, IAsyncReloadable, IResultUpdated
|
||||||
{
|
{
|
||||||
public abstract string SupportedLanguage { get; set; }
|
|
||||||
|
|
||||||
public const string JsonRpc = "JsonRPC";
|
public const string JsonRpc = "JsonRPC";
|
||||||
|
|
||||||
protected abstract IDuplexPipe ClientPipe { get; set; }
|
protected abstract IDuplexPipe ClientPipe { get; set; }
|
||||||
|
|
@ -41,9 +39,23 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext());
|
||||||
|
|
||||||
public override List<Result> LoadContextMenus(Result selectedResult)
|
public override List<Result> LoadContextMenus(Result selectedResult)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
try
|
||||||
|
{
|
||||||
|
var res = JTF.Run(() => RPC.InvokeWithCancellationAsync<JsonRPCQueryResponseModel>("context_menu",
|
||||||
|
new object[] { selectedResult.ContextData }));
|
||||||
|
|
||||||
|
var results = ParseResults(res);
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new List<Result>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
|
public override async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
|
||||||
|
|
@ -51,7 +63,7 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var res = await RPC.InvokeWithCancellationAsync<JsonRPCQueryResponseModel>("query",
|
var res = await RPC.InvokeWithCancellationAsync<JsonRPCQueryResponseModel>("query",
|
||||||
new[] { query },
|
new object[] { query, Settings.Inner },
|
||||||
token);
|
token);
|
||||||
|
|
||||||
var results = ParseResults(res);
|
var results = ParseResults(res);
|
||||||
|
|
@ -88,12 +100,26 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
|
|
||||||
public event ResultUpdatedEventHandler ResultsUpdated;
|
public event ResultUpdatedEventHandler ResultsUpdated;
|
||||||
|
|
||||||
|
protected enum MessageHandlerType
|
||||||
|
{
|
||||||
|
HeaderDelimited,
|
||||||
|
LengthHeaderDelimited,
|
||||||
|
NewLineDelimited
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract MessageHandlerType MessageHandler { get; }
|
||||||
|
|
||||||
|
|
||||||
private void SetupJsonRPC()
|
private void SetupJsonRPC()
|
||||||
{
|
{
|
||||||
var formatter = new SystemTextJsonFormatter { JsonSerializerOptions = RequestSerializeOption };
|
var formatter = new SystemTextJsonFormatter { JsonSerializerOptions = RequestSerializeOption };
|
||||||
var handler = new NewLineDelimitedMessageHandler(ClientPipe,
|
IJsonRpcMessageHandler handler = MessageHandler switch
|
||||||
formatter);
|
{
|
||||||
|
MessageHandlerType.HeaderDelimited => new HeaderDelimitedMessageHandler(ClientPipe, formatter),
|
||||||
|
MessageHandlerType.LengthHeaderDelimited => new LengthHeaderMessageHandler(ClientPipe, formatter),
|
||||||
|
MessageHandlerType.NewLineDelimited => new NewLineDelimitedMessageHandler(ClientPipe, formatter),
|
||||||
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
|
};
|
||||||
|
|
||||||
RPC = new JsonRpc(handler, new JsonRPCPublicAPI(Context.API));
|
RPC = new JsonRpc(handler, new JsonRPCPublicAPI(Context.API));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,29 +10,21 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Execution of JavaScript & TypeScript plugins
|
/// Execution of JavaScript & TypeScript plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class NodePluginV2 : ProcessStreamPluginV2
|
internal sealed class NodePluginV2 : ProcessStreamPluginV2
|
||||||
{
|
{
|
||||||
public NodePluginV2(string filename)
|
public NodePluginV2(string filename)
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo { FileName = filename, };
|
||||||
{
|
|
||||||
FileName = filename,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string SupportedLanguage { get; set; }
|
|
||||||
protected override ProcessStartInfo StartInfo { get; set; }
|
protected override ProcessStartInfo StartInfo { get; set; }
|
||||||
|
|
||||||
public override async Task InitAsync(PluginInitContext context)
|
public override async Task InitAsync(PluginInitContext context)
|
||||||
{
|
{
|
||||||
StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
|
StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
|
||||||
StartInfo.ArgumentList.Add(string.Empty);
|
|
||||||
StartInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
|
|
||||||
await base.InitAsync(context);
|
await base.InitAsync(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override MessageHandlerType MessageHandler { get; } = MessageHandlerType.HeaderDelimited;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
|
|
@ -6,6 +8,7 @@ using System.Threading.Tasks;
|
||||||
using Flow.Launcher.Infrastructure;
|
using Flow.Launcher.Infrastructure;
|
||||||
using Flow.Launcher.Plugin;
|
using Flow.Launcher.Plugin;
|
||||||
using Meziantou.Framework.Win32;
|
using Meziantou.Framework.Win32;
|
||||||
|
using Microsoft.VisualBasic.ApplicationServices;
|
||||||
using Nerdbank.Streams;
|
using Nerdbank.Streams;
|
||||||
|
|
||||||
namespace Flow.Launcher.Core.Plugin
|
namespace Flow.Launcher.Core.Plugin
|
||||||
|
|
@ -18,18 +21,18 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
{
|
{
|
||||||
_jobObject.SetLimits(new JobObjectLimits()
|
_jobObject.SetLimits(new JobObjectLimits()
|
||||||
{
|
{
|
||||||
Flags = JobObjectLimitFlags.KillOnJobClose | JobObjectLimitFlags.DieOnUnhandledException
|
Flags = JobObjectLimitFlags.KillOnJobClose | JobObjectLimitFlags.DieOnUnhandledException |
|
||||||
|
JobObjectLimitFlags.SilentBreakawayOk
|
||||||
});
|
});
|
||||||
|
|
||||||
_jobObject.AssignProcess(Process.GetCurrentProcess());
|
_jobObject.AssignProcess(Process.GetCurrentProcess());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string SupportedLanguage { get; set; }
|
protected sealed override IDuplexPipe ClientPipe { get; set; } = null!;
|
||||||
protected sealed override IDuplexPipe ClientPipe { get; set; }
|
|
||||||
|
|
||||||
protected abstract ProcessStartInfo StartInfo { get; set; }
|
protected abstract ProcessStartInfo StartInfo { get; set; }
|
||||||
|
|
||||||
protected Process ClientProcess { get; set; }
|
protected Process ClientProcess { get; set; } = null!;
|
||||||
|
|
||||||
public override async Task InitAsync(PluginInitContext context)
|
public override async Task InitAsync(PluginInitContext context)
|
||||||
{
|
{
|
||||||
|
|
@ -37,12 +40,18 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
StartInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory;
|
StartInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory;
|
||||||
StartInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory;
|
StartInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory;
|
||||||
|
|
||||||
StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
|
StartInfo.RedirectStandardError = true;
|
||||||
|
StartInfo.RedirectStandardInput = true;
|
||||||
|
StartInfo.RedirectStandardOutput = true;
|
||||||
|
StartInfo.CreateNoWindow = true;
|
||||||
|
StartInfo.UseShellExecute = false;
|
||||||
StartInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
|
StartInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
|
||||||
|
|
||||||
ClientProcess = Process.Start(StartInfo);
|
var process = Process.Start(StartInfo);
|
||||||
ArgumentNullException.ThrowIfNull(ClientProcess);
|
ArgumentNullException.ThrowIfNull(process);
|
||||||
|
ClientProcess = process;
|
||||||
|
_jobObject.AssignProcess(ClientProcess);
|
||||||
|
|
||||||
SetupPipe(ClientProcess);
|
SetupPipe(ClientProcess);
|
||||||
|
|
||||||
ErrorStream = ClientProcess.StandardError;
|
ErrorStream = ClientProcess.StandardError;
|
||||||
|
|
|
||||||
|
|
@ -18,20 +18,11 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
{
|
{
|
||||||
internal sealed class PythonPluginV2 : ProcessStreamPluginV2
|
internal sealed class PythonPluginV2 : ProcessStreamPluginV2
|
||||||
{
|
{
|
||||||
public override string SupportedLanguage { get; set; } = AllowedLanguage.Python;
|
|
||||||
protected override ProcessStartInfo StartInfo { get; set; }
|
protected override ProcessStartInfo StartInfo { get; set; }
|
||||||
|
|
||||||
public PythonPluginV2(string filename)
|
public PythonPluginV2(string filename)
|
||||||
{
|
{
|
||||||
StartInfo = new ProcessStartInfo
|
StartInfo = new ProcessStartInfo { FileName = filename, };
|
||||||
{
|
|
||||||
FileName = filename,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
RedirectStandardInput = true
|
|
||||||
};
|
|
||||||
|
|
||||||
var path = Path.Combine(Constant.ProgramDirectory, JsonRpc);
|
var path = Path.Combine(Constant.ProgramDirectory, JsonRpc);
|
||||||
StartInfo.EnvironmentVariables["PYTHONPATH"] = path;
|
StartInfo.EnvironmentVariables["PYTHONPATH"] = path;
|
||||||
|
|
@ -39,5 +30,13 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
//Add -B flag to tell python don't write .py[co] files. Because .pyc contains location infos which will prevent python portable
|
//Add -B flag to tell python don't write .py[co] files. Because .pyc contains location infos which will prevent python portable
|
||||||
StartInfo.ArgumentList.Add("-B");
|
StartInfo.ArgumentList.Add("-B");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task InitAsync(PluginInitContext context)
|
||||||
|
{
|
||||||
|
StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath);
|
||||||
|
await base.InitAsync(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MessageHandlerType MessageHandler { get; } = MessageHandlerType.NewLineDelimited;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
||||||
|
<PackageReference Include="FastCache.Cached" Version="1.8.2" />
|
||||||
<PackageReference Include="Fody" Version="6.5.5">
|
<PackageReference Include="Fody" Version="6.5.5">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using FastCache;
|
||||||
|
using FastCache.Services;
|
||||||
|
|
||||||
namespace Flow.Launcher.Infrastructure.Image
|
namespace Flow.Launcher.Infrastructure.Image
|
||||||
{
|
{
|
||||||
[Serializable]
|
|
||||||
public class ImageUsage
|
public class ImageUsage
|
||||||
{
|
{
|
||||||
|
|
||||||
public int usage;
|
public int usage;
|
||||||
public ImageSource imageSource;
|
public ImageSource imageSource;
|
||||||
|
|
||||||
|
|
@ -23,16 +23,13 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
|
|
||||||
public class ImageCache
|
public class ImageCache
|
||||||
{
|
{
|
||||||
private const int MaxCached = 50;
|
private const int MaxCached = 150;
|
||||||
public ConcurrentDictionary<(string, bool), ImageUsage> Data { get; } = new();
|
|
||||||
private const int permissibleFactor = 2;
|
|
||||||
private SemaphoreSlim semaphore = new(1, 1);
|
|
||||||
|
|
||||||
public void Initialize(Dictionary<(string, bool), int> usage)
|
public void Initialize(Dictionary<(string, bool), int> usage)
|
||||||
{
|
{
|
||||||
foreach (var key in usage.Keys)
|
foreach (var key in usage.Keys)
|
||||||
{
|
{
|
||||||
Data[key] = new ImageUsage(usage[key], null);
|
Cached<ImageUsage>.Save(key, new ImageUsage(usage[key], null), TimeSpan.MaxValue, MaxCached);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,70 +37,48 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (!Data.TryGetValue((path, isFullImage), out var value))
|
if (!Cached<ImageUsage>.TryGet((path, isFullImage), out var value))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
value.usage++;
|
|
||||||
return value.imageSource;
|
|
||||||
|
|
||||||
|
value.Value.usage++;
|
||||||
|
return value.Value.imageSource;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Data.AddOrUpdate(
|
if (Cached<ImageUsage>.TryGet((path, isFullImage), out var cached))
|
||||||
(path, isFullImage),
|
|
||||||
new ImageUsage(0, value),
|
|
||||||
(k, v) =>
|
|
||||||
{
|
|
||||||
v.imageSource = value;
|
|
||||||
v.usage++;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
SliceExtra();
|
|
||||||
|
|
||||||
async void SliceExtra()
|
|
||||||
{
|
{
|
||||||
// To prevent the dictionary from drastically increasing in size by caching images, the dictionary size is not allowed to grow more than the permissibleFactor * maxCached size
|
cached.Value.imageSource = value;
|
||||||
// This is done so that we don't constantly perform this resizing operation and also maintain the image cache size at the same time
|
cached.Value.usage++;
|
||||||
if (Data.Count > permissibleFactor * MaxCached)
|
|
||||||
{
|
|
||||||
await semaphore.WaitAsync().ConfigureAwait(false);
|
|
||||||
// To delete the images from the data dictionary based on the resizing of the Usage Dictionary
|
|
||||||
// Double Check to avoid concurrent remove
|
|
||||||
if (Data.Count > permissibleFactor * MaxCached)
|
|
||||||
foreach (var key in Data.OrderBy(x => x.Value.usage).Take(Data.Count - MaxCached).Select(x => x.Key))
|
|
||||||
Data.TryRemove(key, out _);
|
|
||||||
semaphore.Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cached<ImageUsage>.Save((path, isFullImage), new ImageUsage(0, value), TimeSpan.MaxValue,
|
||||||
|
MaxCached);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(string key, bool isFullImage)
|
public bool ContainsKey(string key, bool isFullImage)
|
||||||
{
|
{
|
||||||
return key is not null && Data.ContainsKey((key, isFullImage)) && Data[(key, isFullImage)].imageSource != null;
|
return Cached<ImageUsage>.TryGet((key, isFullImage), out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(string key, bool isFullImage, out ImageSource image)
|
public bool TryGetValue(string key, bool isFullImage, out ImageSource image)
|
||||||
{
|
{
|
||||||
if (key is not null)
|
if (Cached<ImageUsage>.TryGet((key, isFullImage), out var value))
|
||||||
{
|
{
|
||||||
bool hasKey = Data.TryGetValue((key, isFullImage), out var imageUsage);
|
image = value.Value.imageSource;
|
||||||
image = hasKey ? imageUsage.imageSource : null;
|
value.Value.usage++;
|
||||||
return hasKey;
|
return image != null;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
image = null;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image = null;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CacheSize()
|
public int CacheSize()
|
||||||
{
|
{
|
||||||
return Data.Count;
|
return CacheManager.TotalCount<(string, bool), ImageUsage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -111,7 +86,14 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int UniqueImagesInCache()
|
public int UniqueImagesInCache()
|
||||||
{
|
{
|
||||||
return Data.Values.Select(x => x.imageSource).Distinct().Count();
|
return CacheManager.EnumerateEntries<(string, bool), ImageUsage>().Select(x => x.Value.imageSource)
|
||||||
|
.Distinct()
|
||||||
|
.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Cached<(string, bool), ImageUsage>> EnumerateEntries()
|
||||||
|
{
|
||||||
|
return CacheManager.EnumerateEntries<(string, bool), ImageUsage>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
{
|
{
|
||||||
await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () =>
|
await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () =>
|
||||||
{
|
{
|
||||||
foreach (var ((path, isFullImage), _) in ImageCache.Data)
|
foreach (var ((path, isFullImage), _) in usage)
|
||||||
{
|
{
|
||||||
await LoadAsync(path, isFullImage);
|
await LoadAsync(path, isFullImage);
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_storage.SaveAsync(ImageCache.Data
|
await _storage.SaveAsync(ImageCache.EnumerateEntries()
|
||||||
.ToDictionary(
|
.ToDictionary(
|
||||||
x => x.Key,
|
x => x.Key,
|
||||||
x => x.Value.usage));
|
x => x.Value.usage));
|
||||||
|
|
@ -125,9 +125,12 @@ namespace Flow.Launcher.Infrastructure.Image
|
||||||
return new ImageResult(MissingImage, ImageType.Error);
|
return new ImageResult(MissingImage, ImageType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImageCache.ContainsKey(path, loadFullImage))
|
// extra scope for use of same variable name
|
||||||
{
|
{
|
||||||
return new ImageResult(ImageCache[path, loadFullImage], ImageType.Cache);
|
if (ImageCache.TryGetValue(path, loadFullImage, out var imageSource))
|
||||||
|
{
|
||||||
|
return new ImageResult(imageSource, ImageType.Cache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uriResult)
|
if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uriResult)
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,11 @@
|
||||||
<PackageReference Include="Moq" Version="4.18.4" />
|
<PackageReference Include="Moq" Version="4.18.4" />
|
||||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -182,7 +182,7 @@
|
||||||
<system:String x:Key="customQuery">Query</system:String>
|
<system:String x:Key="customQuery">Query</system:String>
|
||||||
<system:String x:Key="customShortcut">Shortcut</system:String>
|
<system:String x:Key="customShortcut">Shortcut</system:String>
|
||||||
<system:String x:Key="customShortcutExpansion">Expansion</system:String>
|
<system:String x:Key="customShortcutExpansion">Expansion</system:String>
|
||||||
<system:String x:Key="builtinShortcutDescription">Description</system:String>
|
<system:String x:Key="builtinShortcutDescription">Beschrijving</system:String>
|
||||||
<system:String x:Key="delete">Verwijder</system:String>
|
<system:String x:Key="delete">Verwijder</system:String>
|
||||||
<system:String x:Key="edit">Bewerken</system:String>
|
<system:String x:Key="edit">Bewerken</system:String>
|
||||||
<system:String x:Key="add">Toevoegen</system:String>
|
<system:String x:Key="add">Toevoegen</system:String>
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@
|
||||||
<system:String x:Key="flowlauncherHotkey">Klávesová skratka pre Flow Launcher</system:String>
|
<system:String x:Key="flowlauncherHotkey">Klávesová skratka pre Flow Launcher</system:String>
|
||||||
<system:String x:Key="flowlauncherHotkeyToolTip">Zadajte skratku na zobrazenie/skrytie Flow Launchera.</system:String>
|
<system:String x:Key="flowlauncherHotkeyToolTip">Zadajte skratku na zobrazenie/skrytie Flow Launchera.</system:String>
|
||||||
<system:String x:Key="previewHotkey">Klávesová skratka pre náhľad</system:String>
|
<system:String x:Key="previewHotkey">Klávesová skratka pre náhľad</system:String>
|
||||||
<system:String x:Key="previewHotkeyToolTip">Zadajte klávesovú skratku pre zobrazenie/skytie náhľadu vo vyhľadávacom okne.</system:String>
|
<system:String x:Key="previewHotkeyToolTip">Zadajte klávesovú skratku pre zobrazenie/skrytie náhľadu vo vyhľadávacom okne.</system:String>
|
||||||
<system:String x:Key="openResultModifiers">Modifikačný kláves na otvorenie výsledkov</system:String>
|
<system:String x:Key="openResultModifiers">Modifikačný kláves na otvorenie výsledkov</system:String>
|
||||||
<system:String x:Key="openResultModifiersToolTip">Vyberte modifikačný kláves na otvorenie vybraného výsledku pomocou klávesnice.</system:String>
|
<system:String x:Key="openResultModifiersToolTip">Vyberte modifikačný kláves na otvorenie vybraného výsledku pomocou klávesnice.</system:String>
|
||||||
<system:String x:Key="showOpenResultHotkey">Zobraziť klávesovú skratku</system:String>
|
<system:String x:Key="showOpenResultHotkey">Zobraziť klávesovú skratku</system:String>
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,10 @@
|
||||||
Key="F12"
|
Key="F12"
|
||||||
Command="{Binding ToggleGameModeCommand}"
|
Command="{Binding ToggleGameModeCommand}"
|
||||||
Modifiers="Ctrl" />
|
Modifiers="Ctrl" />
|
||||||
|
<KeyBinding
|
||||||
|
Key="C"
|
||||||
|
Modifiers="Ctrl+Shift"
|
||||||
|
Command="{Binding CopyAlternativeCommand}" />
|
||||||
<KeyBinding
|
<KeyBinding
|
||||||
Key="{Binding PreviewHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
|
Key="{Binding PreviewHotkey, Converter={StaticResource StringToKeyBindingConverter}, ConverterParameter='key'}"
|
||||||
Command="{Binding TogglePreviewCommand}"
|
Command="{Binding TogglePreviewCommand}"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
@ -137,6 +137,8 @@ namespace Flow.Launcher
|
||||||
|
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
|
|
||||||
|
App.API.HideMainWindow();
|
||||||
|
|
||||||
var data = new DataObject(DataFormats.FileDrop, new[]
|
var data = new DataObject(DataFormats.FileDrop, new[]
|
||||||
{
|
{
|
||||||
path
|
path
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
var token = e.Token == default ? _updateToken : e.Token;
|
var token = e.Token == default ? _updateToken : e.Token;
|
||||||
|
|
||||||
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
|
PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query);
|
||||||
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, token)))
|
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(e.Results, pair.Metadata, e.Query,
|
||||||
|
token)))
|
||||||
{
|
{
|
||||||
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
|
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +191,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
Hide();
|
Hide();
|
||||||
|
|
||||||
await PluginManager.ReloadDataAsync().ConfigureAwait(false);
|
await PluginManager.ReloadDataAsync().ConfigureAwait(false);
|
||||||
Notification.Show(InternationalizationManager.Instance.GetTranslation("success"), InternationalizationManager.Instance.GetTranslation("completedSuccessfully"));
|
Notification.Show(InternationalizationManager.Instance.GetTranslation("success"),
|
||||||
|
InternationalizationManager.Instance.GetTranslation("completedSuccessfully"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
|
|
@ -265,6 +267,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
autoCompleteText = $"{result.ActionKeywordAssigned} {defaultSuggestion}";
|
autoCompleteText = $"{result.ActionKeywordAssigned} {defaultSuggestion}";
|
||||||
}
|
}
|
||||||
|
|
||||||
autoCompleteText = SelectedResults.SelectedItem.QuerySuggestionText;
|
autoCompleteText = SelectedResults.SelectedItem.QuerySuggestionText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,11 +289,13 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
results.SelectedIndex = int.Parse(index);
|
results.SelectedIndex = int.Parse(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = results.SelectedItem?.Result;
|
var result = results.SelectedItem?.Result;
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hideWindow = await result.ExecuteAsync(new ActionContext
|
var hideWindow = await result.ExecuteAsync(new ActionContext
|
||||||
{
|
{
|
||||||
// not null means pressing modifier key + number, should ignore the modifier key
|
// not null means pressing modifier key + number, should ignore the modifier key
|
||||||
|
|
@ -371,6 +376,17 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
GameModeStatus = !GameModeStatus;
|
GameModeStatus = !GameModeStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public void CopyAlternative()
|
||||||
|
{
|
||||||
|
var result = Results.SelectedItem?.Result?.CopyText;
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
App.API.CopyToClipboard(result, directCopy: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
@ -403,6 +419,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
public bool GameModeStatus { get; set; } = false;
|
public bool GameModeStatus { get; set; } = false;
|
||||||
|
|
||||||
private string _queryText;
|
private string _queryText;
|
||||||
|
|
||||||
public string QueryText
|
public string QueryText
|
||||||
{
|
{
|
||||||
get => _queryText;
|
get => _queryText;
|
||||||
|
|
@ -426,6 +443,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
Settings.WindowSize += 100;
|
Settings.WindowSize += 100;
|
||||||
Settings.WindowLeft -= 50;
|
Settings.WindowLeft -= 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,6 +459,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
Settings.WindowLeft += 50;
|
Settings.WindowLeft += 50;
|
||||||
Settings.WindowSize -= 100;
|
Settings.WindowSize -= 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -520,18 +539,17 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
if (QueryText != queryText)
|
if (QueryText != queryText)
|
||||||
{
|
{
|
||||||
|
|
||||||
// re-query is done in QueryText's setter method
|
// re-query is done in QueryText's setter method
|
||||||
QueryText = queryText;
|
QueryText = queryText;
|
||||||
// set to false so the subsequent set true triggers
|
// set to false so the subsequent set true triggers
|
||||||
// PropertyChanged and MoveQueryTextToEnd is called
|
// PropertyChanged and MoveQueryTextToEnd is called
|
||||||
QueryTextCursorMovedToEnd = false;
|
QueryTextCursorMovedToEnd = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (isReQuery)
|
else if (isReQuery)
|
||||||
{
|
{
|
||||||
Query(isReQuery: true);
|
Query(isReQuery: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryTextCursorMovedToEnd = true;
|
QueryTextCursorMovedToEnd = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -601,8 +619,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
public string OpenResultCommandModifiers => Settings.OpenResultModifiers;
|
public string OpenResultCommandModifiers => Settings.OpenResultModifiers;
|
||||||
|
|
||||||
public string PreviewHotkey
|
public string PreviewHotkey
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
// TODO try to patch issue #1755
|
// TODO try to patch issue #1755
|
||||||
|
|
@ -616,6 +634,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
Settings.PreviewHotkey = "F1";
|
Settings.PreviewHotkey = "F1";
|
||||||
}
|
}
|
||||||
|
|
||||||
return Settings.PreviewHotkey;
|
return Settings.PreviewHotkey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -684,7 +703,6 @@ namespace Flow.Launcher.ViewModel
|
||||||
results.Add(ContextMenuTopMost(selected));
|
results.Add(ContextMenuTopMost(selected));
|
||||||
results.Add(ContextMenuPluginInfo(selected.PluginID));
|
results.Add(ContextMenuPluginInfo(selected.PluginID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(query))
|
if (!string.IsNullOrEmpty(query))
|
||||||
|
|
@ -703,7 +721,6 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
r.Score = match.Score;
|
r.Score = match.Score;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
ContextMenu.AddResults(filtered, id);
|
ContextMenu.AddResults(filtered, id);
|
||||||
}
|
}
|
||||||
|
|
@ -730,10 +747,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
Title = string.Format(title, h.Query),
|
Title = string.Format(title, h.Query),
|
||||||
SubTitle = string.Format(time, h.ExecutedDateTime),
|
SubTitle = string.Format(time, h.ExecutedDateTime),
|
||||||
IcoPath = "Images\\history.png",
|
IcoPath = "Images\\history.png",
|
||||||
OriginQuery = new Query
|
OriginQuery = new Query { RawQuery = h.Query },
|
||||||
{
|
|
||||||
RawQuery = h.Query
|
|
||||||
},
|
|
||||||
Action = _ =>
|
Action = _ =>
|
||||||
{
|
{
|
||||||
SelectedResults = Results;
|
SelectedResults = Results;
|
||||||
|
|
@ -870,20 +884,23 @@ namespace Flow.Launcher.ViewModel
|
||||||
// Task.Yield will force it to run in ThreadPool
|
// Task.Yield will force it to run in ThreadPool
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
|
|
||||||
IReadOnlyList<Result> results = await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken);
|
IReadOnlyList<Result> results =
|
||||||
|
await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken);
|
||||||
|
|
||||||
currentCancellationToken.ThrowIfCancellationRequested();
|
currentCancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
results ??= _emptyResult;
|
results ??= _emptyResult;
|
||||||
|
|
||||||
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, currentCancellationToken)))
|
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query,
|
||||||
|
currentCancellationToken)))
|
||||||
{
|
{
|
||||||
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
|
Log.Error("MainViewModel", "Unable to add item to Result Update Queue");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Query ConstructQuery(string queryText, IEnumerable<CustomShortcutModel> customShortcuts, IEnumerable<BuiltinShortcutModel> builtInShortcuts)
|
private Query ConstructQuery(string queryText, IEnumerable<CustomShortcutModel> customShortcuts,
|
||||||
|
IEnumerable<BuiltinShortcutModel> builtInShortcuts)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(queryText))
|
if (string.IsNullOrWhiteSpace(queryText))
|
||||||
{
|
{
|
||||||
|
|
@ -893,7 +910,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
StringBuilder queryBuilder = new(queryText);
|
StringBuilder queryBuilder = new(queryText);
|
||||||
StringBuilder queryBuilderTmp = new(queryText);
|
StringBuilder queryBuilderTmp = new(queryText);
|
||||||
|
|
||||||
foreach (var shortcut in customShortcuts)
|
// Sorting order is important here, the reason is for matching longest shortcut by default
|
||||||
|
foreach (var shortcut in customShortcuts.OrderByDescending(x => x.Key.Length))
|
||||||
{
|
{
|
||||||
if (queryBuilder.Equals(shortcut.Key))
|
if (queryBuilder.Equals(shortcut.Key))
|
||||||
{
|
{
|
||||||
|
|
@ -920,7 +938,9 @@ namespace Flow.Launcher.ViewModel
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Log.Exception($"{nameof(MainViewModel)}.{nameof(ConstructQuery)}|Error when expanding shortcut {shortcut.Key}", e);
|
Log.Exception(
|
||||||
|
$"{nameof(MainViewModel)}.{nameof(ConstructQuery)}|Error when expanding shortcut {shortcut.Key}",
|
||||||
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -1065,6 +1085,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
SelectedResults = Results;
|
SelectedResults = Results;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Settings.LastQueryMode)
|
switch (Settings.LastQueryMode)
|
||||||
{
|
{
|
||||||
case LastQueryMode.Empty:
|
case LastQueryMode.Empty:
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
<!-- Dialogues -->
|
<!-- Dialogues -->
|
||||||
<system:String x:Key="plugin_explorer_make_selection_warning">Сначала отметьте что-нибудь</system:String>
|
<system:String x:Key="plugin_explorer_make_selection_warning">Сначала отметьте что-нибудь</system:String>
|
||||||
<system:String x:Key="plugin_explorer_select_folder_link_warning">Please select a folder link</system:String>
|
<system:String x:Key="plugin_explorer_select_folder_link_warning">Пожалуйста, выберите ссылку на папку</system:String>
|
||||||
<system:String x:Key="plugin_explorer_delete_folder_link">Вы уверены, что хотите удалить {0}?</system:String>
|
<system:String x:Key="plugin_explorer_delete_folder_link">Вы уверены, что хотите удалить {0}?</system:String>
|
||||||
<system:String x:Key="plugin_explorer_deletefileconfirm">Вы действительно хотите безвозвратно удалить этот файл?</system:String>
|
<system:String x:Key="plugin_explorer_deletefileconfirm">Вы действительно хотите безвозвратно удалить этот файл?</system:String>
|
||||||
<system:String x:Key="plugin_explorer_deletefilefolderconfirm">Вы действительно хотите безвозвратно удалить этот файл/папку?</system:String>
|
<system:String x:Key="plugin_explorer_deletefilefolderconfirm">Вы действительно хотите безвозвратно удалить этот файл/папку?</system:String>
|
||||||
<system:String x:Key="plugin_explorer_deletefilefoldersuccess">Удаление завершено</system:String>
|
<system:String x:Key="plugin_explorer_deletefilefoldersuccess">Удаление завершено</system:String>
|
||||||
<system:String x:Key="plugin_explorer_deletefilefoldersuccess_detail">Успешно удалено {0}</system:String>
|
<system:String x:Key="plugin_explorer_deletefilefoldersuccess_detail">Успешно удалено {0}</system:String>
|
||||||
<system:String x:Key="plugin_explorer_globalActionKeywordInvalid">Assigning the global action keyword could bring up too many results during search. Please choose a specific action keyword</system:String>
|
<system:String x:Key="plugin_explorer_globalActionKeywordInvalid">Назначение ключевого слова глобальных действий может привести к слишком большому количеству результатов поиска. Пожалуйста, выберите конкретное ключевое слово действий</system:String>
|
||||||
<system:String x:Key="plugin_explorer_quickaccess_globalActionKeywordInvalid">Quick Access can not be set to the global action keyword when enabled. Please choose a specific action keyword</system:String>
|
<system:String x:Key="plugin_explorer_quickaccess_globalActionKeywordInvalid">Quick Access can not be set to the global action keyword when enabled. Please choose a specific action keyword</system:String>
|
||||||
<system:String x:Key="plugin_explorer_windowsSearchServiceNotRunning">The required service for Windows Index Search does not appear to be running</system:String>
|
<system:String x:Key="plugin_explorer_windowsSearchServiceNotRunning">The required service for Windows Index Search does not appear to be running</system:String>
|
||||||
<system:String x:Key="plugin_explorer_windowsSearchServiceFix">To fix this, start the Windows Search service. Select here to remove this warning</system:String>
|
<system:String x:Key="plugin_explorer_windowsSearchServiceFix">To fix this, start the Windows Search service. Select here to remove this warning</system:String>
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
||||||
FileName = FullPath,
|
FileName = FullPath,
|
||||||
WorkingDirectory = ParentDirectory,
|
WorkingDirectory = ParentDirectory,
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
Verb = runAsAdmin ? "runas" : ""
|
Verb = runAsAdmin ? "runas" : "",
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = Task.Run(() => Main.StartProcess(Process.Start, info));
|
_ = Task.Run(() => Main.StartProcess(Process.Start, info));
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||||
|
|
||||||
<!-- Command List -->
|
<!-- Command List -->
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_command">Command</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_command">Opdracht</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_desc">Description</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_desc">Beschrijving</system:String>
|
||||||
|
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer_cmd">Shutdown</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer_cmd">Shutdown</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_restart_computer_cmd">Restart</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_restart_computer_cmd">Restart</system:String>
|
||||||
|
|
@ -27,37 +27,37 @@
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_toggle_game_mode_cmd">Toggle Game Mode</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_toggle_game_mode_cmd">Toggle Game Mode</system:String>
|
||||||
|
|
||||||
<!-- Command Descriptions -->
|
<!-- Command Descriptions -->
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer">Shutdown Computer</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_shutdown_computer">Computer afsluiten</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_restart_computer">Restart Computer</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_restart_computer">Computer opnieuw opstarten</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_restart_advanced">Restart the computer with Advanced Boot Options for Safe and Debugging modes, as well as other options</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_restart_advanced">Start de computer opnieuw op met geavanceerde opstartopties voor veilige en foutopsporing modi en andere opties</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_log_off">Log off</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_log_off">Afmelden</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_lock">Lock this computer</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_lock">Deze computer vergrendelen</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_exit">Close Flow Launcher</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_exit">Sluit Flow Launcher</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_restart">Restart Flow Launcher</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_restart">Flow Launcher herstarten</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_setting">Tweak Flow Launcher's settings</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_setting">Tweak Flow Launcher's settings</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_sleep">Put computer to sleep</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_sleep">De computer in slaapstand zetten</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_emptyrecyclebin">Empty recycle bin</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_emptyrecyclebin">Prullenbak leegmaken</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_openrecyclebin">Open recycle bin</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_openrecyclebin">Open recycle bin</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_indexoption">Indexing Options</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_indexoption">Indexing Options</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_hibernate">Hibernate computer</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_hibernate">De computer in sluimerstand zetten</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_save_all_settings">Save all Flow Launcher settings</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_save_all_settings">Sla alle Flow Launcher instellingen op</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_reload_plugin_data">Refreshes plugin data with new content</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_reload_plugin_data">Vernieuwt plugin data met nieuwe inhoud</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_open_log_location">Open Flow Launcher's log location</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_open_log_location">Open de locatie van Flow Launcher's log bestand</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_check_for_update">Check for new Flow Launcher update</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_check_for_update">Controleer op nieuwe Flow Launcher update</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_open_docs_tips">Visit Flow Launcher's documentation for more help and how to use tips</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_open_docs_tips">Bezoek Flow Launcher's documentatie voor meer hulp en tips</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_open_userdata_location">Open the location where Flow Launcher's settings are stored</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_open_userdata_location">Open de locatie waar Flow Launcher's instellingen worden opgeslagen</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_toggle_game_mode">Toggle Game Mode</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_toggle_game_mode">Toggle Game Mode</system:String>
|
||||||
|
|
||||||
<!-- Dialogs -->
|
<!-- Dialogs -->
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtitle_success">Succesvol</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtitle_success">Succesvol</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_settings_saved">All Flow Launcher settings saved</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_settings_saved">Alle Flow Launcher instellingen opgeslagen</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded">Reloaded all applicable plugin data</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded">Alle toepasselijke plugin gegevens zijn herladen</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_shutdown_computer">Are you sure you want to shut the computer down?</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_shutdown_computer">Weet u zeker dat u de computer wilt uitschakelen?</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer">Are you sure you want to restart the computer?</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer">Weet u zeker dat u de computer wilt herstarten?</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer_advanced">Are you sure you want to restart the computer with Advanced Boot Options?</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_restart_computer_advanced">Weet u zeker dat u de computer wilt herstarten met geavanceerde opstartopties?</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_logoff_computer">Are you sure you want to log off?</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_dlgtext_logoff_computer">Are you sure you want to log off?</system:String>
|
||||||
|
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_plugin_name">System Commands</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_plugin_name">Systeemopdrachten</system:String>
|
||||||
<system:String x:Key="flowlauncher_plugin_sys_plugin_description">Provides System related commands. e.g. shutdown, lock, settings etc.</system:String>
|
<system:String x:Key="flowlauncher_plugin_sys_plugin_description">Voorziet in systeem gerelateerde opdrachten. bijv.: afsluiten, vergrendelen, instellingen, enz.</system:String>
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
|
||||||
|
|
@ -456,7 +456,7 @@
|
||||||
<comment>Area Personalization</comment>
|
<comment>Area Personalization</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Command" xml:space="preserve">
|
<data name="Command" xml:space="preserve">
|
||||||
<value>Command</value>
|
<value>Opdracht</value>
|
||||||
<comment>The command to direct start a setting</comment>
|
<comment>The command to direct start a setting</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConnectedDevices" xml:space="preserve">
|
<data name="ConnectedDevices" xml:space="preserve">
|
||||||
|
|
|
||||||
|
|
@ -1926,10 +1926,10 @@
|
||||||
<value>微软拼音 SimpleFast 选项</value>
|
<value>微软拼音 SimpleFast 选项</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChangeWhatClosingTheLidDoes" xml:space="preserve">
|
<data name="ChangeWhatClosingTheLidDoes" xml:space="preserve">
|
||||||
<value>Change what closing the lid does</value>
|
<value>更改盖上盖子时的操作</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TurnOffUnnecessaryAnimations" xml:space="preserve">
|
<data name="TurnOffUnnecessaryAnimations" xml:space="preserve">
|
||||||
<value>Turn off unnecessary animations</value>
|
<value>关闭不必要的动画效果</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreateARestorePoint" xml:space="preserve">
|
<data name="CreateARestorePoint" xml:space="preserve">
|
||||||
<value>创建还原点</value>
|
<value>创建还原点</value>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue