mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into 240518Adjusthemes
This commit is contained in:
commit
7c07317271
14 changed files with 64 additions and 66 deletions
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
|
||||
<PackageReference Include="FastCache.Cached" Version="1.8.2" />
|
||||
<PackageReference Include="BitFaster.Caching" Version="2.5.0" />
|
||||
<PackageReference Include="Fody" Version="6.5.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
|
|
|||
|
|
@ -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<ImageUsage>.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<ImageUsage>.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<ImageUsage>.TryGet((path, isFullImage), out var cached))
|
||||
{
|
||||
cached.Value.imageSource = value;
|
||||
cached.Value.usage++;
|
||||
}
|
||||
|
||||
Cached<ImageUsage>.Save((path, isFullImage), new ImageUsage(0, value), TimeSpan.MaxValue,
|
||||
MaxCached);
|
||||
CacheManager.AddOrUpdate((path, isFullImage), value);
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<ImageSource> GetOrAddAsync(string key,
|
||||
Func<(string, bool), Task<ImageSource>> valueFactory,
|
||||
bool isFullImage = false)
|
||||
{
|
||||
return await CacheManager.GetOrAddAsync((key, isFullImage), valueFactory);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key, bool isFullImage)
|
||||
{
|
||||
return Cached<ImageUsage>.TryGet((key, isFullImage), out _);
|
||||
return CacheManager.TryGet((key, isFullImage), out _);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, bool isFullImage, out ImageSource image)
|
||||
{
|
||||
if (Cached<ImageUsage>.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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -86,14 +70,14 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
/// </summary>
|
||||
public int UniqueImagesInCache()
|
||||
{
|
||||
return CacheManager.EnumerateEntries<(string, bool), ImageUsage>().Select(x => x.Value.imageSource)
|
||||
return CacheManager.Select(x => x.Value)
|
||||
.Distinct()
|
||||
.Count();
|
||||
}
|
||||
|
||||
public IEnumerable<Cached<(string, bool), ImageUsage>> EnumerateEntries()
|
||||
public IEnumerable<KeyValuePair<(string, bool), ImageSource>> EnumerateEntries()
|
||||
{
|
||||
return CacheManager.EnumerateEntries<(string, bool), ImageUsage>();
|
||||
return CacheManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Dictionary<(string, bool), int>> _storage;
|
||||
private static BinaryStorage<List<(string, bool)>> _storage;
|
||||
private static readonly ConcurrentDictionary<string, string> 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<Dictionary<(string, bool), int>>("Image");
|
||||
_storage = new BinaryStorage<List<(string, bool)>>("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<ConcurrentDictionary<(string, bool), int>> LoadStorageToConcurrentDictionaryAsync()
|
||||
private static async Task<List<(string, bool)>> 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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@
|
|||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Resources\dev.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
|
||||
<Exec Command="taskkill /f /fi "IMAGENAME eq Flow.Launcher.exe"" />
|
||||
</Target>
|
||||
|
|
|
|||
BIN
Flow.Launcher/Images/dev.ico
Normal file
BIN
Flow.Launcher/Images/dev.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -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"
|
||||
|
|
|
|||
8
Flow.Launcher/Properties/Resources.Designer.cs
generated
8
Flow.Launcher/Properties/Resources.Designer.cs
generated
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,15 +112,18 @@
|
|||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="app" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="dev" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\dev.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="gamemode" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Images\gamemode.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
|
|
|
|||
BIN
Flow.Launcher/Resources/dev.ico
Normal file
BIN
Flow.Launcher/Resources/dev.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea
|
|||
|
||||
<img src="https://user-images.githubusercontent.com/6903107/207159486-1993510f-09f2-4e33-bba7-4ca59ca1bc5a.png" width="500">
|
||||
|
||||
- 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 <kbd>Ctrl</kbd> or <kbd>Shift</kbd>, and the operation is displayed on the mouse cursor.
|
||||
|
||||
### Windows & Control Panel Settings
|
||||
|
|
|
|||
Loading…
Reference in a new issue