How to customize ChatMessageInfo / chat author CSS (there is no widget?)

Earlier today, I made a little plugin which lets me customize the author line of each forum post with some CSS based on some special site-specific logic. Example:

function initColorize(api)
{
	api.includePostAttributes('colorized_groups');

	// Hijacking post icons to sneak in CSS for forum posts
	api.addPosterIcons((cfs, attrs) => {
		// (A real icon could be specified by filling in the icon field.
		// I removed the icon though since it was getting a bit cluttered.
		// For now, with no icon specified, it's just for CSS highlighting of name.)	
		if (attrs.colorized_groups.indexOf("developer") > -1)
			return { icon: '', className: 'developer', title: 'Developer' };
		else if (attrs.colorized_groups.indexOf("wip_researcher") > -1)
			return { icon: '', className: 'wip_researcher', title: 'WIP Researcher' };
		else if (attrs.colorized_groups.indexOf("researcher") > -1)
			return { icon: '', className: 'researcher', title: 'Researcher' };
	});

Next, I want to do some similar customizations for real-time chat – but there is no api.addPosterIcons equivalent for real-time chat messages. Maybe I could use the api.decorateWidget, but the corresponding component for chat is ChatMessageInfo which is a component, not a widget.

Sorry if it is obvious, but what would be a good strategy for customizing ChatMessageInfo from a plugin?

(It is intentional that I am not relying on user primary group since there is some special logic for which one should take priority and I don’t want to have to rely on user/admin setting it properly manually.)

Thank you!

Hey,

I think it won’t be easy. There is no available PluginOutlet in this area (don’t hesitate to request it!)

If you want to add only classnames, you should be able to do this way:

api.modifyClass(
  "component:chat/message/info",
  (Superclass) =>
    class extends Superclass {
      get usernameClasses() {
        let classes = super.usernameClasses;

        // Add extra classes
        classes += " developer";

        return classes;
      }
    }
)

it overwrites this code:

1 Like

Thanks for the reply! I actually had gone about it with another solution, but I appreciate you offering yours as it seems a bit cleaner (in mine I have to access the class name and my method feels a bit hacky). Here’s the strategy I used:

// Also colorize names in the real-time chat
api.decorateChatMessage(function (messageContainer, chatChannel) 
{
	let colorized_groups = this.args?.message?.user?.colorized_groups;

	if (colorized_groups == null)
		return; // no groups, nothing to do

	const nameClass = "chat-message-info__username__name";						

	let elements = messageContainer.getElementsByClassName(nameClass);
	if (elements.length == 0) // normal: this might be a second message that does not have the username header
		return; 

	let nameDiv = elements[0];

	if (colorized_groups.indexOf("developer") > -1)
		nameDiv.classList.add("developer");
	else if (colorized_groups.indexOf("wip_researcher") > -1)
		nameDiv.classList.add("wip_researcher");
	else if (colorized_groups.indexOf("researcher") > -1)
		nameDiv.classList.add("researcher");
});

I assume with your method, it also still passes the this.args.message.user ?

1 Like

Good job for finding a way! It’s not that hacky. :smile:
But yes, overwriting the getter is straight and cleaner.

That’s correct. :slight_smile:

1 Like