diff --git a/src/Decho/ViewModels/MainWindowViewModel.cs b/src/Decho/ViewModels/MainWindowViewModel.cs index 6d295c8..ed9ae16 100644 --- a/src/Decho/ViewModels/MainWindowViewModel.cs +++ b/src/Decho/ViewModels/MainWindowViewModel.cs @@ -606,14 +606,17 @@ public sealed class MainWindowViewModel : ViewModelBase try { List history = await ConnectionService.JoinChannelAsync(serverUrl, channel.Name); + 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 { diff --git a/src/Decho/ViewModels/MessageViewModel.cs b/src/Decho/ViewModels/MessageViewModel.cs index ef03859..f8e919e 100644 --- a/src/Decho/ViewModels/MessageViewModel.cs +++ b/src/Decho/ViewModels/MessageViewModel.cs @@ -1,4 +1,5 @@ using Avalonia.Media; +using Avalonia.Media.Imaging; using Decho.Models; @@ -10,6 +11,8 @@ public sealed class MessageViewModel(MessageModel model) : ViewModelBase { public MessageModel Model { get; } = model; + public Bitmap? CachedImage { get; set; } + public string AuthorName => Model.Author.DisplayName; public IBrush? AuthorColor diff --git a/src/Decho/Views/MessageItemView.axaml.cs b/src/Decho/Views/MessageItemView.axaml.cs index 65e02ee..4f9e771 100644 --- a/src/Decho/Views/MessageItemView.axaml.cs +++ b/src/Decho/Views/MessageItemView.axaml.cs @@ -12,7 +12,7 @@ namespace Decho.Views; public partial class MessageItemView : UserControl { private CancellationTokenSource? _loadCts; - private bool _pendingLoad; + private string? _loadedMessageId; public MessageItemView() { @@ -23,20 +23,37 @@ public partial class MessageItemView : UserControl private void OnDataContextChanged(object? sender, EventArgs args) { - _loadCts?.Cancel(); - _loadCts = new CancellationTokenSource(); - _pendingLoad = DataContext is MessageViewModel msg && msg.IsImage && msg.AttachmentUrl is not null; - } - - private void OnLoaded(object? sender, RoutedEventArgs e) - { - if (!_pendingLoad) + if (DataContext is MessageViewModel newMsg && newMsg.Model.Id == _loadedMessageId) { return; } - _pendingLoad = false; - MessageViewModel msg = (MessageViewModel)DataContext!; + _loadCts?.Cancel(); + _loadCts = new CancellationTokenSource(); + this.FindControl("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("MessageImage")!.Source = msg.CachedImage; + return; + } + _ = LoadImageAsync(msg, _loadCts!.Token); } @@ -62,8 +79,8 @@ public partial class MessageItemView : UserControl using MemoryStream stream = new MemoryStream(bytes); Bitmap bitmap = new Bitmap(stream); ct.ThrowIfCancellationRequested(); - Image? image = this.FindControl("MessageImage"); - _ = image?.Source = bitmap; + msg.CachedImage = bitmap; + this.FindControl("MessageImage")!.Source = bitmap; } catch {