Prevent duplicate image loading and cache loaded images in MessageItemView

This commit is contained in:
Stone_Red
2026-07-16 13:38:40 +02:00
parent dddf5b6fc7
commit fd72586827
3 changed files with 42 additions and 19 deletions
+9 -6
View File
@@ -606,14 +606,17 @@ public sealed class MainWindowViewModel : ViewModelBase
try try
{ {
List<MessageModel> history = await ConnectionService.JoinChannelAsync(serverUrl, channel.Name); List<MessageModel> history = await ConnectionService.JoinChannelAsync(serverUrl, channel.Name);
Avalonia.Threading.Dispatcher.UIThread.Post(() => Avalonia.Threading.Dispatcher.UIThread.Post(() =>
{
channel.ClearMessages();
foreach (MessageModel msg in history)
{ {
channel.AddMessage(msg); if (channel.Messages.Count == 0)
} {
}); foreach (MessageModel msg in history)
{
channel.AddMessage(msg);
}
}
});
} }
catch catch
{ {
+3
View File
@@ -1,4 +1,5 @@
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.Imaging;
using Decho.Models; using Decho.Models;
@@ -10,6 +11,8 @@ public sealed class MessageViewModel(MessageModel model) : ViewModelBase
{ {
public MessageModel Model { get; } = model; public MessageModel Model { get; } = model;
public Bitmap? CachedImage { get; set; }
public string AuthorName => Model.Author.DisplayName; public string AuthorName => Model.Author.DisplayName;
public IBrush? AuthorColor public IBrush? AuthorColor
+30 -13
View File
@@ -12,7 +12,7 @@ namespace Decho.Views;
public partial class MessageItemView : UserControl public partial class MessageItemView : UserControl
{ {
private CancellationTokenSource? _loadCts; private CancellationTokenSource? _loadCts;
private bool _pendingLoad; private string? _loadedMessageId;
public MessageItemView() public MessageItemView()
{ {
@@ -23,20 +23,37 @@ public partial class MessageItemView : UserControl
private void OnDataContextChanged(object? sender, EventArgs args) private void OnDataContextChanged(object? sender, EventArgs args)
{ {
_loadCts?.Cancel(); if (DataContext is MessageViewModel newMsg && newMsg.Model.Id == _loadedMessageId)
_loadCts = new CancellationTokenSource();
_pendingLoad = DataContext is MessageViewModel msg && msg.IsImage && msg.AttachmentUrl is not null;
}
private void OnLoaded(object? sender, RoutedEventArgs e)
{
if (!_pendingLoad)
{ {
return; return;
} }
_pendingLoad = false; _loadCts?.Cancel();
MessageViewModel msg = (MessageViewModel)DataContext!; _loadCts = new CancellationTokenSource();
this.FindControl<Image>("MessageImage")?.ClearValue(Image.SourceProperty);
_loadedMessageId = null;
}
private void OnLoaded(object? sender, RoutedEventArgs e)
{
if (DataContext is not MessageViewModel msg || !msg.IsImage || msg.AttachmentUrl is null)
{
return;
}
if (msg.Model.Id == _loadedMessageId)
{
return;
}
_loadedMessageId = msg.Model.Id;
if (msg.CachedImage is not null)
{
this.FindControl<Image>("MessageImage")!.Source = msg.CachedImage;
return;
}
_ = LoadImageAsync(msg, _loadCts!.Token); _ = LoadImageAsync(msg, _loadCts!.Token);
} }
@@ -62,8 +79,8 @@ public partial class MessageItemView : UserControl
using MemoryStream stream = new MemoryStream(bytes); using MemoryStream stream = new MemoryStream(bytes);
Bitmap bitmap = new Bitmap(stream); Bitmap bitmap = new Bitmap(stream);
ct.ThrowIfCancellationRequested(); ct.ThrowIfCancellationRequested();
Image? image = this.FindControl<Image>("MessageImage"); msg.CachedImage = bitmap;
_ = image?.Source = bitmap; this.FindControl<Image>("MessageImage")!.Source = bitmap;
} }
catch catch
{ {