From cf9dd4addb324aeb9224618d4b9c896b0adb4e55 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sun, 30 Oct 2022 14:39:57 -0500 Subject: [PATCH] Respect loadFullImage Option in ImageCache.cs --- .../Image/ImageCache.cs | 36 ++++++++-------- .../Image/ImageLoader.cs | 41 ++++++++++--------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs index 04e11bf1a..2fd2291d4 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs @@ -25,11 +25,11 @@ namespace Flow.Launcher.Infrastructure.Image public class ImageCache { private const int MaxCached = 50; - public ConcurrentDictionary Data { get; private set; } = new ConcurrentDictionary(); + public ConcurrentDictionary<(string, bool), ImageUsage> Data { get; } = new(); private const int permissibleFactor = 2; private SemaphoreSlim semaphore = new(1, 1); - public void Initialization(Dictionary 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(); } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index e0d1d5034..2888b3c92 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -17,7 +17,7 @@ namespace Flow.Launcher.Infrastructure.Image public static class ImageLoader { private static readonly ImageCache ImageCache = new(); - private static BinaryStorage> _storage; + private static BinaryStorage> _storage; private static readonly ConcurrentDictionary 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>("Image"); + _storage = new BinaryStorage>("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 LoadStorageToConcurrentDictionary() + private static ConcurrentDictionary<(string, bool), int> LoadStorageToConcurrentDictionary() { lock (_storage) { - var loaded = _storage.TryLoad(new Dictionary()); + var loaded = _storage.TryLoad(new Dictionary<(string, bool), int>()); - return new ConcurrentDictionary(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 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;