diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index ea2119e60..dd6517a7f 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.IO; @@ -45,8 +45,56 @@ namespace Flow.Launcher.Core.Plugin } } } - - return allPluginMetadata; + + (List uniqueList, List duplicateList) = GetUniqueLatestPluginMetadata(allPluginMetadata); + + duplicateList + .ForEach( + x => Log.Warn("PluginConfig", + string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " + + "not loaded due to version not the highest of the duplicates", + x.Name, x.ID, x.Version), + "GetUniqueLatestPluginMetadata")); + + return uniqueList; + } + + internal static (List, List) GetUniqueLatestPluginMetadata(List allPluginMetadata) + { + var duplicate_list = new List(); + var unique_list = new List(); + + var duplicateGroups = allPluginMetadata.GroupBy(x => x.ID).Where(g => g.Count() > 1).Select(y => y).ToList(); + + foreach (var metadata in allPluginMetadata) + { + var duplicatesExist = false; + foreach (var group in duplicateGroups) + { + if (metadata.ID == group.Key) + { + duplicatesExist = true; + + // If metadata's version greater than each duplicate's version, CompareTo > 0 + var count = group.Where(x => metadata.Version.CompareTo(x.Version) > 0).Count(); + + // Only add if the meatadata's version is the highest of all duplicates in the group + if (count == group.Count() - 1) + { + unique_list.Add(metadata); + } + else + { + duplicate_list.Add(metadata); + } + } + } + + if (!duplicatesExist) + unique_list.Add(metadata); + } + + return (unique_list, duplicate_list); } private static PluginMetadata GetPluginMetadata(string pluginDirectory) diff --git a/Flow.Launcher.Core/Plugin/PythonPlugin.cs b/Flow.Launcher.Core/Plugin/PythonPlugin.cs index 968c0ab23..8f7e5760a 100644 --- a/Flow.Launcher.Core/Plugin/PythonPlugin.cs +++ b/Flow.Launcher.Core/Plugin/PythonPlugin.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using System.Threading; @@ -28,6 +28,11 @@ namespace Flow.Launcher.Core.Plugin var path = Path.Combine(Constant.ProgramDirectory, JsonRPC); _startInfo.EnvironmentVariables["PYTHONPATH"] = path; + _startInfo.EnvironmentVariables["FLOW_VERSION"] = Constant.Version; + _startInfo.EnvironmentVariables["FLOW_PROGRAM_DIRECTORY"] = Constant.ProgramDirectory; + _startInfo.EnvironmentVariables["FLOW_APPLICATION_DIRECTORY"] = Constant.ApplicationDirectory; + + //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"); } @@ -54,4 +59,4 @@ namespace Flow.Launcher.Core.Plugin _startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory; } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Core/Resource/AvailableLanguages.cs b/Flow.Launcher.Core/Resource/AvailableLanguages.cs index 3c3dbc76f..0ad7ede1e 100644 --- a/Flow.Launcher.Core/Resource/AvailableLanguages.cs +++ b/Flow.Launcher.Core/Resource/AvailableLanguages.cs @@ -17,7 +17,8 @@ namespace Flow.Launcher.Core.Resource public static Language German = new Language("de", "Deutsch"); public static Language Korean = new Language("ko", "한국어"); public static Language Serbian = new Language("sr", "Srpski"); - public static Language Portuguese_BR = new Language("pt-br", "Português (Brasil)"); + public static Language Portuguese_Portugal = new Language("pt-pt", "Português"); + public static Language Portuguese_Brazil = new Language("pt-br", "Português (Brasil)"); public static Language Italian = new Language("it", "Italiano"); public static Language Norwegian_Bokmal = new Language("nb-NO", "Norsk Bokmål"); public static Language Slovak = new Language("sk", "Slovenský"); @@ -40,7 +41,8 @@ namespace Flow.Launcher.Core.Resource German, Korean, Serbian, - Portuguese_BR, + Portuguese_Portugal, + Portuguese_Brazil, Italian, Norwegian_Bokmal, Slovak, diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 78e8c5cbf..374f7c71f 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -10,6 +10,7 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Globalization; +using System.Threading.Tasks; namespace Flow.Launcher.Core.Resource { @@ -95,10 +96,13 @@ namespace Flow.Launcher.Core.Resource { LoadLanguage(language); } - UpdatePluginMetadataTranslations(); Settings.Language = language.LanguageCode; CultureInfo.CurrentCulture = new CultureInfo(language.LanguageCode); CultureInfo.CurrentUICulture = CultureInfo.CurrentCulture; + Task.Run(() => + { + UpdatePluginMetadataTranslations(); + }); } public bool PromptShouldUsePinyin(string languageCodeToSet) diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs index 564e03638..cd49217a4 100644 --- a/Flow.Launcher.Infrastructure/Constant.cs +++ b/Flow.Launcher.Infrastructure/Constant.cs @@ -35,8 +35,16 @@ namespace Flow.Launcher.Infrastructure public const string DefaultTheme = "Win11Light"; + public const string Light = "Light"; + public const string Dark = "Dark"; + public const string System = "System"; + public const string Themes = "Themes"; + public const string Settings = "Settings"; + public const string Logs = "Logs"; public const string Website = "https://flow-launcher.github.io"; + public const string GitHub = "https://github.com/Flow-Launcher/Flow.Launcher"; + public const string Docs = "https://flow-launcher.github.io/docs"; } } diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index e01bc1efd..40c2cb956 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -11,6 +11,7 @@ false false false + true @@ -21,7 +22,6 @@ DEBUG;TRACE prompt 4 - true false @@ -32,7 +32,6 @@ TRACE prompt 4 - false false diff --git a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs index e92a93c12..a09185696 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/GlobalHotkey.cs @@ -9,13 +9,14 @@ namespace Flow.Launcher.Infrastructure.Hotkey /// Listens keyboard globally. /// Uses WH_KEYBOARD_LL. /// - public class GlobalHotkey : IDisposable + public unsafe class GlobalHotkey : IDisposable { - private static GlobalHotkey instance; - private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc; - private IntPtr hookId = IntPtr.Zero; + private static readonly IntPtr hookId; + + + public delegate bool KeyboardCallback(KeyEvent keyEvent, int vkCode, SpecialKeyState state); - public event KeyboardCallback hookedKeyboardCallback; + internal static Func hookedKeyboardCallback; //Modifier key constants private const int VK_SHIFT = 0x10; @@ -23,27 +24,13 @@ namespace Flow.Launcher.Infrastructure.Hotkey private const int VK_ALT = 0x12; private const int VK_WIN = 91; - public static GlobalHotkey Instance + static GlobalHotkey() { - get - { - if (instance == null) - { - instance = new GlobalHotkey(); - } - return instance; - } - } - - private GlobalHotkey() - { - // We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime - hookedLowLevelKeyboardProc = LowLevelKeyboardProc; // Set the hook - hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc); + hookId = InterceptKeys.SetHook(& LowLevelKeyboardProc); } - public SpecialKeyState CheckModifiers() + public static SpecialKeyState CheckModifiers() { SpecialKeyState state = new SpecialKeyState(); if ((InterceptKeys.GetKeyState(VK_SHIFT) & 0x8000) != 0) @@ -70,8 +57,8 @@ namespace Flow.Launcher.Infrastructure.Hotkey return state; } - [MethodImpl(MethodImplOptions.NoInlining)] - private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam) + [UnmanagedCallersOnly] + private static IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam) { bool continues = true; @@ -91,17 +78,17 @@ namespace Flow.Launcher.Infrastructure.Hotkey { return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); } - return (IntPtr)1; - } - - ~GlobalHotkey() - { - Dispose(); + return (IntPtr)(-1); } public void Dispose() { InterceptKeys.UnhookWindowsHookEx(hookId); } + + ~GlobalHotkey() + { + Dispose(); + } } } \ No newline at end of file diff --git a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs index c45e685f3..d33bac34c 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs +++ b/Flow.Launcher.Infrastructure/Hotkey/InterceptKeys.cs @@ -4,13 +4,13 @@ using System.Runtime.InteropServices; namespace Flow.Launcher.Infrastructure.Hotkey { - internal static class InterceptKeys + internal static unsafe class InterceptKeys { public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam); private const int WH_KEYBOARD_LL = 13; - public static IntPtr SetHook(LowLevelKeyboardProc proc) + public static IntPtr SetHook(delegate* unmanaged proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) @@ -20,7 +20,7 @@ namespace Flow.Launcher.Infrastructure.Hotkey } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] - public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); + public static extern IntPtr SetWindowsHookEx(int idHook, delegate* unmanaged lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 34e86a3ed..6bf9c2ff0 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -15,6 +15,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings private string language = "en"; public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}"; public string OpenResultModifiers { get; set; } = KeyConstant.Alt; + public string ColorScheme { get; set; } = "System"; public bool ShowOpenResultHotkey { get; set; } = true; public double WindowSize { get; set; } = 580; @@ -38,6 +39,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public string ResultFontWeight { get; set; } public string ResultFontStretch { get; set; } public bool UseGlyphIcons { get; set; } = true; + public bool FirstLaunch { get; set; } = true; public int CustomExplorerIndex { get; set; } = 0; @@ -82,6 +84,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings } }; + public bool UseAnimation { get; set; } = true; + public bool UseSound { get; set; } = true; /// /// when false Alphabet static service will always return empty results @@ -130,8 +134,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool DontPromptUpdateMsg { get; set; } public bool EnableUpdateLog { get; set; } - public bool StartFlowLauncherOnSystemStartup { get; set; } = true; - public bool HideOnStartup { get; set; } + public bool StartFlowLauncherOnSystemStartup { get; set; } = false; + public bool HideOnStartup { get; set; } = true; bool _hideNotifyIcon { get; set; } public bool HideNotifyIcon { @@ -163,4 +167,11 @@ namespace Flow.Launcher.Infrastructure.UserSettings Empty, Preserved } + + public enum ColorSchemes + { + System, + Light, + Dark + } } \ No newline at end of file diff --git a/Flow.Launcher.Plugin/Interfaces/IPluginI18n.cs b/Flow.Launcher.Plugin/Interfaces/IPluginI18n.cs index e332d450e..61662b671 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPluginI18n.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPluginI18n.cs @@ -1,4 +1,6 @@ -namespace Flow.Launcher.Plugin +using System.Globalization; + +namespace Flow.Launcher.Plugin { /// /// Represent plugins that support internationalization @@ -8,5 +10,13 @@ string GetTranslatedPluginTitle(); string GetTranslatedPluginDescription(); + + /// + /// The method will be invoked when language of flow changed + /// + void OnCultureInfoChanged(CultureInfo newCulture) + { + + } } } \ No newline at end of file diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 3abdaf01f..d1444d5db 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -29,6 +29,21 @@ namespace Flow.Launcher.Plugin /// void RestartApp(); + /// + /// Run a shell command + /// + /// The command or program to run + /// the shell type to run, e.g. powershell.exe + /// Thrown when unable to find the file specified in the command + /// Thrown when error occurs during the execution of the command + void ShellRun(string cmd, string filename = "cmd.exe"); + + /// + /// Copy Text to clipboard + /// + /// Text to save on clipboard + public void CopyToClipboard(string text); + /// /// Save everything, all of Flow Launcher and plugins' data and settings /// @@ -104,7 +119,21 @@ namespace Flow.Launcher.Plugin /// Fired after global keyboard events /// if you want to hook something like Ctrl+R, you should use this event /// + [Obsolete("Unable to Retrieve correct return value")] event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent; + + /// + /// Register a callback for Global Keyboard Event + /// + /// + public void RegisterGlobalKeyboardCallback(Func callback); + + /// + /// Remove a callback for Global Keyboard Event + /// + /// + public void RemoveGlobalKeyboardCallback(Func callback); + /// /// Fuzzy Search the string with the given query. This is the core search mechanism Flow uses diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 171b30c26..29f8198ab 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -29,6 +29,13 @@ namespace Flow.Launcher.Plugin /// public string ActionKeywordAssigned { get; set; } + /// + /// This holds the text which can be provided by plugin to help Flow autocomplete text + /// for user on the plugin result. If autocomplete action for example is tab, pressing tab will have + /// the default constructed autocomplete text (result's Title), or the text provided here if not empty. + /// + public string AutoCompleteText { get; set; } + public string IcoPath { get { return _icoPath; } @@ -50,7 +57,7 @@ namespace Flow.Launcher.Plugin /// /// Delegate to Get Image Source /// - public IconDelegate Icon { get; set; } + public IconDelegate Icon; /// /// Information for Glyph Icon diff --git a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs index c5d43a3d9..a2eea19a7 100644 --- a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs +++ b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -60,17 +60,39 @@ namespace Flow.Launcher.Plugin.SharedCommands return sb.ToString(); } - public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "") + public static ProcessStartInfo SetProcessStartInfo(this string fileName, string workingDirectory = "", string arguments = "", string verb = "", bool createNoWindow = false) { var info = new ProcessStartInfo { FileName = fileName, WorkingDirectory = workingDirectory, Arguments = arguments, - Verb = verb + Verb = verb, + CreateNoWindow = createNoWindow }; return info; } + + /// + /// Runs a windows command using the provided ProcessStartInfo + /// + /// Thrown when unable to find the file specified in the command + /// Thrown when error occurs during the execution of the command + public static void Execute(ProcessStartInfo info) + { + Execute(Process.Start, info); + } + + /// + /// Runs a windows command using the provided ProcessStartInfo using a custom execute command function + /// + /// allows you to pass in a custom command execution function + /// Thrown when unable to find the file specified in the command + /// Thrown when error occurs during the execution of the command + public static void Execute(Func startProcess, ProcessStartInfo info) + { + startProcess(info); + } } } diff --git a/Flow.Launcher.Test/PluginLoadTest.cs b/Flow.Launcher.Test/PluginLoadTest.cs new file mode 100644 index 000000000..d6ba48f19 --- /dev/null +++ b/Flow.Launcher.Test/PluginLoadTest.cs @@ -0,0 +1,92 @@ +using NUnit.Framework; +using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Plugin; +using System.Collections.Generic; +using System.Linq; + +namespace Flow.Launcher.Test +{ + [TestFixture] + class PluginLoadTest + { + [Test] + public void GivenDuplicatePluginMetadatasWhenLoadedThenShouldReturnOnlyUniqueList() + { + // Given + var duplicateList = new List + { + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.1" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.2" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B4085823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "ABC0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "ABC0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + } + }; + + // When + (var unique, var duplicates) = PluginConfig.GetUniqueLatestPluginMetadata(duplicateList); + + // Then + Assert.True(unique.FirstOrDefault().ID == "CEA0TYUC6D3B4085823D60DC76F28855" && unique.FirstOrDefault().Version == "1.0.2"); + Assert.True(unique.Count() == 1); + + Assert.False(duplicates.Any(x => x.Version == "1.0.2" && x.ID == "CEA0TYUC6D3B4085823D60DC76F28855")); + Assert.True(duplicates.Count() == 6); + } + + [Test] + public void GivenDuplicatePluginMetadatasWithNoUniquePluginWhenLoadedThenShouldReturnEmptyList() + { + // Given + var duplicateList = new List + { + new PluginMetadata + { + ID = "CEA0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + }, + new PluginMetadata + { + ID = "CEA0TYUC6D3B7855823D60DC76F28855", + Version = "1.0.0" + } + }; + + // When + (var unique, var duplicates) = PluginConfig.GetUniqueLatestPluginMetadata(duplicateList); + + // Then + Assert.True(unique.Count() == 0); + Assert.True(duplicates.Count() == 2); + } + } +} diff --git a/Flow.Launcher.Test/Plugins/PluginInitTest.cs b/Flow.Launcher.Test/Plugins/PluginInitTest.cs deleted file mode 100644 index 299a837ee..000000000 --- a/Flow.Launcher.Test/Plugins/PluginInitTest.cs +++ /dev/null @@ -1,17 +0,0 @@ -using NUnit.Framework; -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Infrastructure.Exception; - -namespace Flow.Launcher.Test.Plugins -{ - - [TestFixture] - public class PluginInitTest - { - [Test] - public void PublicAPIIsNullTest() - { - //Assert.Throws(typeof(Flow.LauncherFatalException), () => PluginManager.Initialize(null)); - } - } -} diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index 21c3b47dc..b8deae553 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -13,7 +13,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{3A73 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher", "Flow.Launcher\Flow.Launcher.csproj", "{DB90F671-D861-46BB-93A3-F1304F5BA1C5}" ProjectSection(ProjectDependencies) = postProject - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0} = {1EE20B48-82FB-48A2-8086-675D6DDAB4F0} {0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {0B9DE348-9361-4940-ADB6-F5953BFFCCEC} {4792A74A-0CEA-4173-A8B2-30E6764C6217} = {4792A74A-0CEA-4173-A8B2-30E6764C6217} {FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {FDB3555B-58EF-4AE6-B5F1-904719637AB4} @@ -23,6 +22,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher", "Flow.Launc {9B130CC5-14FB-41FF-B310-0A95B6894C37} = {9B130CC5-14FB-41FF-B310-0A95B6894C37} {FDED22C8-B637-42E8-824A-63B5B6E05A3A} = {FDED22C8-B637-42E8-824A-63B5B6E05A3A} {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {A3DCCBCA-ACC1-421D-B16E-210896234C26} + {5043CECE-E6A7-4867-9CBE-02D27D83747A} = {5043CECE-E6A7-4867-9CBE-02D27D83747A} {403B57F2-1856-4FC7-8A24-36AB346B763E} = {403B57F2-1856-4FC7-8A24-36AB346B763E} {588088F4-3262-4F9F-9663-A05DE12534C3} = {588088F4-3262-4F9F-9663-A05DE12534C3} EndProjectSection @@ -35,8 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Progra EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.WebSearch", "Plugins\Flow.Launcher.Plugin.WebSearch\Flow.Launcher.Plugin.WebSearch.csproj", "{403B57F2-1856-4FC7-8A24-36AB346B763E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.ControlPanel", "Plugins\Flow.Launcher.Plugin.ControlPanel\Flow.Launcher.Plugin.ControlPanel.csproj", "{1EE20B48-82FB-48A2-8086-675D6DDAB4F0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.PluginIndicator", "Plugins\Flow.Launcher.Plugin.PluginIndicator\Flow.Launcher.Plugin.PluginIndicator.csproj", "{FDED22C8-B637-42E8-824A-63B5B6E05A3A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Sys", "Plugins\Flow.Launcher.Plugin.Sys\Flow.Launcher.Plugin.Sys.csproj", "{0B9DE348-9361-4940-ADB6-F5953BFFCCEC}" @@ -68,6 +66,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Proces EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.PluginsManager", "Plugins\Flow.Launcher.Plugin.PluginsManager\Flow.Launcher.Plugin.PluginsManager.csproj", "{4792A74A-0CEA-4173-A8B2-30E6764C6217}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.WindowsSettings", "Plugins\Flow.Launcher.Plugin.WindowsSettings\Flow.Launcher.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -162,18 +162,6 @@ Global {403B57F2-1856-4FC7-8A24-36AB346B763E}.Release|x64.Build.0 = Release|Any CPU {403B57F2-1856-4FC7-8A24-36AB346B763E}.Release|x86.ActiveCfg = Release|Any CPU {403B57F2-1856-4FC7-8A24-36AB346B763E}.Release|x86.Build.0 = Release|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x64.ActiveCfg = Debug|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x64.Build.0 = Debug|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x86.ActiveCfg = Debug|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Debug|x86.Build.0 = Debug|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|Any CPU.Build.0 = Release|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x64.ActiveCfg = Release|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x64.Build.0 = Release|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x86.ActiveCfg = Release|Any CPU - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0}.Release|x86.Build.0 = Release|Any CPU {FDED22C8-B637-42E8-824A-63B5B6E05A3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FDED22C8-B637-42E8-824A-63B5B6E05A3A}.Debug|Any CPU.Build.0 = Debug|Any CPU {FDED22C8-B637-42E8-824A-63B5B6E05A3A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -283,6 +271,18 @@ Global {4792A74A-0CEA-4173-A8B2-30E6764C6217}.Release|x64.Build.0 = Release|Any CPU {4792A74A-0CEA-4173-A8B2-30E6764C6217}.Release|x86.ActiveCfg = Release|Any CPU {4792A74A-0CEA-4173-A8B2-30E6764C6217}.Release|x86.Build.0 = Release|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.ActiveCfg = Debug|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.Build.0 = Debug|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x86.ActiveCfg = Debug|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x86.Build.0 = Debug|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|Any CPU.Build.0 = Release|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.Build.0 = Release|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x86.ActiveCfg = Release|Any CPU + {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -290,7 +290,6 @@ Global GlobalSection(NestedProjects) = preSolution {FDB3555B-58EF-4AE6-B5F1-904719637AB4} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {403B57F2-1856-4FC7-8A24-36AB346B763E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} - {1EE20B48-82FB-48A2-8086-675D6DDAB4F0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {FDED22C8-B637-42E8-824A-63B5B6E05A3A} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} @@ -300,6 +299,7 @@ Global {F9C4C081-4CC3-4146-95F1-E102B4E10A5F} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {588088F4-3262-4F9F-9663-A05DE12534C3} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {4792A74A-0CEA-4173-A8B2-30E6764C6217} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} + {5043CECE-E6A7-4867-9CBE-02D27D83747A} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F26ACB50-3F6C-4907-B0C9-1ADACC1D0DED} diff --git a/Flow.Launcher/ActionKeywords.xaml b/Flow.Launcher/ActionKeywords.xaml index 32892768d..e94aac9f6 100644 --- a/Flow.Launcher/ActionKeywords.xaml +++ b/Flow.Launcher/ActionKeywords.xaml @@ -1,85 +1,137 @@ - + + + + - + - - + + - - + + + + + + + + + + + + + + - + - - - + + + - - - - - + + + - + + + + + + - - - - \ No newline at end of file diff --git a/Flow.Launcher/App.xaml b/Flow.Launcher/App.xaml index c5214d7ab..b8e2a1cfe 100644 --- a/Flow.Launcher/App.xaml +++ b/Flow.Launcher/App.xaml @@ -1,16 +1,30 @@ - + - + + + + + + + + + + + + + + - + diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 8c869e941..9ee486b3b 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -100,8 +100,6 @@ namespace Flow.Launcher AutoUpdates(); API.SaveAppAllSettings(); - - _mainVM.MainWindowVisibility = _settings.HideOnStartup ? Visibility.Hidden : Visibility.Visible; Log.Info("|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- "); }); } @@ -178,7 +176,7 @@ namespace Flow.Launcher public void OnSecondAppStarted() { - Current.MainWindow.Visibility = Visibility.Visible; + Current.MainWindow.Show(); } } } \ No newline at end of file diff --git a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs index c70796a6d..08ee8571e 100644 --- a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs +++ b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs @@ -1,6 +1,8 @@ using System; using System.Globalization; +using System.Windows.Controls; using System.Windows.Data; +using System.Windows.Media; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.ViewModel; @@ -10,13 +12,13 @@ namespace Flow.Launcher.Converters { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { - if (values.Length != 2) + if (values.Length != 3) { return string.Empty; } + var QueryTextBox = values[0] as TextBox; - // first prop is the current query string - var queryText = (string)values[0]; + var queryText = (string)values[2]; if (string.IsNullOrEmpty(queryText)) return string.Empty; @@ -43,8 +45,20 @@ namespace Flow.Launcher.Converters if (!selectedResultPossibleSuggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)) return string.Empty; + + // For AutocompleteQueryCommand. // When user typed lower case and result title is uppercase, we still want to display suggestion - return queryText + selectedResultPossibleSuggestion.Substring(queryText.Length); + selectedItem.QuerySuggestionText = queryText + selectedResultPossibleSuggestion.Substring(queryText.Length); + + // Check if Text will be larger then our QueryTextBox + System.Windows.Media.Typeface typeface = new Typeface(QueryTextBox.FontFamily, QueryTextBox.FontStyle, QueryTextBox.FontWeight, QueryTextBox.FontStretch); + System.Windows.Media.FormattedText ft = new FormattedText(QueryTextBox.Text, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, typeface, QueryTextBox.FontSize, Brushes.Black); + if (ft.Width > QueryTextBox.ActualWidth || QueryTextBox.HorizontalOffset != 0) + { + return string.Empty; + }; + + return selectedItem.QuerySuggestionText; } catch (Exception e) { diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml b/Flow.Launcher/CustomQueryHotkeySetting.xaml index 23bd89906..4ba55b110 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml @@ -1,59 +1,160 @@ - + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 0109474e1..ab4047cec 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -1,8 +1,6 @@ using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; -using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; -using System; using System.Collections.ObjectModel; using System.Linq; using System.Windows; @@ -91,9 +89,9 @@ namespace Flow.Launcher private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbAction.Text); - Application.Current.MainWindow.Visibility = Visibility.Visible; + Application.Current.MainWindow.Show(); + Application.Current.MainWindow.Opacity = 1; Application.Current.MainWindow.Focus(); - } private void cmdEsc_OnPress(object sender, ExecutedRoutedEventArgs e) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index fd2f5f1d9..f431504c2 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -104,6 +104,12 @@ + + + Always + + + diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index fe25ecf18..98327d8da 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -6,8 +6,6 @@ using NHotkey.Wpf; using Flow.Launcher.Core.Resource; using System.Windows; using Flow.Launcher.ViewModel; -using System.Threading.Tasks; -using System.Threading; namespace Flow.Launcher.Helper { @@ -27,7 +25,8 @@ namespace Flow.Launcher.Helper internal static void OnToggleHotkey(object sender, HotkeyEventArgs args) { - mainViewModel.ToggleFlowLauncher(); + if (!mainViewModel.GameModeStatus) + mainViewModel.ToggleFlowLauncher(); } private static void SetHotkey(string hotkeyStr, EventHandler action) @@ -75,10 +74,10 @@ namespace Flow.Launcher.Helper { SetHotkey(hotkey.Hotkey, (s, e) => { - if (mainViewModel.ShouldIgnoreHotkeys()) + if (mainViewModel.ShouldIgnoreHotkeys() || mainViewModel.GameModeStatus) return; - mainViewModel.MainWindowVisibility = Visibility.Visible; + mainViewModel.Show(); mainViewModel.ChangeQueryText(hotkey.ActionKeyword, true); }); } diff --git a/Flow.Launcher/Helper/SingletonWindowOpener.cs b/Flow.Launcher/Helper/SingletonWindowOpener.cs index fdfaaa4fc..8efc9be99 100644 --- a/Flow.Launcher/Helper/SingletonWindowOpener.cs +++ b/Flow.Launcher/Helper/SingletonWindowOpener.cs @@ -10,7 +10,6 @@ namespace Flow.Launcher.Helper { var window = Application.Current.Windows.OfType().FirstOrDefault(x => x.GetType() == typeof(T)) ?? (T)Activator.CreateInstance(typeof(T), args); - Application.Current.MainWindow.Hide(); // Fix UI bug // Add `window.WindowState = WindowState.Normal` diff --git a/Flow.Launcher/HotkeyControl.xaml b/Flow.Launcher/HotkeyControl.xaml index 285a282ef..9b5f671d8 100644 --- a/Flow.Launcher/HotkeyControl.xaml +++ b/Flow.Launcher/HotkeyControl.xaml @@ -1,26 +1,56 @@ - + - + - - - - press key + + + + Press key - - - + + \ No newline at end of file diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 2b6e275df..bc437d862 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -8,11 +8,16 @@ using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Plugin; +using System.Threading; namespace Flow.Launcher { public partial class HotkeyControl : UserControl { + private Brush tbMsgForegroundColorOriginal; + + private string tbMsgTextOriginal; + public HotkeyModel CurrentHotkey { get; private set; } public bool CurrentHotkeyAvailable { get; private set; } @@ -23,17 +28,24 @@ namespace Flow.Launcher public HotkeyControl() { InitializeComponent(); + tbMsgTextOriginal = tbMsg.Text; + tbMsgForegroundColorOriginal = tbMsg.Foreground; } - void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e) + private CancellationTokenSource hotkeyUpdateSource; + + private void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e) { + hotkeyUpdateSource?.Cancel(); + hotkeyUpdateSource?.Dispose(); + hotkeyUpdateSource = new(); + var token = hotkeyUpdateSource.Token; e.Handled = true; - tbMsg.Visibility = Visibility.Hidden; //when alt is pressed, the real key should be e.SystemKey - Key key = (e.Key == Key.System ? e.SystemKey : e.Key); + Key key = e.Key == Key.System ? e.SystemKey : e.Key; - SpecialKeyState specialKeyState = GlobalHotkey.Instance.CheckModifiers(); + SpecialKeyState specialKeyState = GlobalHotkey.CheckModifiers(); var hotkeyModel = new HotkeyModel( specialKeyState.AltPressed, @@ -49,14 +61,15 @@ namespace Flow.Launcher return; } - Dispatcher.InvokeAsync(async () => + _ = Dispatcher.InvokeAsync(async () => { - await Task.Delay(500); - SetHotkey(hotkeyModel); + await Task.Delay(500, token); + if (!token.IsCancellationRequested) + await SetHotkey(hotkeyModel); }); } - public void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) + public async Task SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) { CurrentHotkey = keyModel; @@ -78,6 +91,13 @@ namespace Flow.Launcher } tbMsg.Visibility = Visibility.Visible; OnHotkeyChanged(); + + var token = hotkeyUpdateSource.Token; + await Task.Delay(500, token); + if (token.IsCancellationRequested) + return; + FocusManager.SetFocusedElement(FocusManager.GetFocusScope(this), null); + Keyboard.ClearFocus(); } } @@ -88,9 +108,12 @@ namespace Flow.Launcher private bool CheckHotkeyAvailability() => HotKeyMapper.CheckAvailability(CurrentHotkey); - public new bool IsFocused + public new bool IsFocused => tbHotkey.IsFocused; + + private void tbHotkey_LostFocus(object sender, RoutedEventArgs e) { - get { return tbHotkey.IsFocused; } + tbMsg.Text = tbMsgTextOriginal; + tbMsg.Foreground = tbMsgForegroundColorOriginal; } } -} +} \ No newline at end of file diff --git a/Flow.Launcher/Images/gamemode.ico b/Flow.Launcher/Images/gamemode.ico new file mode 100644 index 000000000..27a46a904 Binary files /dev/null and b/Flow.Launcher/Images/gamemode.ico differ diff --git a/Flow.Launcher/Images/page_img01.png b/Flow.Launcher/Images/page_img01.png new file mode 100644 index 000000000..fdc411898 Binary files /dev/null and b/Flow.Launcher/Images/page_img01.png differ diff --git a/Flow.Launcher/Images/wizard.png b/Flow.Launcher/Images/wizard.png new file mode 100644 index 000000000..155de20bd Binary files /dev/null and b/Flow.Launcher/Images/wizard.png differ diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 5ca6bdbfd..0c6bb05c6 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -15,6 +15,8 @@ About Exit Close + Game Mode + Suspend the use of Hotkeys. Flow Launcher Settings @@ -54,15 +56,17 @@ Off Action keyword Setting Action keyword - Current action keyword: - New action keyword: - Current Priority: - New Priority: + Current action keyword + New action keyword + Current Priority + New Priority Priority Plugin Directory - Author: + by Init time: Query time: + | Version + Website @@ -83,6 +87,14 @@ Fail to load theme {0}, fallback to default theme Theme Folder Open Theme Folder + Color Scheme + System Default + Light + Dark + Sound Effect + Play a small sound when the search window opens + Animation + Use Animation in UI Hotkey @@ -124,6 +136,8 @@ About Website + Github + Docs Version You have activated Flow Launcher {0} times Check for Updates @@ -134,11 +148,15 @@ or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually. Release Notes - Usage Tips: + Usage Tips + DevTools + Setting Folder + Log Folder + Wizard Select File Manager - Please specify the file location of the file manager you using and add arguments if necessary. The default arguments is "%d", and a path is entered at that location. For example, If a command is required such as "totalcmd.exe /A c:\windows", argument is /A "%d". + Please specify the file location of the file manager you using and add arguments if necessary. The default arguments are "%d", and a path is entered at that location. For example, If a command is required such as "totalcmd.exe /A c:\windows", argument is /A "%d". "%f" is an argument that represent the file path. It is used to emphasize the file/folder name when opening a specific file location in 3rd party file manager. This argument is only available in the "Arg for File" item. If the file manager does not have that function, you can use "%d". File Manager Profile Name @@ -161,7 +179,7 @@ This new Action Keyword is already assigned to another plugin, please choose a different one Success Completed successfully - Enter the action keyword you need to start the plug-in. Use * if you don't want to specify an action keyword. In the case, The plug-in works without keywords. + Enter the action keyword you like to use to start the plugin. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. Custom Query Hotkey @@ -214,4 +232,40 @@ Update files Update description + + Skip + Welcome to Flow Launcher + Hello, this is the first time you are running Flow Launcher! + Before starting, this wizard will assist in setting up Flow Launcher. You can skip this if you wish. Please choose a language + Search and run all files and applications on your PC + Search everything from applications, files, bookmarks, YouTube, Twitter and more. All from the comfort of your keyboard without ever touching the mouse. + Flow Launcher starts with the hotkey below, go ahead and try it out now. To change it, click on the input and press the desired hotkey on the keyboard. + Hotkeys + Action Keyword and Commands + Search the web, launch applications or run various functions through Flow Launcher plugins. Certain functions start with an action keyword, and if necessary, they can be used without action keywords. Try the queries below in Flow Launcher. + Let's Start Flow Launcher + Finished. Enjoy Flow Launcher. Don't forget the hotkey to start :) + + + + Back / Context Menu + Item Navigation + Open Context Menu + Open Contaning Folder + Run as Admin + Query History + Back to Result in Context Menu + Open / Run Selected Item + Open Setting Window + Reload Plugin Data + + Weather + Weather in Google Result + > ping 8.8.8.8 + Shell Command + Bluetooth + Bluetooth in Windows Setting + sn + Sticky Notes + diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 649895cea..66d101a5a 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -1,8 +1,9 @@ - - - 핫키 등록 실패: {0} + + + 단축키 등록 실패: {0} {0}을 실행할 수 없습니다. Flow Launcher 플러그인 파일 형식이 유효하지 않습니다. 이 쿼리의 최상위로 설정 @@ -14,8 +15,10 @@ 정보 종료 닫기 + 게임 모드 + 단축키 사용을 일시중단합니다. - + Flow Launcher 설정 일반 포터블 모드 @@ -31,43 +34,50 @@ 직전 쿼리 내용 선택 직전 쿼리 지우기 표시할 결과 수 - 전체화면 모드에서는 핫키 무시 + 전체화면 모드에서는 단축키 무시 게이머라면 켜는 것을 추천합니다. + 기본 파일관리자 + 폴더를 열 때 사용할 파일관리자를 선택하세요. Python 디렉토리 자동 업데이트 선택 시작 시 Flow Launcher 숨김 트레이 아이콘 숨기기 - 쿼리 검색 정확도 - 검색 결과가 좀 더 정확해집니다. + 쿼리 검색 정밀도 + 검색 결과에 필요한 최소 매치 점수를 변경합니다. 항상 Pinyin 사용 Pinyin을 사용하여 검색할 수 있습니다. Pinyin(병음)은 로마자 중국어 입력 방식입니다. 반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다. - + 플러그인 플러그인 더 찾아보기 - On - Off + + 액션 키워드 + 현재 액션 키워드 + 새 액션 키워드 현재 중요도: 새 중요도: 중요도 - 플러그인 디렉토리 - 저자 + 플러그인 폴더 + 제작자 초기화 시간: 쿼리 시간: - - - + | 버전 + 웹사이트 + + + 플러그인 스토어 새로고침 설치 - + 테마 - 테마 더 찾아보기 + 테마 갤러리 + 테마 제작 안내 Hi There 쿼리 상자 글꼴 결과 항목 글꼴 @@ -77,28 +87,37 @@ {0} 테마 로드에 실패했습니다. 기본 테마로 변경합니다. 테마 폴더 테마 폴더 열기 + 앱 색상 + 시스템 기본 + 밝게 + 어둡게 + 소리 효과 + 검색창을 열 때 작은 소리를 재생합니다. + 애니메이션 + 일부 UI에 애니메이션을 사용합니다. - - 핫키 - Flow Launcher 핫키 + + 단축키 + Flow Launcher 단축키 Flow Launcher를 열 때 사용할 단축키를 입력합니다. 결과 선택 단축키 결과 목록을 선택하는 단축키입니다. 단축키 표시 결과창에서 결과 선택 단축키를 표시합니다. - 사용자지정 쿼리 핫키 - Query + 사용자지정 쿼리 단축키 + 쿼리 삭제 편집 추가 항목을 선택하세요. - {0} 플러그인 핫키를 삭제하시겠습니까? + {0} 플러그인 단축키를 삭제하시겠습니까? 그림자 효과 그림자 효과는 GPU를 사용합니다. 컴퓨터 퍼포먼스가 제한적인 경우 사용을 추천하지 않습니다. + 창 넓이 플루언트 아이콘 사용 결과 및 일부 메뉴에서 플루언트 아이콘을 사용합니다. - + HTTP 프록시 HTTP 프록시 켜기 HTTP 서버 @@ -114,26 +133,42 @@ 프록시 설정 정상 프록시 연결 실패 - + 정보 웹사이트 + Github + 문서 버전 Flow Launcher를 {0}번 실행했습니다. 업데이트 확인 새 버전({0})이 있습니다. Flow Launcher를 재시작하세요. 업데이트 확인을 실패했습니다. api.github.com로의 연결 또는 프록시 설정을 확인해주세요. - 업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요. + 업데이트 다운로드에 실패했습니다. github-cloud.s3.amazonaws.com의 연결 또는 프록시 설정을 확인해주세요. 수동 다운로드를 하려면 https://github.com/Flow-Launcher/Flow.Launcher/releases 으로 방문하세요. - 릴리즈 노트: - 사용 팁: + 릴리즈 노트 + 사용 팁 + 개발자도구 + 설정 폴더 + 로그 폴더 + 마법사 - + + 파일관리자 선택 + 사용하려는 파일관리자를 선택하고 필요한 경우 인수를 추가하세요. 기본 인수는 "%d" 이며 해당 위치에 경로가 입력됩니다. 예를들어 "totalcmd.exe /A c:\windows"와 같은 명령이 필요한 경우, 인수는 /A "%d" 입니다. + "%f"는 특정 파일의 경로를 나타냅니다. 파일관리자에서 선택한 파일/폴더의 위치를 강조하는 기능에서 사용됩니다. 이 인수는 "파일경로 인수" 항목에서만 사용할 수 있습니다. 파일관리자에 해당 기능이 없거나 잘 모를 경우 "%d" 인수를 사용할 수 있습니다. + 파일관리자 + 프로필 이름 + 파일관리자 경로 + 폴더경로 인수 + 파일경로 인수 + + 중요도 변경 - 높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮추고 싶다면, 그보다 낮은 수를 입력하세요. + 높은 수를 넣을수록 상위 결과에 표시됩니다. 5를 시도해보세요. 다른 플러그인 보다 결과를 낮춰 표시하고 싶다면, 그보다 낮은 수를 입력하세요. 중요도에 올바른 정수를 입력하세요. - + 예전 액션 키워드 새 액션 키워드 취소 @@ -143,19 +178,20 @@ 새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요. 성공 성공적으로 완료했습니다. - 액션 키워드를 지정하지 않으려면 *를 사용하세요. + 플러그인을 시작하는데 필요한 액션 키워드를 입력하세요. 액션 키워드를 지정하지 않으려면 *를 사용하세요. 이 경우 키워드를 입력하지 않아도 동작합니다. - - 커스텀 플러그인 핫키 + + 커스텀 플러그인 단축키 + 단축키를 지정하여 특정 쿼리를 자동으로 입력할 수 있습니다. 사용하고 싶은 단축키를 눌러 지정한 후, 사용할 쿼리를 입력하세요. 미리보기 - 핫키를 사용할 수 없습니다. 다른 핫키를 입력하세요. - 플러그인 핫키가 유효하지 않습니다. + 단축키를 사용할 수 없습니다. 다른 단축키를 입력하세요. + 플러그인 단축키가 유효하지 않습니다. 업데이트 - - 핫키를 사용할 수 없습니다. + + 단축키를 사용할 수 없습니다. - + 버전 시간 수정을 위해 애플리케이션이 어떻게 충돌했는지 알려주세요. @@ -170,17 +206,19 @@ 보고서를 정상적으로 보냈습니다. 보고서를 보내지 못했습니다. Flow Launcher에 문제가 발생했습니다. - - + + 잠시 기다려주세요... - + 새 업데이트 확인 중 새 Flow Launcher 버전({0})을 사용할 수 있습니다. 이미 가장 최신 버전의 Flow Launcher를 사용중입니다. 업데이트 발견 업데이트 중... - Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다. - 프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요. + + Flow Launcher가 유저 정보 데이터를 새버전으로 옮길 수 없습니다. + 프로필 데이터 폴더를 수동으로 {0} 에서 {1}로 옮겨주세요. + 새 업데이트 소프트웨어 업데이트를 설치하는 중에 오류가 발생했습니다. 업데이트 @@ -192,4 +230,41 @@ 업데이트 파일 업데이트 설명 + + + 건너뛰기 + Flow Launcher에 오신 것을 환영합니다 + 안녕하세요, Flow Launcher를 처음 실행하시네요! + 시작하기전에 이 마법사가 간단한 설정을 도와드릴겁니다. 물론 건너 뛰셔도 됩니다. 사용하시는 언어를 선택해주세요. + PC에서 모든 파일과 프로그램을 검색하고 실행합니다 + 프로그램, 파일, 즐겨찾기, YouTube, Twitter 등 모든 것을 검색하세요. 마우스에 손대지 않고 키보드만으로 모든 것을 얻을 수 있습니다. + Flow는 아래의 단축키로 실행합니다. 변경하려면 입력창을 선택하고 키보드에서 원하는 단축키를 누릅니다. + 단축키 + 액션 키워드와 명령어 + Flow Launcher는 플러그인을 통해 웹 검색, 프로그램 실행, 다양한 기능을 실행합니다. 특정 기능은 액션 키워드로 시작하며, 필요한 경우 액션 키워드 없이 사용할 수 있습니다. Flow Launcher에서 아래 쿼리를 사용해 보세요. + Flow Launcher를 시작합시다 + 끝났습니다. Flow Launcher를 즐겨주세요. 시작하는 단축키를 잊지마세요 :) + + + + 뒤로/ 콘텍스트 메뉴 + 아이템 이동 + 콘텍스트 메뉴 열기 + 포함된 폴더 열기 + 관리자 권한으로 실행 + 검색 기록 + 콘텍스트 메뉴에서 뒤로 가기 + 선택한 아이템 열기 + 설정창 열기 + 플러그인 데이터 새로고침 + + 날씨 + 구글 날씨 검색 + > ping 8.8.8.8 + 쉘 명령어 + 블루투스 + 윈도우 블루투스 설정 + 스메 + 스티커 메모 + \ No newline at end of file diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml new file mode 100644 index 000000000..0bee02ace --- /dev/null +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -0,0 +1,231 @@ + + + + Falha ao registar tecla de atalho: {0} + Não foi possível iniciar {0} + Formato do ficheiro inválido como plugin + Definir como principal para esta consulta + Cancelar como principal para esta consulta + Executar consulta: {0} + Última execução: {0} + Abrir + Definições + Acerca + Sair + Fechar + Modo de jogo + Suspender utilização de teclas de atalho + + + Definições Flow launcher + Geral + Modo portátil + Guardar todas as definições e dados do utilizador numa pasta (indicado se utilizar discos amovíveis ou serviços cloud) + Iniciar Flow launcher ao arrancar o sistema + Ocultar Flow launcher ao perder o foco + Não notificar acerca de novas versões + Memorizar localização anterior + Idioma + Estilo da última consulta + Mostrar/ocultar resultados anteriores ao reiniciar Flow Launcher + Manter última consulta + Selecionar última consulta + Limpar última consulta + N.º máximo de resultados + Ignorar teclas de atalho se em ecrã completo + Desativar ativação do Flow Launcher se alguma aplicação estiver em ecrã completo (recomendado para jogos) + Gestor de ficheiros padrão + Selecione o gestor de ficheiros utilizado para abrir a página + Diretório Python + Atualização automática + Selecionar + Ocultar Flow Launcher no arranque + Ocultar ícone da bandeja + Precisão da pesquisa + Altera a precisão mínima necessário para obter resultados + Utilizar Pinyin + Permitir Pinyin para a pesquisa. Pinyin é o sistema padrão da ortografia romanizada para tradução de mandarim + O efeito sombra não é permitido com este tema porque o efeito desfocar está ativo + + + Plugins + Mais plugins + Ativar + Desativar + Definição de palavra-chave + Palavra-chave da ação + Palavra-chave atual + Nova palavra-chave + Prioridade atual + Nova prioridade + Prioridade + Diretório de plugins + Autor: + Tempo de inicialização: + Tempo de consulta: + | Versão + Site + + + + Loja de plugins + Recarregar + Instalar + + + Tema + Galeria de temas + Como criar um tema + Olá + Tipo de letra da caixa de pesquisa + Tipo de letra dos resultados + Modo da janela + Opacidade + O tema {0} não existe e será utilizado o tema padrão + Não foi possível carregar o tema {0}, será utilizado o tema padrão + Pasta de temas + Abrir pasta de temas + Esquema de cores + Padrão do sistema + Claro + Escuro + Efeitos sonoros + Reproduzir um som ao abrir a janela de pesquisa + Animação + Utilizar animações na aplicação + + + Tecla de atalho + Tecla de atalho Flow Launcher + Introduza o atalho para mostrar/ocultar Flow launcher + Tecla modificadora para os resultados + Selecione a tecla modificadora para abrir o resultado através do teclado + Mostrar tecla de atalho + Mostrar tecla de atalho em conjunto com os resultados. + Tecla de atalho personalizada + Consulta + Eliminar + Editar + Adicionar + Selecione um item + Tem a certeza de que deseja remover a tecla de atalho do plugin {0}? + Efeito de sombra da janela + Este efeito intensifica a utilização da GPU. Não deve ativar esta opção se o desempenho do seu computador for fraco. + Largura da janela + Utilizar ícones Segoe Fluent + Se possível, utilizar ícones Segoe Fluent para os resultados + + + Proxy HTTP + Ativar proxy HTTP + Servidor HTTP + Porta + Nome de utilizador + Palavra-passe + Testar + Guardar + Campo Servidor não pode estar vazio + Campo Porta não pode estar vazio + Formato de porta inválido + Configuração proxy guardada com sucesso + Proxy configurado corretamente + Falha na ligação ao proxy + + + Acerca + Site + GitHub + Documentos + Versão + Ativou o Flow Launcher {0} vezes + Procurar atualizações + Está disponível a versão {0}. Gostaria de reiniciar Flow Launcher para atualizar a sua versão? + Erro ao procurar atualizações. Verifique a sua ligação e as definições do proxy estabelecidas para api.github.com + + Não foi possível descarregar a atualização. Verifique a sua ligação e as definições do proxy estabelecidas para github-cloud.s3.amazonaws.com ou aceda a https://github.com/Flow-Launcher/Flow.Launcher/releases para descarregar a atualização. + + Notas da versão + Dicas de utilização + DevTools + Pasta de definições + Pasta de registos + + + Selecione o gestor de ficheiros + Especifique a localização do executável do gestor de ficheiros e, eventualmente, alguns argumentos. Os argumentos padrão são "%d" e o caminho é introduzido nesse local. Por exemplo, se necessitar de um comando como "totalcmd.exe /A c:\windows", o argumento é /A "%d". + "%f" é o argumento que representa o caminho do ficheiro. É utilizado para dar ênfase ao nome do ficheiro ou da pasta se utilizar um gestor de ficheiros não nativo. Este argumento apenas está disponível para o item "Arg para ficheiro". Se o seu gestor de ficheiros não possuir esta funcionalidade, pode utilizar "%d". + Gestor de ficheiros + Nome do perfil + Caminho do gestor de ficheiros + Argumento para pasta + Argumento para ficheiro + + + Alterar prioridade + Quanto maior for o número, melhor avaliação terá o resultado. Experimente com o número 5. Se quiser que os resultados sejam inferiores aos dos outros plugins, indique um número negativo. + Tem que indicar um valor inteiro para a prioridade! + + + Palavra-chave atual + Nova palavra-chave + Cancelar + Feito + Plugin não encontrado + A nova palavra-chave não pode estar vazia + Esta palavra-chave já está associada a um plugin. Por favor escolha outra. + Sucesso + Terminado com sucesso + Introduza a palavra-chave a utilizar para iniciar o plugin. Utilize * se não quiser utilizar esta funcionalidade e o plugin não será ativada com palavras-chave. + + + Tecla de atalho personalizada + Prima a tecla de atalho personalizada para introduzir automaticamente a consulta especificada + Antevisão + Tecla de atalho indisponível, por favor escolha outra + Tecla de atalho inválida + Atualizar + + + Tecla de atalho indisponível + + + Versão + Hora + Indique-nos, por favor, como é que o erro ocorreu para que o possamos corrigir + Enviar relatório + Cancelar + Geral + Exceções + Tipo de exceção + Origem + Stack Trace + A enviar + Relatório enviado com sucesso + Falha ao enviar o relatório + Ocorreu um erro + + + Por favor aguarde... + + + A procurar atualizações... + A sua versão de Flow Launcher é a mais recente + Atualização encontrada + A atualizar... + + Flow Launcher não conseguiu mover o seu perfil de dados para a nova versão. +Queira por favor mover a pasta do seu perfil de {0} para {1} + + Nova atualização + Está disponível a versão {0} do Flow Launcher + Ocorreu um erro ao tentar instalar as atualizações + Atualizar + Cancelar + Falha ao atualizar + Verifique a sua ligação e as definições do proxy estabelecidas para github-cloud.s3.amazonaws.com + Esta atualização irá reiniciar o Flow Launcher + Os seguintes ficheiros serão atualizados + Atualizar ficheiros + Atualizar descrição + + diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 4014d215f..aea9f1d64 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -1,201 +1,269 @@ - - - Nepodarilo sa registrovať klávesovú skratku {0} - Nepodarilo sa spustiť {0} - Neplatný formát súboru pre plugin Flow Launchera - Pri tomto zadaní umiestniť navrchu - Zrušiť umiestnenie navrchu pri tomto zadaní - Spustiť dopyt: {0} - Posledný čas realizácie: {0} - Otvoriť - Nastavenia - O aplikácii - Ukončiť - Zavrieť - - - Nastavenia Flow Launchera - Všeobecné - Prenosný režim - Uloží všetky nastavenia a používateľské údaje do jedného centrálneho priečinka (Užitočné pri vyberateľných diskoch a cloudových službách). - Spustiť Flow Launcher po štarte systému - Schovať Flow Launcher po strate fokusu - Nezobrazovať upozornenia na novú verziu - Zapamätať si posledné umiestnenie - Jazyk - Posledné vyhľadávanie - Zobrazí/skryje predchádzajúce výsledky pri opätovnej aktivácii Flow Launchera. - Ponechať - Označiť - Vymazať - Max. výsledkov - Ignorovať klávesové skratky v režime na celú obrazovku - Zakázať aktiváciu Flow Launchera, keď je aktívna aplikácia na celú obrazovku (odporúčané pre hry). - Priečinok s Pythonom - Automatická aktualizácia - Vybrať - Schovať Flow Launcher po spustení - Schovať ikonu z oblasti oznámení - Presnosť vyhľadávania - Mení minimálne skóre zhody potrebné na zobrazenie výsledkov. - Použiť Pinyin - Umožňuje vyhľadávanie pomocou Pinyin. Pinyin je štandardný systém romanizovaného pravopisu pre transliteráciu čínštiny - Efekt tieňa nie je povolený, kým má aktuálny motív povolený efekt rozostrenia - - - Pluginy - Nájsť ďalšie pluginy - Zap. - Vyp. - Nastavenie kľúčového slova akcie - Skratka akcie - Aktuálna akcia skratky: - Nová akcia skratky: - Aktuálna priorita: - Nová priorita: - Priorita - Priečinok s pluginmi - Autor: - Príprava: - Čas dopytu: - - - - Repozitár pluginov - Obnoviť - Inštalovať - - - Motív - Galéria motívov - Ako vytvoriť motív - Ahojte - Písmo vyhľadávacieho poľa - Písmo výsledkov - Režim okno - Nepriehľadnosť - Motív {0} neexistuje, návrat na predvolený motív - Nepodarilo sa nečítať motív {0}, návrat na predvolený motív - Priečinok s motívmi - Otvoriť priečinok s motívmi - - - Klávesové skratky - Klávesová skratka pre Flow Launcher - Zadajte skratku na zobrazenie/skrytie Flow Launchera. - Otvoriť výsledok modifikačným klávesom - Vyberte modifikačný kláves na otvorenie výsledku pomocou klávesnice. - Zobraziť klávesovú skratku - Zobrazí klávesovú skratku spolu s výsledkami. - Vlastná klávesová skratka na vyhľadávanie - Dopyt - Odstrániť - Upraviť - Pridať - Vyberte položku, prosím - Ste si istý, že chcete odstrániť klávesovú skratku {0} pre plugin? - Tieňový efekt v poli vyhľadávania - Tieňový efekt významne využíva GPU. Neodporúča sa, ak je výkon počítača obmedzený. - Použiť ikony Segoe Fluent - Použiť ikony Segoe Fluent, ak sú podporované - - - HTTP Proxy - Povoliť HTTP Proxy - HTTP Server - Port - Používateľské meno - Heslo - Test Proxy - Uložiť - Pole Server nemôže byť prázdne - Pole Port nemôže byť prázdne - Neplatný formát portu - Nastavenie proxy úspešne uložené - Nastavenie proxy je v poriadku - Pripojenie proxy zlyhalo - - - O aplikácii - Webstránka - Verzia - Flow Launcher bol aktivovaný {0}-krát - Skontrolovať aktualizácie - Je dostupná nová verzia {0}, chcete reštartovať Flow Launcher, aby sa mohol aktualizovať? - Kontrola aktualizácií zlyhala, prosím, skontrolujte pripojenie na internet a nastavenie proxy k api.github.com. - - Sťahovanie aktualizácií zlyhalo, skontrolujte pripojenie na internet a nastavenie proxy k github-cloud.s3.amazonaws.com, - alebo prejdite na https://github.com/Flow-Launcher/Flow.Launcher/releases pre manuálne stiahnutie aktualizácie. - - Poznámky k vydaniu - Tipy na používanie: - - - Zmena priority - Vyššie číslo znamená, že výsledok bude vyššie. Skúste nastaviť napr. 5. Ak chcete, aby boli výsledky nižšie ako ktorékoľvek iné doplnky, zadajte záporné číslo - Prosím, zadajte platné číslo pre prioritu! - - - Stará skratka akcie - Nová skratka akcie - Zrušiť - Hotovo - Nepodarilo sa nájsť zadaný plugin - Nová skratka pre akciu nemôže byť prázdna - Nová skratka pre akciu bola priradená pre iný plugin, prosím, zvoľte inú skratku - Úspešné - Úspešne dokončené - Zadajte skratku akcie, ktorá je potrebná na spustenie pluginu. Ak nechcete zadať skratku akcie, použite *. V tom prípade plugin funguje bez kľúčových slov. - - - Klávesová skratka pre vlastné vyhľadávanie - Stlačením klávesovej skratky sa automaticky vloží zadaný výraz. - Náhľad - Klávesová skratka je nedostupná, prosím, zadajte novú - Neplatná klávesová skratka pluginu - Aktualizovať - - - Klávesová skratka nedostupná - - - Verzia - Čas - Prosím, napíšte nám, ako došlo k pádu aplikácie, aby sme to mohli opraviť - Odoslať hlásenie - Zrušiť - Všeobecné - Výnimky - Typ výnimky - Zdroj - Stack Trace - Odosiela sa - Hlásenie bolo úspešne odoslané - Odoslanie hlásenia zlyhalo - Flow Launcher zaznamenal chybu - - - Čakajte, prosím… - - - Kontrolujú sa aktualizácie - Už máte najnovšiu verziu Flow Launchera - Bola nájdená aktualizácia - Aktualizuje sa… - Flow Launcher nedokázal presunúť používateľské údaje do aktualizovanej verzie. - Prosím, presuňte profilový priečinok data z {0} do {1} - Nová aktualizácia - Je dostupná nová verzia Flow Launchera {0} - Počas inštalácie aktualizácií došlo k chybe - Aktualizovať - Zrušiť - Aktualizácia zlyhala - Skontrolujte pripojenie a skúste aktualizovať nastavenia servera proxy na github-cloud.s3.amazonaws.com. - Tento upgrade reštartuje Flow Launcher - Nasledujúce súbory budú aktualizované - Aktualizovať súbory - Aktualizovať popis - - + + + + Nepodarilo sa registrovať klávesovú skratku {0} + Nepodarilo sa spustiť {0} + Neplatný formát súboru pre plugin Flow Launchera + Pri tomto zadaní umiestniť navrchu + Zrušiť umiestnenie navrchu pri tomto zadaní + Spustiť dopyt: {0} + Posledný čas realizácie: {0} + Otvoriť + Nastavenia + O aplikácii + Ukončiť + Zavrieť + Herný režim + Pozastaviť používanie klávesových skratiek. + + + Nastavenia Flow Launchera + Všeobecné + Prenosný režim + Uloží všetky nastavenia a používateľské údaje do jedného priečinka (Užitočné pri vyberateľných diskoch a cloudových službách). + Spustiť Flow Launcher po štarte systému + Schovať Flow Launcher po strate fokusu + Nezobrazovať upozornenia na novú verziu + Zapamätať si posledné umiestnenie + Jazyk + Posledné vyhľadávanie + Zobrazí/skryje predchádzajúce výsledky pri opätovnej aktivácii Flow Launchera. + Ponechať + Označiť + Vymazať + Max. výsledkov + Ignorovať klávesové skratky v režime na celú obrazovku + Zakázať aktiváciu Flow Launchera, keď je aktívna aplikácia na celú obrazovku (odporúčané pre hry). + Predvolený správca súborov + Vyberte správcu súborov, ktorý sa má použiť pri otváraní priečinka. + Priečinok s Pythonom + Automatická aktualizácia + Vybrať + Schovať Flow Launcher po spustení + Schovať ikonu z oblasti oznámení + Presnosť vyhľadávania + Mení minimálne skóre zhody potrebné na zobrazenie výsledkov. + Použiť Pinyin + Umožňuje vyhľadávanie pomocou Pinyin. Pinyin je štandardný systém romanizovaného pravopisu pre transliteráciu čínštiny + Efekt tieňa nie je povolený, kým má aktuálny motív povolený efekt rozostrenia + + + Pluginy + Nájsť ďalšie pluginy + Zap. + Vyp. + Nastavenie kľúčového slova akcie + Skratka akcie + Aktuálna akcia skratky: + Nová akcia skratky: + Aktuálna priorita: + Nová priorita: + Priorita + Priečinok s pluginmi + od + Príprava: + Čas dopytu: + | Verzia + Webstránka + + + + Repozitár pluginov + Obnoviť + Inštalovať + + + Motív + Galéria motívov + Ako vytvoriť motív + Ahojte + Písmo vyhľadávacieho poľa + Písmo výsledkov + Režim okno + Nepriehľadnosť + Motív {0} neexistuje, návrat na predvolený motív + Nepodarilo sa nečítať motív {0}, návrat na predvolený motív + Priečinok s motívmi + Otvoriť priečinok s motívmi + Farebná schéma + Predvolené systémom + Svetlý + Tmavý + Zvukový efekt + Po otvorení okna vyhľadávania prehrať krátky zvuk + Animácia + Animovať používateľské rozhranie + + + Klávesové skratky + Klávesová skratka pre Flow Launcher + Zadajte skratku na zobrazenie/skrytie Flow Launchera. + 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 + Zobrazí klávesovú skratku spolu s výsledkami. + Vlastná klávesová skratka na vyhľadávanie + Dopyt + Odstrániť + Upraviť + Pridať + Vyberte položku, prosím + Ste si istý, že chcete odstrániť klávesovú skratku {0} pre plugin? + Tieňový efekt v poli vyhľadávania + Tieňový efekt významne využíva GPU. Neodporúča sa, ak je výkon počítača obmedzený. + Veľkosť šírky okna + Použiť ikony Segoe Fluent + Použiť ikony Segoe Fluent, ak sú podporované + + + HTTP proxy + Povoliť HTTP Proxy + HTTP server + Port + Používateľské meno + Heslo + Test proxy + Uložiť + Pole Server nemôže byť prázdne + Pole Port nemôže byť prázdne + Neplatný formát portu + Nastavenie proxy úspešne uložené + Nastavenie proxy je v poriadku + Pripojenie proxy zlyhalo + + + O aplikácii + Webstránka + Github + Dokumentácia + Verzia + Flow Launcher bol aktivovaný {0}-krát + Skontrolovať aktualizácie + Je dostupná nová verzia {0}, chcete reštartovať Flow Launcher, aby sa mohol aktualizovať? + Kontrola aktualizácií zlyhala, prosím, skontrolujte pripojenie na internet a nastavenie proxy k api.github.com. + + Sťahovanie aktualizácií zlyhalo, skontrolujte pripojenie na internet a nastavenie proxy k github-cloud.s3.amazonaws.com, + alebo prejdite na https://github.com/Flow-Launcher/Flow.Launcher/releases pre manuálne stiahnutie aktualizácie. + + Poznámky k vydaniu + Tipy na používanie + Nástroje pre vývojárov + Priečinok s nastaveniami + Priečinok s logmi + Sprievodca + + + Vyberte správcu súborov + Zadajte umiestnenie súboru správcu súborov, ktorý používate, a v prípade potreby pridajte argumenty. Predvolené argumenty sú "%d" a cesta sa zadáva na tomto mieste. Napríklad, ak sa vyžaduje príkaz, ako napríklad "totalcmd.exe /A c:\windows", argument je /A "%d". + "%f" je argument, ktorý predstavuje cestu k súboru. Používa sa na zvýraznenie názvu súboru/priečinka pri otváraní konkrétneho umiestnenia súboru v správcovi súborov tretej strany. Tento argument je k dispozícii len v položke "Arg. pre súbor". Ak správca súborov nemá túto funkciu, môžete použiť "%d". + Správca súborov + Názov profilu + Cesta k správcovi súborov + Arg. pre priečinok + Arg. pre súbor + + + Zmena priority + Vyššie číslo znamená, že výsledok bude vyššie. Skúste nastaviť napr. 5. Ak chcete, aby boli výsledky nižšie ako ktorékoľvek iné doplnky, zadajte záporné číslo + Prosím, zadajte platné číslo pre prioritu! + + + Stará skratka akcie + Nová skratka akcie + Zrušiť + Hotovo + Nepodarilo sa nájsť zadaný plugin + Nová skratka pre akciu nemôže byť prázdna + Nová skratka pre akciu bola priradená pre iný plugin, prosím, zvoľte inú skratku + Úspešné + Úspešne dokončené + Zadajte skratku akcie, ktorá je potrebná na spustenie pluginu. Ak nechcete zadať skratku akcie, použite *. V tom prípade plugin funguje bez kľúčových slov. + + + Klávesová skratka pre vlastné vyhľadávanie + Stlačením klávesovej skratky sa automaticky vloží zadaný výraz. + Náhľad + Klávesová skratka je nedostupná, prosím, zadajte novú + Neplatná klávesová skratka pluginu + Aktualizovať + + + Klávesová skratka nedostupná + + + Verzia + Čas + Prosím, napíšte nám, ako došlo k pádu aplikácie, aby sme to mohli opraviť + Odoslať hlásenie + Zrušiť + Všeobecné + Výnimky + Typ výnimky + Zdroj + Trasovanie zásobníka + Odosiela sa + Hlásenie bolo úspešne odoslané + Odoslanie hlásenia zlyhalo + Flow Launcher zaznamenal chybu + + + Čakajte, prosím… + + + Kontrolujú sa aktualizácie + Už máte najnovšiu verziu Flow Launchera + Bola nájdená aktualizácia + Aktualizuje sa… + + Flow Launcher nedokázal presunúť používateľské údaje do aktualizovanej verzie. + Prosím, presuňte profilový priečinok data z {0} do {1} + + Nová aktualizácia + Je dostupná nová verzia Flow Launchera {0} + Počas inštalácie aktualizácií došlo k chybe + Aktualizovať + Zrušiť + Aktualizácia zlyhala + Skontrolujte pripojenie a skúste aktualizovať nastavenia servera proxy na github-cloud.s3.amazonaws.com. + Tento upgrade reštartuje Flow Launcher + Nasledujúce súbory budú aktualizované + Aktualizovať súbory + Aktualizovať popis + + + Preskočiť + Vitajte vo Flow Launcheri + Dobrý deň, toto je prvýkrát, čo spúšťate Flow Launcher! + Pred spustením vám tento sprievodca pomôže s nastavením aplikácie Flow Launcher. Ak chcete, môžete ho preskočiť. Vyberte si jazyk + Vyhľadávajte a spúšťajte všetky súbory a aplikácie v počítači + Vyhľadávajte vo všetkých aplikáciách, súboroch, záložkách, YouTube, Twitteri a ďalších. Všetko z pohodlia klávesnice bez toho, aby ste sa dotkli myši. + Flow Launcher sa spúšťa pomocou dole uvedenej klávesovej skratky, poďte si to vyskúšať. Ak ju chcete zmeniť, kliknite na vstupné pole a stlačte požadovanú klávesovú skratku na klávesnici. + Klávesové skratky + Kľúčové slovo akcie a príkazy + Vyhľadávajte na webe, spúšťajte aplikácie alebo spúšťajte rôzne funkcie pomocou pluginov Flow Launchera. Niektoré funkcie sa začínajú kľúčovým slovom akcie a v prípade potreby ich možno použiť aj bez kľúčových slov akcie. Vyskúšajte nižšie uvedené dopyty v aplikácii Flow Launcher. + Spustite Flow Launcher + Hotovo. Užite si Flow Launcher. Nezabudnite na klávesovú skratku na spustenie :) + + + + Späť/kontextová ponuka + Navigácia medzi položkami + Otvoriť kontextovú ponuku + Otvoriť umiestnenie priečinka + Spustiť ako správca + História dopytov + Návrat na výsledky z kontextovej ponuky + Otvoriť/spustiť vybranú položku + Otvoriť okno s nastaveniami + Znova načítať údaje pluginov + + Počasie + Počasie na Googli + > ping 8.8.8.8 + Príkazový riadok + Bluetooth + Bluetooth v nastaveniach Windowsu + sn + Sticky Notes + + diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index 0c2307dc5..01cd97467 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,176 +1,269 @@ - - - 注册热键:{0} 失败 - 启动命令 {0} 失败 - Flow Launcher插件格式错误 - 在当前查询中置顶 - 取消置顶 - 执行查询:{0} - 上次执行时间:{0} - 打开 - 设置 - 关于 - 退出 - - - Flow Launcher设置 - 通用 - 便携模式 - 开机自动启动 - 失去焦点时自动隐藏Flow Launcher - 不显示新版本提示 - 记住上次启动位置 - 语言 - 上次搜索关键字模式 - 保留上次搜索关键字 - 选择上次搜索关键字 - 清空上次搜索关键字 - 最大结果显示个数 - 全屏模式下忽略热键 - Python 路径 - 自动更新 - 选择 - 启动时不显示主窗口 - 隐藏任务栏图标 - 查询搜索精度 - 启动拼音搜索 - 允许使用拼音进行搜索。 - - - 插件 - 浏览更多插件 - 启用 - 禁用 - 触发关键字 - 当前操作关键字: - 新动作关键字: - 当前优先级: - 新优先级: - 插件目录 - 作者 - 加载耗时 - 查询耗时 - - - 主题 - 浏览更多主题 - 在这里输入 - 查询框字体 - 结果项字体 - 窗口模式 - 透明度 - 无法找到主题 {0} ,切换为默认主题 - 无法加载主题 {0} ,切换为默认主题 - - - 热键 - Flow Launcher激活热键 - 开放结果修饰符 - 显示热键 - 自定义查询热键 - 删除 - 编辑 - 增加 - 请选择一项 - 你确定要删除插件 {0} 的热键吗? - 查询窗口阴影效果 - 阴影效果将占用大量的GPU资源。 如果您的计算机性能有限,则不建议使用。 - - - HTTP 代理 - 启用 HTTP 代理 - HTTP 服务器 - 端口 - 用户名 - 密码 - 测试代理 - 保存 - 服务器不能为空 - 端口不能为空 - 非法的端口格式 - 保存代理设置成功 - 代理设置正确 - 代理连接失败 - - - 关于 - 网站 - 版本 - 你已经激活了Flow Launcher {0} 次 - 检查更新 - 发现新版本 {0} , 请重启 Flow Launcher。 - 下载更新失败,请检查您与 api.github.com 的连接状态或检查代理设置。 - - 下载更新失败,请检查您与 github-cloud.s3.amazonaws.com 的连接状态或检查代理设置, - 或访问 https://github.com/Flow-Launcher/Flow.Launcher/releases 手动下载更新。 - - 更新说明: - 使用技巧: - - - 数字越大,结果排名越高。如果你想要结果比任何其他插件的低,请使用负数 - 请提供有效的整数作为优先级设置值! - - - 旧触发关键字 - 新触发关键字 - 取消 - 确定 - 找不到指定的插件 - 新触发关键字不能为空 - 新触发关键字已经被指派给其他插件了,请换一个关键字 - 成功 - 成功完成 - 如果你不想设置触发关键字,可以使用*代替 - - - 自定义插件热键 - 预览 - 热键不可用,请选择一个新的热键 - 插件热键不合法 - 更新 - - - 热键不可用 - - - 版本 - 时间 - 请告诉我们如何重现此问题,以便我们进行修复 - 发送报告 - 取消 - 基本信息 - 异常信息 - 异常类型 - 异常源 - 堆栈信息 - 发送中 - 发送成功 - 发送失败 - Flow Launcher出错啦 - - - 请稍等... - - - 检查新的更新 - 您已经拥有最新的Flow Launcher版本 - 检查到更新 - 更新中... - Flow Launcher无法将您的用户配置文件数据移动到新的更新版本中。 - 请手动将您的用户配置文件数据文件夹从 {0} 到 {1} - 新的更新 - 发现Flow Launcher新版本 V{0} - 尝试安装软件更新时发生错误 - 更新 - 取消 - 更新错误 - 检查网络是否可以连接至github-cloud.s3.amazonaws.com. - 此次更新需要重启Flow Launcher - 下列文件会被更新 - 更新文件 - 更新日志 - - \ No newline at end of file + + + + 注册热键:{0} 失败 + 启动命令 {0} 失败 + 无效的 Flow Launcher 插件文件格式 + 在当前查询中置顶 + 取消置顶 + 执行查询:{0} + 上次执行时间:{0} + 打开 + 设置 + 关于 + 退出 + 关闭 + 游戏模式 + 暂停使用快捷键。 + + + Flow Launcher设置 + 通用 + 便携模式 + 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 + 开机自启 + 失去焦点时自动隐藏Flow Launcher + 不显示新版本提示 + 记住上次启动位置 + 语言 + 再次激活时 + 重启Flow Launcher时显示/隐藏以前的结果。 + 保留上次搜索关键字 + 选择上次搜索关键字 + 清空上次搜索关键字 + 最大结果显示个数 + 全屏模式下忽略热键 + 当全屏应用程序激活时禁用快捷键。 + 默认文件管理器 + 选择打开文件夹时要使用的文件管理器。 + Python 路径 + 自动更新 + 选择 + 系统启动时不显示主窗口 + 隐藏任务栏图标 + 查询搜索精度 + 更改匹配成功所需的最低分数。 + 启动拼音搜索 + 允许使用拼音进行搜索 + 当前主题已启用模糊效果,不允许启用阴影效果 + + + 插件 + 浏览更多插件 + 启用 + 禁用 + 动作关键字设置 + 触发关键字 + 当前触发关键字 + 新触发关键字 + 当前优先级 + 新优先级 + 优先级 + 插件目录 + 出自 + 加载耗时: + 查询耗时: + | 版本 + 官方网站 + + + + 插件商店 + 刷新 + 安装 + + + 主题 + 浏览更多主题 + 如何创建一个主题 + 你好! + 查询框字体 + 结果项字体 + 窗口模式 + 透明度 + 无法找到主题 {0} ,切换为默认主题 + 无法加载主题 {0} ,切换为默认主题 + 主题目录 + 打开主题目录... + 颜色主题 + 跟随系统 + 浅色 + 深色 + 音效 + 启用激活音效 + 动画 + 启用动画 + + + 热键 + Flow Launcher激活热键 + 输入显示/隐藏Flow Launcher的快捷键。 + 开放结果修饰符 + 指定修饰符用于打开指定的选项。 + 显示热键 + 显示热键用于快速选择选项。 + 自定义查询热键 + 查询 + 删除 + 编辑 + 增加 + 请选择一项 + 你确定要删除插件 {0} 的热键吗? + 查询窗口阴影效果 + 阴影效果将占用大量的GPU资源。 如果您的计算机性能有限,则不建议使用。 + 窗口宽度 + 使用Segoe Fluent图标 + 在支持时在选项中显示 Segoe Fluent 图标 + + + HTTP 代理 + 启用 HTTP 代理 + HTTP 服务器 + 端口 + 用户名 + 密码 + 测试代理 + 保存 + 服务器不能为空 + 端口不能为空 + 非法的端口格式 + 保存代理设置成功 + 代理设置正确 + 代理连接失败 + + + 关于 + 网站 + Github + 文档 + 版本 + 你已经激活了Flow Launcher {0} 次 + 检查更新 + 发现新版本 {0} , 请重启 Flow Launcher + 下载更新失败,请检查您与 api.github.com 的连接状态或检查代理设置 + + 下载更新失败,请检查您与 github-cloud.s3.amazonaws.com 的连接状态或检查代理设置, + 或访问 https://github.com/Flow-Launcher/Flow.Launcher/releases 手动下载更新 + + 更新说明: + 使用技巧: + 开发工具 + 设置目录 + 日志目录 + 向导 + + + 默认文件管理器 + 请指定文件管理器的文件位置,并在必要时修改参数。 默认参数是%d",作为占位符代表文件路径。 例如命令 “totalcmd.exe /A c:\winds”,参数是 /A "%d”。 + %f是一个表示文件路径的参数。 它用于在第三方文件管理器中打开特定文件位置时强调文件/文件夹名称。 此参数仅在“选中文件参数”项目中可用。 如果文件管理器没有该功能,“%d” 仍然可用。 + 文件管理器 + 档案名称 + 文件管理器路径 + 文件夹路径参数 + 选中文件路径参数 + + + 更改优先级 + 数字越大,结果排名越高。如果你想要结果比任何其他插件的低,请使用负数 + 请提供有效的整数作为优先级设置值 + + + 旧触发关键字 + 新触发关键字 + 取消 + 确认 + 找不到指定的插件 + 新触发关键字不能为空 + 此触发关键字已经被指派给其他插件了,请换一个关键字 + 成功 + 成功完成 + 如果你不想设置触发关键字,可以使用*代替 + + + 自定义插件热键 + 按下自定义快捷键激活Flow Launcher并插入指定的查询前缀。 + 预览 + 热键不可用,请选择一个新的热键 + 插件热键不合法 + 更新 + + + 热键不可用 + + + 版本 + 时间 + 请告诉我们如何重现此问题,以便我们进行修复 + 发送报告 + 取消 + 基本信息 + 异常信息 + 异常类型 + 异常源 + 堆栈信息 + 发送中 + 发送成功 + 发送失败 + Flow Launcher出错啦 + + + 请稍等... + + + 检查新的更新 + 您已经拥有最新的Flow Launcher版本 + 检查到更新 + 更新中... + + Flow Launcher无法将您的用户配置文件数据移动到新的更新版本中。 + 请手动将您的用户配置文件数据文件夹从 {0} 到 {1} + + 新的更新 + 发现Flow Launcher新版本 V{0} + 尝试安装软件更新时发生错误 + 更新 + 取消 + 更新失败 + 检查网络是否可以连接至github-cloud.s3.amazonaws.com. + 此次更新需要重启Flow Launcher + 下列文件会被更新 + 更新文件 + 更新日志 + + + 跳过 + 欢迎使用Flow Launcher + 你好,这是你第一次运行Flow Launcher! + 在启动前,这个向导将有助于设置Flow Launcher。如果您愿意,您可以跳过。请选择一种语言 + 搜索并运行您PC上的文件和应用程序 + 搜索所有应用程序、 文件、 书签、 YouTube、 Twitter等。所有都只需要键盘而不需要触摸鼠标。 + Flow Launcher默认使用下面的快捷键激活。 要更改它,请点击输入并按键盘上所需的热键。 + 快捷键 + 动作关键词和命令 + 通过Flow Launcher 插件搜索网站、启动应用程序或运行各种功能。 某些函数起始于一个动作关键词,如有必要,它们可以在没有动作关键词的情况下使用。欢迎尝试一下的查询语句。 + 开始使用Flow Launcher + 完成了!享受Flow Launcher。不要忘记激活快捷键 :) + + + + 返回/上下文菜单 + 选项导航 + 打开菜单目录 + 打开所在目录 + 以管理员身份运行 + 查询历史 + 返回查询界面 + 打开/运行选中项目 + 打开设置窗口 + 重新加载插件数据 + + 天气 + 谷歌天气结果 + > ping 8.8.8.8 + 命令行命令 + Bluetooth + Windows 设置中的蓝牙 + sn + Sticky Notes + + diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index daea406db..129ceeea5 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -1,105 +1,203 @@ - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + - + - - - - - - + + + + + + - + @@ -121,49 +219,69 @@ - + - - + - - - + + + - + - - - + + + - - - + + + - + - - - + + + - - - - + + + + diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 16e4be8a0..cf40c5ebf 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Threading.Tasks; using System.Windows; @@ -11,16 +11,12 @@ using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.ViewModel; -using Microsoft.AspNetCore.Authorization; -using Application = System.Windows.Application; using Screen = System.Windows.Forms.Screen; using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip; -using DataFormats = System.Windows.DataFormats; using DragEventArgs = System.Windows.DragEventArgs; using KeyEventArgs = System.Windows.Input.KeyEventArgs; -using MessageBox = System.Windows.MessageBox; using NotifyIcon = System.Windows.Forms.NotifyIcon; -using System.Windows.Interop; +using Flow.Launcher.Infrastructure; namespace Flow.Launcher { @@ -34,6 +30,7 @@ namespace Flow.Launcher private NotifyIcon _notifyIcon; private ContextMenu contextMenu; private MainViewModel _viewModel; + private bool _animating; #endregion @@ -43,6 +40,7 @@ namespace Flow.Launcher _viewModel = mainVM; _settings = settings; InitializeComponent(); + InitializePosition(); } public MainWindow() @@ -52,6 +50,8 @@ namespace Flow.Launcher private async void OnClosing(object sender, CancelEventArgs e) { + _settings.WindowTop = Top; + _settings.WindowLeft = Left; _notifyIcon.Visible = false; _viewModel.Save(); e.Cancel = true; @@ -65,12 +65,13 @@ namespace Flow.Launcher private void OnLoaded(object sender, RoutedEventArgs _) { + CheckFirstLaunch(); + HideStartup(); // show notify icon when flowlauncher is hidden InitializeNotifyIcon(); - + InitializeColorScheme(); WindowsInteropHelper.DisableControlBox(this); InitProgressbarAnimation(); - InitializePosition(); // since the default main window visibility is visible // so we need set focus during startup QueryTextBox.Focus(); @@ -79,13 +80,13 @@ namespace Flow.Launcher { switch (e.PropertyName) { - case nameof(MainViewModel.MainWindowVisibility): + case nameof(MainViewModel.MainWindowVisibilityStatus): { - if (_viewModel.MainWindowVisibility == Visibility.Visible) + if (_viewModel.MainWindowVisibilityStatus) { + UpdatePosition(); Activate(); QueryTextBox.Focus(); - UpdatePosition(); _settings.ActivateTimes++; if (!_viewModel.LastQuerySelected) { @@ -117,7 +118,7 @@ namespace Flow.Launcher _progressBarStoryboard.Stop(ProgressBar); isProgressBarStoryboardPaused = true; } - else if (_viewModel.MainWindowVisibility == Visibility.Visible && + else if (_viewModel.MainWindowVisibilityStatus && isProgressBarStoryboardPaused) { _progressBarStoryboard.Begin(ProgressBar, true); @@ -148,24 +149,29 @@ namespace Flow.Launcher break; } }; - - InitializePosition(); } private void InitializePosition() { - Top = WindowTop(); - Left = WindowLeft(); - _settings.WindowTop = Top; - _settings.WindowLeft = Left; + if (_settings.RememberLastLaunchLocation) + { + Top = _settings.WindowTop; + Left = _settings.WindowLeft; + } + else + { + Left = WindowLeft(); + Top = WindowTop(); + } } private void UpdateNotifyIconText() { var menu = contextMenu; ((MenuItem)menu.Items[1]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen"); - ((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"); - ((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"); + ((MenuItem)menu.Items[2]).Header = InternationalizationManager.Instance.GetTranslation("GameMode"); + ((MenuItem)menu.Items[3]).Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"); + ((MenuItem)menu.Items[4]).Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"); } private void InitializeNotifyIcon() @@ -180,13 +186,17 @@ namespace Flow.Launcher var header = new MenuItem { - Header = "Flow Launcher", + Header = "Flow Launcher", IsEnabled = false }; var open = new MenuItem { Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") }; + var gamemode = new MenuItem + { + Header = InternationalizationManager.Instance.GetTranslation("GameMode") + }; var settings = new MenuItem { Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings") @@ -196,11 +206,14 @@ namespace Flow.Launcher Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit") }; - open.Click += (o, e) => Visibility = Visibility.Visible; + open.Click += (o, e) => _viewModel.ToggleFlowLauncher(); + gamemode.Click += (o, e) => ToggleGameMode(); settings.Click += (o, e) => App.API.OpenSettingDialog(); exit.Click += (o, e) => Close(); contextMenu.Items.Add(header); contextMenu.Items.Add(open); + gamemode.ToolTip = InternationalizationManager.Instance.GetTranslation("GameModeToolTip"); + contextMenu.Items.Add(gamemode); contextMenu.Items.Add(settings); contextMenu.Items.Add(exit); @@ -220,6 +233,33 @@ namespace Flow.Launcher }; } + private void CheckFirstLaunch() + { + if (_settings.FirstLaunch) + { + _settings.FirstLaunch = false; + PluginManager.API.SaveAppAllSettings(); + OpenWelcomeWindow(); + } + } + private void OpenWelcomeWindow() + { + var WelcomeWindow = new WelcomeWindow(_settings); + WelcomeWindow.Show(); + } + private void ToggleGameMode() + { + if (_viewModel.GameModeStatus) + { + _notifyIcon.Icon = Properties.Resources.app; + _viewModel.GameModeStatus = false; + } + else + { + _notifyIcon.Icon = Properties.Resources.gamemode; + _viewModel.GameModeStatus = true; + } + } private void InitProgressbarAnimation() { var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 150, @@ -234,6 +274,53 @@ namespace Flow.Launcher _viewModel.ProgressBarVisibility = Visibility.Hidden; isProgressBarStoryboardPaused = true; } + public void WindowAnimator() + { + if (_animating) + return; + + _animating = true; + UpdatePosition(); + Storyboard sb = new Storyboard(); + Storyboard iconsb = new Storyboard(); + CircleEase easing = new CircleEase(); // or whatever easing class you want + easing.EasingMode = EasingMode.EaseInOut; + var da = new DoubleAnimation + { + From = 0, + To = 1, + Duration = TimeSpan.FromSeconds(0.25), + FillBehavior = FillBehavior.Stop + }; + + var da2 = new DoubleAnimation + { + From = Top + 10, + To = Top, + Duration = TimeSpan.FromSeconds(0.25), + FillBehavior = FillBehavior.Stop + }; + var da3 = new DoubleAnimation + { + From = 12, + To = 0, + EasingFunction = easing, + Duration = TimeSpan.FromSeconds(0.36), + FillBehavior = FillBehavior.Stop + }; + Storyboard.SetTarget(da, this); + Storyboard.SetTargetProperty(da, new PropertyPath(Window.OpacityProperty)); + Storyboard.SetTargetProperty(da2, new PropertyPath(Window.TopProperty)); + Storyboard.SetTargetProperty(da3, new PropertyPath(TopProperty)); + sb.Children.Add(da); + sb.Children.Add(da2); + iconsb.Children.Add(da3); + sb.Completed += (_, _) => _animating = false; + _settings.WindowLeft = Left; + _settings.WindowTop = Top; + iconsb.Begin(SearchIcon); + sb.Begin(FlowMainWindow); + } private void OnMouseDown(object sender, MouseButtonEventArgs e) { @@ -267,22 +354,41 @@ namespace Flow.Launcher e.Handled = true; } - private void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e) + private async void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e) { + _viewModel.Hide(); + + if(_settings.UseAnimation) + await Task.Delay(100); + App.API.OpenSettingDialog(); } - private void OnDeactivated(object sender, EventArgs e) + private async void OnDeactivated(object sender, EventArgs e) { - if (_settings.HideWhenDeactive) + //This condition stops extra hide call when animator is on, + // which causes the toggling to occasional hide instead of show. + if (_viewModel.MainWindowVisibilityStatus) { - _viewModel.Hide(); + // Need time to initialize the main query window animation. + // This also stops the mainwindow from flickering occasionally after Settings window is opened + // and always after Settings window is closed. + if (_settings.UseAnimation) + await Task.Delay(100); + + if (_settings.HideWhenDeactive) + { + _viewModel.Hide(); + } } } private void UpdatePosition() { + if (_animating) + return; + if (_settings.RememberLastLaunchLocation) { Left = _settings.WindowLeft; @@ -297,6 +403,8 @@ namespace Flow.Launcher private void OnLocationChanged(object sender, EventArgs e) { + if (_animating) + return; if (_settings.RememberLastLaunchLocation) { _settings.WindowLeft = Left; @@ -304,7 +412,20 @@ namespace Flow.Launcher } } - private double WindowLeft() + public void HideStartup() + { + UpdatePosition(); + if (_settings.HideOnStartup) + { + _viewModel.Hide(); + } + else + { + _viewModel.Show(); + } + } + + public double WindowLeft() { var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); @@ -313,7 +434,7 @@ namespace Flow.Launcher return left; } - private double WindowTop() + public double WindowTop() { var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); @@ -372,5 +493,17 @@ namespace Flow.Launcher { QueryTextBox.CaretIndex = QueryTextBox.Text.Length; } + + public void InitializeColorScheme() + { + if (_settings.ColorScheme == Constant.Light) + { + ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Light; + } + else if (_settings.ColorScheme == Constant.Dark) + { + ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Dark; + } + } } } \ No newline at end of file diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index 2c82e1451..d8f9fd45e 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -11,8 +11,8 @@ namespace Flow.Launcher [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] public static void Show(string title, string subTitle, string iconPath) { - var legacy = Environment.OSVersion.Version.Major < 10; - // Handle notification for win7/8 + var legacy = Environment.OSVersion.Version.Build < 19041; + // Handle notification for win7/8/early win10 if (legacy) { LegacyShow(title, subTitle, iconPath); diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml index bbe601010..8fb27c470 100644 --- a/Flow.Launcher/PriorityChangeWindow.xaml +++ b/Flow.Launcher/PriorityChangeWindow.xaml @@ -7,84 +7,118 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="http://schemas.modernwpf.com/2019" Title="{DynamicResource changePriorityWindow}" - Background="#F3F3F3" - BorderBrush="#cecece" + Width="350" + Background="{DynamicResource PopuBGColor}" + Foreground="{DynamicResource PopupTextColor}" Loaded="PriorityChangeWindow_Loaded" MouseDown="window_MouseDown" ResizeMode="NoResize" - SizeToContent="WidthAndHeight" + SizeToContent="Height" WindowStartupLocation="CenterScreen" mc:Ignorable="d"> - + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + diff --git a/Flow.Launcher/Properties/Resources.Designer.cs b/Flow.Launcher/Properties/Resources.Designer.cs index a19716073..43927cb98 100644 --- a/Flow.Launcher/Properties/Resources.Designer.cs +++ b/Flow.Launcher/Properties/Resources.Designer.cs @@ -69,5 +69,13 @@ namespace Flow.Launcher.Properties { return ((System.Drawing.Icon)(obj)); } } + internal static System.Drawing.Icon gamemode + { + get + { + object obj = ResourceManager.GetObject("gamemode", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } } } diff --git a/Flow.Launcher/Properties/Resources.resx b/Flow.Launcher/Properties/Resources.resx index 3ae43d89b..2126cb185 100644 --- a/Flow.Launcher/Properties/Resources.resx +++ b/Flow.Launcher/Properties/Resources.resx @@ -112,13 +112,16 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + ..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Images\gamemode.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e90a53fc3..6713929d6 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; @@ -14,6 +14,7 @@ using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Flow.Launcher.Plugin.SharedModels; +using Flow.Launcher.Plugin.SharedCommands; using System.Threading; using System.IO; using Flow.Launcher.Infrastructure.Http; @@ -40,7 +41,7 @@ namespace Flow.Launcher _settingsVM = settingsVM; _mainVM = mainVM; _alphabet = alphabet; - GlobalHotkey.Instance.hookedKeyboardCallback += KListener_hookedKeyboardCallback; + GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } @@ -55,7 +56,7 @@ namespace Flow.Launcher public void RestartApp() { - _mainVM.MainWindowVisibility = Visibility.Hidden; + _mainVM.Hide(); // we must manually save // UpdateManager.RestartApp() will call Environment.Exit(0) @@ -70,7 +71,7 @@ namespace Flow.Launcher public void RestarApp() => RestartApp(); - public void ShowMainWindow() => _mainVM.MainWindowVisibility = Visibility.Visible; + public void ShowMainWindow() => _mainVM.Show(); public void CheckForNewUpdate() => _settingsVM.UpdateApp(); @@ -106,6 +107,19 @@ namespace Flow.Launcher }); } + public void ShellRun(string cmd, string filename = "cmd.exe") + { + var args = filename == "cmd.exe" ? $"/C {cmd}" : $"{cmd}"; + + var startInfo = ShellCommand.SetProcessStartInfo(filename, arguments: args, createNoWindow: true); + ShellCommand.Execute(startInfo); + } + + public void CopyToClipboard(string text) + { + Clipboard.SetDataObject(text); + } + public void StartLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Visible; public void StopLoadingBar() => _mainVM.ProgressBarVisibility = Visibility.Collapsed; @@ -190,27 +204,37 @@ namespace Flow.Launcher Arguments = FileName is null ? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath) : explorerInfo.FileArgument.Replace("%d", DirectoryPath).Replace("%f", - Path.IsPathRooted(FileName) ? FileName : Path.Combine(DirectoryPath, FileName)) + Path.IsPathRooted(FileName) ? FileName : Path.Combine(DirectoryPath, FileName)) }; explorer.Start(); } public event FlowLauncherGlobalKeyboardEventHandler GlobalKeyboardEvent; + private readonly List> _globalKeyboardHandlers = new(); + + public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); + public void RemoveGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Remove(callback); + #endregion #region Private Methods private bool KListener_hookedKeyboardCallback(KeyEvent keyevent, int vkcode, SpecialKeyState state) { + var continueHook = true; if (GlobalKeyboardEvent != null) { - return GlobalKeyboardEvent((int)keyevent, vkcode, state); + continueHook = GlobalKeyboardEvent((int)keyevent, vkcode, state); + } + foreach (var x in _globalKeyboardHandlers) + { + continueHook &= x((int)keyevent, vkcode, state); } - return true; + return continueHook; } #endregion } -} \ No newline at end of file +} diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index 877a97645..dd9dba391 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -4,532 +4,130 @@ xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:ui="http://schemas.modernwpf.com/2019"> - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -105,7 +157,7 @@ - + + + + + + + + - + @@ -86,7 +115,7 @@ + Fill="{StaticResource Color03B}" /> - + + + + + + + - - - diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 2b5fd2397..0e6945531 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -14,7 +14,7 @@ xmlns:vm="clr-namespace:Flow.Launcher.ViewModel" Title="{DynamicResource flowlauncher_settings}" Width="1000" - Height="700" + Height="650" MinWidth="900" MinHeight="600" d:DataContext="{d:DesignInstance vm:SettingWindowViewModel}" @@ -22,9 +22,13 @@ Icon="Images\app.ico" Loaded="OnLoaded" MouseDown="window_MouseDown" - ResizeMode="CanResizeWithGrip" + ResizeMode="CanResize" + StateChanged="Window_StateChanged" WindowStartupLocation="CenterScreen" mc:Ignorable="d"> + + + @@ -64,8 +68,8 @@ + + - + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - + + + + + + + + + + -  + Grid.Row="1" + Margin="0,12,0,0" + Style="{StaticResource TabMenu}" + Text="Flow Launcher" + TextAlignment="center" /> + + + + + + + + + + + + +  - - - - - - - - - -  - - - + Grid.Column="1" + Style="{StaticResource TabMenu}" + Text="{DynamicResource general}" /> + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - -  - - - - - - - - - - - -  - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  - - - - - + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs index 23f8f13cd..27e4a0b9a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs @@ -100,6 +100,10 @@ namespace Flow.Launcher.Plugin.Explorer.Views MessageBox.Show(settingsViewModel.Context.API.GetTranslation("newActionKeywordsHasBeenAssigned")); } + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } private void TxtCurrentActionKeyword_OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 50171a363..ce8ecb6ff 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -1,82 +1,145 @@ - + - + - + - + - - + + + + + + + + + + - - + + - + - - + + - + + Drop="lbxAccessLinks_Drop" + ItemTemplate="{StaticResource ListViewTemplateAccessLinks}" /> - + + Drop="lbxAccessLinks_Drop" + ItemTemplate="{StaticResource ListViewTemplateExcludedPaths}" /> - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +