Skip to content

Commit 9df5363

Browse files
authored
Merge branch 'dev' into net9
2 parents d57eb6c + 79d54d0 commit 9df5363

24 files changed

+300
-153
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ public static class PluginManager
2929
public static readonly HashSet<PluginPair> GlobalPlugins = new();
3030
public static readonly Dictionary<string, PluginPair> NonGlobalPlugins = new();
3131

32-
public static IPublicAPI API { get; private set; } = Ioc.Default.GetRequiredService<IPublicAPI>();
32+
// We should not initialize API in static constructor because it will create another API instance
33+
private static IPublicAPI api = null;
34+
private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService<IPublicAPI>();
3335

3436
private static PluginsSettings Settings;
3537
private static List<PluginMetadata> _metadatas;

Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,17 +323,16 @@ public interface IPublicAPI
323323
public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.OK);
324324

325325
/// <summary>
326-
/// Displays a standardised Flow message box.
327-
/// If there is issue when showing the message box, it will return null.
326+
/// Displays a standardised Flow progress box.
328327
/// </summary>
329-
/// <param name="caption">The caption of the message box.</param>
328+
/// <param name="caption">The caption of the progress box.</param>
330329
/// <param name="reportProgressAsync">
331330
/// Time-consuming task function, whose input is the action to report progress.
332331
/// The input of the action is the progress value which is a double value between 0 and 100.
333332
/// If there are any exceptions, this action will be null.
334333
/// </param>
335-
/// <param name="forceClosed">When user closes the progress box manually by button or esc key, this action will be called.</param>
336-
/// <returns>A progress box interface.</returns>
337-
public Task ShowProgressBoxAsync(string caption, Func<Action<double>, Task> reportProgressAsync, Action forceClosed = null);
334+
/// <param name="cancelProgress">When user cancel the progress, this action will be called.</param>
335+
/// <returns></returns>
336+
public Task ShowProgressBoxAsync(string caption, Func<Action<double>, Task> reportProgressAsync, Action cancelProgress = null);
338337
}
339338
}

Flow.Launcher/App.xaml.cs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,64 @@ public partial class App : IDisposable, ISingleInstanceApp
3535
public App()
3636
{
3737
// Initialize settings
38-
var storage = new FlowLauncherJsonStorage<Settings>();
39-
_settings = storage.Load();
40-
_settings.SetStorage(storage);
41-
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
38+
try
39+
{
40+
var storage = new FlowLauncherJsonStorage<Settings>();
41+
_settings = storage.Load();
42+
_settings.SetStorage(storage);
43+
_settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled();
44+
}
45+
catch (Exception e)
46+
{
47+
ShowErrorMsgBoxAndFailFast("Cannot load setting storage, please check local data directory", e);
48+
return;
49+
}
4250

4351
// Configure the dependency injection container
44-
var host = Host.CreateDefaultBuilder()
45-
.UseContentRoot(AppContext.BaseDirectory)
46-
.ConfigureServices(services => services
47-
.AddSingleton(_ => _settings)
48-
.AddSingleton(sp => new Updater(sp.GetRequiredService<IPublicAPI>(), Launcher.Properties.Settings.Default.GithubRepo))
49-
.AddSingleton<Portable>()
50-
.AddSingleton<SettingWindowViewModel>()
51-
.AddSingleton<IAlphabet, PinyinAlphabet>()
52-
.AddSingleton<StringMatcher>()
53-
.AddSingleton<Internationalization>()
54-
.AddSingleton<IPublicAPI, PublicAPIInstance>()
55-
.AddSingleton<MainViewModel>()
56-
.AddSingleton<Theme>()
57-
).Build();
58-
Ioc.Default.ConfigureServices(host.Services);
52+
try
53+
{
54+
var host = Host.CreateDefaultBuilder()
55+
.UseContentRoot(AppContext.BaseDirectory)
56+
.ConfigureServices(services => services
57+
.AddSingleton(_ => _settings)
58+
.AddSingleton(sp => new Updater(sp.GetRequiredService<IPublicAPI>(), Launcher.Properties.Settings.Default.GithubRepo))
59+
.AddSingleton<Portable>()
60+
.AddSingleton<SettingWindowViewModel>()
61+
.AddSingleton<IAlphabet, PinyinAlphabet>()
62+
.AddSingleton<StringMatcher>()
63+
.AddSingleton<Internationalization>()
64+
.AddSingleton<IPublicAPI, PublicAPIInstance>()
65+
.AddSingleton<MainViewModel>()
66+
.AddSingleton<Theme>()
67+
).Build();
68+
Ioc.Default.ConfigureServices(host.Services);
69+
}
70+
catch (Exception e)
71+
{
72+
ShowErrorMsgBoxAndFailFast("Cannot configure dependency injection container, please open new issue in Flow.Launcher", e);
73+
return;
74+
}
5975

6076
// Initialize the public API and Settings first
61-
API = Ioc.Default.GetRequiredService<IPublicAPI>();
62-
_settings.Initialize();
77+
try
78+
{
79+
API = Ioc.Default.GetRequiredService<IPublicAPI>();
80+
_settings.Initialize();
81+
}
82+
catch (Exception e)
83+
{
84+
ShowErrorMsgBoxAndFailFast("Cannot initialize api and settings, please open new issue in Flow.Launcher", e);
85+
return;
86+
}
87+
}
88+
89+
private static void ShowErrorMsgBoxAndFailFast(string message, Exception e)
90+
{
91+
// Firstly show users the message
92+
MessageBox.Show(e.ToString(), message, MessageBoxButton.OK, MessageBoxImage.Error);
93+
94+
// Flow cannot construct its App instance, so ensure Flow crashes w/ the exception info.
95+
Environment.FailFast(message, e);
6396
}
6497

6598
[STAThread]

Flow.Launcher/CustomQueryHotkeySetting.xaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,11 @@
3232
<StackPanel>
3333
<Grid>
3434
<Grid.ColumnDefinitions>
35-
<ColumnDefinition Width="Auto" />
3635
<ColumnDefinition Width="*" />
3736
<ColumnDefinition Width="Auto" />
38-
<ColumnDefinition Width="Auto" />
39-
<ColumnDefinition Width="Auto" />
4037
</Grid.ColumnDefinitions>
4138
<Button
42-
Grid.Column="4"
39+
Grid.Column="1"
4340
Click="BtnCancel_OnClick"
4441
Style="{StaticResource TitleBarCloseButtonStyle}">
4542
<Path

Flow.Launcher/CustomShortcutSetting.xaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,11 @@
3030
<StackPanel>
3131
<Grid>
3232
<Grid.ColumnDefinitions>
33-
<ColumnDefinition Width="Auto" />
3433
<ColumnDefinition Width="*" />
3534
<ColumnDefinition Width="Auto" />
36-
<ColumnDefinition Width="Auto" />
37-
<ColumnDefinition Width="Auto" />
3835
</Grid.ColumnDefinitions>
3936
<Button
40-
Grid.Column="4"
37+
Grid.Column="1"
4138
Click="BtnCancel_OnClick"
4239
Style="{StaticResource TitleBarCloseButtonStyle}">
4340
<Path

Flow.Launcher/Flow.Launcher.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
</PackageReference>
9393
<PackageReference Include="InputSimulator" Version="1.0.4" />
9494
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
95-
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
95+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
9696
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
9797
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.106">
9898
<PrivateAssets>all</PrivateAssets>
@@ -104,7 +104,7 @@
104104
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
105105
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
106106
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
107-
<PackageReference Include="TaskScheduler" Version="2.11.0" />
107+
<PackageReference Include="Jack251970.TaskScheduler" Version="2.12.1" />
108108
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.1" />
109109
</ItemGroup>
110110

Flow.Launcher/Helper/WallpaperPathRetrieval.cs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
24
using System.Linq;
35
using System.Runtime.InteropServices;
4-
using System.Text;
5-
using System.Windows.Documents;
6+
using System.Windows;
67
using System.Windows.Media;
8+
using System.Windows.Media.Imaging;
79
using Microsoft.Win32;
810
using Windows.Win32;
911
using Windows.Win32.UI.WindowsAndMessaging;
@@ -13,8 +15,70 @@ namespace Flow.Launcher.Helper;
1315
public static class WallpaperPathRetrieval
1416
{
1517
private static readonly int MAX_PATH = 260;
18+
private static readonly int MAX_CACHE_SIZE = 3;
1619

17-
public static unsafe string GetWallpaperPath()
20+
private static readonly Dictionary<(string, DateTime), ImageBrush> wallpaperCache = new();
21+
22+
public static Brush GetWallpaperBrush()
23+
{
24+
// Invoke the method on the UI thread
25+
if (!Application.Current.Dispatcher.CheckAccess())
26+
{
27+
return Application.Current.Dispatcher.Invoke(GetWallpaperBrush);
28+
}
29+
30+
try
31+
{
32+
var wallpaperPath = GetWallpaperPath();
33+
if (wallpaperPath is not null && File.Exists(wallpaperPath))
34+
{
35+
// Since the wallpaper file name can be the same (TranscodedWallpaper),
36+
// we need to add the last modified date to differentiate them
37+
var dateModified = File.GetLastWriteTime(wallpaperPath);
38+
wallpaperCache.TryGetValue((wallpaperPath, dateModified), out var cachedWallpaper);
39+
if (cachedWallpaper != null)
40+
{
41+
return cachedWallpaper;
42+
}
43+
44+
// We should not dispose the memory stream since the bitmap is still in use
45+
var memStream = new MemoryStream(File.ReadAllBytes(wallpaperPath));
46+
var bitmap = new BitmapImage();
47+
bitmap.BeginInit();
48+
bitmap.StreamSource = memStream;
49+
bitmap.DecodePixelWidth = 800;
50+
bitmap.DecodePixelHeight = 600;
51+
bitmap.EndInit();
52+
bitmap.Freeze(); // Make the bitmap thread-safe
53+
var wallpaperBrush = new ImageBrush(bitmap) { Stretch = Stretch.UniformToFill };
54+
wallpaperBrush.Freeze(); // Make the brush thread-safe
55+
56+
// Manage cache size
57+
if (wallpaperCache.Count >= MAX_CACHE_SIZE)
58+
{
59+
// Remove the oldest wallpaper from the cache
60+
var oldestCache = wallpaperCache.Keys.OrderBy(k => k.Item2).FirstOrDefault();
61+
if (oldestCache != default)
62+
{
63+
wallpaperCache.Remove(oldestCache);
64+
}
65+
}
66+
67+
wallpaperCache.Add((wallpaperPath, dateModified), wallpaperBrush);
68+
return wallpaperBrush;
69+
}
70+
71+
var wallpaperColor = GetWallpaperColor();
72+
return new SolidColorBrush(wallpaperColor);
73+
}
74+
catch (Exception ex)
75+
{
76+
App.API.LogException(nameof(WallpaperPathRetrieval), "Error retrieving wallpaper", ex);
77+
return new SolidColorBrush(Colors.Transparent);
78+
}
79+
}
80+
81+
private static unsafe string GetWallpaperPath()
1882
{
1983
var wallpaperPtr = stackalloc char[MAX_PATH];
2084
PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETDESKWALLPAPER, (uint)MAX_PATH,
@@ -25,7 +89,7 @@ public static unsafe string GetWallpaperPath()
2589
return wallpaper.ToString();
2690
}
2791

28-
public static Color GetWallpaperColor()
92+
private static Color GetWallpaperColor()
2993
{
3094
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", true);
3195
var result = key?.GetValue("Background", null);

Flow.Launcher/Languages/en.xaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@
368368
<system:String x:Key="commonOK">OK</system:String>
369369
<system:String x:Key="commonYes">Yes</system:String>
370370
<system:String x:Key="commonNo">No</system:String>
371+
<system:String x:Key="commonBackground">Background</system:String>
371372

372373
<!-- Crash Reporter -->
373374
<system:String x:Key="reportWindow_version">Version</system:String>
@@ -384,6 +385,9 @@
384385
<system:String x:Key="reportWindow_report_succeed">Report sent successfully</system:String>
385386
<system:String x:Key="reportWindow_report_failed">Failed to send report</system:String>
386387
<system:String x:Key="reportWindow_flowlauncher_got_an_error">Flow Launcher got an error</system:String>
388+
<system:String x:Key="reportWindow_please_open_issue">Please open new issue in</system:String>
389+
<system:String x:Key="reportWindow_upload_log">1. Upload log file: {0}</system:String>
390+
<system:String x:Key="reportWindow_copy_below">2. Copy below exception message</system:String>
387391

388392
<!-- General Notice -->
389393
<system:String x:Key="pleaseWait">Please wait...</system:String>

Flow.Launcher/MainWindow.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ private void CheckFirstLaunch()
438438
if (_settings.FirstLaunch)
439439
{
440440
_settings.FirstLaunch = false;
441-
PluginManager.API.SaveAppAllSettings();
441+
App.API.SaveAppAllSettings();
442442
OpenWelcomeWindow();
443443
}
444444
}

Flow.Launcher/PriorityChangeWindow.xaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,11 @@
2929
<StackPanel>
3030
<Grid>
3131
<Grid.ColumnDefinitions>
32-
<ColumnDefinition Width="Auto" />
3332
<ColumnDefinition Width="*" />
3433
<ColumnDefinition Width="Auto" />
35-
<ColumnDefinition Width="Auto" />
36-
<ColumnDefinition Width="Auto" />
3734
</Grid.ColumnDefinitions>
3835
<Button
39-
Grid.Column="4"
36+
Grid.Column="1"
4037
Click="BtnCancel_OnClick"
4138
Style="{StaticResource TitleBarCloseButtonStyle}">
4239
<Path

0 commit comments

Comments
 (0)