diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
index d7df11f8303..9e932a5085b 100644
--- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj
+++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj
@@ -55,6 +55,7 @@
+
diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
index 431458881ec..22f547a5a75 100644
--- a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
+++ b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
@@ -11,7 +11,9 @@
using System.Windows.Forms;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Plugin;
+using ICSharpCode.SharpZipLib.Zip;
using JetBrains.Annotations;
+using Microsoft.IO;
namespace Flow.Launcher.Core.Plugin
{
@@ -33,9 +35,11 @@ internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu
protected abstract string ExecuteCallback(JsonRPCRequestModel rpcRequest);
protected abstract string ExecuteContextMenu(Result selectedResult);
+ private static readonly RecyclableMemoryStreamManager BufferManager = new();
+
public List LoadContextMenus(Result selectedResult)
{
- string output = ExecuteContextMenu(selectedResult);
+ var output = ExecuteContextMenu(selectedResult);
try
{
return DeserializedResult(output);
@@ -61,12 +65,23 @@ private async Task> DeserializedResultAsync(Stream output)
{
if (output == Stream.Null) return null;
- var queryResponseModel = await
- JsonSerializer.DeserializeAsync(output, options);
+ try
+ {
+ var queryResponseModel =
+ await JsonSerializer.DeserializeAsync(output, options);
- await output.DisposeAsync();
-
- return ParseResults(queryResponseModel);
+ return ParseResults(queryResponseModel);
+ }
+ catch (JsonException e)
+ {
+ Log.Exception(GetType().FullName, "Unexpected Json Input", e);
+ }
+ finally
+ {
+ await output.DisposeAsync();
+ }
+
+ return null;
}
private List DeserializedResult(string output)
@@ -81,7 +96,6 @@ private List DeserializedResult(string output)
private List ParseResults(JsonRPCQueryResponseModel queryResponseModel)
{
- var results = new List();
if (queryResponseModel.Result == null) return null;
if (!string.IsNullOrEmpty(queryResponseModel.DebugMessage))
@@ -89,7 +103,7 @@ private List ParseResults(JsonRPCQueryResponseModel queryResponseModel)
context.API.ShowMsg(queryResponseModel.DebugMessage);
}
- foreach (JsonRPCResult result in queryResponseModel.Result)
+ foreach (var result in queryResponseModel.Result)
{
result.Action = c =>
{
@@ -114,7 +128,8 @@ private List ParseResults(JsonRPCQueryResponseModel queryResponseModel)
return !result.JsonRPCAction.DontHideAfterAction;
}
- var jsonRpcRequestModel = JsonSerializer.Deserialize(actionResponse, options);
+ var jsonRpcRequestModel =
+ JsonSerializer.Deserialize(actionResponse, options);
if (jsonRpcRequestModel?.Method?.StartsWith("Flow.Launcher.") ?? false)
{
@@ -125,9 +140,12 @@ private List ParseResults(JsonRPCQueryResponseModel queryResponseModel)
return !result.JsonRPCAction.DontHideAfterAction;
};
- results.Add(result);
}
+ var results = new List();
+
+ results.AddRange(queryResponseModel.Result);
+
return results;
}
@@ -217,16 +235,42 @@ protected string Execute(ProcessStartInfo startInfo)
protected async Task ExecuteAsync(ProcessStartInfo startInfo, CancellationToken token = default)
{
+ Process process = null;
+ bool disposed = false;
try
{
- using var process = Process.Start(startInfo);
+ process = Process.Start(startInfo);
if (process == null)
{
Log.Error("|JsonRPCPlugin.ExecuteAsync|Can't start new process");
return Stream.Null;
}
- var result = process.StandardOutput.BaseStream;
+ await using var source = process.StandardOutput.BaseStream;
+
+ var buffer = BufferManager.GetStream();
+
+ token.Register(() =>
+ {
+ // ReSharper disable once AccessToModifiedClosure
+ // Manually Check whether disposed
+ if (!disposed && !process.HasExited)
+ process.Kill();
+ });
+
+ try
+ {
+ // token expire won't instantly trigger the exception,
+ // manually kill process at before
+ await source.CopyToAsync(buffer, token);
+ }
+ catch (OperationCanceledException)
+ {
+ await buffer.DisposeAsync();
+ return Stream.Null;
+ }
+
+ buffer.Seek(0, SeekOrigin.Begin);
token.ThrowIfCancellationRequested();
@@ -245,7 +289,7 @@ protected async Task ExecuteAsync(ProcessStartInfo startInfo, Cancellati
return Stream.Null;
}
- return result;
+ return buffer;
}
catch (Exception e)
{
@@ -254,15 +298,24 @@ protected async Task ExecuteAsync(ProcessStartInfo startInfo, Cancellati
e);
return Stream.Null;
}
+ finally
+ {
+ process?.Dispose();
+ disposed = true;
+ }
}
public async Task> QueryAsync(Query query, CancellationToken token)
{
- var output = await ExecuteQueryAsync(query, token);
try
{
+ var output = await ExecuteQueryAsync(query, token);
return await DeserializedResultAsync(output);
}
+ catch (OperationCanceledException)
+ {
+ return null;
+ }
catch (Exception e)
{
Log.Exception($"|JsonRPCPlugin.Query|Exception when query <{query}>", e);
diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs
index b3e9052fc54..c2a32100dbb 100644
--- a/Flow.Launcher/App.xaml.cs
+++ b/Flow.Launcher/App.xaml.cs
@@ -75,7 +75,7 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
Http.API = API;
Http.Proxy = _settings.Proxy;
-
+
await PluginManager.InitializePlugins(API);
var window = new MainWindow(_settings, _mainVM);
@@ -99,6 +99,8 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
AutoStartup();
AutoUpdates();
+ API.SaveAppAllSettings();
+
_mainVM.MainWindowVisibility = _settings.HideOnStartup ? Visibility.Hidden : Visibility.Visible;
Log.Info("|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- ");
});
diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml
index ec1b015daa6..346c708377c 100644
--- a/Flow.Launcher/Languages/sk.xaml
+++ b/Flow.Launcher/Languages/sk.xaml
@@ -31,12 +31,15 @@
Ignorovať klávesové skratky v režime na celú obrazovku
Priečinok s Pythonom
Automatická aktualizácia
+ Automaticky skryť posuvník
+ Automaticky skrývať posuvník v okne nastavení a zobraziť ho, keď naň prejdete myšou
Vybrať
Schovať Flow Launcher po spustení
Schovať ikonu z oblasti oznámení
Presnosť vyhľadávania
Použiť Pinyin
Umožňuje vyhľadávanie pomocou Pinyin. Pinyin je štandardný systém romanizovaného pravopisu pre transliteráciu čínštiny
+ Efekt tieňa nie je povolený, kým má aktuálny motív povolený efekt rozostrenia
Plugin
@@ -48,6 +51,7 @@
Nová akcia skratky:
Aktuálna priorita:
Nová priorita:
+ Priorita:
Priečinok s pluginmi
Autor
Príprava:
@@ -70,6 +74,7 @@
Modifikáčné klávesy na otvorenie výsledkov
Zobraziť klávesovú skratku
Vlastná klávesová skratka na vyhľadávanie
+ Dopyt
Odstrániť
Upraviť
Pridať
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index 8b81bb94abe..fcc3af5c502 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -1,4 +1,4 @@
-
-
{
- if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
+ Dispatcher.Invoke(async () =>
{
- await Task.Delay(50);
- _progressBarStoryboard.Stop(ProgressBar);
- isProgressBarStoryboardPaused = true;
- }
- else if (_viewModel.MainWindowVisibility == Visibility.Visible &&
- isProgressBarStoryboardPaused)
- {
- _progressBarStoryboard.Begin(ProgressBar, true);
- isProgressBarStoryboardPaused = false;
- }
- }, System.Windows.Threading.DispatcherPriority.Render);
-
- break;
- }
+ if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
+ {
+ await Task.Delay(50);
+ _progressBarStoryboard.Stop(ProgressBar);
+ isProgressBarStoryboardPaused = true;
+ }
+ else if (_viewModel.MainWindowVisibility == Visibility.Visible &&
+ isProgressBarStoryboardPaused)
+ {
+ _progressBarStoryboard.Begin(ProgressBar, true);
+ isProgressBarStoryboardPaused = false;
+ }
+ }, System.Windows.Threading.DispatcherPriority.Render);
+
+ break;
+ }
case nameof(MainViewModel.QueryTextCursorMovedToEnd):
if (_viewModel.QueryTextCursorMovedToEnd)
{
@@ -230,10 +229,10 @@ private void OnPreviewMouseButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender != null && e.OriginalSource != null)
{
- var r = (ResultListBox) sender;
- var d = (DependencyObject) e.OriginalSource;
+ var r = (ResultListBox)sender;
+ var d = (DependencyObject)e.OriginalSource;
var item = ItemsControl.ContainerFromElement(r, d) as ListBoxItem;
- var result = (ResultViewModel) item?.DataContext;
+ var result = (ResultViewModel)item?.DataContext;
if (result != null)
{
if (e.ChangedButton == MouseButton.Left)
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index 478e114f9ff..38168a66c92 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -38,7 +38,7 @@
-
+
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
index a989327be26..b23931fcf78 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml
@@ -10,6 +10,10 @@
Deletion successful
Successfully deleted the {0}
Assigning the global action keyword could bring up too many results during search. Please choose a specific action keyword
+ The required service for Windows Index Search does not appear to be running
+ To fix this, start the Windows Search service. Select here to remove this warning
+ The warning message has been switched off. As an alternative for searching files and folders, would you like to install Everything plugin?{0}{0}Select 'Yes' to install Everything plugin, or 'No' to return
+ Explorer Alternative
Delete
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml
new file mode 100644
index 00000000000..cab8520bca1
--- /dev/null
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml
@@ -0,0 +1,66 @@
+
+
+
+ Najprv vyberte položku
+ Vyberte odkaz na priečinok
+ Naozaj chcete odstrániť {0}?
+ Naozaj chcete natrvalo odstrániť túto položku {0}?
+ Odstránenie bolo úspešné
+ Úspešne odstránené {0}
+ Priradenie globálnej skratky akcie by mohlo počas vyhľadávania poskytnúť príliš veľa výsledkov. Vyberte si konkrétne kľúčové slovo akcie
+ Zdá sa, že požadovaná služba Windows Index Search nie je spustená
+ Ak to chcete opraviť, spustite službu Windows Search. Ak chcete odstrániť toto upozornenie, kliknite sem
+ Upozornenie bolo vypnuté. Chceli by ste ako alternatívu na vyhľadávanie súborov a priečinkov nainštalovať plugin Everything?{0}{0}Ak chcete nainštalovať plugin Everything, zvoľte 'Áno', pre návrat zvoľte 'Nie'
+ Alternatíva pre Explorer
+
+
+ Odstrániť
+ Upraviť
+ Pridať
+ Upraviť skratku akcie
+ Odkazy Rýchleho prístupu
+ Vylúčené umiestnenia indexovania
+ Možnosti indexovania
+ Vyhľadávanie:
+ Vyhľadávanie umiestnenia:
+ Vyhľadávanie obsahu súborov:
+ Vyhľadávanie v indexe:
+ Aktuálna skratka:
+ Hotovo
+ Povolené
+ Ak je vypnuté, Flow túto možnosť vyhľadávania nevykoná a následne sa vráti späť na "*", aby sa uvoľnila skratka akcie.
+
+
+ Explorer
+ Vyhľadáva a spravuje súbory a priečinky. Explorer používa indexovanie vyhľadávania vo Windowse
+
+
+ Kopírovať cestu
+ Kopírovať
+ Odstrániť
+ Umiestnenie:
+ Odstrániť vybrané
+ Spustiť ako iný používateľ
+ Spustí vybranú položku ako používateľ s iným kontom
+ Otvoriť umiestnenie priečinka
+ Otvorí umiestnenie, ktoré obsahuje súbor alebo priečinok
+ Otvoriť editorom:
+ Vylúčiť položku a jej podpriečinky z indexu vyhľadávania
+ Vylúčiť z indexu vyhľadávania
+ Otvoriť možnosti vyhľadávania vo Windowse
+ Správa indexovaných súborov a priečinkov
+ Nepodarilo sa otvoriť možnosti indexu vyhľadávania
+ Pridať do Rýchleho prístupu
+ Pridať tento {0} do Rýchleho prístupu
+ Úspešne pridané
+ Úspešne pridané do Rýchleho prístupu
+ Úspešne odstránené
+ Úspešne odstránené z Rýchleho prístupu
+ Pridať do Rýchleho prístupu, aby ho bolo možné otvoriť pomocou skratky akcie pluginu Explorer
+ Odstráni z Rýchleho prístupu
+ Odstrániť z Rýchleho prístupu
+ Odstráni {0} z Rýchleho prístupu
+
+
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 2aa389f8950..9995f45d380 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -12,14 +12,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search
{
public class SearchManager
{
- private readonly PluginInitContext context;
+ internal static PluginInitContext Context;
- private readonly Settings settings;
+ internal static Settings Settings;
public SearchManager(Settings settings, PluginInitContext context)
{
- this.context = context;
- this.settings = settings;
+ Context = context;
+ Settings = settings;
}
private class PathEqualityComparator : IEqualityComparer
@@ -71,14 +71,14 @@ private bool ActionKeywordMatch(Query query, Settings.ActionKeyword allowedActio
return allowedActionKeyword switch
{
- Settings.ActionKeyword.SearchActionKeyword => settings.SearchActionKeywordEnabled &&
- keyword == settings.SearchActionKeyword,
- Settings.ActionKeyword.PathSearchActionKeyword => settings.PathSearchKeywordEnabled &&
- keyword == settings.PathSearchActionKeyword,
+ Settings.ActionKeyword.SearchActionKeyword => Settings.SearchActionKeywordEnabled &&
+ keyword == Settings.SearchActionKeyword,
+ Settings.ActionKeyword.PathSearchActionKeyword => Settings.PathSearchKeywordEnabled &&
+ keyword == Settings.PathSearchActionKeyword,
Settings.ActionKeyword.FileContentSearchActionKeyword => keyword ==
- settings.FileContentSearchActionKeyword,
- Settings.ActionKeyword.IndexSearchActionKeyword => settings.IndexOnlySearchKeywordEnabled &&
- keyword == settings.IndexSearchActionKeyword
+ Settings.FileContentSearchActionKeyword,
+ Settings.ActionKeyword.IndexSearchActionKeyword => Settings.IndexOnlySearchKeywordEnabled &&
+ keyword == Settings.IndexSearchActionKeyword
};
}
@@ -88,18 +88,18 @@ public async Task> PathSearchAsync(Query query, CancellationToken t
// This allows the user to type the assigned action keyword and only see the list of quick folder links
if (string.IsNullOrEmpty(query.Search))
- return QuickAccess.AccessLinkListAll(query, settings.QuickAccessLinks);
+ return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks);
var results = new HashSet(PathEqualityComparator.Instance);
- var quickaccessLinks = QuickAccess.AccessLinkListMatched(query, settings.QuickAccessLinks);
+ var quickaccessLinks = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks);
results.UnionWith(quickaccessLinks);
var isEnvironmentVariable = EnvironmentVariables.IsEnvironmentVariableSearch(querySearch);
if (isEnvironmentVariable)
- return EnvironmentVariables.GetEnvironmentStringPathSuggestions(querySearch, query, context);
+ return EnvironmentVariables.GetEnvironmentStringPathSuggestions(querySearch, query, Context);
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
var isEnvironmentVariablePath = querySearch[1..].Contains("%\\");
@@ -136,22 +136,23 @@ public async Task> PathSearchAsync(Query query, CancellationToken t
private async Task> WindowsIndexFileContentSearchAsync(Query query, string querySearchString,
CancellationToken token)
{
- var queryConstructor = new QueryConstructor(settings);
+ var queryConstructor = new QueryConstructor(Settings);
if (string.IsNullOrEmpty(querySearchString))
return new List();
- return await IndexSearch.WindowsIndexSearchAsync(querySearchString,
- queryConstructor.CreateQueryHelper().ConnectionString,
+ return await IndexSearch.WindowsIndexSearchAsync(
+ querySearchString,
+ queryConstructor.CreateQueryHelper(),
queryConstructor.QueryForFileContentSearch,
- settings.IndexSearchExcludedSubdirectoryPaths,
+ Settings.IndexSearchExcludedSubdirectoryPaths,
query,
token).ConfigureAwait(false);
}
public bool IsFileContentSearch(string actionKeyword)
{
- return actionKeyword == settings.FileContentSearchActionKeyword;
+ return actionKeyword == Settings.FileContentSearchActionKeyword;
}
private List DirectoryInfoClassSearch(Query query, string querySearch, CancellationToken token)
@@ -176,12 +177,13 @@ public async Task> TopLevelDirectorySearchBehaviourAsync(
private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString,
CancellationToken token)
{
- var queryConstructor = new QueryConstructor(settings);
+ var queryConstructor = new QueryConstructor(Settings);
- return await IndexSearch.WindowsIndexSearchAsync(querySearchString,
- queryConstructor.CreateQueryHelper().ConnectionString,
+ return await IndexSearch.WindowsIndexSearchAsync(
+ querySearchString,
+ queryConstructor.CreateQueryHelper(),
queryConstructor.QueryForAllFilesAndFolders,
- settings.IndexSearchExcludedSubdirectoryPaths,
+ Settings.IndexSearchExcludedSubdirectoryPaths,
query,
token).ConfigureAwait(false);
}
@@ -189,12 +191,13 @@ private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query qu
private async Task> WindowsIndexTopLevelFolderSearchAsync(Query query, string path,
CancellationToken token)
{
- var queryConstructor = new QueryConstructor(settings);
+ var queryConstructor = new QueryConstructor(Settings);
- return await IndexSearch.WindowsIndexSearchAsync(path,
- queryConstructor.CreateQueryHelper().ConnectionString,
+ return await IndexSearch.WindowsIndexSearchAsync(
+ path,
+ queryConstructor.CreateQueryHelper(),
queryConstructor.QueryForTopLevelDirectorySearch,
- settings.IndexSearchExcludedSubdirectoryPaths,
+ Settings.IndexSearchExcludedSubdirectoryPaths,
query,
token).ConfigureAwait(false);
}
@@ -203,10 +206,10 @@ private bool UseWindowsIndexForDirectorySearch(string locationPath)
{
var pathToDirectory = FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath);
- if (!settings.UseWindowsIndexForDirectorySearch)
+ if (!Settings.UseWindowsIndexForDirectorySearch)
return false;
- if (settings.IndexSearchExcludedSubdirectoryPaths
+ if (Settings.IndexSearchExcludedSubdirectoryPaths
.Any(x => FilesFolders.ReturnPreviousDirectoryIfIncompleteString(pathToDirectory)
.StartsWith(x.Path, StringComparison.OrdinalIgnoreCase)))
return false;
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs
index cfb564924c0..010a19b583a 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IndexSearch.cs
@@ -5,9 +5,11 @@
using System.Collections.Generic;
using System.Data.OleDb;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
+using System.Windows;
namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
@@ -84,22 +86,36 @@ internal static async Task> ExecuteWindowsIndexSearchAsync(string i
return results;
}
- internal async static Task> WindowsIndexSearchAsync(string searchString, string connectionString,
- Func constructQuery,
- List exclusionList,
- Query query,
- CancellationToken token)
+ internal async static Task> WindowsIndexSearchAsync(
+ string searchString,
+ CSearchQueryHelper queryHelper,
+ Func constructQuery,
+ List exclusionList,
+ Query query,
+ CancellationToken token)
{
var regexMatch = Regex.Match(searchString, reservedStringPattern);
if (regexMatch.Success)
return new List();
+
+ try
+ {
+ var constructedQuery = constructQuery(searchString);
- var constructedQuery = constructQuery(searchString);
- return RemoveResultsInExclusionList(
- await ExecuteWindowsIndexSearchAsync(constructedQuery, connectionString, query, token).ConfigureAwait(false),
+ return RemoveResultsInExclusionList(
+ await ExecuteWindowsIndexSearchAsync(constructedQuery, queryHelper.ConnectionString, query, token).ConfigureAwait(false),
exclusionList,
token);
+ }
+ catch (COMException)
+ {
+ // Occurs because the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin
+ if (!SearchManager.Settings.WarnWindowsSearchServiceOff)
+ return new List();
+
+ return ResultForWindexSearchOff(query.RawQuery);
+ }
}
private static List RemoveResultsInExclusionList(List results, List exclusionList, CancellationToken token)
@@ -137,9 +153,66 @@ private static List RemoveResultsInExclusionList(List results, L
internal static bool PathIsIndexed(string path)
{
- var csm = new CSearchManager();
- var indexManager = csm.GetCatalog("SystemIndex").GetCrawlScopeManager();
- return indexManager.IncludedInCrawlScope(path) > 0;
+ try
+ {
+ var csm = new CSearchManager();
+ var indexManager = csm.GetCatalog("SystemIndex").GetCrawlScopeManager();
+ return indexManager.IncludedInCrawlScope(path) > 0;
+ }
+ catch(COMException)
+ {
+ // Occurs because the Windows Indexing (WSearch) is turned off in services and unable to be used by Explorer plugin
+ return false;
+ }
+ }
+
+ private static List ResultForWindexSearchOff(string rawQuery)
+ {
+ var api = SearchManager.Context.API;
+
+ return new List
+ {
+ new Result
+ {
+ Title = api.GetTranslation("plugin_explorer_windowsSearchServiceNotRunning"),
+ SubTitle = api.GetTranslation("plugin_explorer_windowsSearchServiceFix"),
+ Action = c =>
+ {
+ SearchManager.Settings.WarnWindowsSearchServiceOff = false;
+
+ var pluginsManagerPlugin= api.GetAllPlugins().FirstOrDefault(x => x.Metadata.ID == "9f8f9b14-2518-4907-b211-35ab6290dee7");
+
+ var actionKeywordCount = pluginsManagerPlugin.Metadata.ActionKeywords.Count;
+
+ if (actionKeywordCount > 1)
+ LogException("PluginsManager's action keyword has increased to more than 1, this does not allow for determining the " +
+ "right action keyword. Explorer's code for managing Windows Search service not running exception needs to be updated",
+ new InvalidOperationException());
+
+ if (MessageBox.Show(string.Format(api.GetTranslation("plugin_explorer_alternative"), Environment.NewLine),
+ api.GetTranslation("plugin_explorer_alternative_title"),
+ MessageBoxButton.YesNo) == MessageBoxResult.Yes
+ && actionKeywordCount == 1)
+ {
+ api.ChangeQuery(string.Format("{0} install everything", pluginsManagerPlugin.Metadata.ActionKeywords[0]));
+ }
+ else
+ {
+ // Clears the warning message because same query string will not alter the displayed result list
+ api.ChangeQuery(string.Empty);
+
+ api.ChangeQuery(rawQuery);
+ }
+
+ var mainWindow = Application.Current.MainWindow;
+ mainWindow.Visibility = Visibility.Visible;
+ mainWindow.Focus();
+
+ return false;
+ },
+ IcoPath = Constants.ExplorerIconImagePath
+ }
+ };
}
private static void LogException(string message, Exception e)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
index 13f938dea1c..88656a40172 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
@@ -1,4 +1,4 @@
-using Flow.Launcher.Plugin.Explorer.Search;
+using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using System;
@@ -33,6 +33,8 @@ public class Settings
public bool IndexOnlySearchKeywordEnabled { get; set; }
+ public bool WarnWindowsSearchServiceOff { get; set; } = true;
+
internal enum ActionKeyword
{
SearchActionKeyword,
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json
index 5bd49949f48..59a31ec139c 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json
@@ -9,7 +9,7 @@
"Name": "Explorer",
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
"Author": "Jeremy Wu",
- "Version": "1.8.0",
+ "Version": "1.8.2",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs
index 90ce19db44a..364216778bd 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs
@@ -17,7 +17,8 @@ public ContextMenu(PluginInitContext context)
public List LoadContextMenus(Result selectedResult)
{
- var pluginManifestInfo = selectedResult.ContextData as UserPlugin;
+ if(selectedResult.ContextData is not UserPlugin pluginManifestInfo)
+ return new List();
return new List
{
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
index 1aa39469b11..995ac0fedfe 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
@@ -269,7 +269,13 @@ await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath)
}
return false;
- }
+ },
+ ContextData =
+ new UserPlugin
+ {
+ Website = x.PluginNewUserPlugin.Website,
+ UrlSourceCode = x.PluginNewUserPlugin.UrlSourceCode
+ }
});
return Search(results, uninstallSearch);
diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
index 2555466860f..fa916a29d03 100644
--- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
+++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
@@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
- "Version": "1.8.3",
+ "Version": "1.8.4",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
diff --git a/README.md b/README.md
index e9c7e33606f..e89558d5705 100644
--- a/README.md
+++ b/README.md
@@ -49,8 +49,8 @@ Flow Launcher. Dedicated to make your workflow flow more seamlessly. Aimed at be
### Installation
-| [Windows 7 and up installer](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest) | `WinGet install "Flow Launcher"` |
-| -------------------------------------------------------------------------------------------- | -------------------------------- |
+| [Windows 7 and up installer](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest) | [Portable](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest/download/Flow-Launcher-Portable.zip) | `WinGet 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.
diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1
index 093f92768b4..b573b984b64 100644
--- a/Scripts/post_build.ps1
+++ b/Scripts/post_build.ps1
@@ -107,6 +107,13 @@ function Publish-Self-Contained ($p) {
dotnet publish -c Release $csproj /p:PublishProfile=$profile
}
+function Publish-Portable ($outputLocation, $version) {
+
+ & $outputLocation\Flow-Launcher-v$v.exe --silent | Out-Null
+ mkdir "$env:LocalAppData\FlowLauncher\app-$version\UserData"
+ Compress-Archive -Path $env:LocalAppData\FlowLauncher -DestinationPath $outputLocation\Flow-Launcher-Portable.zip
+}
+
function Main {
$p = Build-Path
$v = Build-Version
@@ -123,6 +130,8 @@ function Main {
$o = "$p\Output\Packages"
Validate-Directory $o
Pack-Squirrel-Installer $p $v $o
+
+ Publish-Portable $o $v
}
}
diff --git a/appveyor.yml b/appveyor.yml
index 9961a9111e8..191ee480332 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: '1.8.0.{build}'
+version: '1.8.1.{build}'
init:
- ps: |
@@ -36,6 +36,8 @@ artifacts:
name: Plugin nupkg
- path: 'Output\Packages\Flow-Launcher-*.exe'
name: Squirrel Installer
+- path: Output\Packages\Flow-Launcher-Portable.zip
+ name: Portable Version
- path: 'Output\Packages\FlowLauncher-*-full.nupkg'
name: Squirrel nupkg
- path: 'Output\Packages\RELEASES'
@@ -47,13 +49,13 @@ deploy:
api_key:
secure: n80IeWR3pN81p0w4uXq4mO0TdTXoJSHHFL+yTB9YBJ0Wni2DjZGYwOFdaWzW4hRi
on:
- branch: master
+ APPVEYOR_REPO_TAG: true
- provider: GitHub
release: v$(flowVersion)
auth_token:
secure: ij4UeXUYQBDJxn2YRAAhUOjklOGVKDB87Hn5J8tKIzj13yatoI7sLM666QDQFEgv
- artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES
+ artifact: Squirrel Installer, Portable Version, Squirrel nupkg, Squirrel RELEASES
draft: true
force_update: true
on:
@@ -63,7 +65,19 @@ deploy:
release: v$(flowVersion)
auth_token:
secure: ij4UeXUYQBDJxn2YRAAhUOjklOGVKDB87Hn5J8tKIzj13yatoI7sLM666QDQFEgv
- artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES
+ artifact: Squirrel Installer, Portable Version, Squirrel nupkg, Squirrel RELEASES
force_update: true
on:
APPVEYOR_REPO_TAG: true
+
+environment:
+ winget_token:
+ secure: HKfVT2FYZITAG0qqMCePYhIem5a/gzvAgYDSlr6RlXfGmeBUOANUtgJ9X6fNroxN
+
+on_success:
+ - ps: |
+ if ($env:APPVEYOR_REPO_BRANCH -eq "master" -and $env:APPVEYOR_REPO_TAG -eq "true")
+ {
+ iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
+ .\wingetcreate.exe update Flow-Launcher.Flow-Launcher -s true -u https://github.com/Flow-Launcher/Flow.Launcher/releases/download/v$env:flowVersion/Flow-Launcher-v$env:flowVersion.exe -v $env:flowVersion -t $env:winget_token
+ }