add color to server

This commit is contained in:
Benjamin Palko 2025-05-22 14:19:37 -04:00
parent 5147dbefc9
commit 1781d2acbb
5 changed files with 118 additions and 24 deletions

17
client/UserUtils.cs Normal file
View file

@ -0,0 +1,17 @@
using Godot;
using SpacetimeDB.Types;
public static class UserUtils
{
public static Color ParseColor(User user)
{
return user.Color != null && Color.HtmlIsValid(user.Color)
? Color.FromHtml(user.Color)
: Colors.AliceBlue;
}
public static string UserNameOrIdentity(User user)
{
return user != null ? user.Name ?? user.Identity.ToString()[..8] : "unknown";
}
}

1
client/UserUtils.cs.uid Normal file
View file

@ -0,0 +1 @@
uid://dnaxnse8ipje0

View file

@ -4,7 +4,7 @@ using SpacetimeDB.Types;
public partial class ChatLog : RichTextLabel
{
const string SystemColor = "#747474";
private static readonly Color SystemColor = Colors.Gray;
public override void _EnterTree()
{
@ -17,14 +17,9 @@ public partial class ChatLog : RichTextLabel
RegisterSubscriptions(conn);
}
string UserNameOrIdentity(User user)
void PushMessage(string name, string message, Color color)
{
return user != null ? user.Name ?? user.Identity.ToString()[..8] : "unknown";
}
void PushMessage(string name, string message, string color)
{
string entry = $"[color={color}]{name}:[/color] {message}";
string entry = $"[color={color.ToHtml()}]{name}:[/color] {message}";
this.Text += $"{entry}\n";
}
@ -47,7 +42,11 @@ public partial class ChatLog : RichTextLabel
{
return;
}
PushMessage("System", $"{UserNameOrIdentity(insertedValue)} connected", SystemColor);
PushMessage(
"System",
$"{UserUtils.UserNameOrIdentity(insertedValue)} connected",
SystemColor
);
}
void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
@ -56,7 +55,7 @@ public partial class ChatLog : RichTextLabel
{
PushMessage(
"System",
$"{UserNameOrIdentity(oldValue)} renamed to {UserNameOrIdentity(newValue)}",
$"{UserUtils.UserNameOrIdentity(oldValue)} renamed to {UserUtils.UserNameOrIdentity(newValue)}",
SystemColor
);
}
@ -64,11 +63,19 @@ public partial class ChatLog : RichTextLabel
{
if (newValue.Online)
{
PushMessage("System", $"{UserNameOrIdentity(newValue)} connected", SystemColor);
PushMessage(
"System",
$"{UserUtils.UserNameOrIdentity(newValue)} connected",
SystemColor
);
}
else
{
PushMessage("System", $"{UserNameOrIdentity(newValue)} disconnected", SystemColor);
PushMessage(
"System",
$"{UserUtils.UserNameOrIdentity(newValue)} disconnected",
SystemColor
);
}
}
}
@ -76,12 +83,12 @@ public partial class ChatLog : RichTextLabel
void Message_OnInsert(EventContext ctx, Message insertedValue)
{
User sender = ctx.Db.User.Identity.Find(insertedValue.Sender);
string color = sender.Identity.Equals(Spacetime.Instance.Identity) ? "blue" : "red";
Color color = ctx.Identity == sender.Identity ? UserUtils.ParseColor(sender) : Colors.Red;
if (ctx.Event is Event<Reducer>.SubscribeApplied)
{
PushMessage(UserNameOrIdentity(sender), insertedValue.Text, color);
PushMessage(UserUtils.UserNameOrIdentity(sender), insertedValue.Text, color);
return;
}
PushMessage(UserNameOrIdentity(sender), insertedValue.Text, color);
PushMessage(UserUtils.UserNameOrIdentity(sender), insertedValue.Text, color);
}
}

View file

@ -12,8 +12,10 @@ public partial class ChatOptions : HBoxContainer
Username = GetNode<LineEdit>("Username");
ColorPicker = GetNode<ColorPickerButton>("ColorPicker");
Username.TextSubmitted += OnUsernameInput;
Username.TextSubmitted += OnUsernameChanged;
Username.FocusExited += ResetUsername;
ColorPicker.ColorChanged += OnColorChange;
}
public override void _Ready()
@ -22,24 +24,52 @@ public partial class ChatOptions : HBoxContainer
RegisterSubscriptions(conn);
}
string UserNameOrIdentity(User user)
{
return user != null ? user.Name ?? user.Identity.ToString()[..8] : "unknown";
}
void ResetUsername()
{
Username.Text = UserNameOrIdentity(Spacetime.Instance.Me);
Username.Text = UserUtils.UserNameOrIdentity(Spacetime.Instance.Me);
}
void OnUsernameInput(string text)
void OnUsernameChanged(string text)
{
Spacetime.Instance.Connection.Reducers.SetName(text);
}
void OnColorChange(Color color)
{
Spacetime.Instance.Connection.Reducers.SetColor(color.ToHtml(false));
}
void RegisterSubscriptions(DbConnection conn)
{
conn.Db.User.OnInsert += User_OnInsert;
conn.Db.User.OnUpdate += User_OnUpdate;
conn.Reducers.OnSetName += Reducer_OnSetNameEvent;
conn.Reducers.OnSetColor += Reducer_OnSetColorEvent;
}
void User_OnInsert(EventContext ctx, User insertedValue)
{
// It's me
if (ctx.Identity == insertedValue.Identity)
{
Username.Text = insertedValue.Name;
ColorPicker.Color =
insertedValue.Color != null && Color.HtmlIsValid(insertedValue.Color)
? Color.FromHtml(insertedValue.Color)
: Colors.AliceBlue;
}
}
void User_OnUpdate(EventContext ctx, User oldValue, User newValue)
{
if (ctx.Identity == oldValue.Identity && ctx.Identity == newValue.Identity)
{
Username.Text = newValue.Name;
ColorPicker.Color =
newValue.Color != null && Color.HtmlIsValid(newValue.Color)
? Color.FromHtml(newValue.Color)
: Colors.AliceBlue;
}
}
/// Our `OnSetNameEvent` callback: print a warning if the reducer failed.
@ -57,4 +87,19 @@ public partial class ChatOptions : HBoxContainer
return;
}
}
void Reducer_OnSetColorEvent(ReducerEventContext ctx, string color)
{
var e = ctx.Event;
if (e.CallerIdentity != Spacetime.Instance.Identity)
{
// Not me
return;
}
if (e.Status is Status.Failed(var error))
{
GD.PrintErr($"Failed to change color to {color}: {error}");
return;
}
}
}

View file

@ -1,3 +1,4 @@
using System.Text.RegularExpressions;
using SpacetimeDB;
public static partial class Module
@ -8,6 +9,7 @@ public static partial class Module
[PrimaryKey]
public Identity Identity;
public string? Name;
public string? Color;
public bool Online;
}
@ -42,6 +44,29 @@ public static partial class Module
return name;
}
[Reducer]
public static void SetColor(ReducerContext ctx, string color)
{
color = ValidateColor(color);
var user = ctx.Db.User.Identity.Find(ctx.Sender);
if (user is not null)
{
user.Color = color;
ctx.Db.User.Identity.Update(user);
}
}
private static string ValidateColor(string color)
{
var regex = new Regex("^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$");
if (!regex.IsMatch(color))
{
throw new Exception("Invalid color code");
}
return color;
}
[Reducer]
public static void SendMessage(ReducerContext ctx, string text)
{
@ -113,4 +138,3 @@ public static partial class Module
}
}
}