diff --git a/binaries/data/mods/public/gui/common/functions_utility.js b/binaries/data/mods/public/gui/common/functions_utility.js index 5c95b242ac..1dfdb26ed6 100644 --- a/binaries/data/mods/public/gui/common/functions_utility.js +++ b/binaries/data/mods/public/gui/common/functions_utility.js @@ -300,3 +300,18 @@ async function pageLoop(page, args) return completionValue; } + +function formatXmppAnnouncement(subject, text) +{ + var message = ""; + const subjectTrimmed = subject.trim(); + const textTrimmed = text.trim(); + if (subjectTrimmed.length > 0) + message += subjectTrimmed; + if (subjectTrimmed.length > 0 && textTrimmed.length > 0) + message += "\n\n"; + if (textTrimmed.length > 0) + message += textTrimmed; + + return message; +} diff --git a/binaries/data/mods/public/gui/lobby/LobbyPage/AnnouncementHandler.js b/binaries/data/mods/public/gui/lobby/LobbyPage/AnnouncementHandler.js index 43b9f763eb..74f9db8b6a 100644 --- a/binaries/data/mods/public/gui/lobby/LobbyPage/AnnouncementHandler.js +++ b/binaries/data/mods/public/gui/lobby/LobbyPage/AnnouncementHandler.js @@ -5,16 +5,17 @@ class AnnouncementHandler { constructor(xmppMessages) { - xmppMessages.registerXmppMessageHandler("chat", "private-message", this.onPrivateMessage.bind(this)); + xmppMessages.registerXmppMessageHandler("chat", "headline", this.onAnnouncementMessage.bind(this)); } - onPrivateMessage(message) + onAnnouncementMessage(message) { - // Announcements and the Message of the Day are sent by the server directly - if (!message.from && message.text.length > 0) - messageBox( - 400, 250, - message.text.trim(), - translate("Notice")); + if (message.subject.trim().length === 0 && message.text.trim().length === 0) + return; + + messageBox( + 400, 250, + formatXmppAnnouncement(message.subject, message.text), + translate("Notice")); } } diff --git a/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageEvents.js b/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageEvents.js index 7556a1260c..a8866074c1 100644 --- a/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageEvents.js +++ b/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageEvents.js @@ -9,6 +9,7 @@ ChatMessageEvents.PlayerChat = class this.chatMessageFormat = new ChatMessageFormat(); xmppMessages.registerXmppMessageHandler("chat", "room-message", this.onRoomMessage.bind(this)); xmppMessages.registerXmppMessageHandler("chat", "private-message", this.onPrivateMessage.bind(this)); + xmppMessages.registerXmppMessageHandler("chat", "headline", this.onAnnouncementMessage.bind(this)); } onRoomMessage(message) @@ -19,8 +20,14 @@ ChatMessageEvents.PlayerChat = class onPrivateMessage(message) { // We intend to not support private messages between users - if ((!message.from && message.text.length > 0) || Engine.LobbyGetPlayerRole(message.from) == "moderator") + if (Engine.LobbyGetPlayerRole(message.from) === "moderator") // some XMPP clients send trailing whitespace this.chatMessagesPanel.addText(message.time, this.chatMessageFormat.format(message)); } + + onAnnouncementMessage(message) + { + if (message.subject.trim().length > 0 || message.text.trim().length > 0) + this.chatMessagesPanel.addText(message.time, this.chatMessageFormat.format(message)); + } }; diff --git a/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormat.js b/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormat.js index 3eb1a7fee0..816798359f 100644 --- a/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormat.js +++ b/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormat.js @@ -8,6 +8,7 @@ class ChatMessageFormat { constructor() { + this.chatMessageFormatAnnouncement = new ChatMessageFormatAnnouncement(); this.chatMessageFormatMe = new ChatMessageFormatMe(); this.chatMessageFormatSay = new ChatMessageFormatSay(); this.chatMessagePrivateWrapper = new ChatMessagePrivateWrapper(); @@ -59,9 +60,12 @@ class ChatMessageFormat } } else - formattedMessage = this.chatMessageFormatSay.format(sender, text); + if (message.level === "headline") + formattedMessage = this.chatMessageFormatAnnouncement.format(message.subject, text); + else + formattedMessage = this.chatMessageFormatSay.format(sender, text); - if (message.level == "private-message") + if (message.level === "private-message") formattedMessage = this.chatMessagePrivateWrapper.format(formattedMessage); return formattedMessage; diff --git a/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormatAnnouncement.js b/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormatAnnouncement.js new file mode 100644 index 0000000000..966ff7c9ed --- /dev/null +++ b/binaries/data/mods/public/gui/lobby/LobbyPage/Chat/ChatMessages/ChatMessageFormatAnnouncement.js @@ -0,0 +1,37 @@ +/** + * This class adds an indication that the chat message was an announcement to the given text. + */ +class ChatMessageFormatAnnouncement +{ + constructor() + { + this.args = { + "prefix": setStringTags(this.AnnouncementPrefix, this.AnnouncementPrefixTags) + }; + } + + /** + * Text is formatted, escapeText is the responsibility of the caller. + */ + format(subject, text) + { + var message = formatXmppAnnouncement(subject, text); + this.args.message = setStringTags(message, this.AnnouncementMessageTags); + return sprintf(this.AnnouncementMessageFormat, this.args); + } +} + +ChatMessageFormatAnnouncement.prototype.AnnouncementPrefix = translate("Notice"); + +ChatMessageFormatAnnouncement.prototype.AnnouncementMessageFormat = translate("== %(prefix)s:\n%(message)s"); + +/** + * Color for announcements in the chat. + */ +ChatMessageFormatAnnouncement.prototype.AnnouncementPrefixTags = { + "font": "sans-bold-13" +}; + +ChatMessageFormatAnnouncement.prototype.AnnouncementMessageTags = { + "font": "sans-bold-13" +}; diff --git a/binaries/data/mods/public/gui/lobby/XmppMessages.js b/binaries/data/mods/public/gui/lobby/XmppMessages.js index b8fdfe8578..7d6f378120 100644 --- a/binaries/data/mods/public/gui/lobby/XmppMessages.js +++ b/binaries/data/mods/public/gui/lobby/XmppMessages.js @@ -104,7 +104,8 @@ XmppMessages.prototype.MessageTypes = { "kicked", "banned", "room-message", - "private-message" + "private-message", + "headline" ], "game": [ "gamelist", diff --git a/source/lobby/XmppClient.cpp b/source/lobby/XmppClient.cpp index e1279c2dec..ae2ccd2cb6 100644 --- a/source/lobby/XmppClient.cpp +++ b/source/lobby/XmppClient.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -821,9 +821,10 @@ void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::M CreateGUIMessage( "chat", - "private-message", + msg.subtype() == gloox::Message::MessageType::Headline ? "headline" : "private-message", ComputeTimestamp(msg), "from", msg.from().resource(), + "subject", msg.subject(), "text", msg.body()); }