mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-04 16:46:08 +02:00
feat: load more message history when scrolling to top
This commit is contained in:
@@ -186,6 +186,39 @@ public sealed class ChatMessageManager
|
||||
MessagesChanged?.Invoke(channelName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepend older messages at the front of a channel's buffer, skipping any that are already present.
|
||||
/// Fires <see cref="HistoryPrepended"/> when new lines are actually inserted.
|
||||
/// </summary>
|
||||
public void PrependHistory(string channelName, List<MessageDto> olderMessages)
|
||||
{
|
||||
if (!_channelMessages.TryGetValue(channelName, out var existing))
|
||||
return;
|
||||
|
||||
var existingIds = existing
|
||||
.Where(l => l.MessageId.HasValue)
|
||||
.Select(l => l.MessageId!.Value)
|
||||
.ToHashSet();
|
||||
|
||||
var newLines = olderMessages
|
||||
.Where(m => !existingIds.Contains(m.Id))
|
||||
.SelectMany(FormatMessage)
|
||||
.ToList();
|
||||
|
||||
if (newLines.Count == 0)
|
||||
return;
|
||||
|
||||
existing.InsertRange(0, newLines);
|
||||
|
||||
if (channelName == _currentChannel)
|
||||
HistoryPrepended?.Invoke(channelName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fired after older messages are prepended to a channel's buffer. Parameter is the channel name.
|
||||
/// </summary>
|
||||
public event Action<string>? HistoryPrepended;
|
||||
|
||||
/// <summary>
|
||||
/// Reset all message state (used on disconnect).
|
||||
/// </summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
using EchoHub.Client.Services;
|
||||
using EchoHub.Client.Themes;
|
||||
@@ -117,6 +118,11 @@ public sealed partial class MainWindow : Runnable
|
||||
/// </summary>
|
||||
public event Action? OnSavedServersRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the user scrolls to the top of the message list and older messages should be loaded.
|
||||
/// </summary>
|
||||
public event Action? OnLoadMoreRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the user requests to create a new channel.
|
||||
/// </summary>
|
||||
@@ -162,6 +168,7 @@ public sealed partial class MainWindow : Runnable
|
||||
_app = app;
|
||||
_messageManager = messageManager;
|
||||
_messageManager.MessagesChanged += OnMessagesChanged;
|
||||
_messageManager.HistoryPrepended += OnHistoryPrepended;
|
||||
Arrangement = ViewArrangement.Fixed;
|
||||
|
||||
// Menu bar at the top
|
||||
@@ -222,6 +229,9 @@ public sealed partial class MainWindow : Runnable
|
||||
};
|
||||
_messageList.Source = new ChatListSource();
|
||||
_messageList.Accepting += OnMessageListAccepting;
|
||||
_messageList.VerticalScrollBar.Scrolled += OnMessageListVerticalScrollBarScrolled;
|
||||
_messageList.VerticalScrollBar.Visible = true;
|
||||
|
||||
_chatFrame.Add(_messageList);
|
||||
Add(_chatFrame);
|
||||
|
||||
@@ -478,6 +488,12 @@ public sealed partial class MainWindow : Runnable
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMessageListVerticalScrollBarScrolled(object? sender, EventArgs<int> e)
|
||||
{
|
||||
if (_messageList.VerticalScrollBar.Value == 0)
|
||||
OnLoadMoreRequested?.Invoke();
|
||||
}
|
||||
|
||||
private void OnUsersListAccepting(object? sender, CommandEventArgs e)
|
||||
{
|
||||
var index = _usersList.SelectedItem;
|
||||
@@ -631,6 +647,26 @@ public sealed partial class MainWindow : Runnable
|
||||
RefreshChannelList();
|
||||
}
|
||||
|
||||
private void OnHistoryPrepended(string channelName)
|
||||
{
|
||||
if (channelName != _messageManager.CurrentChannel)
|
||||
return;
|
||||
|
||||
var messages = _messageManager.GetMessages(channelName);
|
||||
if (messages is null)
|
||||
return;
|
||||
|
||||
var oldCount = (_messageList.Source as ChatListSource)?.Count ?? 0;
|
||||
|
||||
RefreshMessages();
|
||||
|
||||
// Scroll to the item that was at the top before the prepend so the user
|
||||
// stays at their previous reading position rather than jumping to the top.
|
||||
var prependedCount = (_messageList.Source as ChatListSource)?.Count - oldCount;
|
||||
if (prependedCount > 0)
|
||||
_messageList.SelectedItem = prependedCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the list of available channels, storing topics, and refresh the channel list view.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user