Skip to content

Commit 9211fe4

Browse files
authored
Merge branch 'dev' into squirrel_upgrade
2 parents f7b3a7c + 7a7760c commit 9211fe4

File tree

49 files changed

+835
-545
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+835
-545
lines changed

Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public async Task<List<UserPlugin>> FetchAsync(CancellationToken token)
7575
}
7676
catch (OperationCanceledException) when (token.IsCancellationRequested)
7777
{
78-
API.LogInfo(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller.");
78+
API.LogDebug(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller.");
7979
return null;
8080
}
8181
catch (TaskCanceledException)

Flow.Launcher.Core/Resource/Internationalization.cs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Globalization;
44
using System.IO;
@@ -14,7 +14,7 @@
1414

1515
namespace Flow.Launcher.Core.Resource
1616
{
17-
public class Internationalization
17+
public class Internationalization : IDisposable
1818
{
1919
private static readonly string ClassName = nameof(Internationalization);
2020

@@ -30,6 +30,7 @@ public class Internationalization
3030
private readonly List<string> _languageDirectories = [];
3131
private readonly List<ResourceDictionary> _oldResources = [];
3232
private static string SystemLanguageCode;
33+
private readonly SemaphoreSlim _langChangeLock = new(1, 1);
3334

3435
public Internationalization(Settings settings)
3536
{
@@ -185,20 +186,33 @@ private static Language GetLanguageByLanguageCode(string languageCode)
185186

186187
private async Task ChangeLanguageAsync(Language language, bool updateMetadata = true)
187188
{
188-
// Remove old language files and load language
189-
RemoveOldLanguageFiles();
190-
if (language != AvailableLanguages.English)
189+
await _langChangeLock.WaitAsync();
190+
191+
try
191192
{
192-
LoadLanguage(language);
193-
}
193+
// Remove old language files and load language
194+
RemoveOldLanguageFiles();
195+
if (language != AvailableLanguages.English)
196+
{
197+
LoadLanguage(language);
198+
}
194199

195-
// Change culture info
196-
ChangeCultureInfo(language.LanguageCode);
200+
// Change culture info
201+
ChangeCultureInfo(language.LanguageCode);
197202

198-
if (updateMetadata)
203+
if (updateMetadata)
204+
{
205+
// Raise event for plugins after culture is set
206+
await Task.Run(UpdatePluginMetadataTranslations);
207+
}
208+
}
209+
catch (Exception e)
199210
{
200-
// Raise event for plugins after culture is set
201-
await Task.Run(UpdatePluginMetadataTranslations);
211+
API.LogException(ClassName, $"Failed to change language to <{language.LanguageCode}>", e);
212+
}
213+
finally
214+
{
215+
_langChangeLock.Release();
202216
}
203217
}
204218

@@ -257,6 +271,7 @@ private void RemoveOldLanguageFiles()
257271
{
258272
dicts.Remove(r);
259273
}
274+
_oldResources.Clear();
260275
}
261276

262277
private void LoadLanguage(Language language)
@@ -368,5 +383,15 @@ public static void UpdatePluginMetadataTranslations()
368383
}
369384

370385
#endregion
386+
387+
#region IDisposable
388+
389+
public void Dispose()
390+
{
391+
RemoveOldLanguageFiles();
392+
_langChangeLock.Dispose();
393+
}
394+
395+
#endregion
371396
}
372397
}
Lines changed: 5 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.IO;
4-
using System.Linq;
5-
using Windows.Win32;
62

73
namespace Flow.Launcher.Infrastructure
84
{
@@ -13,84 +9,23 @@ public static class FileExplorerHelper
139
/// </summary>
1410
public static string GetActiveExplorerPath()
1511
{
16-
var explorerWindow = GetActiveExplorer();
17-
string locationUrl = explorerWindow?.LocationURL;
18-
return !string.IsNullOrEmpty(locationUrl) ? GetDirectoryPath(new Uri(locationUrl).LocalPath) : null;
12+
var explorerPath = DialogJump.DialogJump.GetActiveExplorerPath();
13+
return !string.IsNullOrEmpty(explorerPath) ?
14+
GetDirectoryPath(new Uri(explorerPath).LocalPath) :
15+
null;
1916
}
2017

2118
/// <summary>
2219
/// Get directory path from a file path
2320
/// </summary>
2421
private static string GetDirectoryPath(string path)
2522
{
26-
if (!path.EndsWith("\\"))
23+
if (!path.EndsWith('\\'))
2724
{
2825
return path + "\\";
2926
}
3027

3128
return path;
3229
}
33-
34-
/// <summary>
35-
/// Gets the file explorer that is currently in the foreground
36-
/// </summary>
37-
private static dynamic GetActiveExplorer()
38-
{
39-
Type type = Type.GetTypeFromProgID("Shell.Application");
40-
if (type == null) return null;
41-
dynamic shell = Activator.CreateInstance(type);
42-
if (shell == null)
43-
{
44-
return null;
45-
}
46-
47-
var explorerWindows = new List<dynamic>();
48-
var openWindows = shell.Windows();
49-
for (int i = 0; i < openWindows.Count; i++)
50-
{
51-
var window = openWindows.Item(i);
52-
if (window == null) continue;
53-
54-
// find the desired window and make sure that it is indeed a file explorer
55-
// we don't want the Internet Explorer or the classic control panel
56-
// ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE"
57-
if (Path.GetFileName((string)window.FullName)?.ToLower() == "explorer.exe")
58-
{
59-
explorerWindows.Add(window);
60-
}
61-
}
62-
63-
if (explorerWindows.Count == 0) return null;
64-
65-
var zOrders = GetZOrder(explorerWindows);
66-
67-
return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First;
68-
}
69-
70-
/// <summary>
71-
/// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1.
72-
/// </summary>
73-
private static IEnumerable<int> GetZOrder(List<dynamic> hWnds)
74-
{
75-
var z = new int[hWnds.Count];
76-
for (var i = 0; i < hWnds.Count; i++) z[i] = -1;
77-
78-
var index = 0;
79-
var numRemaining = hWnds.Count;
80-
PInvoke.EnumWindows((wnd, _) =>
81-
{
82-
var searchIndex = hWnds.FindIndex(x => new IntPtr(x.HWND) == wnd);
83-
if (searchIndex != -1)
84-
{
85-
z[searchIndex] = index;
86-
numRemaining--;
87-
if (numRemaining == 0) return false;
88-
}
89-
index++;
90-
return true;
91-
}, IntPtr.Zero);
92-
93-
return z;
94-
}
9530
}
9631
}

Flow.Launcher.Infrastructure/Image/ImageLoader.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static class ImageLoader
2222
private static Lock storageLock { get; } = new();
2323
private static BinaryStorage<List<(string, bool)>> _storage;
2424
private static readonly ConcurrentDictionary<string, string> GuidToKey = new();
25-
private static IImageHashGenerator _hashGenerator;
25+
private static ImageHashGenerator _hashGenerator;
2626
private static readonly bool EnableImageHash = true;
2727
public static ImageSource Image => ImageCache[Constant.ImageIcon, false];
2828
public static ImageSource MissingImage => ImageCache[Constant.MissingImgIcon, false];
@@ -31,7 +31,7 @@ public static class ImageLoader
3131
public const int FullIconSize = 256;
3232
public const int FullImageSize = 320;
3333

34-
private static readonly string[] ImageExtensions = { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico" };
34+
private static readonly string[] ImageExtensions = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico"];
3535
private static readonly string SvgExtension = ".svg";
3636

3737
public static async Task InitializeAsync()
@@ -327,7 +327,7 @@ public static async ValueTask<ImageSource> LoadAsync(string path, bool loadFullI
327327
return img;
328328
}
329329

330-
private static ImageSource LoadFullImage(string path)
330+
private static BitmapImage LoadFullImage(string path)
331331
{
332332
BitmapImage image = new BitmapImage();
333333
image.BeginInit();
@@ -364,7 +364,7 @@ private static ImageSource LoadFullImage(string path)
364364
return image;
365365
}
366366

367-
private static ImageSource LoadSvgImage(string path, bool loadFullImage = false)
367+
private static RenderTargetBitmap LoadSvgImage(string path, bool loadFullImage = false)
368368
{
369369
// Set up drawing settings
370370
var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize;

Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
using System.Text.Json.Serialization;
2+
using CommunityToolkit.Mvvm.DependencyInjection;
13
using Flow.Launcher.Plugin;
2-
using System.Text.Json.Serialization;
34

45
namespace Flow.Launcher.Infrastructure.UserSettings
56
{
67
public class CustomBrowserViewModel : BaseModel
78
{
9+
// We should not initialize API in static constructor because it will create another API instance
10+
private static IPublicAPI api = null;
11+
private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService<IPublicAPI>();
12+
813
public string Name { get; set; }
14+
[JsonIgnore]
15+
public string DisplayName => Name == "Default" ? API.GetTranslation("defaultBrowser_default") : Name;
916
public string Path { get; set; }
1017
public string PrivateArg { get; set; }
1118
public bool EnablePrivate { get; set; }
@@ -26,8 +33,10 @@ public CustomBrowserViewModel Copy()
2633
Editable = Editable
2734
};
2835
}
36+
37+
public void OnDisplayNameChanged()
38+
{
39+
OnPropertyChanged(nameof(DisplayName));
40+
}
2941
}
3042
}
31-
32-
33-

Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
using Flow.Launcher.Plugin;
1+
using System.Text.Json.Serialization;
2+
using CommunityToolkit.Mvvm.DependencyInjection;
3+
using Flow.Launcher.Plugin;
24

3-
namespace Flow.Launcher.ViewModel
5+
namespace Flow.Launcher.Infrastructure.UserSettings
46
{
57
public class CustomExplorerViewModel : BaseModel
68
{
9+
// We should not initialize API in static constructor because it will create another API instance
10+
private static IPublicAPI api = null;
11+
private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService<IPublicAPI>();
12+
713
public string Name { get; set; }
14+
[JsonIgnore]
15+
public string DisplayName => Name == "Explorer" ? API.GetTranslation("fileManagerExplorer") : Name;
816
public string Path { get; set; }
917
public string FileArgument { get; set; } = "\"%d\"";
1018
public string DirectoryArgument { get; set; } = "\"%d\"";
@@ -21,5 +29,10 @@ public CustomExplorerViewModel Copy()
2129
Editable = Editable
2230
};
2331
}
32+
33+
public void OnDisplayNameChanged()
34+
{
35+
OnPropertyChanged(nameof(DisplayName));
36+
}
2437
}
2538
}

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using Flow.Launcher.Infrastructure.Storage;
1010
using Flow.Launcher.Plugin;
1111
using Flow.Launcher.Plugin.SharedModels;
12-
using Flow.Launcher.ViewModel;
1312

1413
namespace Flow.Launcher.Infrastructure.UserSettings
1514
{

Flow.Launcher.Infrastructure/Win32Helper.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
44
using System.Diagnostics;
@@ -904,5 +904,19 @@ public static void EnableWin32DarkMode(string colorScheme)
904904
}
905905

906906
#endregion
907+
908+
#region File / Folder Dialog
909+
910+
public static string SelectFile()
911+
{
912+
var dlg = new OpenFileDialog();
913+
var result = dlg.ShowDialog();
914+
if (result == true)
915+
return dlg.FileName;
916+
917+
return string.Empty;
918+
}
919+
920+
#endregion
907921
}
908922
}

Flow.Launcher.Test/Flow.Launcher.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
</ItemGroup>
4040

4141
<ItemGroup>
42+
<ProjectReference Include="..\Plugins\Flow.Launcher.Plugin.Calculator\Flow.Launcher.Plugin.Calculator.csproj" />
4243
<ProjectReference Include="..\Plugins\Flow.Launcher.Plugin.Explorer\Flow.Launcher.Plugin.Explorer.csproj" />
4344
<ProjectReference Include="..\Plugins\Flow.Launcher.Plugin.Program\Flow.Launcher.Plugin.Program.csproj" />
4445
<ProjectReference Include="..\Plugins\Flow.Launcher.Plugin.Url\Flow.Launcher.Plugin.Url.csproj" />

0 commit comments

Comments
 (0)