mirror of
https://github.com/Stone-Red-Code/EchoHub.git
synced 2026-09-04 09:06:07 +02:00
feat: Implement chat line wrapping and viewport resizing for message display
This commit is contained in:
@@ -35,6 +35,58 @@ public partial class ChatLine
|
||||
|
||||
public override string ToString() => string.Concat(Segments.Select(s => s.Text));
|
||||
|
||||
/// <summary>
|
||||
/// Wrap this line into multiple lines that fit within the given width.
|
||||
/// Continuation lines are indented with the specified number of spaces.
|
||||
/// </summary>
|
||||
public List<ChatLine> Wrap(int width, int continuationIndent = 0)
|
||||
{
|
||||
if (width <= 0 || TextLength <= width)
|
||||
return [this];
|
||||
|
||||
var results = new List<ChatLine>();
|
||||
var currentSegments = new List<ChatSegment>();
|
||||
int col = 0;
|
||||
|
||||
foreach (var segment in Segments)
|
||||
{
|
||||
int segPos = 0;
|
||||
while (segPos < segment.Text.Length)
|
||||
{
|
||||
int remaining = width - col;
|
||||
if (remaining <= 0)
|
||||
{
|
||||
// Emit current line and start a new one
|
||||
results.Add(new ChatLine(currentSegments));
|
||||
currentSegments = [];
|
||||
|
||||
// Add indent for continuation
|
||||
if (continuationIndent > 0)
|
||||
{
|
||||
currentSegments.Add(new ChatSegment(new string(' ', continuationIndent), null));
|
||||
col = continuationIndent;
|
||||
}
|
||||
else
|
||||
{
|
||||
col = 0;
|
||||
}
|
||||
|
||||
remaining = width - col;
|
||||
}
|
||||
|
||||
int take = Math.Min(segment.Text.Length - segPos, remaining);
|
||||
currentSegments.Add(new ChatSegment(segment.Text.Substring(segPos, take), segment.Color));
|
||||
col += take;
|
||||
segPos += take;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentSegments.Count > 0)
|
||||
results.Add(new ChatLine(currentSegments));
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a string containing ANSI 24-bit color escape codes into colored segments.
|
||||
/// Format: \x1b[38;2;R;G;Bm (foreground color), \x1b[0m (reset)
|
||||
|
||||
@@ -45,6 +45,7 @@ public sealed class MainWindow : Runnable
|
||||
private readonly Dictionary<string, string?> _channelTopics = [];
|
||||
private string _currentChannel = string.Empty;
|
||||
private string _currentUser = string.Empty;
|
||||
private int _lastChatWidth;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when the user selects a channel. Parameter is the channel name.
|
||||
@@ -192,6 +193,9 @@ public sealed class MainWindow : Runnable
|
||||
// Apply our custom color schemes to all views
|
||||
ApplyColorSchemes();
|
||||
|
||||
// Re-wrap messages when the chat area is resized
|
||||
_messageList.ViewportChanged += (_, _) => OnChatViewportChanged();
|
||||
|
||||
// Window-level key handling for Ctrl+C (quit)
|
||||
KeyDown += OnWindowKeyDown;
|
||||
}
|
||||
@@ -368,6 +372,16 @@ public sealed class MainWindow : Runnable
|
||||
}
|
||||
}
|
||||
|
||||
private void OnChatViewportChanged()
|
||||
{
|
||||
var newWidth = _messageList.Viewport.Width;
|
||||
if (newWidth > 0 && newWidth != _lastChatWidth)
|
||||
{
|
||||
_lastChatWidth = newWidth;
|
||||
RefreshMessages();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWindowKeyDown(object? sender, Key e)
|
||||
{
|
||||
// Ctrl+C quits from anywhere
|
||||
@@ -588,11 +602,22 @@ public sealed class MainWindow : Runnable
|
||||
{
|
||||
if (_channelMessages.TryGetValue(_currentChannel, out var messages))
|
||||
{
|
||||
var width = _messageList.Viewport.Width;
|
||||
var source = new ChatListSource();
|
||||
source.AddRange(messages);
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
foreach (var line in messages)
|
||||
source.AddRange(line.Wrap(width));
|
||||
}
|
||||
else
|
||||
{
|
||||
source.AddRange(messages);
|
||||
}
|
||||
|
||||
_messageList.Source = source;
|
||||
if (messages.Count > 0)
|
||||
_messageList.SelectedItem = messages.Count - 1;
|
||||
if (source.Count > 0)
|
||||
_messageList.SelectedItem = source.Count - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -146,7 +146,8 @@ public sealed class UserPanelDialog
|
||||
Width = Dim.Fill(1),
|
||||
Height = 3,
|
||||
Text = bioText,
|
||||
ReadOnly = true
|
||||
ReadOnly = true,
|
||||
WordWrap = true
|
||||
};
|
||||
bioView.SetScheme(new Scheme
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user