Skip to content

Commit 620ed4a

Browse files
authored
Merge pull request #604 from Flow-Launcher/dev
Release 1.8.1
2 parents aeba056 + 309ee29 commit 620ed4a

File tree

19 files changed

+348
-110
lines changed

19 files changed

+348
-110
lines changed

Flow.Launcher.Core/Flow.Launcher.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
<ItemGroup>
5656
<PackageReference Include="Droplex" Version="1.3.1" />
5757
<PackageReference Include="FSharp.Core" Version="4.7.1" />
58+
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="2.1.3" />
5859
<PackageReference Include="squirrel.windows" Version="1.5.2" />
5960
</ItemGroup>
6061

Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
using System.Windows.Forms;
1212
using Flow.Launcher.Infrastructure.Logger;
1313
using Flow.Launcher.Plugin;
14+
using ICSharpCode.SharpZipLib.Zip;
1415
using JetBrains.Annotations;
16+
using Microsoft.IO;
1517

1618
namespace Flow.Launcher.Core.Plugin
1719
{
@@ -33,9 +35,11 @@ internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu
3335
protected abstract string ExecuteCallback(JsonRPCRequestModel rpcRequest);
3436
protected abstract string ExecuteContextMenu(Result selectedResult);
3537

38+
private static readonly RecyclableMemoryStreamManager BufferManager = new();
39+
3640
public List<Result> LoadContextMenus(Result selectedResult)
3741
{
38-
string output = ExecuteContextMenu(selectedResult);
42+
var output = ExecuteContextMenu(selectedResult);
3943
try
4044
{
4145
return DeserializedResult(output);
@@ -61,12 +65,23 @@ private async Task<List<Result>> DeserializedResultAsync(Stream output)
6165
{
6266
if (output == Stream.Null) return null;
6367

64-
var queryResponseModel = await
65-
JsonSerializer.DeserializeAsync<JsonRPCQueryResponseModel>(output, options);
68+
try
69+
{
70+
var queryResponseModel =
71+
await JsonSerializer.DeserializeAsync<JsonRPCQueryResponseModel>(output, options);
6672

67-
await output.DisposeAsync();
68-
69-
return ParseResults(queryResponseModel);
73+
return ParseResults(queryResponseModel);
74+
}
75+
catch (JsonException e)
76+
{
77+
Log.Exception(GetType().FullName, "Unexpected Json Input", e);
78+
}
79+
finally
80+
{
81+
await output.DisposeAsync();
82+
}
83+
84+
return null;
7085
}
7186

7287
private List<Result> DeserializedResult(string output)
@@ -81,15 +96,14 @@ private List<Result> DeserializedResult(string output)
8196

8297
private List<Result> ParseResults(JsonRPCQueryResponseModel queryResponseModel)
8398
{
84-
var results = new List<Result>();
8599
if (queryResponseModel.Result == null) return null;
86100

87101
if (!string.IsNullOrEmpty(queryResponseModel.DebugMessage))
88102
{
89103
context.API.ShowMsg(queryResponseModel.DebugMessage);
90104
}
91105

92-
foreach (JsonRPCResult result in queryResponseModel.Result)
106+
foreach (var result in queryResponseModel.Result)
93107
{
94108
result.Action = c =>
95109
{
@@ -114,7 +128,8 @@ private List<Result> ParseResults(JsonRPCQueryResponseModel queryResponseModel)
114128
return !result.JsonRPCAction.DontHideAfterAction;
115129
}
116130

117-
var jsonRpcRequestModel = JsonSerializer.Deserialize<JsonRPCRequestModel>(actionResponse, options);
131+
var jsonRpcRequestModel =
132+
JsonSerializer.Deserialize<JsonRPCRequestModel>(actionResponse, options);
118133

119134
if (jsonRpcRequestModel?.Method?.StartsWith("Flow.Launcher.") ?? false)
120135
{
@@ -125,9 +140,12 @@ private List<Result> ParseResults(JsonRPCQueryResponseModel queryResponseModel)
125140

126141
return !result.JsonRPCAction.DontHideAfterAction;
127142
};
128-
results.Add(result);
129143
}
130144

145+
var results = new List<Result>();
146+
147+
results.AddRange(queryResponseModel.Result);
148+
131149
return results;
132150
}
133151

@@ -217,16 +235,42 @@ protected string Execute(ProcessStartInfo startInfo)
217235

218236
protected async Task<Stream> ExecuteAsync(ProcessStartInfo startInfo, CancellationToken token = default)
219237
{
238+
Process process = null;
239+
bool disposed = false;
220240
try
221241
{
222-
using var process = Process.Start(startInfo);
242+
process = Process.Start(startInfo);
223243
if (process == null)
224244
{
225245
Log.Error("|JsonRPCPlugin.ExecuteAsync|Can't start new process");
226246
return Stream.Null;
227247
}
228248

229-
var result = process.StandardOutput.BaseStream;
249+
await using var source = process.StandardOutput.BaseStream;
250+
251+
var buffer = BufferManager.GetStream();
252+
253+
token.Register(() =>
254+
{
255+
// ReSharper disable once AccessToModifiedClosure
256+
// Manually Check whether disposed
257+
if (!disposed && !process.HasExited)
258+
process.Kill();
259+
});
260+
261+
try
262+
{
263+
// token expire won't instantly trigger the exception,
264+
// manually kill process at before
265+
await source.CopyToAsync(buffer, token);
266+
}
267+
catch (OperationCanceledException)
268+
{
269+
await buffer.DisposeAsync();
270+
return Stream.Null;
271+
}
272+
273+
buffer.Seek(0, SeekOrigin.Begin);
230274

231275
token.ThrowIfCancellationRequested();
232276

@@ -245,7 +289,7 @@ protected async Task<Stream> ExecuteAsync(ProcessStartInfo startInfo, Cancellati
245289
return Stream.Null;
246290
}
247291

248-
return result;
292+
return buffer;
249293
}
250294
catch (Exception e)
251295
{
@@ -254,15 +298,24 @@ protected async Task<Stream> ExecuteAsync(ProcessStartInfo startInfo, Cancellati
254298
e);
255299
return Stream.Null;
256300
}
301+
finally
302+
{
303+
process?.Dispose();
304+
disposed = true;
305+
}
257306
}
258307

259308
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
260309
{
261-
var output = await ExecuteQueryAsync(query, token);
262310
try
263311
{
312+
var output = await ExecuteQueryAsync(query, token);
264313
return await DeserializedResultAsync(output);
265314
}
315+
catch (OperationCanceledException)
316+
{
317+
return null;
318+
}
266319
catch (Exception e)
267320
{
268321
Log.Exception($"|JsonRPCPlugin.Query|Exception when query <{query}>", e);

Flow.Launcher/App.xaml.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
7575

7676
Http.API = API;
7777
Http.Proxy = _settings.Proxy;
78-
78+
7979
await PluginManager.InitializePlugins(API);
8080
var window = new MainWindow(_settings, _mainVM);
8181

@@ -99,6 +99,8 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () =>
9999
AutoStartup();
100100
AutoUpdates();
101101

102+
API.SaveAppAllSettings();
103+
102104
_mainVM.MainWindowVisibility = _settings.HideOnStartup ? Visibility.Hidden : Visibility.Visible;
103105
Log.Info("|App.OnStartup|End Flow Launcher startup ---------------------------------------------------- ");
104106
});

Flow.Launcher/Languages/sk.xaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@
3131
<system:String x:Key="ignoreHotkeysOnFullscreen">Ignorovať klávesové skratky v režime na celú obrazovku</system:String>
3232
<system:String x:Key="pythonDirectory">Priečinok s Pythonom</system:String>
3333
<system:String x:Key="autoUpdates">Automatická aktualizácia</system:String>
34+
<system:String x:Key="autoHideScrollBar">Automaticky skryť posuvník</system:String>
35+
<system:String x:Key="autoHideScrollBarToolTip">Automaticky skrývať posuvník v okne nastavení a zobraziť ho, keď naň prejdete myšou</system:String>
3436
<system:String x:Key="selectPythonDirectory">Vybrať</system:String>
3537
<system:String x:Key="hideOnStartup">Schovať Flow Launcher po spustení</system:String>
3638
<system:String x:Key="hideNotifyIcon">Schovať ikonu z oblasti oznámení</system:String>
3739
<system:String x:Key="querySearchPrecision">Presnosť vyhľadávania</system:String>
3840
<system:String x:Key="ShouldUsePinyin">Použiť Pinyin</system:String>
3941
<system:String x:Key="ShouldUsePinyinToolTip">Umožňuje vyhľadávanie pomocou Pinyin. Pinyin je štandardný systém romanizovaného pravopisu pre transliteráciu čínštiny</system:String>
42+
<system:String x:Key="shadowEffectNotAllowed">Efekt tieňa nie je povolený, kým má aktuálny motív povolený efekt rozostrenia</system:String>
4043

4144
<!--Setting Plugin-->
4245
<system:String x:Key="plugin">Plugin</system:String>
@@ -48,6 +51,7 @@
4851
<system:String x:Key="newActionKeyword">Nová akcia skratky:</system:String>
4952
<system:String x:Key="currentPriority">Aktuálna priorita:</system:String>
5053
<system:String x:Key="newPriority">Nová priorita:</system:String>
54+
<system:String x:Key="priority">Priorita:</system:String>
5155
<system:String x:Key="pluginDirectory">Priečinok s pluginmi</system:String>
5256
<system:String x:Key="author">Autor</system:String>
5357
<system:String x:Key="plugin_init_time">Príprava:</system:String>
@@ -70,6 +74,7 @@
7074
<system:String x:Key="openResultModifiers">Modifikáčné klávesy na otvorenie výsledkov</system:String>
7175
<system:String x:Key="showOpenResultHotkey">Zobraziť klávesovú skratku</system:String>
7276
<system:String x:Key="customQueryHotkey">Vlastná klávesová skratka na vyhľadávanie</system:String>
77+
<system:String x:Key="customQuery">Dopyt</system:String>
7378
<system:String x:Key="delete">Odstrániť</system:String>
7479
<system:String x:Key="edit">Upraviť</system:String>
7580
<system:String x:Key="add">Pridať</system:String>

Flow.Launcher/MainWindow.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Window x:Class="Flow.Launcher.MainWindow"
1+
<Window x:Class="Flow.Launcher.MainWindow"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:flowlauncher="clr-namespace:Flow.Launcher"
@@ -93,7 +93,7 @@
9393
</ContextMenu>
9494
</TextBox.ContextMenu>
9595
</TextBox>
96-
<svgc:SvgControl Source="{Binding Image}" HorizontalAlignment="Right" Width="48" Height="48"
96+
<svgc:SvgControl Source="{Binding Image}" HorizontalAlignment="Right" Width="42" Height="42"
9797
Background="Transparent"/>
9898
</Grid>
9999
<Line x:Name="ProgressBar" HorizontalAlignment="Right"

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -77,54 +77,53 @@ private void OnLoaded(object sender, RoutedEventArgs _)
7777
switch (e.PropertyName)
7878
{
7979
case nameof(MainViewModel.MainWindowVisibility):
80-
{
81-
if (_viewModel.MainWindowVisibility == Visibility.Visible)
8280
{
83-
Activate();
84-
QueryTextBox.Focus();
85-
UpdatePosition();
86-
_settings.ActivateTimes++;
87-
if (!_viewModel.LastQuerySelected)
81+
if (_viewModel.MainWindowVisibility == Visibility.Visible)
8882
{
89-
QueryTextBox.SelectAll();
90-
_viewModel.LastQuerySelected = true;
83+
Activate();
84+
QueryTextBox.Focus();
85+
UpdatePosition();
86+
_settings.ActivateTimes++;
87+
if (!_viewModel.LastQuerySelected)
88+
{
89+
QueryTextBox.SelectAll();
90+
_viewModel.LastQuerySelected = true;
91+
}
92+
93+
if (_viewModel.ProgressBarVisibility == Visibility.Visible && isProgressBarStoryboardPaused)
94+
{
95+
_progressBarStoryboard.Begin(ProgressBar, true);
96+
isProgressBarStoryboardPaused = false;
97+
}
9198
}
92-
93-
if (_viewModel.ProgressBarVisibility == Visibility.Visible && isProgressBarStoryboardPaused)
99+
else if (!isProgressBarStoryboardPaused)
94100
{
95-
_progressBarStoryboard.Begin(ProgressBar, true);
96-
isProgressBarStoryboardPaused = false;
101+
_progressBarStoryboard.Stop(ProgressBar);
102+
isProgressBarStoryboardPaused = true;
97103
}
98-
}
99104

100-
if (!isProgressBarStoryboardPaused)
101-
{
102-
_progressBarStoryboard.Stop(ProgressBar);
103-
isProgressBarStoryboardPaused = true;
105+
break;
104106
}
105-
106-
break;
107-
}
108107
case nameof(MainViewModel.ProgressBarVisibility):
109-
{
110-
Dispatcher.Invoke(async () =>
111108
{
112-
if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
109+
Dispatcher.Invoke(async () =>
113110
{
114-
await Task.Delay(50);
115-
_progressBarStoryboard.Stop(ProgressBar);
116-
isProgressBarStoryboardPaused = true;
117-
}
118-
else if (_viewModel.MainWindowVisibility == Visibility.Visible &&
119-
isProgressBarStoryboardPaused)
120-
{
121-
_progressBarStoryboard.Begin(ProgressBar, true);
122-
isProgressBarStoryboardPaused = false;
123-
}
124-
}, System.Windows.Threading.DispatcherPriority.Render);
125-
126-
break;
127-
}
111+
if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
112+
{
113+
await Task.Delay(50);
114+
_progressBarStoryboard.Stop(ProgressBar);
115+
isProgressBarStoryboardPaused = true;
116+
}
117+
else if (_viewModel.MainWindowVisibility == Visibility.Visible &&
118+
isProgressBarStoryboardPaused)
119+
{
120+
_progressBarStoryboard.Begin(ProgressBar, true);
121+
isProgressBarStoryboardPaused = false;
122+
}
123+
}, System.Windows.Threading.DispatcherPriority.Render);
124+
125+
break;
126+
}
128127
case nameof(MainViewModel.QueryTextCursorMovedToEnd):
129128
if (_viewModel.QueryTextCursorMovedToEnd)
130129
{
@@ -230,10 +229,10 @@ private void OnPreviewMouseButtonDown(object sender, MouseButtonEventArgs e)
230229
{
231230
if (sender != null && e.OriginalSource != null)
232231
{
233-
var r = (ResultListBox) sender;
234-
var d = (DependencyObject) e.OriginalSource;
232+
var r = (ResultListBox)sender;
233+
var d = (DependencyObject)e.OriginalSource;
235234
var item = ItemsControl.ContainerFromElement(r, d) as ListBoxItem;
236-
var result = (ResultViewModel) item?.DataContext;
235+
var result = (ResultViewModel)item?.DataContext;
237236
if (result != null)
238237
{
239238
if (e.ChangedButton == MouseButton.Left)

Flow.Launcher/SettingWindow.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<TabControl Height="auto" SelectedIndex="0">
3939
<TabItem Header="{DynamicResource general}">
4040
<ScrollViewer ui:ScrollViewerHelper.AutoHideScrollBars="{Binding AutoHideScrollBar, Mode=OneWay}" Margin="60,0,0,0">
41-
<StackPanel Orientation="Vertical" Margin="0,30,0,0">
41+
<StackPanel Orientation="Vertical" Margin="0,30,0,30">
4242
<ui:ToggleSwitch Margin="10" IsOn="{Binding PortableMode}">
4343
<TextBlock Text="{DynamicResource portableMode}" />
4444
</ui:ToggleSwitch>

Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
<system:String x:Key="plugin_explorer_deletefilefoldersuccess">Deletion successful</system:String>
1111
<system:String x:Key="plugin_explorer_deletefilefoldersuccess_detail">Successfully deleted the {0}</system:String>
1212
<system:String x:Key="plugin_explorer_globalActionKeywordInvalid">Assigning the global action keyword could bring up too many results during search. Please choose a specific action keyword</system:String>
13+
<system:String x:Key="plugin_explorer_windowsSearchServiceNotRunning">The required service for Windows Index Search does not appear to be running</system:String>
14+
<system:String x:Key="plugin_explorer_windowsSearchServiceFix">To fix this, start the Windows Search service. Select here to remove this warning</system:String>
15+
<system:String x:Key="plugin_explorer_alternative">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</system:String>
16+
<system:String x:Key="plugin_explorer_alternative_title">Explorer Alternative</system:String>
1317

1418
<!--Controls-->
1519
<system:String x:Key="plugin_explorer_delete">Delete</system:String>

0 commit comments

Comments
 (0)