Browse Source

Fix cached image appearing after deletion

pull/165/head
Ionite 1 year ago
parent
commit
2eb9ca99e9
No known key found for this signature in database
  1. 21
      StabilityMatrix.Avalonia/FallbackRamCachedWebImageLoader.cs
  2. 5
      StabilityMatrix.Avalonia/ViewModels/Inference/ImageFolderCardViewModel.cs
  3. 68
      StabilityMatrix.Core/Extensions/ObjectExtensions.cs

21
StabilityMatrix.Avalonia/FallbackRamCachedWebImageLoader.cs

@ -75,12 +75,27 @@ public class FallbackRamCachedWebImageLoader : RamCachedWebImageLoader
}
}
public void RemoveFromCache(string url)
public void RemovePathFromCache(string filePath)
{
// ConcurrentDictionary<string, Task<Bitmap?>> _memoryCache
var cache =
this.GetPrivateField<ConcurrentDictionary<string, Task<Bitmap?>>>("_memoryCache")
?? throw new NullReferenceException("Memory cache not found");
cache.TryRemove(url, out _);
cache.TryRemove(filePath, out _);
}
public void RemoveAllNamesFromCache(string fileName)
{
var cache =
this.GetPrivateField<ConcurrentDictionary<string, Task<Bitmap?>>>("_memoryCache")
?? throw new NullReferenceException("Memory cache not found");
foreach (var (key, _) in cache)
{
if (Path.GetFileName(key) == fileName)
{
cache.TryRemove(key, out _);
}
}
}
}

5
StabilityMatrix.Avalonia/ViewModels/Inference/ImageFolderCardViewModel.cs

@ -133,7 +133,8 @@ public partial class ImageFolderCardViewModel : ViewModelBase
}
// Delete the file
var result = await notificationService.TryAsync(new FilePath(imagePath).DeleteAsync());
var imageFile = new FilePath(imagePath);
var result = await notificationService.TryAsync(imageFile.DeleteAsync());
if (!result.IsSuccessful)
{
@ -149,7 +150,7 @@ public partial class ImageFolderCardViewModel : ViewModelBase
// Invalidate cache
if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader)
{
loader.RemoveFromCache(imagePath);
loader.RemoveAllNamesFromCache(imageFile.Name);
}
}

68
StabilityMatrix.Core/Extensions/ObjectExtensions.cs

@ -3,19 +3,24 @@ using RockLib.Reflection.Optimized;
namespace StabilityMatrix.Core.Extensions;
public static class ObjectExtensions
{
/// <summary>
/// Cache of Types to named field getters
/// </summary>
private static readonly Dictionary<Type, Dictionary<string, Func<object, object>>> FieldGetterTypeCache = new();
private static readonly Dictionary<
Type,
Dictionary<string, Func<object, object>>
> FieldGetterTypeCache = new();
/// <summary>
/// Cache of Types to named field setters
/// </summary>
private static readonly Dictionary<Type, Dictionary<string, Action<object, object>>> FieldSetterTypeCache = new();
private static readonly Dictionary<
Type,
Dictionary<string, Action<object, object>>
> FieldSetterTypeCache = new();
/// <summary>
/// Get the value of a named private field from an object
/// </summary>
@ -27,22 +32,29 @@ public static class ObjectExtensions
if (!fieldGetterCache.TryGetValue(fieldName, out var fieldGetter))
{
// Get the field
var field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
var field = obj.GetType()
.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
// Try get from parent
field ??= obj.GetType()
.BaseType?.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field is null)
{
throw new ArgumentException($"Field {fieldName} not found on type {obj.GetType().Name}");
throw new ArgumentException(
$"Field {fieldName} not found on type {obj.GetType().Name}"
);
}
// Create a getter for the field
fieldGetter = field.CreateGetter();
// Add to cache
fieldGetterCache.Add(fieldName, fieldGetter);
}
return (T?) fieldGetter(obj);
return (T?)fieldGetter(obj);
}
/// <summary>
/// Set the value of a named private field on an object
/// </summary>
@ -54,25 +66,29 @@ public static class ObjectExtensions
if (!fieldSetterCache.TryGetValue(fieldName, out var fieldSetter))
{
// Get the field
var field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
var field = obj.GetType()
.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
// Try get from parent
field ??= obj.GetType().BaseType?.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
field ??= obj.GetType()
.BaseType?.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field is null)
{
throw new ArgumentException($"Field {fieldName} not found on type {obj.GetType().Name}");
throw new ArgumentException(
$"Field {fieldName} not found on type {obj.GetType().Name}"
);
}
// Create a setter for the field
fieldSetter = field.CreateSetter();
// Add to cache
fieldSetterCache.Add(fieldName, fieldSetter);
}
fieldSetter(obj, value);
}
/// <summary>
/// Set the value of a named private field on an object
/// </summary>
@ -84,18 +100,22 @@ public static class ObjectExtensions
if (!fieldSetterCache.TryGetValue(fieldName, out var fieldSetter))
{
// Get the field
var field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
var field = obj.GetType()
.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
// Try get from parent
field ??= obj.GetType().BaseType?.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
field ??= obj.GetType()
.BaseType?.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field is null)
{
throw new ArgumentException($"Field {fieldName} not found on type {obj.GetType().Name}");
throw new ArgumentException(
$"Field {fieldName} not found on type {obj.GetType().Name}"
);
}
// Create a setter for the field
fieldSetter = field.CreateSetter();
// Add to cache
fieldSetterCache.Add(fieldName, fieldSetter);
}

Loading…
Cancel
Save