diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 2d6fdb7f0..c4b1ee849 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -106,3 +106,4 @@ alreadyexists JsonRPC JsonRPCV2 Softpedia +img diff --git a/Flow.Launcher.Core/Plugin/ExecutablePluginV2.cs b/Flow.Launcher.Core/Plugin/ExecutablePluginV2.cs index ee1b315c2..852f57b9f 100644 --- a/Flow.Launcher.Core/Plugin/ExecutablePluginV2.cs +++ b/Flow.Launcher.Core/Plugin/ExecutablePluginV2.cs @@ -12,15 +12,9 @@ namespace Flow.Launcher.Core.Plugin public ExecutablePluginV2(string filename) { - StartInfo = new ProcessStartInfo - { - FileName = filename, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true - }; + StartInfo = new ProcessStartInfo { FileName = filename }; } + protected override MessageHandlerType MessageHandler { get; } = MessageHandlerType.NewLineDelimited; } } diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index 390da072b..46c72624a 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -15,8 +15,6 @@ namespace Flow.Launcher.Core.Plugin { internal abstract class JsonRPCPluginV2 : JsonRPCPluginBase, IAsyncDisposable, IAsyncReloadable, IResultUpdated { - public abstract string SupportedLanguage { get; set; } - public const string JsonRpc = "JsonRPC"; 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 LoadContextMenus(Result selectedResult) { - throw new NotImplementedException(); + try + { + var res = JTF.Run(() => RPC.InvokeWithCancellationAsync("context_menu", + new object[] { selectedResult.ContextData })); + + var results = ParseResults(res); + + return results; + } + catch + { + return new List(); + } } public override async Task> QueryAsync(Query query, CancellationToken token) @@ -51,7 +63,7 @@ namespace Flow.Launcher.Core.Plugin try { var res = await RPC.InvokeWithCancellationAsync("query", - new[] { query }, + new object[] { query, Settings.Inner }, token); var results = ParseResults(res); @@ -88,12 +100,26 @@ namespace Flow.Launcher.Core.Plugin public event ResultUpdatedEventHandler ResultsUpdated; + protected enum MessageHandlerType + { + HeaderDelimited, + LengthHeaderDelimited, + NewLineDelimited + } + + protected abstract MessageHandlerType MessageHandler { get; } + private void SetupJsonRPC() { var formatter = new SystemTextJsonFormatter { JsonSerializerOptions = RequestSerializeOption }; - var handler = new NewLineDelimitedMessageHandler(ClientPipe, - formatter); + IJsonRpcMessageHandler handler = MessageHandler switch + { + 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)); diff --git a/Flow.Launcher.Core/Plugin/NodePluginV2.cs b/Flow.Launcher.Core/Plugin/NodePluginV2.cs index 6c95777f0..c8cc37c57 100644 --- a/Flow.Launcher.Core/Plugin/NodePluginV2.cs +++ b/Flow.Launcher.Core/Plugin/NodePluginV2.cs @@ -10,29 +10,21 @@ namespace Flow.Launcher.Core.Plugin /// /// Execution of JavaScript & TypeScript plugins /// - internal class NodePluginV2 : ProcessStreamPluginV2 + internal sealed class NodePluginV2 : ProcessStreamPluginV2 { public NodePluginV2(string filename) { - StartInfo = new ProcessStartInfo - { - FileName = filename, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true - }; + StartInfo = new ProcessStartInfo { FileName = filename, }; } - public override string SupportedLanguage { get; set; } protected override ProcessStartInfo StartInfo { get; set; } public override async Task InitAsync(PluginInitContext context) { StartInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); - StartInfo.ArgumentList.Add(string.Empty); - StartInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory; await base.InitAsync(context); } + + protected override MessageHandlerType MessageHandler { get; } = MessageHandlerType.HeaderDelimited; } } diff --git a/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs b/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs index 16f9dfbf9..a14baf271 100644 --- a/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs @@ -1,4 +1,6 @@ -using System; +#nullable enable + +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO.Pipelines; @@ -6,6 +8,7 @@ using System.Threading.Tasks; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; using Meziantou.Framework.Win32; +using Microsoft.VisualBasic.ApplicationServices; using Nerdbank.Streams; namespace Flow.Launcher.Core.Plugin @@ -18,18 +21,18 @@ namespace Flow.Launcher.Core.Plugin { _jobObject.SetLimits(new JobObjectLimits() { - Flags = JobObjectLimitFlags.KillOnJobClose | JobObjectLimitFlags.DieOnUnhandledException + Flags = JobObjectLimitFlags.KillOnJobClose | JobObjectLimitFlags.DieOnUnhandledException | + JobObjectLimitFlags.SilentBreakawayOk }); - + _jobObject.AssignProcess(Process.GetCurrentProcess()); } - public override string SupportedLanguage { get; set; } - protected sealed override IDuplexPipe ClientPipe { get; set; } + protected sealed override IDuplexPipe ClientPipe { get; set; } = null!; protected abstract ProcessStartInfo StartInfo { get; set; } - protected Process ClientProcess { get; set; } + protected Process ClientProcess { get; set; } = null!; 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_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; - ClientProcess = Process.Start(StartInfo); - ArgumentNullException.ThrowIfNull(ClientProcess); - + var process = Process.Start(StartInfo); + ArgumentNullException.ThrowIfNull(process); + ClientProcess = process; + _jobObject.AssignProcess(ClientProcess); + SetupPipe(ClientProcess); ErrorStream = ClientProcess.StandardError; diff --git a/Flow.Launcher.Core/Plugin/PythonPluginV2.cs b/Flow.Launcher.Core/Plugin/PythonPluginV2.cs index 4a8d8d7de..5c36e0eea 100644 --- a/Flow.Launcher.Core/Plugin/PythonPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/PythonPluginV2.cs @@ -18,20 +18,11 @@ namespace Flow.Launcher.Core.Plugin { internal sealed class PythonPluginV2 : ProcessStreamPluginV2 { - public override string SupportedLanguage { get; set; } = AllowedLanguage.Python; protected override ProcessStartInfo StartInfo { get; set; } - + public PythonPluginV2(string filename) { - StartInfo = new ProcessStartInfo - { - FileName = filename, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - RedirectStandardInput = true - }; + StartInfo = new ProcessStartInfo { FileName = filename, }; var path = Path.Combine(Constant.ProgramDirectory, JsonRpc); 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 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; } } diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index b24f069c1..574f3686a 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -49,6 +49,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs index 7a2b57637..55545b9a7 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs @@ -4,13 +4,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows.Media; +using FastCache; +using FastCache.Services; namespace Flow.Launcher.Infrastructure.Image { - [Serializable] public class ImageUsage { - public int usage; public ImageSource imageSource; @@ -23,16 +23,13 @@ namespace Flow.Launcher.Infrastructure.Image public class ImageCache { - private const int MaxCached = 50; - public ConcurrentDictionary<(string, bool), ImageUsage> Data { get; } = new(); - private const int permissibleFactor = 2; - private SemaphoreSlim semaphore = new(1, 1); + private const int MaxCached = 150; public void Initialize(Dictionary<(string, bool), int> usage) { foreach (var key in usage.Keys) { - Data[key] = new ImageUsage(usage[key], null); + Cached.Save(key, new ImageUsage(usage[key], null), TimeSpan.MaxValue, MaxCached); } } @@ -40,70 +37,48 @@ namespace Flow.Launcher.Infrastructure.Image { get { - if (!Data.TryGetValue((path, isFullImage), out var value)) + if (!Cached.TryGet((path, isFullImage), out var value)) { return null; } - value.usage++; - return value.imageSource; + value.Value.usage++; + return value.Value.imageSource; } set { - Data.AddOrUpdate( - (path, isFullImage), - new ImageUsage(0, value), - (k, v) => - { - v.imageSource = value; - v.usage++; - return v; - } - ); - - SliceExtra(); - - async void SliceExtra() + if (Cached.TryGet((path, isFullImage), out var cached)) { - // 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 - // This is done so that we don't constantly perform this resizing operation and also maintain the image cache size at the same time - 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.Value.imageSource = value; + cached.Value.usage++; } + + Cached.Save((path, isFullImage), new ImageUsage(0, value), TimeSpan.MaxValue, + MaxCached); } } public bool ContainsKey(string key, bool isFullImage) { - return key is not null && Data.ContainsKey((key, isFullImage)) && Data[(key, isFullImage)].imageSource != null; + return Cached.TryGet((key, isFullImage), out _); } public bool TryGetValue(string key, bool isFullImage, out ImageSource image) { - if (key is not null) + if (Cached.TryGet((key, isFullImage), out var value)) { - bool hasKey = Data.TryGetValue((key, isFullImage), out var imageUsage); - image = hasKey ? imageUsage.imageSource : null; - return hasKey; - } - else - { - image = null; - return false; + image = value.Value.imageSource; + value.Value.usage++; + return image != null; } + + image = null; + return false; } public int CacheSize() { - return Data.Count; + return CacheManager.TotalCount<(string, bool), ImageUsage>(); } /// @@ -111,7 +86,14 @@ namespace Flow.Launcher.Infrastructure.Image /// 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> EnumerateEntries() + { + return CacheManager.EnumerateEntries<(string, bool), ImageUsage>(); } } } diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index add6d4e92..75c2a4ec9 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -49,7 +49,7 @@ namespace Flow.Launcher.Infrastructure.Image { 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); } @@ -65,7 +65,7 @@ namespace Flow.Launcher.Infrastructure.Image try { - _storage.SaveAsync(ImageCache.Data + await _storage.SaveAsync(ImageCache.EnumerateEntries() .ToDictionary( x => x.Key, x => x.Value.usage)); @@ -125,9 +125,12 @@ namespace Flow.Launcher.Infrastructure.Image 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) diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index add321b8f..724fd1865 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -51,7 +51,11 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 3a2ba44c1..5b28c5712 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -182,7 +182,7 @@ Query Shortcut Expansion - Description + Beschrijving Verwijder Bewerken Toevoegen diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 91ae87631..252bfb81d 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -171,7 +171,7 @@ Klávesová skratka pre Flow Launcher Zadajte skratku na zobrazenie/skrytie Flow Launchera. Klávesová skratka pre náhľad - Zadajte klávesovú skratku pre zobrazenie/skytie náhľadu vo vyhľadávacom okne. + Zadajte klávesovú skratku pre zobrazenie/skrytie náhľadu vo vyhľadávacom okne. Modifikačný kláves na otvorenie výsledkov Vyberte modifikačný kláves na otvorenie vybraného výsledku pomocou klávesnice. Zobraziť klávesovú skratku diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 88e95aa69..e2c74d367 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -186,6 +186,10 @@ Key="F12" Command="{Binding ToggleGameModeCommand}" Modifiers="Ctrl" /> + _queryText; @@ -426,6 +443,7 @@ namespace Flow.Launcher.ViewModel Settings.WindowSize += 100; Settings.WindowLeft -= 50; } + OnPropertyChanged(); } @@ -441,6 +459,7 @@ namespace Flow.Launcher.ViewModel Settings.WindowLeft += 50; Settings.WindowSize -= 100; } + OnPropertyChanged(); } @@ -520,18 +539,17 @@ namespace Flow.Launcher.ViewModel { if (QueryText != queryText) { - // re-query is done in QueryText's setter method QueryText = queryText; // set to false so the subsequent set true triggers // PropertyChanged and MoveQueryTextToEnd is called QueryTextCursorMovedToEnd = false; - } else if (isReQuery) { Query(isReQuery: true); } + QueryTextCursorMovedToEnd = true; }); } @@ -601,8 +619,8 @@ namespace Flow.Launcher.ViewModel public string OpenResultCommandModifiers => Settings.OpenResultModifiers; - public string PreviewHotkey - { + public string PreviewHotkey + { get { // TODO try to patch issue #1755 @@ -616,6 +634,7 @@ namespace Flow.Launcher.ViewModel { Settings.PreviewHotkey = "F1"; } + return Settings.PreviewHotkey; } } @@ -684,7 +703,6 @@ namespace Flow.Launcher.ViewModel results.Add(ContextMenuTopMost(selected)); results.Add(ContextMenuPluginInfo(selected.PluginID)); } - if (!string.IsNullOrEmpty(query)) @@ -703,7 +721,6 @@ namespace Flow.Launcher.ViewModel r.Score = match.Score; return true; - }).ToList(); ContextMenu.AddResults(filtered, id); } @@ -730,10 +747,7 @@ namespace Flow.Launcher.ViewModel Title = string.Format(title, h.Query), SubTitle = string.Format(time, h.ExecutedDateTime), IcoPath = "Images\\history.png", - OriginQuery = new Query - { - RawQuery = h.Query - }, + OriginQuery = new Query { RawQuery = h.Query }, Action = _ => { SelectedResults = Results; @@ -870,20 +884,23 @@ namespace Flow.Launcher.ViewModel // Task.Yield will force it to run in ThreadPool await Task.Yield(); - IReadOnlyList results = await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken); + IReadOnlyList results = + await PluginManager.QueryForPluginAsync(plugin, query, currentCancellationToken); currentCancellationToken.ThrowIfCancellationRequested(); 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"); } } } - private Query ConstructQuery(string queryText, IEnumerable customShortcuts, IEnumerable builtInShortcuts) + private Query ConstructQuery(string queryText, IEnumerable customShortcuts, + IEnumerable builtInShortcuts) { if (string.IsNullOrWhiteSpace(queryText)) { @@ -893,7 +910,8 @@ namespace Flow.Launcher.ViewModel StringBuilder queryBuilder = 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)) { @@ -920,7 +938,9 @@ namespace Flow.Launcher.ViewModel } 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; } + switch (Settings.LastQueryMode) { case LastQueryMode.Empty: diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml index efb08c3f1..cb7f2cda5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml @@ -3,13 +3,13 @@ Сначала отметьте что-нибудь - Please select a folder link + Пожалуйста, выберите ссылку на папку Вы уверены, что хотите удалить {0}? Вы действительно хотите безвозвратно удалить этот файл? Вы действительно хотите безвозвратно удалить этот файл/папку? Удаление завершено Успешно удалено {0} - Assigning the global action keyword could bring up too many results during search. Please choose a specific action keyword + Назначение ключевого слова глобальных действий может привести к слишком большому количеству результатов поиска. Пожалуйста, выберите конкретное ключевое слово действий Quick Access can not be set to the global action keyword when enabled. Please choose a specific action keyword The required service for Windows Index Search does not appear to be running To fix this, start the Windows Search service. Select here to remove this warning diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 7d08d3670..a7f447598 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -196,7 +196,7 @@ namespace Flow.Launcher.Plugin.Program.Programs FileName = FullPath, WorkingDirectory = ParentDirectory, UseShellExecute = true, - Verb = runAsAdmin ? "runas" : "" + Verb = runAsAdmin ? "runas" : "", }; _ = Task.Run(() => Main.StartProcess(Process.Start, info)); diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml index ca798f9d7..a71e28e98 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml @@ -2,8 +2,8 @@ - Command - Description + Opdracht + Beschrijving Shutdown Restart @@ -27,37 +27,37 @@ Toggle Game Mode - Shutdown Computer - Restart Computer - Restart the computer with Advanced Boot Options for Safe and Debugging modes, as well as other options - Log off - Lock this computer - Close Flow Launcher - Restart Flow Launcher + Computer afsluiten + Computer opnieuw opstarten + Start de computer opnieuw op met geavanceerde opstartopties voor veilige en foutopsporing modi en andere opties + Afmelden + Deze computer vergrendelen + Sluit Flow Launcher + Flow Launcher herstarten Tweak Flow Launcher's settings - Put computer to sleep - Empty recycle bin + De computer in slaapstand zetten + Prullenbak leegmaken Open recycle bin Indexing Options - Hibernate computer - Save all Flow Launcher settings - Refreshes plugin data with new content - Open Flow Launcher's log location - Check for new Flow Launcher update - Visit Flow Launcher's documentation for more help and how to use tips - Open the location where Flow Launcher's settings are stored + De computer in sluimerstand zetten + Sla alle Flow Launcher instellingen op + Vernieuwt plugin data met nieuwe inhoud + Open de locatie van Flow Launcher's log bestand + Controleer op nieuwe Flow Launcher update + Bezoek Flow Launcher's documentatie voor meer hulp en tips + Open de locatie waar Flow Launcher's instellingen worden opgeslagen Toggle Game Mode Succesvol - All Flow Launcher settings saved - Reloaded all applicable plugin data - Are you sure you want to shut the computer down? - Are you sure you want to restart the computer? - Are you sure you want to restart the computer with Advanced Boot Options? + Alle Flow Launcher instellingen opgeslagen + Alle toepasselijke plugin gegevens zijn herladen + Weet u zeker dat u de computer wilt uitschakelen? + Weet u zeker dat u de computer wilt herstarten? + Weet u zeker dat u de computer wilt herstarten met geavanceerde opstartopties? Are you sure you want to log off? - System Commands - Provides System related commands. e.g. shutdown, lock, settings etc. + Systeemopdrachten + Voorziet in systeem gerelateerde opdrachten. bijv.: afsluiten, vergrendelen, instellingen, enz. diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.nl-NL.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.nl-NL.resx index e5ff84248..c28489cc8 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.nl-NL.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.nl-NL.resx @@ -456,7 +456,7 @@ Area Personalization - Command + Opdracht The command to direct start a setting diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.zh-cn.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.zh-cn.resx index 8e71e09a3..2b39d48e4 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.zh-cn.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.zh-cn.resx @@ -1926,10 +1926,10 @@ 微软拼音 SimpleFast 选项 - Change what closing the lid does + 更改盖上盖子时的操作 - Turn off unnecessary animations + 关闭不必要的动画效果 创建还原点