mirror of
https://github.com/RedWizardsLab/EchoHub.git
synced 2026-09-04 08:36:11 +02:00
feat: enhance file upload and URL sending with optional size parameter
This commit is contained in:
@@ -214,7 +214,8 @@ public class ChatListSource : IListDataSource
|
||||
listView.Move(Math.Max(col - viewportX, 0), row);
|
||||
|
||||
var chatLine = _lines[item];
|
||||
var normalAttr = listView.GetAttributeForRole(selected ? VisualRole.Focus : VisualRole.Normal);
|
||||
// Always use Normal — chat messages should not show focus/selection highlight
|
||||
var normalAttr = listView.GetAttributeForRole(VisualRole.Normal);
|
||||
var mentionBg = chatLine.IsMention ? ChatColors.MentionHighlightAttr.Background : (Color?)null;
|
||||
|
||||
int charPos = 0;
|
||||
@@ -368,6 +369,85 @@ public class ChannelListSource : IListDataSource
|
||||
public void Dispose() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom list data source for the online users panel with per-user nickname colors.
|
||||
/// </summary>
|
||||
public class UserListSource : IListDataSource
|
||||
{
|
||||
private readonly List<(string Text, Attribute? NameColor)> _users = [];
|
||||
|
||||
public event NotifyCollectionChangedEventHandler? CollectionChanged;
|
||||
public int Count => _users.Count;
|
||||
public int MaxItemLength { get; private set; }
|
||||
public bool SuspendCollectionChangedEvent { get; set; }
|
||||
|
||||
public void Update(List<(string Text, Attribute? NameColor)> users)
|
||||
{
|
||||
_users.Clear();
|
||||
_users.AddRange(users);
|
||||
MaxItemLength = users.Count > 0 ? users.Max(u => u.Text.Length) : 0;
|
||||
if (!SuspendCollectionChangedEvent)
|
||||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
public bool IsMarked(int item) => false;
|
||||
public void SetMark(int item, bool value) { }
|
||||
public IList ToList() => _users.Select(u => u.Text).ToList();
|
||||
|
||||
public void Render(ListView listView, bool selected, int item, int col, int row, int width, int viewportX = 0)
|
||||
{
|
||||
listView.Move(Math.Max(col - viewportX, 0), row);
|
||||
|
||||
var (text, nameColor) = _users[item];
|
||||
var normalAttr = listView.GetAttributeForRole(selected ? VisualRole.Focus : VisualRole.Normal);
|
||||
|
||||
// Find where the name starts (after status icon + space + optional role badge)
|
||||
// Format: "● ★Username" or "● Username"
|
||||
int nameStart = 0;
|
||||
int i = 0;
|
||||
// Skip status icon
|
||||
while (i < text.Length && !char.IsLetterOrDigit(text[i]) && text[i] != '_') i++;
|
||||
nameStart = i;
|
||||
|
||||
int drawnChars = 0;
|
||||
|
||||
// Draw prefix (status icon + role badge) in normal color
|
||||
var prefixAttr = normalAttr;
|
||||
for (int c = 0; c < nameStart && c < text.Length; c++)
|
||||
{
|
||||
if (drawnChars < width)
|
||||
{
|
||||
listView.SetAttribute(prefixAttr);
|
||||
listView.AddRune(new Rune(text[c]));
|
||||
drawnChars++;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw name in nickname color
|
||||
var userAttr = nameColor ?? normalAttr;
|
||||
if (selected) userAttr = normalAttr; // use focus attr when selected
|
||||
for (int c = nameStart; c < text.Length; c++)
|
||||
{
|
||||
if (drawnChars < width)
|
||||
{
|
||||
listView.SetAttribute(userAttr);
|
||||
listView.AddRune(new Rune(text[c]));
|
||||
drawnChars++;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill rest
|
||||
listView.SetAttribute(normalAttr);
|
||||
while (drawnChars < width)
|
||||
{
|
||||
listView.AddRune(new Rune(' '));
|
||||
drawnChars++;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shared color attributes for chat rendering (timestamps, system messages).
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using EchoHub.Client.Themes;
|
||||
using EchoHub.Core.DTOs;
|
||||
@@ -30,6 +29,7 @@ public sealed class MainWindow : Runnable
|
||||
// Online users panel
|
||||
private readonly FrameView _usersFrame;
|
||||
private readonly ListView _usersList;
|
||||
private readonly UserListSource _usersListSource;
|
||||
private bool _usersPanelVisible = true;
|
||||
private const int UsersPanelWidth = 22;
|
||||
private static readonly Key F2Key = Key.F2;
|
||||
@@ -215,7 +215,8 @@ public sealed class MainWindow : Runnable
|
||||
Width = Dim.Fill(),
|
||||
Height = Dim.Fill()
|
||||
};
|
||||
_usersList.SetSource(new ObservableCollection<string>());
|
||||
_usersListSource = new UserListSource();
|
||||
_usersList.Source = _usersListSource;
|
||||
_usersFrame.Add(_usersList);
|
||||
Add(_usersFrame);
|
||||
|
||||
@@ -679,7 +680,8 @@ public sealed class MainWindow : Runnable
|
||||
_chatFrame.Title = "Chat";
|
||||
_topicLabel.Visible = false;
|
||||
_chatFrame.Y = 1;
|
||||
_usersList.SetSource(new ObservableCollection<string>());
|
||||
_usersListSource.Update([]);
|
||||
_usersList.Source = _usersListSource;
|
||||
_usersFrame.Title = "Users";
|
||||
RefreshMessages();
|
||||
}
|
||||
@@ -805,10 +807,13 @@ public sealed class MainWindow : Runnable
|
||||
ServerRole.Mod => "\u2740", // ❀
|
||||
_ => ""
|
||||
};
|
||||
return $"{statusIcon} {roleTag}{name}";
|
||||
var text = $"{statusIcon} {roleTag}{name}";
|
||||
var nameColor = ColorHelper.ParseHexColor(u.NicknameColor);
|
||||
return (text, nameColor);
|
||||
}).ToList();
|
||||
|
||||
_usersList.SetSource(new ObservableCollection<string>(displayItems));
|
||||
_usersListSource.Update(displayItems);
|
||||
_usersList.Source = _usersListSource;
|
||||
_usersFrame.Title = $"Users ({users.Count})";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user