From 2a46ee708e275c70fcee6af3dcd851898d4da1ac Mon Sep 17 00:00:00 2001 From: pajlada Date: Sat, 1 Jun 2024 13:07:01 +0200 Subject: [PATCH] Fixed restricted users' usernames not being clickable (#5405) --- CHANGELOG.md | 1 + src/messages/MessageBuilder.cpp | 2 +- src/messages/MessageElement.cpp | 27 +++++++++++- src/messages/MessageElement.hpp | 11 +++-- src/providers/twitch/TwitchMessageBuilder.cpp | 41 +++++++++---------- 5 files changed, 55 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d9c45114..430291ed0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Minor: Added the ability to duplicate tabs. (#5277) - Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426) - Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378) +- Bugfix: Fixed restricted users usernames not being clickable. (#5405) - Bugfix: Fixed a crash that could occur when logging was enabled in IRC servers that were removed. (#5419) - Dev: Update Windows build from Qt 6.5.0 to Qt 6.7.1. (#5420) - Dev: Update vcpkg build Qt from 6.5.0 to 6.7.0, boost from 1.83.0 to 1.85.0, openssl from 3.1.3 to 3.3.0. (#5422) diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index 1ffd5ba28..cccd540d0 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -763,7 +763,7 @@ void MessageBuilder::addTextOrEmoji(const QString &string_) auto &&textColor = this->textColor_; if (string.startsWith('@')) { - this->emplace(string, textColor, textColor); + this->emplace(string, "", textColor, textColor); } else { diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 17de12706..0fb47cd0e 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -703,11 +703,14 @@ Link LinkElement::getLink() const return {Link::Url, this->linkInfo_.url()}; } -MentionElement::MentionElement(const QString &name, MessageColor fallbackColor_, +MentionElement::MentionElement(const QString &displayName, QString loginName_, + MessageColor fallbackColor_, MessageColor userColor_) - : TextElement(name, {MessageElementFlag::Text, MessageElementFlag::Mention}) + : TextElement(displayName, + {MessageElementFlag::Text, MessageElementFlag::Mention}) , fallbackColor(fallbackColor_) , userColor(userColor_) + , userLoginName(std::move(loginName_)) { } @@ -735,6 +738,26 @@ void MentionElement::addToContainer(MessageLayoutContainer &container, TextElement::addToContainer(container, flags); } +MessageElement *MentionElement::setLink(const Link &link) +{ + assert(false && "MentionElement::setLink should not be called. Pass " + "through a valid login name in the constructor and it will " + "automatically be a UserInfo link"); + + return TextElement::setLink(link); +} + +Link MentionElement::getLink() const +{ + if (this->userLoginName.isEmpty()) + { + // Some rare mention elements don't have the knowledge of the login name + return {}; + } + + return {Link::UserInfo, this->userLoginName}; +} + // TIMESTAMP TimestampElement::TimestampElement(QTime time) : MessageElement(MessageElementFlag::Timestamp) diff --git a/src/messages/MessageElement.hpp b/src/messages/MessageElement.hpp index 2c1e98f4e..49ce762cb 100644 --- a/src/messages/MessageElement.hpp +++ b/src/messages/MessageElement.hpp @@ -169,7 +169,7 @@ public: MessageElement(MessageElement &&) = delete; MessageElement &operator=(MessageElement &&) = delete; - MessageElement *setLink(const Link &link); + virtual MessageElement *setLink(const Link &link); MessageElement *setTooltip(const QString &tooltip); MessageElement *setTrailingSpace(bool value); @@ -314,8 +314,8 @@ private: class MentionElement : public TextElement { public: - MentionElement(const QString &name, MessageColor fallbackColor_, - MessageColor userColor_); + MentionElement(const QString &displayName, QString loginName_, + MessageColor fallbackColor_, MessageColor userColor_); ~MentionElement() override = default; MentionElement(const MentionElement &) = delete; MentionElement(MentionElement &&) = delete; @@ -325,6 +325,9 @@ public: void addToContainer(MessageLayoutContainer &container, MessageElementFlags flags) override; + MessageElement *setLink(const Link &link) override; + Link getLink() const override; + private: /** * The color of the element in case the "Colorize @usernames" is disabled @@ -335,6 +338,8 @@ private: * The color of the element in case the "Colorize @usernames" is enabled **/ MessageColor userColor; + + QString userLoginName; }; // contains emote data and will pick the emote based on : diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 3dfd39720..f69264cb3 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -770,9 +770,8 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) auto prefixedUsername = '@' + username; auto remainder = string.remove(prefixedUsername); - this->emplace(prefixedUsername, originalTextColor, - textColor) - ->setLink({Link::UserInfo, username}) + this->emplace(prefixedUsername, username, + originalTextColor, textColor) ->setTrailingSpace(remainder.isEmpty()); if (!remainder.isEmpty()) @@ -802,9 +801,8 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) } auto remainder = string.remove(username); - this->emplace(username, originalTextColor, + this->emplace(username, username, originalTextColor, textColor) - ->setLink({Link::UserInfo, username}) ->setTrailingSpace(remainder.isEmpty()); if (!remainder.isEmpty()) @@ -1821,8 +1819,10 @@ void TwitchMessageBuilder::listOfUsersSystemMessage(QString prefix, } } - builder->emplace(username, MessageColor::System, color) - ->setLink({Link::UserInfo, username}) + // TODO: Ensure we make use of display name / username(login name) correctly here + builder + ->emplace(username, username, MessageColor::System, + color) ->setTrailingSpace(false); } } @@ -1867,9 +1867,8 @@ void TwitchMessageBuilder::listOfUsersSystemMessage( } builder - ->emplace(user.userName, MessageColor::System, - color) - ->setLink({Link::UserInfo, user.userLogin}) + ->emplace(user.userName, user.userLogin, + MessageColor::System, color) ->setTrailingSpace(false); } @@ -1938,8 +1937,8 @@ MessagePtr TwitchMessageBuilder::makeAutomodInfoMessage( builder.emplace(makeAutoModBadge(), MessageElementFlag::BadgeChannelAuthority); // AutoMod "username" - builder.emplace("AutoMod:", AUTOMOD_USER_COLOR, - AUTOMOD_USER_COLOR); + builder.emplace("AutoMod:", MessageElementFlag::Text, + AUTOMOD_USER_COLOR, FontStyle::ChatMediumBold); switch (action.type) { case AutomodInfoAction::OnHold: { @@ -1993,8 +1992,9 @@ std::pair TwitchMessageBuilder::makeAutomodMessage( builder.emplace(makeAutoModBadge(), MessageElementFlag::BadgeChannelAuthority); // AutoMod "username" - builder2.emplace("AutoMod:", AUTOMOD_USER_COLOR, - AUTOMOD_USER_COLOR); + builder2.emplace("AutoMod:", MessageElementFlag::Text, + AUTOMOD_USER_COLOR, + FontStyle::ChatMediumBold); // AutoMod header message builder.emplace( ("Held a message for reason: " + action.reason + @@ -2041,10 +2041,9 @@ std::pair TwitchMessageBuilder::makeAutomodMessage( builder2.message().flags.set(MessageFlag::AutoModOffendingMessage); // sender username - builder2 - .emplace(action.target.displayName + ":", - MessageColor::Text, action.target.color) - ->setLink({Link::UserInfo, action.target.login}); + builder2.emplace(action.target.displayName + ":", + action.target.login, MessageColor::Text, + action.target.color); // sender's message caught by AutoMod builder2.emplace(action.message, MessageElementFlag::Text, MessageColor::Text); @@ -2239,9 +2238,9 @@ std::pair TwitchMessageBuilder::makeLowTrustUserMessage( appendBadges(&builder2, action.senderBadges, {}, twitchChannel); // sender username - builder2.emplace(action.suspiciousUserDisplayName + ":", - MessageColor::Text, - action.suspiciousUserColor); + builder2.emplace( + action.suspiciousUserDisplayName + ":", action.suspiciousUserLogin, + MessageColor::Text, action.suspiciousUserColor); // sender's message caught by AutoMod for (const auto &fragment : action.fragments)