diff --git a/src/EchoHub.Client/UI/ChatRenderer.cs b/src/EchoHub.Client/UI/ChatRenderer.cs
index 911c595..d1b1fbb 100644
--- a/src/EchoHub.Client/UI/ChatRenderer.cs
+++ b/src/EchoHub.Client/UI/ChatRenderer.cs
@@ -35,6 +35,58 @@ public partial class ChatLine
public override string ToString() => string.Concat(Segments.Select(s => s.Text));
+ ///
+ /// Wrap this line into multiple lines that fit within the given width.
+ /// Continuation lines are indented with the specified number of spaces.
+ ///
+ public List Wrap(int width, int continuationIndent = 0)
+ {
+ if (width <= 0 || TextLength <= width)
+ return [this];
+
+ var results = new List();
+ var currentSegments = new List();
+ 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;
+ }
+
///
/// 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)
diff --git a/src/EchoHub.Client/UI/MainWindow.cs b/src/EchoHub.Client/UI/MainWindow.cs
index 3cebdd3..a385f4b 100644
--- a/src/EchoHub.Client/UI/MainWindow.cs
+++ b/src/EchoHub.Client/UI/MainWindow.cs
@@ -45,6 +45,7 @@ public sealed class MainWindow : Runnable
private readonly Dictionary _channelTopics = [];
private string _currentChannel = string.Empty;
private string _currentUser = string.Empty;
+ private int _lastChatWidth;
///
/// 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
{
diff --git a/src/EchoHub.Client/UI/UserPanelDialog.cs b/src/EchoHub.Client/UI/UserPanelDialog.cs
index 0291063..b82e357 100644
--- a/src/EchoHub.Client/UI/UserPanelDialog.cs
+++ b/src/EchoHub.Client/UI/UserPanelDialog.cs
@@ -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
{