diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 000000000..718a28dbd --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,91 @@ +# This workflow will build a .NET project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net + +name: Build + +on: + workflow_dispatch: + push: + branches: + - dev + - master + pull_request: + +jobs: + build: + + runs-on: windows-latest + env: + FlowVersion: 1.19.5 + NUGET_CERT_REVOCATION_MODE: offline + BUILD_NUMBER: ${{ github.run_number }} + steps: + - uses: actions/checkout@v4 + - name: Set Flow.Launcher.csproj version + id: update + uses: vers-one/dotnet-project-version-updater@v1.5 + with: + file: | + "**/SolutionAssemblyInfo.cs" + version: ${{ env.FlowVersion }}.${{ env.BUILD_NUMBER }} + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 7.0.x +# cache: true +# cache-dependency-path: | +# Flow.Launcher/packages.lock.json +# Flow.Launcher.Core/packages.lock.json +# Flow.Launcher.Infrastructure/packages.lock.json +# Flow.Launcher.Plugin/packages.lock.json + - name: Install vpk + run: dotnet tool install -g vpk + - name: Restore dependencies + run: nuget restore + - name: Build + run: dotnet build --no-restore -c Release + - name: Initialize Service + run: | + sc config WSearch start= auto # Starts Windows Search service- Needed for running ExplorerTest + net start WSearch + - name: Test + run: dotnet test --no-build --verbosity normal -c Release + - name: Perform post_build tasks + shell: powershell + run: .\Scripts\post_build.ps1 + - name: Upload Plugin Nupkg + uses: actions/upload-artifact@v4 + with: + name: Plugin nupkg + path: | + Output\Release\Flow.Launcher.Plugin.*.nupkg + compression-level: 0 + - name: Upload Setup + uses: actions/upload-artifact@v4 + with: + name: Flow Installer + path: | + Output\Packages\Flow-Launcher-*.exe + compression-level: 0 + - name: Upload Portable Version + uses: actions/upload-artifact@v4 + with: + name: Portable Version + path: | + Output\Packages\Flow-Launcher-Portable.zip + compression-level: 0 + - name: Upload Full Nupkg + uses: actions/upload-artifact@v4 + with: + name: Full nupkg + path: | + Output\Packages\FlowLauncher-*-full.nupkg + + compression-level: 0 + - name: Upload Release Information + uses: actions/upload-artifact@v4 + with: + name: RELEASES + path: | + Output\Packages\RELEASES + compression-level: 0 diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index ac27c523c..6f3b23e11 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -16,12 +16,12 @@ namespace Flow.Launcher.Core.ExternalPlugins { public record CommunityPluginSource(string ManifestFileUrl) { + private static readonly string ClassName = nameof(CommunityPluginSource); + // We should not initialize API in static constructor because it will create another API instance private static IPublicAPI api = null; private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); - private static readonly string ClassName = nameof(CommunityPluginSource); - private string latestEtag = ""; private List plugins = new(); @@ -70,7 +70,7 @@ namespace Flow.Launcher.Core.ExternalPlugins else { API.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}"); - return plugins; + return null; } } catch (Exception e) @@ -83,7 +83,7 @@ namespace Flow.Launcher.Core.ExternalPlugins { API.LogException(ClassName, "Error Occurred", e); } - return plugins; + return null; } } } diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs index 1f23c2f66..bdc1ad3dd 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs @@ -40,10 +40,14 @@ namespace Flow.Launcher.Core.ExternalPlugins var completedTask = await Task.WhenAny(tasks); if (completedTask.IsCompletedSuccessfully) { - // one of the requests completed successfully; keep its results - // and cancel the remaining http requests. - pluginResults = await completedTask; - cts.Cancel(); + var result = await completedTask; + if (result != null) + { + // one of the requests completed successfully; keep its results + // and cancel the remaining http requests. + pluginResults = result; + cts.Cancel(); + } } tasks.Remove(completedTask); } diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index d91574bdc..17792c0c1 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -1,12 +1,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Drawing; -using System.Globalization; -using System.Linq; using System.Text.Json.Serialization; using System.Windows; -using System.Windows.Media; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.Logger; @@ -14,7 +9,6 @@ using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.ViewModel; -using SystemFonts = System.Windows.SystemFonts; namespace Flow.Launcher.Infrastructure.UserSettings { @@ -38,69 +32,6 @@ namespace Flow.Launcher.Infrastructure.UserSettings _storage.Save(); } - private string language = Constant.SystemLanguageCode; - private static readonly Dictionary LanguageToNotoSans = new() - { - { "ko", "Noto Sans KR" }, - { "ja", "Noto Sans JP" }, - { "zh-CN", "Noto Sans SC" }, - { "zh-SG", "Noto Sans SC" }, - { "zh-Hans", "Noto Sans SC" }, - { "zh-TW", "Noto Sans TC" }, - { "zh-HK", "Noto Sans TC" }, - { "zh-MO", "Noto Sans TC" }, - { "zh-Hant", "Noto Sans TC" }, - { "th", "Noto Sans Thai" }, - { "ar", "Noto Sans Arabic" }, - { "he", "Noto Sans Hebrew" }, - { "hi", "Noto Sans Devanagari" }, - { "bn", "Noto Sans Bengali" }, - { "ta", "Noto Sans Tamil" }, - { "el", "Noto Sans Greek" }, - { "ru", "Noto Sans" }, - { "en", "Noto Sans" }, - { "fr", "Noto Sans" }, - { "de", "Noto Sans" }, - { "es", "Noto Sans" }, - { "pt", "Noto Sans" } - }; - - public static string GetSystemDefaultFont(bool? useNoto = null) - { - try - { - if (useNoto != false) - { - var culture = CultureInfo.CurrentCulture; - var language = culture.Name; // e.g., "zh-TW" - var langPrefix = language.Split('-')[0]; // e.g., "zh" - - if (TryGetNotoFont(language, out var notoFont) || TryGetNotoFont(langPrefix, out notoFont)) - { - if (Fonts.SystemFontFamilies.Any(f => f.Source.Equals(notoFont))) - return notoFont; - } - } - - var font = SystemFonts.MessageFontFamily; - if (font.FamilyNames.TryGetValue(System.Windows.Markup.XmlLanguage.GetLanguage("en-US"), out var englishName)) - { - return englishName; - } - - return font.Source ?? "Segoe UI"; - } - catch - { - return "Segoe UI"; - } - } - - private static bool TryGetNotoFont(string langKey, out string notoFont) - { - return LanguageToNotoSans.TryGetValue(langKey, out notoFont); - } - private string _theme = Constant.DefaultTheme; public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}"; public string OpenResultModifiers { get; set; } = KeyConstant.Alt; @@ -121,12 +52,13 @@ namespace Flow.Launcher.Infrastructure.UserSettings public string CycleHistoryUpHotkey { get; set; } = $"{KeyConstant.Alt} + Up"; public string CycleHistoryDownHotkey { get; set; } = $"{KeyConstant.Alt} + Down"; + private string _language = Constant.SystemLanguageCode; public string Language { - get => language; + get => _language; set { - language = value; + _language = value; OnPropertyChanged(); } } @@ -152,15 +84,15 @@ namespace Flow.Launcher.Infrastructure.UserSettings public double QueryBoxFontSize { get; set; } = 16; public double ResultItemFontSize { get; set; } = 16; public double ResultSubItemFontSize { get; set; } = 13; - public string QueryBoxFont { get; set; } = GetSystemDefaultFont(); + public string QueryBoxFont { get; set; } = Win32Helper.GetSystemDefaultFont(); public string QueryBoxFontStyle { get; set; } public string QueryBoxFontWeight { get; set; } public string QueryBoxFontStretch { get; set; } - public string ResultFont { get; set; } = GetSystemDefaultFont(); + public string ResultFont { get; set; } = Win32Helper.GetSystemDefaultFont(); public string ResultFontStyle { get; set; } public string ResultFontWeight { get; set; } public string ResultFontStretch { get; set; } - public string ResultSubFont { get; set; } = GetSystemDefaultFont(); + public string ResultSubFont { get; set; } = Win32Helper.GetSystemDefaultFont(); public string ResultSubFontStyle { get; set; } public string ResultSubFontWeight { get; set; } public string ResultSubFontStretch { get; set; } @@ -184,7 +116,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public double? SettingWindowLeft { get; set; } = null; public WindowState SettingWindowState { get; set; } = WindowState.Normal; - bool _showPlaceholder { get; set; } = true; + private bool _showPlaceholder { get; set; } = true; public bool ShowPlaceholder { get => _showPlaceholder; @@ -197,7 +129,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings } } } - string _placeholderText { get; set; } = string.Empty; + private string _placeholderText { get; set; } = string.Empty; public string PlaceholderText { get => _placeholderText; @@ -376,7 +308,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool StartFlowLauncherOnSystemStartup { get; set; } = false; public bool UseLogonTaskForStartup { get; set; } = false; public bool HideOnStartup { get; set; } = true; - bool _hideNotifyIcon { get; set; } + private bool _hideNotifyIcon; public bool HideNotifyIcon { get => _hideNotifyIcon; @@ -554,5 +486,4 @@ namespace Flow.Launcher.Infrastructure.UserSettings Mica, MicaAlt } - } diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 798501ae3..6a5af41df 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -1,10 +1,13 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; +using System.Linq; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; +using System.Windows.Markup; using System.Windows.Media; using Flow.Launcher.Infrastructure.UserSettings; using Microsoft.Win32; @@ -14,6 +17,7 @@ using Windows.Win32.Graphics.Dwm; using Windows.Win32.UI.Input.KeyboardAndMouse; using Windows.Win32.UI.WindowsAndMessaging; using Point = System.Windows.Point; +using SystemFonts = System.Windows.SystemFonts; namespace Flow.Launcher.Infrastructure { @@ -595,5 +599,73 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region System Font + + private static readonly Dictionary _languageToNotoSans = new() + { + { "ko", "Noto Sans KR" }, + { "ja", "Noto Sans JP" }, + { "zh-CN", "Noto Sans SC" }, + { "zh-SG", "Noto Sans SC" }, + { "zh-Hans", "Noto Sans SC" }, + { "zh-TW", "Noto Sans TC" }, + { "zh-HK", "Noto Sans TC" }, + { "zh-MO", "Noto Sans TC" }, + { "zh-Hant", "Noto Sans TC" }, + { "th", "Noto Sans Thai" }, + { "ar", "Noto Sans Arabic" }, + { "he", "Noto Sans Hebrew" }, + { "hi", "Noto Sans Devanagari" }, + { "bn", "Noto Sans Bengali" }, + { "ta", "Noto Sans Tamil" }, + { "el", "Noto Sans Greek" }, + { "ru", "Noto Sans" }, + { "en", "Noto Sans" }, + { "fr", "Noto Sans" }, + { "de", "Noto Sans" }, + { "es", "Noto Sans" }, + { "pt", "Noto Sans" } + }; + + public static string GetSystemDefaultFont() + { + try + { + var culture = CultureInfo.CurrentCulture; + var language = culture.Name; // e.g., "zh-TW" + var langPrefix = language.Split('-')[0]; // e.g., "zh" + + // First, try to find by full name, and if not found, fallback to prefix + if (TryGetNotoFont(language, out var notoFont) || TryGetNotoFont(langPrefix, out notoFont)) + { + // If the font is installed, return it + if (Fonts.SystemFontFamilies.Any(f => f.Source.Equals(notoFont))) + { + return notoFont; + } + } + + // If Noto font is not found, fallback to the system default font + var font = SystemFonts.MessageFontFamily; + if (font.FamilyNames.TryGetValue(XmlLanguage.GetLanguage("en-US"), out var englishName)) + { + return englishName; + } + + return font.Source ?? "Segoe UI"; + } + catch + { + return "Segoe UI"; + } + } + + private static bool TryGetNotoFont(string langKey, out string notoFont) + { + return _languageToNotoSans.TryGetValue(langKey, out notoFont); + } + + #endregion } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index a73ead814..31580fbe8 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -223,11 +223,15 @@ namespace Flow.Launcher.Plugin Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath, Action reportProgress = null, CancellationToken token = default); /// - /// Add ActionKeyword and update action keyword metadata for specific plugin + /// Add ActionKeyword and update action keyword metadata for specific plugin. /// Before adding, please check if action keyword is already assigned by /// /// ID for plugin that needs to add action keyword /// The actionkeyword that is supposed to be added + /// + /// If new action keyword contains any whitespace, FL will still add it but it will not work for users. + /// So plugin should check the whitespace before calling this function. + /// void AddActionKeyword(string pluginId, string newActionKeyword); /// @@ -280,9 +284,10 @@ namespace Flow.Launcher.Plugin T LoadSettingJsonStorage() where T : new(); /// - /// Save JsonStorage for current plugin's setting. This is the method used to save settings to json in Flow.Launcher + /// Save JsonStorage for current plugin's setting. This is the method used to save settings to json in Flow. /// This method will save the original instance loaded with LoadJsonStorage. - /// This API call is for manually Save. Flow will automatically save all setting type that has called LoadSettingJsonStorage or SaveSettingJsonStorage previously. + /// This API call is for manually Save. + /// Flow will automatically save all setting type that has called or previously. /// /// Type for Serialization /// @@ -424,9 +429,10 @@ namespace Flow.Launcher.Plugin Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new(); /// - /// Save BinaryStorage for current plugin's cache. This is the method used to save cache to binary in Flow.Launcher + /// Save BinaryStorage for current plugin's cache. This is the method used to save cache to binary in Flow. /// This method will save the original instance loaded with LoadCacheBinaryStorageAsync. - /// This API call is for manually Save. Flow will automatically save all cache type that has called LoadCacheBinaryStorageAsync or SaveCacheBinaryStorageAsync previously. + /// This API call is for manually Save. + /// Flow will automatically save all cache type that has called or previously. /// /// Type for Serialization /// Cache file name diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 87677f58a..87698a545 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -202,18 +202,11 @@ namespace Flow.Launcher { // we try to enable auto-startup on first launch, or reenable if it was removed // but the user still has the setting set - if (_settings.StartFlowLauncherOnSystemStartup && !Helper.AutoStartup.IsEnabled) + if (_settings.StartFlowLauncherOnSystemStartup) { try { - if (_settings.UseLogonTaskForStartup) - { - Helper.AutoStartup.EnableViaLogonTask(); - } - else - { - Helper.AutoStartup.EnableViaRegistry(); - } + Helper.AutoStartup.CheckIsEnabled(_settings.UseLogonTaskForStartup); } catch (Exception e) { diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 568ea7944..b83bb5948 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -3,7 +3,6 @@ using System.IO; using System.Linq; using System.Security.Principal; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Microsoft.Win32; using Microsoft.Win32.TaskScheduler; @@ -17,29 +16,37 @@ public class AutoStartup private const string LogonTaskName = $"{Constant.FlowLauncher} Startup"; private const string LogonTaskDesc = $"{Constant.FlowLauncher} Auto Startup"; - public static bool IsEnabled + public static void CheckIsEnabled(bool useLogonTaskForStartup) { - get + // We need to check both because if both of them are enabled, + // Hide Flow Launcher on startup will not work since the later one will trigger main window show event + var logonTaskEnabled = CheckLogonTask(); + var registryEnabled = CheckRegistry(); + if (useLogonTaskForStartup) { - // Check if logon task is enabled - if (CheckLogonTask()) + // Enable logon task + if (!logonTaskEnabled) { - return true; + Enable(true); } - - // Check if registry is enabled - try + // Disable registry + if (registryEnabled) { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - var path = key?.GetValue(Constant.FlowLauncher) as string; - return path == Constant.ExecutablePath; + Disable(false); } - catch (Exception e) + } + else + { + // Enable registry + if (!registryEnabled) { - App.API.LogError(ClassName, $"Ignoring non-critical registry error (querying if enabled): {e}"); + Enable(false); + } + // Disable logon task + if (logonTaskEnabled) + { + Disable(true); } - - return false; } } @@ -70,22 +77,28 @@ public class AutoStartup return false; } + private static bool CheckRegistry() + { + try + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + var path = key?.GetValue(Constant.FlowLauncher) as string; + return path == Constant.ExecutablePath; + } + catch (Exception e) + { + App.API.LogError(ClassName, $"Ignoring non-critical registry error (querying if enabled): {e}"); + } + + return false; + } + public static void DisableViaLogonTaskAndRegistry() { Disable(true); Disable(false); } - public static void EnableViaLogonTask() - { - Enable(true); - } - - public static void EnableViaRegistry() - { - Enable(false); - } - public static void ChangeToViaLogonTask() { Disable(false); diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 1e83415cc..e5fabb3a8 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -5,7 +5,6 @@ using NHotkey; using NHotkey.Wpf; using Flow.Launcher.ViewModel; using ChefKeys; -using Flow.Launcher.Infrastructure.Logger; using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Helper; diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 5a6fd3d74..caa9a7129 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -58,7 +58,7 @@ Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications - Search Window Position + Search Window Location Remember Last Position Monitor with Mouse Cursor Monitor with Focused Window diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml index 4d765d161..112815ed0 100644 --- a/Flow.Launcher/Resources/Light.xaml +++ b/Flow.Launcher/Resources/Light.xaml @@ -22,7 +22,7 @@ - + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 021c9d7fe..6b56caf5e 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -48,11 +48,11 @@ public partial class SettingsPaneGeneralViewModel : BaseModel { if (UseLogonTaskForStartup) { - AutoStartup.EnableViaLogonTask(); + AutoStartup.ChangeToViaLogonTask(); } else { - AutoStartup.EnableViaRegistry(); + AutoStartup.ChangeToViaRegistry(); } } else diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index d62fd906b..1138b2869 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Windows; +using System.Windows.Controls; using System.Globalization; using System.IO; using System.Linq; @@ -17,13 +17,12 @@ using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.ViewModel; using ModernWpf; using ThemeManagerForColorSchemeSwitch = ModernWpf.ThemeManager; -using System.Windows.Controls; namespace Flow.Launcher.SettingPages.ViewModels; public partial class SettingsPaneThemeViewModel : BaseModel { - private string DefaultFont = Settings.GetSystemDefaultFont(); + private readonly string DefaultFont = Win32Helper.GetSystemDefaultFont(); public string BackdropSubText => !Win32Helper.IsBackdropSupported() ? App.API.GetTranslation("BackdropTypeDisabledToolTip") : ""; public Settings Settings { get; } private readonly Theme _theme = Ioc.Default.GetRequiredService(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml index d42505348..37a7ccb8d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml @@ -80,6 +80,7 @@ Width="135" HorizontalAlignment="Left" VerticalAlignment="Center" + DataObject.Pasting="TextBox_Pasting" PreviewKeyDown="TxtCurrentActionKeyword_OnKeyDown" Text="{Binding ActionKeyword}" /> diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs index 000b2558d..10ce28fe4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.ComponentModel; +using System.Linq; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Input; @@ -85,7 +86,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views DialogResult = false; Close(); } - + private void TxtCurrentActionKeyword_OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) @@ -94,14 +95,34 @@ namespace Flow.Launcher.Plugin.Explorer.Views OnDoneButtonClick(sender, e); e.Handled = true; } + if (e.Key == Key.Space) + { + e.Handled = true; + } } - + + private void TextBox_Pasting(object sender, DataObjectPastingEventArgs e) + { + if (e.DataObject.GetDataPresent(DataFormats.Text)) + { + string text = e.DataObject.GetData(DataFormats.Text) as string; + if (!string.IsNullOrEmpty(text) && text.Any(char.IsWhiteSpace)) + { + e.CancelCommand(); + } + } + else + { + e.CancelCommand(); + } + } + public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } - + private bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml index 3df50b3ed..746c9cf84 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml @@ -56,13 +56,13 @@ - + - +