Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CmdPal.Ext.WebSearch.Helpers;
using Microsoft.CommandPalette.Extensions.Toolkit;

using BrowserInfo = Microsoft.CmdPal.Ext.WebSearch.Helpers.DefaultBrowserInfo;

namespace Microsoft.CmdPal.Ext.WebSearch.Commands;

internal sealed partial class OpenURLCommand : InvokableCommand
{
private readonly SettingsManager _settingsManager;

public string Url { get; internal set; } = string.Empty;

internal OpenURLCommand(string url, SettingsManager settingsManager)
{
Url = url;
BrowserInfo.UpdateIfTimePassed();
Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@niels9001 do we have a better icon we can use to differentiate between "search the web" and "open this website"? That might help clarify the difference between these two commands

Name = string.Empty;
_settingsManager = settingsManager;
}

public override CommandResult Invoke()
{
if (!ShellHelpers.OpenCommandInShell(BrowserInfo.Path, BrowserInfo.ArgumentsPattern, $"{Url}"))
{
// TODO GH# 138 --> actually display feedback from the extension somewhere.
return CommandResult.KeepOpen();
}

return CommandResult.Dismiss();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Globalization;
using System.Text;
using Microsoft.CmdPal.Ext.WebSearch.Commands;
using Microsoft.CmdPal.Ext.WebSearch.Helpers;
using Microsoft.CmdPal.Ext.WebSearch.Properties;
using Microsoft.CommandPalette.Extensions.Toolkit;
using BrowserInfo = Microsoft.CmdPal.Ext.WebSearch.Helpers.DefaultBrowserInfo;

namespace Microsoft.CmdPal.Ext.WebSearch;

internal sealed partial class FallbackOpenURLItem : FallbackCommandItem
{
private readonly OpenURLCommand _executeItem;
private static readonly CompositeFormat PluginOpenURL = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open_url);
private static readonly CompositeFormat PluginOpenUrlInBrowser = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open_url_in_browser);

public FallbackOpenURLItem(SettingsManager settings)
: base(new OpenURLCommand(string.Empty, settings), string.Empty)
{
_executeItem = (OpenURLCommand)this.Command!;
Title = string.Empty;
_executeItem.Name = string.Empty;
Subtitle = string.Empty;
Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png");
}

public override void UpdateQuery(string query)
{
if (!IsValidUrl(query))
{
Title = string.Empty;
Subtitle = string.Empty;
return;
}

var success = Uri.TryCreate(query, UriKind.Absolute, out var uri);

// if url not contain schema, add http:// by default.
if (!success)
{
query = "https://" + query;
}

_executeItem.Url = query;
_executeItem.Name = string.IsNullOrEmpty(query) ? string.Empty : Properties.Resources.open_in_default_browser;

Title = string.Format(CultureInfo.CurrentCulture, PluginOpenURL, query);
Subtitle = string.Format(CultureInfo.CurrentCulture, PluginOpenUrlInBrowser, BrowserInfo.Name ?? BrowserInfo.MSEdgeName);
}

public static bool IsValidUrl(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
return false;
}

if (!url.Contains('.', StringComparison.OrdinalIgnoreCase))
{
// eg: 'com', 'org'. We don't think it's a valid url.
// This can simplify the logic of checking if the url is valid.
return false;
}

if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
return true;
}

if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase) &&
!url.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase) &&
!url.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
{
if (Uri.IsWellFormedUriString("https://" + url, UriKind.Absolute))
{
return true;
}
}

return false;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@
<data name="plugin_open" xml:space="preserve">
<value>Search the web in {0}</value>
</data>
<data name="plugin_open_url" xml:space="preserve">
<value>Open "{0}"</value>
</data>
<data name="plugin_open_url_in_browser" xml:space="preserve">
<value>Open url in {0}</value>
</data>
<data name="plugin_search_failed" xml:space="preserve">
<value>Failed to open {0}.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public partial class WebSearchCommandsProvider : CommandProvider
{
private readonly SettingsManager _settingsManager = new();
private readonly FallbackExecuteSearchItem _fallbackItem;
private readonly FallbackOpenURLItem _openUrlFallbackItem;

public WebSearchCommandsProvider()
{
Expand All @@ -23,6 +24,7 @@ public WebSearchCommandsProvider()
Settings = _settingsManager.Settings;

_fallbackItem = new FallbackExecuteSearchItem(_settingsManager);
_openUrlFallbackItem = new FallbackOpenURLItem(_settingsManager);
}

public override ICommandItem[] TopLevelCommands()
Expand All @@ -36,5 +38,5 @@ public override ICommandItem[] TopLevelCommands()
];
}

public override IFallbackCommandItem[]? FallbackCommands() => [_fallbackItem];
public override IFallbackCommandItem[]? FallbackCommands() => [_openUrlFallbackItem, _fallbackItem];
}
Loading