feat: enhance profile view dialog to render ASCII avatars with color tags

This commit is contained in:
HueByte
2026-02-19 19:48:48 +01:00
parent 0dbb02d12a
commit 7181748d40
2 changed files with 74 additions and 20 deletions
+48 -15
View File
@@ -136,20 +136,8 @@ public class CommandHandler
if (string.IsNullOrWhiteSpace(args))
return new CommandResult(true, "Usage: /send <filepath or URL> [-s|-m|-l]", IsError: true);
// Parse optional size flag (-s, -m, -l)
string? size = null;
var parts = args.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
var targetParts = new List<string>();
foreach (var part in parts)
{
if (part is "-s" or "-m" or "-l")
size = part[1..]; // "s", "m", or "l"
else
targetParts.Add(part);
}
var target = string.Join(' ', targetParts).Trim('"');
// Extract optional size flag from end or start, respecting quoted paths
var (target, size) = ParsePathAndSizeFlag(args);
if (string.IsNullOrWhiteSpace(target))
return new CommandResult(true, "Usage: /send <filepath or URL> [-s|-m|-l]", IsError: true);
@@ -186,7 +174,7 @@ public class CommandHandler
if (string.IsNullOrWhiteSpace(args))
return new CommandResult(true, "Usage: /avatar <URL or filepath>", IsError: true);
var target = args.Trim().Trim('"');
var target = StripQuotes(args.Trim());
if (OnSetAvatar is not null)
await OnSetAvatar(target);
@@ -362,6 +350,51 @@ public class CommandHandler
""");
}
/// <summary>
/// Extract a file path (possibly quoted) and an optional size flag (-s, -m, -l).
/// The flag can appear before or after the path.
/// </summary>
private static (string Path, string? Size) ParsePathAndSizeFlag(string args)
{
var trimmed = args.Trim();
string? size = null;
// Check for flag at the end: "path" -m or path -m
if (trimmed.Length > 3)
{
var suffix = trimmed[^2..];
if (suffix is "-s" or "-m" or "-l" && trimmed[^3] == ' ')
{
size = suffix[1..];
trimmed = trimmed[..^3].TrimEnd();
}
}
// Check for flag at the start: -m "path" or -m path
if (size is null && trimmed.Length > 3)
{
var prefix = trimmed[..2];
if (prefix is "-s" or "-m" or "-l" && trimmed[2] == ' ')
{
size = prefix[1..];
trimmed = trimmed[3..].TrimStart();
}
}
return (StripQuotes(trimmed), size);
}
/// <summary>
/// Remove matching surrounding quotes (double or single) from a string.
/// </summary>
private static string StripQuotes(string s)
{
if (s.Length >= 2 &&
((s[0] == '"' && s[^1] == '"') || (s[0] == '\'' && s[^1] == '\'')))
return s[1..^1];
return s;
}
private static bool IsValidHex(string s) =>
s.All(c => char.IsAsciiHexDigit(c));
}
+26 -5
View File
@@ -140,12 +140,20 @@ public sealed class ProfileViewDialog
dialog.Add(bioView);
row += 3;
// ASCII Avatar
// ASCII Avatar — render with color tags
if (!string.IsNullOrWhiteSpace(profile.AvatarAscii))
{
row++;
var avatarLines = profile.AvatarAscii.Split('\n').Length;
var avatarHeight = Math.Min(avatarLines + 2, 6);
var rawLines = profile.AvatarAscii.Split('\n');
var avatarSource = new ChatListSource();
foreach (var line in rawLines)
{
avatarSource.Add(ChatLine.HasColorTags(line)
? ChatLine.FromColoredText(line)
: new ChatLine(line));
}
var avatarHeight = Math.Min(rawLines.Length + 2, 24);
var avatarFrame = new FrameView
{
Title = "Avatar",
@@ -154,9 +162,22 @@ public sealed class ProfileViewDialog
Width = Dim.Fill(2),
Height = avatarHeight
};
avatarFrame.Add(new Label { Text = profile.AvatarAscii, X = 0, Y = 0 });
var avatarList = new ListView
{
X = 0,
Y = 0,
Width = Dim.Fill(),
Height = Dim.Fill(),
Source = avatarSource
};
avatarFrame.Add(avatarList);
dialog.Add(avatarFrame);
// Grow dialog to fit avatar
// Grow dialog to fit avatar + widen for art
var artWidth = rawLines.Max(l => ChatLine.HasColorTags(l)
? ChatLine.FromColoredText(l).TextLength
: l.Length);
dialog.Width = Math.Max(50, artWidth + 6);
dialog.Height = row + avatarHeight + 4;
}