Skip to content

Commit ea65c8f

Browse files
authored
Merge pull request #2082 from VictoriousRaptor/quicklook
Add external preview (QuickLook) support
2 parents 3f3612a + 7f31fef commit ea65c8f

File tree

9 files changed

+300
-66
lines changed

9 files changed

+300
-66
lines changed

.github/actions/spelling/expect.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ Português
9898
Português (Brasil)
9999
Italiano
100100
Slovenský
101+
quicklook
101102
Tiếng Việt
102103
Droplex
103104
Preinstalled

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Flow.Launcher.Core.ExternalPlugins;
1+
using Flow.Launcher.Core.ExternalPlugins;
22
using System;
33
using System.Collections.Concurrent;
44
using System.Collections.Generic;
@@ -90,6 +90,48 @@ public static async Task ReloadDataAsync()
9090
}).ToArray());
9191
}
9292

93+
public static async Task OpenExternalPreviewAsync(string path, bool sendFailToast = true)
94+
{
95+
await Task.WhenAll(AllPlugins.Select(plugin => plugin.Plugin switch
96+
{
97+
IAsyncExternalPreview p => p.OpenPreviewAsync(path, sendFailToast),
98+
_ => Task.CompletedTask,
99+
}).ToArray());
100+
}
101+
102+
public static async Task CloseExternalPreviewAsync()
103+
{
104+
await Task.WhenAll(AllPlugins.Select(plugin => plugin.Plugin switch
105+
{
106+
IAsyncExternalPreview p => p.ClosePreviewAsync(),
107+
_ => Task.CompletedTask,
108+
}).ToArray());
109+
}
110+
111+
public static async Task SwitchExternalPreviewAsync(string path, bool sendFailToast = true)
112+
{
113+
await Task.WhenAll(AllPlugins.Select(plugin => plugin.Plugin switch
114+
{
115+
IAsyncExternalPreview p => p.SwitchPreviewAsync(path, sendFailToast),
116+
_ => Task.CompletedTask,
117+
}).ToArray());
118+
}
119+
120+
public static bool UseExternalPreview()
121+
{
122+
return GetPluginsForInterface<IAsyncExternalPreview>().Any(x => !x.Metadata.Disabled);
123+
}
124+
125+
public static bool AllowAlwaysPreview()
126+
{
127+
var plugin = GetPluginsForInterface<IAsyncExternalPreview>().FirstOrDefault(x => !x.Metadata.Disabled);
128+
129+
if (plugin is null)
130+
return false;
131+
132+
return ((IAsyncExternalPreview)plugin.Plugin).AllowAlwaysPreview();
133+
}
134+
93135
static PluginManager()
94136
{
95137
// validate user directory

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ public CustomBrowserViewModel CustomBrowser
185185
/// when false Alphabet static service will always return empty results
186186
/// </summary>
187187
public bool ShouldUsePinyin { get; set; } = false;
188+
188189
public bool AlwaysPreview { get; set; } = false;
190+
189191
public bool AlwaysStartEn { get; set; } = false;
190192

191193
private SearchPrecisionScore _querySearchPrecision = SearchPrecisionScore.Regular;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Threading.Tasks;
2+
3+
namespace Flow.Launcher.Plugin
4+
{
5+
/// <summary>
6+
/// This interface is for plugins that wish to provide file preview (external preview)
7+
/// via a third party app instead of the default preview.
8+
/// </summary>
9+
public interface IAsyncExternalPreview : IFeatures
10+
{
11+
/// <summary>
12+
/// Method for opening/showing the preview.
13+
/// </summary>
14+
/// <param name="path">The file path to open the preview for</param>
15+
/// <param name="sendFailToast">Whether to send a toast message notification on failure for the user</param>
16+
public Task OpenPreviewAsync(string path, bool sendFailToast = true);
17+
18+
/// <summary>
19+
/// Method for closing/hiding the preview.
20+
/// </summary>
21+
public Task ClosePreviewAsync();
22+
23+
/// <summary>
24+
/// Method for switching the preview to the next file result.
25+
/// This requires the external preview be already open/showing
26+
/// </summary>
27+
/// <param name="path">The file path to switch the preview for</param>
28+
/// <param name="sendFailToast">Whether to send a toast message notification on failure for the user</param>
29+
public Task SwitchPreviewAsync(string path, bool sendFailToast = true);
30+
31+
/// <summary>
32+
/// Allows the preview plugin to override the AlwaysPreview setting. Typically useful if plugin's preview does not
33+
/// fully work well with being shown together when the query window appears with results.
34+
/// When AlwaysPreview setting is on and this is set to false, the preview will not be shown when query
35+
/// window appears with results, instead the internal preview will be shown.
36+
/// </summary>
37+
/// <returns></returns>
38+
public bool AllowAlwaysPreview();
39+
}
40+
}

Flow.Launcher.Plugin/Result.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,25 +270,30 @@ public record PreviewInfo
270270
/// <summary>
271271
/// Full image used for preview panel
272272
/// </summary>
273-
public string PreviewImagePath { get; set; }
273+
public string PreviewImagePath { get; set; } = null;
274274

275275
/// <summary>
276276
/// Determines if the preview image should occupy the full width of the preview panel.
277277
/// </summary>
278-
public bool IsMedia { get; set; }
278+
public bool IsMedia { get; set; } = false;
279279

280280
/// <summary>
281281
/// Result description text that is shown at the bottom of the preview panel.
282282
/// </summary>
283283
/// <remarks>
284284
/// When a value is not set, the <see cref="SubTitle"/> will be used.
285285
/// </remarks>
286-
public string Description { get; set; }
286+
public string Description { get; set; } = null;
287287

288288
/// <summary>
289289
/// Delegate to get the preview panel's image
290290
/// </summary>
291-
public IconDelegate PreviewDelegate { get; set; }
291+
public IconDelegate PreviewDelegate { get; set; } = null;
292+
293+
/// <summary>
294+
/// File path of the result. For third-party programs providing external preview.
295+
/// </summary>
296+
public string FilePath { get; set; } = null;
292297

293298
/// <summary>
294299
/// Default instance of <see cref="PreviewInfo"/>
@@ -299,6 +304,7 @@ public record PreviewInfo
299304
Description = null,
300305
IsMedia = false,
301306
PreviewDelegate = null,
307+
FilePath = null,
302308
};
303309
}
304310
}

Flow.Launcher/MainWindow.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@
427427
VerticalAlignment="Stretch"
428428
Background="Transparent"
429429
ShowsPreview="True"
430-
Visibility="{Binding PreviewVisible, Converter={StaticResource BoolToVisibilityConverter}}">
430+
Visibility="{Binding InternalPreviewVisible, Converter={StaticResource BoolToVisibilityConverter}}">
431431
<GridSplitter.Template>
432432
<ControlTemplate TargetType="{x:Type GridSplitter}">
433433
<Border Style="{DynamicResource PreviewBorderStyle}" />
@@ -439,7 +439,7 @@
439439
Grid.Column="2"
440440
VerticalAlignment="Stretch"
441441
Style="{DynamicResource PreviewArea}"
442-
Visibility="{Binding PreviewVisible, Converter={StaticResource BoolToVisibilityConverter}}">
442+
Visibility="{Binding InternalPreviewVisible, Converter={StaticResource BoolToVisibilityConverter}}">
443443
<Border
444444
MinHeight="380"
445445
d:DataContext="{d:DesignInstance vm:ResultViewModel}"

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ private async void OnDeactivated(object sender, EventArgs e)
630630
if (_settings.UseAnimation)
631631
await Task.Delay(100);
632632

633-
if (_settings.HideWhenDeactivated)
633+
if (_settings.HideWhenDeactivated && !_viewModel.ExternalPreviewVisible)
634634
{
635635
_viewModel.Hide();
636636
}

0 commit comments

Comments
 (0)