mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #3944 from Flow-Launcher/url_open_enhancement
Enhancement: Support Custom Browser Path & Open in window / tab & In private for URL Plugin
This commit is contained in:
commit
eb261f503b
7 changed files with 287 additions and 27 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,22 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_open_search_in">Open search in:</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_new_window">New Window</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_new_tab">New Tab</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_open_url">Open url:{0}</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_url_cannot_open_url">Can't open url:{0}</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_plugin_name">URL</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_url_plugin_description">Open the typed URL from Flow Launcher</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_plugin_set_tip">Please set your browser path:</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_url_plugin_choose">Choose</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_url_plugin_filter">Application(*.exe)|*.exe|All files|*.*</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_use_custom_browser">Use custom instead of Flow's default web browser</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_url_browser_path">Browser path</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_new_tab">New tab</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_url_new_window">New window</system:String>
|
||||
|
||||
<system:String x:Key="flowlauncher_plugin_url_private_mode">Private mode</system:String>
|
||||
</ResourceDictionary>
|
||||
|
|
@ -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 @@ namespace Flow.Launcher.Plugin.Url
|
|||
// 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<Result> Query(Query query)
|
||||
{
|
||||
var raw = query.Search;
|
||||
if (IsURL(raw))
|
||||
{
|
||||
return new List<Result>
|
||||
{
|
||||
new Result
|
||||
return
|
||||
[
|
||||
new()
|
||||
{
|
||||
Title = raw,
|
||||
SubTitle = Localize.flowlauncher_plugin_url_open_url(raw),
|
||||
|
|
@ -58,14 +60,28 @@ namespace Flow.Launcher.Plugin.Url
|
|||
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 @@ namespace Flow.Launcher.Plugin.Url
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
];
|
||||
}
|
||||
return new List<Result>(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 @@ namespace Flow.Launcher.Plugin.Url
|
|||
public void Init(PluginInitContext context)
|
||||
{
|
||||
Context = context;
|
||||
|
||||
_settings = context.API.LoadSettingJsonStorage<Settings>();
|
||||
|
||||
Settings = context.API.LoadSettingJsonStorage<Settings>();
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
|
|
@ -113,5 +130,10 @@ namespace Flow.Launcher.Plugin.Url
|
|||
{
|
||||
return Localize.flowlauncher_plugin_url_plugin_description();
|
||||
}
|
||||
|
||||
public Control CreateSettingPanel()
|
||||
{
|
||||
return new SettingsControl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
117
Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml
Normal file
117
Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<UserControl
|
||||
x:Class="Flow.Launcher.Plugin.Url.SettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Flow.Launcher.Plugin.Url.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Flow.Launcher.Plugin.Url"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
DataContext="{Binding RelativeSource={RelativeSource Self}}"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<converters:InverseBoolConverter x:Key="InverseBoolConverter" />
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Margin="{StaticResource SettingPanelMargin}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<CheckBox
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource SettingPanelItemTopBottomMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content="{DynamicResource flowlauncher_plugin_url_use_custom_browser}"
|
||||
IsChecked="{Binding Settings.UseCustomBrowser, Mode=TwoWay}" />
|
||||
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Left"
|
||||
Visibility="{Binding Settings.UseCustomBrowser, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource SettingPanelItemRightTopBottomMargin}"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_url_browser_path}" />
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource SettingPanelItemLeftTopBottomMargin}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding Settings.BrowserPath, Mode=OneWay}" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource SettingPanelItemLeftMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Click="SelectBrowserPath"
|
||||
Content="{DynamicResource flowlauncher_plugin_url_plugin_choose}" />
|
||||
</Grid>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource SettingPanelItemLeftTopBottomMargin}"
|
||||
Orientation="Horizontal">
|
||||
<RadioButton Content="{DynamicResource flowlauncher_plugin_url_new_tab}" IsChecked="{Binding Settings.OpenInNewBrowserWindow, Converter={StaticResource InverseBoolConverter}, Mode=TwoWay}" />
|
||||
<RadioButton Content="{DynamicResource flowlauncher_plugin_url_new_window}" IsChecked="{Binding Settings.OpenInNewBrowserWindow, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource SettingPanelItemTopBottomMargin}"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="{DynamicResource flowlauncher_plugin_url_private_mode}" />
|
||||
<Grid
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource SettingPanelItemLeftTopBottomMargin}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Settings.PrivateModeArgument, Mode=TwoWay}" />
|
||||
<CheckBox
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource SettingPanelItemLeftMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content=""
|
||||
IsChecked="{Binding Settings.OpenInPrivateMode, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
27
Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml.cs
Normal file
27
Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Url;
|
||||
|
||||
public partial class SettingsControl : UserControl
|
||||
{
|
||||
public Settings Settings { get; } = Main.Settings;
|
||||
|
||||
public SettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SelectBrowserPath(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new Microsoft.Win32.OpenFileDialog
|
||||
{
|
||||
Filter = Localize.flowlauncher_plugin_url_plugin_filter()
|
||||
};
|
||||
|
||||
if (dlg.ShowDialog() == true && !string.IsNullOrEmpty(dlg.FileName))
|
||||
{
|
||||
Settings.BrowserPath = dlg.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue