diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
index e36b9c5e0..7d6448c43 100644
--- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
+++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj
@@ -49,7 +49,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
index 55545b9a7..ddbab4ef0 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs
@@ -3,33 +3,23 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
+using System.Threading.Tasks;
using System.Windows.Media;
-using FastCache;
-using FastCache.Services;
+using BitFaster.Caching.Lfu;
namespace Flow.Launcher.Infrastructure.Image
{
- public class ImageUsage
- {
- public int usage;
- public ImageSource imageSource;
-
- public ImageUsage(int usage, ImageSource image)
- {
- this.usage = usage;
- imageSource = image;
- }
- }
-
public class ImageCache
{
private const int MaxCached = 150;
- public void Initialize(Dictionary<(string, bool), int> usage)
+ private ConcurrentLfu<(string, bool), ImageSource> CacheManager { get; set; } = new(MaxCached);
+
+ public void Initialize(IEnumerable<(string, bool)> usage)
{
- foreach (var key in usage.Keys)
+ foreach (var key in usage)
{
- Cached.Save(key, new ImageUsage(usage[key], null), TimeSpan.MaxValue, MaxCached);
+ CacheManager.AddOrUpdate(key, null);
}
}
@@ -37,48 +27,42 @@ namespace Flow.Launcher.Infrastructure.Image
{
get
{
- if (!Cached.TryGet((path, isFullImage), out var value))
- {
- return null;
- }
-
- value.Value.usage++;
- return value.Value.imageSource;
+ return CacheManager.TryGet((path, isFullImage), out var value) ? value : null;
}
set
{
- if (Cached.TryGet((path, isFullImage), out var cached))
- {
- cached.Value.imageSource = value;
- cached.Value.usage++;
- }
-
- Cached.Save((path, isFullImage), new ImageUsage(0, value), TimeSpan.MaxValue,
- MaxCached);
+ CacheManager.AddOrUpdate((path, isFullImage), value);
}
}
+ public async ValueTask GetOrAddAsync(string key,
+ Func<(string, bool), Task> valueFactory,
+ bool isFullImage = false)
+ {
+ return await CacheManager.GetOrAddAsync((key, isFullImage), valueFactory);
+ }
+
public bool ContainsKey(string key, bool isFullImage)
{
- return Cached.TryGet((key, isFullImage), out _);
+ return CacheManager.TryGet((key, isFullImage), out _);
}
public bool TryGetValue(string key, bool isFullImage, out ImageSource image)
{
- if (Cached.TryGet((key, isFullImage), out var value))
+ if (CacheManager.TryGet((key, isFullImage), out var value))
{
- image = value.Value.imageSource;
- value.Value.usage++;
+ image = value;
return image != null;
}
+
image = null;
return false;
}
public int CacheSize()
{
- return CacheManager.TotalCount<(string, bool), ImageUsage>();
+ return CacheManager.Count;
}
///
@@ -86,14 +70,14 @@ namespace Flow.Launcher.Infrastructure.Image
///
public int UniqueImagesInCache()
{
- return CacheManager.EnumerateEntries<(string, bool), ImageUsage>().Select(x => x.Value.imageSource)
+ return CacheManager.Select(x => x.Value)
.Distinct()
.Count();
}
- public IEnumerable> EnumerateEntries()
+ public IEnumerable> EnumerateEntries()
{
- return CacheManager.EnumerateEntries<(string, bool), ImageUsage>();
+ return CacheManager;
}
}
}
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index 75c2a4ec9..612f495be 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Flow.Launcher.Infrastructure.Logger;
@@ -17,7 +18,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
private static readonly ImageCache ImageCache = new();
private static SemaphoreSlim storageLock { get; } = new SemaphoreSlim(1, 1);
- private static BinaryStorage> _storage;
+ private static BinaryStorage> _storage;
private static readonly ConcurrentDictionary GuidToKey = new();
private static IImageHashGenerator _hashGenerator;
private static readonly bool EnableImageHash = true;
@@ -31,12 +32,12 @@ namespace Flow.Launcher.Infrastructure.Image
public static async Task InitializeAsync()
{
- _storage = new BinaryStorage>("Image");
+ _storage = new BinaryStorage>("Image");
_hashGenerator = new ImageHashGenerator();
var usage = await LoadStorageToConcurrentDictionaryAsync();
- ImageCache.Initialize(usage.ToDictionary(x => x.Key, x => x.Value));
+ ImageCache.Initialize(usage);
foreach (var icon in new[] { Constant.DefaultIcon, Constant.MissingImgIcon })
{
@@ -49,7 +50,7 @@ namespace Flow.Launcher.Infrastructure.Image
{
await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () =>
{
- foreach (var ((path, isFullImage), _) in usage)
+ foreach (var (path, isFullImage) in usage)
{
await LoadAsync(path, isFullImage);
}
@@ -66,9 +67,8 @@ namespace Flow.Launcher.Infrastructure.Image
try
{
await _storage.SaveAsync(ImageCache.EnumerateEntries()
- .ToDictionary(
- x => x.Key,
- x => x.Value.usage));
+ .Select(x => x.Key)
+ .ToList());
}
finally
{
@@ -76,14 +76,12 @@ namespace Flow.Launcher.Infrastructure.Image
}
}
- private static async Task> LoadStorageToConcurrentDictionaryAsync()
+ private static async Task> LoadStorageToConcurrentDictionaryAsync()
{
await storageLock.WaitAsync();
try
{
- var loaded = await _storage.TryLoadAsync(new Dictionary<(string, bool), int>());
-
- return new ConcurrentDictionary<(string, bool), int>(loaded);
+ return await _storage.TryLoadAsync(new List<(string, bool)>());
}
finally
{
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index a679643fd..2a439b8cc 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -67,7 +67,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
catch (System.Exception e)
{
- Log.Exception($"|BinaryStorage.Deserialize|Deserialize error for file <{FilePath}>", e);
+ // Log.Exception($"|BinaryStorage.Deserialize|Deserialize error for file <{FilePath}>", e);
return defaultData;
}
}
diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
index 67b2ae406..626ca31c2 100644
--- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
+++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs
@@ -88,8 +88,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings
public double SettingWindowWidth { get; set; } = 1000;
public double SettingWindowHeight { get; set; } = 700;
- public double SettingWindowTop { get; set; }
- public double SettingWindowLeft { get; set; }
+ public double? SettingWindowTop { get; set; } = null;
+ public double? SettingWindowLeft { get; set; } = null;
public System.Windows.WindowState SettingWindowState { get; set; } = WindowState.Normal;
public int CustomExplorerIndex { get; set; } = 0;
diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj
index 53c1bafc7..848c52f1f 100644
--- a/Flow.Launcher/Flow.Launcher.csproj
+++ b/Flow.Launcher/Flow.Launcher.csproj
@@ -111,6 +111,12 @@
+
+
+ PreserveNewest
+
+
+
diff --git a/Flow.Launcher/Images/dev.ico b/Flow.Launcher/Images/dev.ico
new file mode 100644
index 000000000..aba4eb2f9
Binary files /dev/null and b/Flow.Launcher/Images/dev.ico differ
diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml
index 1dca83dad..bd6b13934 100644
--- a/Flow.Launcher/MainWindow.xaml
+++ b/Flow.Launcher/MainWindow.xaml
@@ -344,8 +344,22 @@
-
+
@@ -439,6 +453,7 @@
Style="{DynamicResource PreviewArea}"
Visibility="{Binding InternalPreviewVisible, Converter={StaticResource BoolToVisibilityConverter}}">
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
+
..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Images\dev.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\Images\gamemode.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
diff --git a/Flow.Launcher/Resources/dev.ico b/Flow.Launcher/Resources/dev.ico
new file mode 100644
index 000000000..5d06b9f28
Binary files /dev/null and b/Flow.Launcher/Resources/dev.ico differ
diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs
index 957379ce4..de4fd1f91 100644
--- a/Flow.Launcher/SettingWindow.xaml.cs
+++ b/Flow.Launcher/SettingWindow.xaml.cs
@@ -110,15 +110,15 @@ public partial class SettingWindow
public void InitializePosition()
{
- if (_settings.SettingWindowTop == null)
+ if (_settings.SettingWindowTop == null || _settings.SettingWindowLeft == null)
{
Top = WindowTop();
Left = WindowLeft();
}
else
{
- Top = _settings.SettingWindowTop;
- Left = _settings.SettingWindowLeft;
+ Top = _settings.SettingWindowTop.Value;
+ Left = _settings.SettingWindowLeft.Value;
}
WindowState = _settings.SettingWindowState;
}
diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml
index 2ba3a5929..fe17bdbf5 100644
--- a/Flow.Launcher/Themes/Base.xaml
+++ b/Flow.Launcher/Themes/Base.xaml
@@ -28,8 +28,8 @@
-
-
+
+
@@ -69,7 +69,7 @@
@@ -91,7 +91,7 @@
@@ -312,7 +312,7 @@
x:Name="PART_VerticalScrollBar"
Grid.Row="0"
Grid.Column="0"
- Margin="0,0,0,0"
+ Margin="0 0 0 0"
HorizontalAlignment="Right"
AutomationProperties.AutomationId="VerticalScrollBar"
Cursor="Arrow"
@@ -368,22 +368,7 @@
-
+
@@ -413,15 +398,15 @@
@@ -495,7 +480,7 @@
@@ -503,7 +488,7 @@
x:Key="ClockPanelPosition"
BasedOn="{StaticResource BaseClockPanelPosition}"
TargetType="{x:Type Canvas}">
-
+
-
-
-
+
+
+
+
+
-
-
+
+
+
-
+
@@ -70,7 +86,7 @@
-- Drag a file/folder to File Exlporer, or even Discord.
+- Drag a file/folder to File Explorer, or even Discord.
- Copy/move behavior can be change via Ctrl or Shift, and the operation is displayed on the mouse cursor.
### Windows & Control Panel Settings