Merge branch 'dev' into websearchUri
|
|
@ -29,6 +29,13 @@ namespace Flow.Launcher.Plugin
|
|||
/// </summary>
|
||||
public string ActionKeywordAssigned { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This holds the text which can be provided by plugin to be copied to the
|
||||
/// user's clipboard when Ctrl + C is pressed on a result. If the text is a file/directory path
|
||||
/// flow will copy the actual file/folder instead of just the path text.
|
||||
/// </summary>
|
||||
public string CopyText { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ namespace Flow.Launcher
|
|||
DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// let exception throw as normal is better for Debug
|
||||
/// </summary>
|
||||
|
|
@ -179,4 +178,4 @@ namespace Flow.Launcher
|
|||
Current.MainWindow.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="InputSimulator" Version="1.0.4" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="ModernWpfUI" Version="0.9.4" />
|
||||
<PackageReference Include="NHotkey.Wpf" Version="2.1.0" />
|
||||
<PackageReference Include="NuGet.CommandLine" Version="5.4.0">
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 796 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 506 B After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 339 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 634 B After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 674 B After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 792 B After Width: | Height: | Size: 752 B |
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 760 B After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 794 B After Width: | Height: | Size: 1.4 KiB |
|
|
@ -18,6 +18,9 @@
|
|||
<system:String x:Key="copy">Copy</system:String>
|
||||
<system:String x:Key="cut">Cut</system:String>
|
||||
<system:String x:Key="paste">Paste</system:String>
|
||||
<system:String x:Key="fileTitle">File</system:String>
|
||||
<system:String x:Key="folderTitle">Folder</system:String>
|
||||
<system:String x:Key="textTitle">Text</system:String>
|
||||
<system:String x:Key="GameMode">Game Mode</system:String>
|
||||
<system:String x:Key="GameModeToolTip">Suspend the use of Hotkeys.</system:String>
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@
|
|||
Style="{DynamicResource QueryBoxStyle}"
|
||||
Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Visibility="Visible">
|
||||
<TextBox.CommandBindings>
|
||||
<CommandBinding Command="ApplicationCommands.Copy" Executed="OnCopy" />
|
||||
</TextBox.CommandBindings>
|
||||
<TextBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Command="ApplicationCommands.Cut" Header="{DynamicResource cut}" />
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
|||
using NotifyIcon = System.Windows.Forms.NotifyIcon;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using System.Windows.Media;
|
||||
using Flow.Launcher.Infrastructure.Hotkey;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
|
|
@ -50,7 +52,18 @@ namespace Flow.Launcher
|
|||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
private void OnCopy(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
if (QueryTextBox.SelectionLength == 0)
|
||||
{
|
||||
_viewModel.ResultCopy(string.Empty);
|
||||
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(QueryTextBox.Text))
|
||||
{
|
||||
_viewModel.ResultCopy(QueryTextBox.SelectedText);
|
||||
}
|
||||
}
|
||||
private async void OnClosing(object sender, CancelEventArgs e)
|
||||
{
|
||||
_settings.WindowTop = Top;
|
||||
|
|
@ -59,6 +72,7 @@ namespace Flow.Launcher
|
|||
_viewModel.Save();
|
||||
e.Cancel = true;
|
||||
await PluginManager.DisposePluginsAsync();
|
||||
Notification.Uninstall();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -498,6 +512,24 @@ namespace Flow.Launcher
|
|||
e.Handled = true;
|
||||
}
|
||||
break;
|
||||
case Key.Back:
|
||||
var specialKeyState = GlobalHotkey.CheckModifiers();
|
||||
if (specialKeyState.CtrlPressed)
|
||||
{
|
||||
if (_viewModel.SelectedIsFromQueryResults()
|
||||
&& QueryTextBox.CaretIndex == QueryTextBox.Text.Length)
|
||||
{
|
||||
var queryWithoutActionKeyword =
|
||||
QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.NonGlobalPlugins).Search;
|
||||
|
||||
if (FilesFolders.IsLocationPathString(queryWithoutActionKeyword))
|
||||
{
|
||||
_viewModel.BackspaceCommand.Execute(null);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Flow.Launcher.Infrastructure;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Windows.Data.Xml.Dom;
|
||||
|
|
@ -8,10 +9,17 @@ namespace Flow.Launcher
|
|||
{
|
||||
internal static class Notification
|
||||
{
|
||||
internal static bool legacy = Environment.OSVersion.Version.Build < 19041;
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
internal static void Uninstall()
|
||||
{
|
||||
if (!legacy)
|
||||
ToastNotificationManagerCompat.Uninstall();
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public static void Show(string title, string subTitle, string iconPath)
|
||||
{
|
||||
var legacy = Environment.OSVersion.Version.Build < 19041;
|
||||
// Handle notification for win7/8/early win10
|
||||
if (legacy)
|
||||
{
|
||||
|
|
@ -24,13 +32,11 @@ namespace Flow.Launcher
|
|||
? Path.Combine(Constant.ProgramDirectory, "Images\\app.png")
|
||||
: iconPath;
|
||||
|
||||
var xml = $"<?xml version=\"1.0\"?><toast><visual><binding template=\"ToastImageAndText04\"><image id=\"1\" src=\"{Icon}\" alt=\"meziantou\"/><text id=\"1\">{title}</text>" +
|
||||
$"<text id=\"2\">{subTitle}</text></binding></visual></toast>";
|
||||
var toastXml = new XmlDocument();
|
||||
toastXml.LoadXml(xml);
|
||||
var toast = new ToastNotification(toastXml);
|
||||
ToastNotificationManager.CreateToastNotifier("Flow Launcher").Show(toast);
|
||||
|
||||
new ToastContentBuilder()
|
||||
.AddText(title, hintMaxLines: 1)
|
||||
.AddText(subTitle)
|
||||
.AddAppLogoOverride(new Uri(Icon))
|
||||
.Show();
|
||||
}
|
||||
|
||||
private static void LegacyShow(string title, string subTitle, string iconPath)
|
||||
|
|
|
|||
|
|
@ -2514,6 +2514,18 @@
|
|||
Margin="14,14,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Color15B}"
|
||||
TextWrapping="WrapWithOverflow">
|
||||
<Hyperlink NavigateUri="https://icons8.com" RequestNavigate="OnRequestNavigate">
|
||||
<Run Text="Icons by icons8.com" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock
|
||||
Margin="14,4,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
DockPanel.Dock="Bottom"
|
||||
FontSize="12"
|
||||
Foreground="{DynamicResource Color15B}"
|
||||
|
|
|
|||
|
|
@ -13,12 +13,14 @@ using Flow.Launcher.Infrastructure.Hotkey;
|
|||
using Flow.Launcher.Infrastructure.Storage;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
using Flow.Launcher.Storage;
|
||||
using Flow.Launcher.Infrastructure.Logger;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using System.Threading.Channels;
|
||||
using ISavable = Flow.Launcher.Plugin.ISavable;
|
||||
|
||||
using System.IO;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
|
|
@ -252,6 +254,18 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
});
|
||||
|
||||
BackspaceCommand = new RelayCommand(index =>
|
||||
{
|
||||
var query = QueryBuilder.Build(QueryText.Trim(), PluginManager.NonGlobalPlugins);
|
||||
|
||||
// GetPreviousExistingDirectory does not require trailing '\', otherwise will return empty string
|
||||
var path = FilesFolders.GetPreviousExistingDirectory((_) => true, query.Search.TrimEnd('\\'));
|
||||
|
||||
var actionKeyword = string.IsNullOrEmpty(query.ActionKeyword) ? string.Empty : $"{query.ActionKeyword} ";
|
||||
|
||||
ChangeQueryText($"{actionKeyword}{path}");
|
||||
});
|
||||
|
||||
LoadContextMenuCommand = new RelayCommand(_ =>
|
||||
{
|
||||
if (SelectedIsFromQueryResults())
|
||||
|
|
@ -398,6 +412,7 @@ namespace Flow.Launcher.ViewModel
|
|||
public string PluginIconPath { get; set; } = null;
|
||||
|
||||
public ICommand EscCommand { get; set; }
|
||||
public ICommand BackspaceCommand { get; set; }
|
||||
public ICommand SelectNextItemCommand { get; set; }
|
||||
public ICommand SelectPrevItemCommand { get; set; }
|
||||
public ICommand SelectNextPageCommand { get; set; }
|
||||
|
|
@ -410,6 +425,9 @@ namespace Flow.Launcher.ViewModel
|
|||
public ICommand OpenSettingCommand { get; set; }
|
||||
public ICommand ReloadPluginDataCommand { get; set; }
|
||||
public ICommand ClearQueryCommand { get; private set; }
|
||||
|
||||
public ICommand CopyToClipboard { get; set; }
|
||||
|
||||
public ICommand AutocompleteQueryCommand { get; set; }
|
||||
|
||||
public string OpenResultCommandModifiers { get; private set; }
|
||||
|
|
@ -706,7 +724,11 @@ namespace Flow.Launcher.ViewModel
|
|||
IcoPath = icon,
|
||||
SubTitle = subtitle,
|
||||
PluginDirectory = metadata.PluginDirectory,
|
||||
Action = _ => false
|
||||
Action = _ =>
|
||||
{
|
||||
App.API.OpenUrl(metadata.Website);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return menu;
|
||||
}
|
||||
|
|
@ -853,6 +875,52 @@ namespace Flow.Launcher.ViewModel
|
|||
Results.AddResults(resultsForUpdates, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the global copy method for an individual result. If no text is passed,
|
||||
/// the method will work out what is to be copied based on the result, so plugin can offer the text
|
||||
/// to be copied via the result model. If the text is a directory/file path,
|
||||
/// then actual file/folder will be copied instead.
|
||||
/// The result's subtitle text is the default text to be copied
|
||||
/// </summary>
|
||||
public void ResultCopy(string stringToCopy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stringToCopy))
|
||||
{
|
||||
var result = Results.SelectedItem?.Result;
|
||||
if (result != null)
|
||||
{
|
||||
string copyText = string.IsNullOrEmpty(result.CopyText) ? result.SubTitle : result.CopyText;
|
||||
var isFile = File.Exists(copyText);
|
||||
var isFolder = Directory.Exists(copyText);
|
||||
if (isFile || isFolder)
|
||||
{
|
||||
var paths = new StringCollection();
|
||||
paths.Add(copyText);
|
||||
|
||||
Clipboard.SetFileDropList(paths);
|
||||
App.API.ShowMsg(
|
||||
App.API.GetTranslation("copy")
|
||||
+" "
|
||||
+ (isFile? App.API.GetTranslation("fileTitle") : App.API.GetTranslation("folderTitle")),
|
||||
App.API.GetTranslation("completedSuccessfully"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Clipboard.SetDataObject(copyText.ToString());
|
||||
App.API.ShowMsg(
|
||||
App.API.GetTranslation("copy")
|
||||
+ " "
|
||||
+ App.API.GetTranslation("textTitle"),
|
||||
App.API.GetTranslation("completedSuccessfully"));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Clipboard.SetDataObject(stringToCopy);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,16 @@ using Flow.Launcher.Infrastructure.Logger;
|
|||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
using Flow.Launcher.Plugin;
|
||||
using System.IO;
|
||||
using System.Drawing.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Flow.Launcher.ViewModel
|
||||
{
|
||||
public class ResultViewModel : BaseModel
|
||||
{
|
||||
private static PrivateFontCollection fontCollection = new();
|
||||
private static Dictionary<string, string> fonts = new();
|
||||
|
||||
public ResultViewModel(Result result, Settings settings)
|
||||
{
|
||||
if (result != null)
|
||||
|
|
@ -23,13 +28,29 @@ namespace Flow.Launcher.ViewModel
|
|||
// Checks if it's a system installed font, which does not require path to be provided.
|
||||
if (glyph.FontFamily.EndsWith(".ttf") || glyph.FontFamily.EndsWith(".otf"))
|
||||
{
|
||||
var fontPath = Result.Glyph.FontFamily;
|
||||
Glyph = Path.IsPathRooted(fontPath)
|
||||
? Result.Glyph
|
||||
: Result.Glyph with
|
||||
string fontFamilyPath = glyph.FontFamily;
|
||||
|
||||
if (!Path.IsPathRooted(fontFamilyPath))
|
||||
{
|
||||
fontFamilyPath = Path.Combine(Result.PluginDirectory, fontFamilyPath);
|
||||
}
|
||||
|
||||
if (fonts.ContainsKey(fontFamilyPath))
|
||||
{
|
||||
Glyph = glyph with
|
||||
{
|
||||
FontFamily = Path.Combine(Result.PluginDirectory, fontPath)
|
||||
FontFamily = fonts[fontFamilyPath]
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
fontCollection.AddFontFile(fontFamilyPath);
|
||||
fonts[fontFamilyPath] = $"{Path.GetDirectoryName(fontFamilyPath)}/#{fontCollection.Families[^1].Name}";
|
||||
Glyph = glyph with
|
||||
{
|
||||
FontFamily = fonts[fontFamilyPath]
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -310,4 +310,4 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 3.2 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "Browser Bookmarks",
|
||||
"Description": "Search your browser bookmarks",
|
||||
"Author": "qianlifeng, Ioannis G.",
|
||||
"Version": "1.6.2",
|
||||
"Version": "1.6.3",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.BrowserBookmark.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 501 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.3 KiB |
|
|
@ -10,7 +10,7 @@
|
|||
"Name": "Explorer",
|
||||
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
|
||||
"Author": "Jeremy Wu",
|
||||
"Version": "1.11.1",
|
||||
"Version": "1.11.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 269 B After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 484 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 2.7 KiB |
|
|
@ -6,7 +6,7 @@
|
|||
"Name": "Plugins Manager",
|
||||
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
|
||||
"Author": "Jeremy Wu",
|
||||
"Version": "1.12.0",
|
||||
"Version": "1.12.1",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name":"Process Killer",
|
||||
"Description":"Kill running processes from Flow",
|
||||
"Author":"Flow-Launcher",
|
||||
"Version":"1.2.5",
|
||||
"Version":"1.2.6",
|
||||
"Language":"csharp",
|
||||
"Website":"https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller",
|
||||
"IcoPath":"Images\\app.png",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 774 B After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.3 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "Program",
|
||||
"Description": "Search programs in Flow.Launcher",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.8.1",
|
||||
"Version": "1.8.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Program.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 752 B After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 3.3 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "Shell",
|
||||
"Description": "Provide executing commands from Flow Launcher",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.4.9",
|
||||
"Version": "1.4.10",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 674 B After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 760 B After Width: | Height: | Size: 2.3 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "System Commands",
|
||||
"Description": "Provide System related commands. e.g. shutdown,lock, setting etc.",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.6.1",
|
||||
"Version": "1.6.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Sys.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 873 B After Width: | Height: | Size: 2.7 KiB |
|
|
@ -4,7 +4,7 @@
|
|||
"Name": "URL",
|
||||
"Description": "Open the typed URL from Flow Launcher",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.2.1",
|
||||
"Version": "1.2.2",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.Url.dll",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
|
@ -41,8 +41,8 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
var results = new List<Result>();
|
||||
|
||||
foreach (SearchSource searchSource in _settings.SearchSources.Where(o => (o.ActionKeyword == query.ActionKeyword ||
|
||||
o.ActionKeyword == SearchSourceGlobalPluginWildCardSign)
|
||||
&& o.Enabled))
|
||||
o.ActionKeyword == SearchSourceGlobalPluginWildCardSign)
|
||||
&& o.Enabled))
|
||||
{
|
||||
string keyword = string.Empty;
|
||||
keyword = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? query.ToString() : query.Search;
|
||||
|
|
@ -105,11 +105,11 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
if (_settings.EnableSuggestion)
|
||||
{
|
||||
var suggestions = await SuggestionsAsync(keyword, subtitle, searchSource, token).ConfigureAwait(false);
|
||||
if (token.IsCancellationRequested || !suggestions.Any())
|
||||
var enumerable = suggestions?.ToList();
|
||||
if (token.IsCancellationRequested || enumerable is not { Count: > 0 })
|
||||
return;
|
||||
|
||||
|
||||
results.AddRange(suggestions);
|
||||
|
||||
results.AddRange(enumerable);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
|
@ -118,32 +118,32 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
private async Task<IEnumerable<Result>> SuggestionsAsync(string keyword, string subtitle, SearchSource searchSource, CancellationToken token)
|
||||
{
|
||||
var source = _settings.SelectedSuggestion;
|
||||
if (source != null)
|
||||
if (source == null)
|
||||
{
|
||||
//Suggestions appear below actual result, and appear above global action keyword match if non-global;
|
||||
var score = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? scoreSuggestions : scoreSuggestions + 1;
|
||||
|
||||
var suggestions = await source.Suggestions(keyword, token).ConfigureAwait(false);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var resultsFromSuggestion = suggestions?.Select(o => new Result
|
||||
{
|
||||
Title = o,
|
||||
SubTitle = subtitle,
|
||||
Score = score,
|
||||
IcoPath = searchSource.IconPath,
|
||||
ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword,
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return resultsFromSuggestion;
|
||||
return new List<Result>();
|
||||
}
|
||||
return new List<Result>();
|
||||
//Suggestions appear below actual result, and appear above global action keyword match if non-global;
|
||||
var score = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? scoreSuggestions : scoreSuggestions + 1;
|
||||
|
||||
var suggestions = await source.SuggestionsAsync(keyword, token).ConfigureAwait(false);
|
||||
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var resultsFromSuggestion = suggestions?.Select(o => new Result
|
||||
{
|
||||
Title = o,
|
||||
SubTitle = subtitle,
|
||||
Score = score,
|
||||
IcoPath = searchSource.IconPath,
|
||||
ActionKeywordAssigned = searchSource.ActionKeyword == SearchSourceGlobalPluginWildCardSign ? string.Empty : searchSource.ActionKeyword,
|
||||
Action = c =>
|
||||
{
|
||||
_context.API.OpenUrl(searchSource.Url.Replace("{q}", Uri.EscapeDataString(o)));
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return resultsFromSuggestion;
|
||||
}
|
||||
|
||||
public Task InitAsync(PluginInitContext context)
|
||||
|
|
@ -191,4 +191,4 @@ namespace Flow.Launcher.Plugin.WebSearch
|
|||
|
||||
public event ResultUpdatedEventHandler ResultsUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
private readonly Regex _reg = new Regex("window.baidu.sug\\((.*)\\)");
|
||||
|
||||
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
string result;
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
const string api = "http://suggestion.baidu.com/su?json=1&wd=";
|
||||
result = await Http.GetAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e.InnerException is TimeoutException)
|
||||
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
|
||||
{
|
||||
Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
class Bing : SuggestionSource
|
||||
{
|
||||
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
|
||||
try
|
||||
|
|
@ -40,7 +40,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
|
||||
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e.InnerException is TimeoutException)
|
||||
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
|
||||
{
|
||||
Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
public class Google : SuggestionSource
|
||||
{
|
||||
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||
public override async Task<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -32,7 +32,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
return results.EnumerateArray().Select(o => o.GetString()).ToList();
|
||||
|
||||
}
|
||||
catch (Exception e) when (e is HttpRequestException || e.InnerException is TimeoutException)
|
||||
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
|
||||
{
|
||||
Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
{
|
||||
public abstract class SuggestionSource
|
||||
{
|
||||
public abstract Task<List<string>> Suggestions(string query, CancellationToken token);
|
||||
public abstract Task<List<string>> SuggestionsAsync(string query, CancellationToken token);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
"Name": "Web Searches",
|
||||
"Description": "Provide the web search ability",
|
||||
"Author": "qianlifeng",
|
||||
"Version": "1.5.2",
|
||||
"Version": "1.5.3",
|
||||
"Language": "csharp",
|
||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||
"ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll",
|
||||
|
|
|
|||
11
README.md
|
|
@ -51,8 +51,8 @@ Dedicated to making your workflow flow more seamless. Search everything from app
|
|||
|
||||
### Installation
|
||||
|
||||
| [Windows 7+ installer](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Setup.exe) | [Portable](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Portable.zip) | `WinGet install "Flow Launcher"` |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: | :------------------------------: |
|
||||
| [Windows 7+ installer](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Setup.exe) | [Portable](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Portable.zip) | `winget install "Flow Launcher"` | `scoop install Flow-Launcher` |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: | :------------------------------: | :------------------------------: |
|
||||
|
||||
> Windows may complain about security due to code not being signed, this will be completed at a later stage. If you downloaded from this repo, you are good to continue the set up.
|
||||
|
||||
|
|
@ -215,17 +215,18 @@ And you can download <a href="https://github.com/Flow-Launcher/Flow.Launcher/dis
|
|||
|
||||
| Hotkey | Description |
|
||||
| ------------------------------------------------------------ | -------------------------------------------- |
|
||||
| <kbd>Alt</kbd>+ <kbd>Space</kbd> | Open Search Box (Default and Configurable) |
|
||||
| <kbd>Alt</kbd>+ <kbd>Space</kbd> | Open Search Box (default and configurable) |
|
||||
| <kbd>Enter</kbd> | Execute |
|
||||
| <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>Enter</kbd> | Run As Admin |
|
||||
| <kbd>↑</kbd><kbd>↓</kbd> | Scroll up & Down |
|
||||
| <kbd>←</kbd><kbd>→</kbd> | Back to Result / Open Context Menu |
|
||||
| <kbd>Ctrl</kbd> +<kbd>o</kbd> , <kbd>Shift</kbd> +<kbd>Enter</kbd> | Open Context Menu |
|
||||
| <kbd>Tab</kbd> | Autocomplete |
|
||||
| <kbd>Ctrl</kbd> +<kbd>o</kbd> , <kbd>Shift</kbd> +<kbd>Enter</kbd> | Open Context Menu |
|
||||
| <kbd>Tab</kbd> | Autocomplete |
|
||||
| <kbd>Esc</kbd> | Back to Result & Close |
|
||||
| <kbd>Ctrl</kbd> +<kbd>i</kbd> | Open Setting Window |
|
||||
| <kbd>F5</kbd> | Reload All Plugin Data & Window Search Index |
|
||||
| <kbd>Ctrl</kbd> + <kbd>h</kbd> | Open Query History |
|
||||
| <kbd>Ctrl</kbd> + <kbd>Backspace</kbd> | Back to Previous Directory |
|
||||
|
||||
|
||||
## System Command List
|
||||
|
|
|
|||