mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Respect loadFullImage Option in ImageCache.cs
This commit is contained in:
parent
0fd127ab98
commit
cf9dd4addb
2 changed files with 40 additions and 37 deletions
|
|
@ -25,11 +25,11 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
public class ImageCache
|
||||
{
|
||||
private const int MaxCached = 50;
|
||||
public ConcurrentDictionary<string, ImageUsage> Data { get; private set; } = new ConcurrentDictionary<string, ImageUsage>();
|
||||
public ConcurrentDictionary<(string, bool), ImageUsage> Data { get; } = new();
|
||||
private const int permissibleFactor = 2;
|
||||
private SemaphoreSlim semaphore = new(1, 1);
|
||||
|
||||
public void Initialization(Dictionary<string, int> usage)
|
||||
public void Initialization(Dictionary<(string, bool), int> usage)
|
||||
{
|
||||
foreach (var key in usage.Keys)
|
||||
{
|
||||
|
|
@ -37,29 +37,29 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
}
|
||||
|
||||
public ImageSource this[string path]
|
||||
public ImageSource this[string path, bool isFullImage = false]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Data.TryGetValue(path, out var value))
|
||||
if (!Data.TryGetValue((path, isFullImage), out var value))
|
||||
{
|
||||
value.usage++;
|
||||
return value.imageSource;
|
||||
return null;
|
||||
}
|
||||
value.usage++;
|
||||
return value.imageSource;
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
Data.AddOrUpdate(
|
||||
path,
|
||||
new ImageUsage(0, value),
|
||||
(k, v) =>
|
||||
{
|
||||
v.imageSource = value;
|
||||
v.usage++;
|
||||
return v;
|
||||
}
|
||||
(path, isFullImage),
|
||||
new ImageUsage(0, value),
|
||||
(k, v) =>
|
||||
{
|
||||
v.imageSource = value;
|
||||
v.usage++;
|
||||
return v;
|
||||
}
|
||||
);
|
||||
|
||||
SliceExtra();
|
||||
|
|
@ -82,9 +82,9 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
public bool ContainsKey(string key, bool isFullImage)
|
||||
{
|
||||
return key is not null && Data.ContainsKey(key) && Data[key].imageSource != null;
|
||||
return key is not null && Data.ContainsKey((key, isFullImage)) && Data[(key, isFullImage)].imageSource != null;
|
||||
}
|
||||
|
||||
public int CacheSize()
|
||||
|
|
@ -100,4 +100,4 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
return Data.Values.Select(x => x.imageSource).Distinct().Count();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
public static class ImageLoader
|
||||
{
|
||||
private static readonly ImageCache ImageCache = new();
|
||||
private static BinaryStorage<Dictionary<string, int>> _storage;
|
||||
private static BinaryStorage<Dictionary<(string, bool), int>> _storage;
|
||||
private static readonly ConcurrentDictionary<string, string> GuidToKey = new();
|
||||
private static IImageHashGenerator _hashGenerator;
|
||||
private static readonly bool EnableImageHash = true;
|
||||
|
|
@ -32,7 +32,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
|
||||
public static void Initialize()
|
||||
{
|
||||
_storage = new BinaryStorage<Dictionary<string, int>>("Image");
|
||||
_storage = new BinaryStorage<Dictionary<(string, bool), int>>("Image");
|
||||
_hashGenerator = new ImageHashGenerator();
|
||||
|
||||
var usage = LoadStorageToConcurrentDictionary();
|
||||
|
|
@ -44,16 +44,16 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
ImageSource img = new BitmapImage(new Uri(icon));
|
||||
img.Freeze();
|
||||
ImageCache[icon] = img;
|
||||
ImageCache[icon, false] = img;
|
||||
}
|
||||
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () =>
|
||||
{
|
||||
foreach (var imageUsage in ImageCache.Data)
|
||||
foreach (var ((path, isFullImage), _) in ImageCache.Data)
|
||||
{
|
||||
await LoadAsync(imageUsage.Key);
|
||||
await LoadAsync(path, isFullImage);
|
||||
}
|
||||
});
|
||||
Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}");
|
||||
|
|
@ -64,17 +64,20 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
lock (_storage)
|
||||
{
|
||||
_storage.Save(ImageCache.Data.Select(x => (x.Key, x.Value.usage)).ToDictionary(x => x.Key, x => x.usage));
|
||||
_storage.Save(ImageCache.Data
|
||||
.ToDictionary(
|
||||
x => x.Key,
|
||||
x => x.Value.usage));
|
||||
}
|
||||
}
|
||||
|
||||
private static ConcurrentDictionary<string, int> LoadStorageToConcurrentDictionary()
|
||||
private static ConcurrentDictionary<(string, bool), int> LoadStorageToConcurrentDictionary()
|
||||
{
|
||||
lock (_storage)
|
||||
{
|
||||
var loaded = _storage.TryLoad(new Dictionary<string, int>());
|
||||
var loaded = _storage.TryLoad(new Dictionary<(string, bool), int>());
|
||||
|
||||
return new ConcurrentDictionary<string, int>(loaded);
|
||||
return new ConcurrentDictionary<(string, bool), int>(loaded);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,17 +111,17 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return new ImageResult(ImageCache[Constant.MissingImgIcon], ImageType.Error);
|
||||
return new ImageResult(ImageCache[Constant.MissingImgIcon, false], ImageType.Error);
|
||||
}
|
||||
if (ImageCache.ContainsKey(path))
|
||||
if (ImageCache.ContainsKey(path, loadFullImage))
|
||||
{
|
||||
return new ImageResult(ImageCache[path], ImageType.Cache);
|
||||
return new ImageResult(ImageCache[path, loadFullImage], ImageType.Cache);
|
||||
}
|
||||
if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uriResult)
|
||||
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps))
|
||||
{
|
||||
var image = await LoadRemoteImageAsync(loadFullImage, uriResult);
|
||||
ImageCache[path] = image;
|
||||
ImageCache[path, false] = image;
|
||||
return new ImageResult(image, ImageType.ImageFile);
|
||||
}
|
||||
if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase))
|
||||
|
|
@ -147,8 +150,8 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e);
|
||||
Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2);
|
||||
|
||||
ImageSource image = ImageCache[Constant.MissingImgIcon];
|
||||
ImageCache[path] = image;
|
||||
ImageSource image = ImageCache[Constant.MissingImgIcon, false];
|
||||
ImageCache[path, false] = image;
|
||||
imageResult = new ImageResult(image, ImageType.Error);
|
||||
}
|
||||
}
|
||||
|
|
@ -220,7 +223,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
else
|
||||
{
|
||||
image = ImageCache[Constant.MissingImgIcon];
|
||||
image = ImageCache[Constant.MissingImgIcon, false];
|
||||
path = Constant.MissingImgIcon;
|
||||
}
|
||||
|
||||
|
|
@ -243,7 +246,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
|
||||
public static bool CacheContainImage(string path)
|
||||
{
|
||||
return ImageCache.ContainsKey(path) && ImageCache[path] != null;
|
||||
return ImageCache.ContainsKey(path, false) && ImageCache[path, false] != null;
|
||||
}
|
||||
|
||||
public static async ValueTask<ImageSource> LoadAsync(string path, bool loadFullImage = false)
|
||||
|
|
@ -259,7 +262,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
|
||||
if (GuidToKey.TryGetValue(hash, out string key))
|
||||
{ // image already exists
|
||||
img = ImageCache[key] ?? img;
|
||||
img = ImageCache[key, false] ?? img;
|
||||
}
|
||||
else
|
||||
{ // new guid
|
||||
|
|
@ -268,7 +271,7 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
|
||||
// update cache
|
||||
ImageCache[path] = img;
|
||||
ImageCache[path, false] = img;
|
||||
}
|
||||
|
||||
return img;
|
||||
|
|
|
|||
Loading…
Reference in a new issue