New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Overhaul IRC in preparation for the global chat UI #9586
Conversation
The dispose commit will need to be redone. It currently disposes even when a window is temporarily hidden, which then breaks the chat when it is added to the game lobby (doesn't affect testing in the server brwoser, though). |
{ | ||
Log.Write("debug", "Failed to load server browser IRC chrome layout"); | ||
} | ||
Game.LoadWidget(null, "GLOBALCHAT_PANEL", panel.Get("GLOBALCHAT_ROOT"), new WidgetArgs()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will make the IRC feature mandatory for every mod. Attention @phrohdoh this will break your RA2 branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should be making any widget mandatory, and we shouldn't force (our!) IRC on thirdparty mods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mods that don't want this can define a dummy GLOBALCHAT_PANEL
widget to disable it. The try/catch makes it impossible to debug any errors in the IRC logic, and leaves a bogus widget state when it does die.
Fixed the disposing logic. |
var font = Game.Renderer.Fonts[widget.Font]; | ||
|
||
var color = message.Type == ChatMessageType.Notification ? | ||
Color.LightGray : Color.White; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the subtle color differentiation, but I guess this wants to live in metrics.yaml
instead.
This can crash if the IRC thread adds a message to the History or Users collections while the UI thread is enumerating them. I'll need to ensure that all dictionary accesses are done on the main thread - running just the widget updates in a RunAfterTick is not enough. |
} | ||
} | ||
|
||
public sealed class ChatUserComparer : IComparer<string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use one of the static members on System.StringComparer
and save yourself this class.
9c96722
to
189033c
Compare
Fixed all above comments. |
|
||
public class GlobalChat : IDisposable | ||
{ | ||
volatile IrcClient client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
volatile
is pointless here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was carried over from the earlier code, where I believe you asked for it yourself :P.
But you're right - this is only ever accessed from the worker thread now.
{ | ||
// Set a random default nick | ||
if (Game.Settings.Chat.Nickname == new ChatSettings().Nickname) | ||
Game.Settings.Chat.Nickname += Game.CosmeticRandom.Next(100, 999); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying globals from a random static constructor is just asking for trouble with initialization order. You should move this somewhere more deterministic.
Updated. |
connectionStatus = ChatConnectionStatus.Connected; | ||
|
||
// Guard against settings.yaml modification | ||
Game.Settings.Chat.Nickname = SanitizedName(Game.Settings.Chat.Nickname); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This write isn't thread-safe (since we usually only muck with globals on the UI thread).
d6cf33f
to
0464afa
Compare
Fixed some more. Also fixed an inherited jank when first connecting to the IRC sever. |
Game.RunAfterTick(() => Log.Write("irc", e.ToString())); | ||
} | ||
|
||
client.Listen(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the connect fails, do we still want to listen?
Chat still works. ✅ / 👍 |
* Simplified UI plumbing. * Improves handling of errors and kicks. * Persists chat history between session. * Fixes leaks of the old widget tree when exiting. * A few small UI polish improvements.
Updated. |
foreach (DictionaryEntry user in channel.Users) | ||
{ | ||
var u = (ChannelUser)user.Value; | ||
Game.RunAfterTick(() => Users.Add(u.Nick, new ChatUser(u.Nick, u.IsOp, u.IsVoice))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is supposed to sync the server's and client's state, right? If so, wouldn't you need to use Users.Clear()
before repopulating the list? Or does this only happen once when joining?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't read the docs on this callback, but @Mailaender set it up as if it were used exclusively on first join to the channel. If it may be called multiple times, it would indeed be necessary to clear the dict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it only happens that once. At least it doesn't happen when users join or leave. Could be that it's run once every hour or so, but I didn't test that long.
Looks and works fine. 👍 |
Overhaul IRC in preparation for the global chat UI
The existing code didn't scale to multiple panels, so I have reorganized and simplified it in preparation for the lobby and ingame integration.
This mainly focuses on the backend code, but there are a few visible changes: