diff --git a/Plugins/Flow.Launcher.Plugin.Url/Converters/BoolToVisibilityConverter.cs b/Plugins/Flow.Launcher.Plugin.Url/Converters/BoolToVisibilityConverter.cs new file mode 100644 index 00000000000..00f41a174a5 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Url/Converters/BoolToVisibilityConverter.cs @@ -0,0 +1,23 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Flow.Launcher.Plugin.Url.Converters; + +[ValueConversion(typeof(bool), typeof(Visibility))] +public class BoolToVisibilityConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is not bool) + throw new ArgumentException("value should be boolean", nameof(value)); + + return (bool)value ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new InvalidOperationException(); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Url/Converters/InverseBoolConverter.cs b/Plugins/Flow.Launcher.Plugin.Url/Converters/InverseBoolConverter.cs new file mode 100644 index 00000000000..c46d416a826 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Url/Converters/InverseBoolConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Flow.Launcher.Plugin.Url.Converters; + +[ValueConversion(typeof(bool), typeof(bool))] +public class InverseBoolConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is not bool) + throw new ArgumentException("value should be boolean", nameof(value)); + + return !(bool)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is not bool) + throw new ArgumentException("value should be boolean", nameof(value)); + + return !(bool)value; + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/en.xaml index 461ccd1970b..b9f3b04772a 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/en.xaml @@ -1,18 +1,22 @@ - + - Open search in: - New Window - New Tab - Open url:{0} Can't open url:{0} URL Open the typed URL from Flow Launcher - Please set your browser path: Choose Application(*.exe)|*.exe|All files|*.* + + Use custom instead of Flow's default web browser + Browser path + + New tab + New window + + Private mode \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Url/Main.cs b/Plugins/Flow.Launcher.Plugin.Url/Main.cs index db7cecbdebb..0b2e4b7f811 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Url/Main.cs @@ -1,13 +1,15 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using System.Windows.Controls; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.Url { - public class Main : IPlugin, IPluginI18n + public class Main : IPlugin, IPluginI18n, ISettingProvider { //based on https://gist.github.com/dperini/729294 - private const string urlPattern = "^" + + private const string UrlPattern = "^" + // protocol identifier "(?:(?:https?|ftp)://|)" + // user:pass authentication @@ -39,18 +41,18 @@ public class Main : IPlugin, IPluginI18n // resource path "(?:/\\S*)?" + "$"; - Regex reg = new Regex(urlPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); + private readonly Regex UrlRegex = new(UrlPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); internal static PluginInitContext Context { get; private set; } - private Settings _settings; - + internal static Settings Settings { get; private set; } + public List Query(Query query) { var raw = query.Search; if (IsURL(raw)) { - return new List - { - new Result + return + [ + new() { Title = raw, SubTitle = Localize.flowlauncher_plugin_url_open_url(raw), @@ -58,14 +60,28 @@ public List Query(Query query) Score = 8, Action = _ => { - if (!raw.ToLower().StartsWith("http")) + if (!raw.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { raw = "http://" + raw; } try { - Context.API.OpenUrl(raw); - + if (Settings.UseCustomBrowser) + { + if (Settings.OpenInNewBrowserWindow) + { + SearchWeb.OpenInBrowserWindow(raw, Settings.BrowserPath, Settings.OpenInPrivateMode, Settings.PrivateModeArgument); + } + else + { + SearchWeb.OpenInBrowserTab(raw, Settings.BrowserPath, Settings.OpenInPrivateMode, Settings.PrivateModeArgument); + } + } + else + { + Context.API.OpenWebUrl(raw); + } + return true; } catch(Exception) @@ -75,16 +91,17 @@ public List Query(Query query) } } } - }; + ]; } - return new List(0); + + return []; } public bool IsURL(string raw) { raw = raw.ToLower(); - if (reg.Match(raw).Value == raw) return true; + if (UrlRegex.Match(raw).Value == raw) return true; if (raw == "localhost" || raw.StartsWith("localhost:") || raw == "http://localhost" || raw.StartsWith("http://localhost:") || @@ -100,8 +117,8 @@ public bool IsURL(string raw) public void Init(PluginInitContext context) { Context = context; - - _settings = context.API.LoadSettingJsonStorage(); + + Settings = context.API.LoadSettingJsonStorage(); } public string GetTranslatedPluginTitle() @@ -113,5 +130,10 @@ public string GetTranslatedPluginDescription() { return Localize.flowlauncher_plugin_url_plugin_description(); } + + public Control CreateSettingPanel() + { + return new SettingsControl(); + } } } diff --git a/Plugins/Flow.Launcher.Plugin.Url/Settings.cs b/Plugins/Flow.Launcher.Plugin.Url/Settings.cs index a8d89e27f33..a46194f7475 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Url/Settings.cs @@ -1,9 +1,51 @@ namespace Flow.Launcher.Plugin.Url { - public class Settings + public class Settings : BaseModel { - public string BrowserPath { get; set; } + private bool _useCustomBrowser = false; + public bool UseCustomBrowser + { + get => _useCustomBrowser; + set + { + if (_useCustomBrowser != value) + { + _useCustomBrowser = value; + OnPropertyChanged(); + } + } + } - public bool OpenInNewBrowserWindow { get; set; } = true; + private string _browserPath = string.Empty; + public string BrowserPath + { + get => _browserPath; + set + { + if (_browserPath != value) + { + _browserPath = value; + OnPropertyChanged(); + } + } + } + + private bool _openInNewBrowserWindow = true; + public bool OpenInNewBrowserWindow + { + get => _openInNewBrowserWindow; + set + { + if (_openInNewBrowserWindow != value) + { + _openInNewBrowserWindow = value; + OnPropertyChanged(); + } + } + } + + public bool OpenInPrivateMode { get; set; } = false; + + public string PrivateModeArgument { get; set; } = string.Empty; } } diff --git a/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml new file mode 100644 index 00000000000..b8d282551ec --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +