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 7396a5bb2..44e104895 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.cs b/Flow.Launcher/MainWindow.xaml.cs
index efeed5148..22799a63d 100644
--- a/Flow.Launcher/MainWindow.xaml.cs
+++ b/Flow.Launcher/MainWindow.xaml.cs
@@ -341,11 +341,10 @@ namespace Flow.Launcher
_notifyIcon = new NotifyIcon
{
Text = Infrastructure.Constant.FlowLauncherFullName,
- Icon = Properties.Resources.app,
+ Icon = Constant.Version == "1.0.0" ? Properties.Resources.dev : Properties.Resources.app,
Visible = !_settings.HideNotifyIcon
};
-
var openIcon = new FontIcon
{
Glyph = "\ue71e"
diff --git a/Flow.Launcher/Properties/Resources.Designer.cs b/Flow.Launcher/Properties/Resources.Designer.cs
index 43927cb98..ce4d4fe13 100644
--- a/Flow.Launcher/Properties/Resources.Designer.cs
+++ b/Flow.Launcher/Properties/Resources.Designer.cs
@@ -77,5 +77,13 @@ namespace Flow.Launcher.Properties {
return ((System.Drawing.Icon)(obj));
}
}
+ internal static System.Drawing.Icon dev
+ {
+ get
+ {
+ object obj = ResourceManager.GetObject("dev", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
}
}
diff --git a/Flow.Launcher/Properties/Resources.resx b/Flow.Launcher/Properties/Resources.resx
index 2126cb185..d608b69d5 100644
--- a/Flow.Launcher/Properties/Resources.resx
+++ b/Flow.Launcher/Properties/Resources.resx
@@ -112,15 +112,18 @@
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/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
index 481802045..04dd6312b 100644
--- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
+++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs
@@ -52,13 +52,13 @@ public class SettingWindowViewModel : BaseModel
set => Settings.SettingWindowHeight = value;
}
- public double SettingWindowTop
+ public double? SettingWindowTop
{
get => Settings.SettingWindowTop;
set => Settings.SettingWindowTop = value;
}
- public double SettingWindowLeft
+ public double? SettingWindowLeft
{
get => Settings.SettingWindowLeft;
set => Settings.SettingWindowLeft = value;
diff --git a/README.md b/README.md
index 858d39d1c..866cdf8b3 100644
--- a/README.md
+++ b/README.md
@@ -121,7 +121,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea
-- 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