diff --git a/CHANGELOG.md b/CHANGELOG.md index ef547e8bc18..6a9654f3ffe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Major: Release plugins alpha. (#5288) - Major: Improve high-DPI support on Windows. (#4868) - Minor: Add option to customise Moderation buttons with images. (#5369) +- Minor: Colored usernames now update on the fly when changing the "Color @usernames" setting. (#5300) - Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378) - Dev: Use Qt's high DPI scaling. (#4868) - Dev: Add doxygen build target. (#5377) diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index e1719454971..1ffd5ba28db 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -763,10 +763,7 @@ void MessageBuilder::addTextOrEmoji(const QString &string_) auto &&textColor = this->textColor_; if (string.startsWith('@')) { - this->emplace(string, MessageElementFlag::BoldUsername, - textColor, FontStyle::ChatMediumBold); - this->emplace(string, MessageElementFlag::NonBoldUsername, - textColor); + this->emplace(string, textColor, textColor); } else { diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 3d5ab64e7f7..17de1270608 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -703,6 +703,38 @@ Link LinkElement::getLink() const return {Link::Url, this->linkInfo_.url()}; } +MentionElement::MentionElement(const QString &name, MessageColor fallbackColor_, + MessageColor userColor_) + : TextElement(name, {MessageElementFlag::Text, MessageElementFlag::Mention}) + , fallbackColor(fallbackColor_) + , userColor(userColor_) +{ +} + +void MentionElement::addToContainer(MessageLayoutContainer &container, + MessageElementFlags flags) +{ + if (getSettings()->colorUsernames) + { + this->color_ = this->userColor; + } + else + { + this->color_ = this->fallbackColor; + } + + if (getSettings()->boldUsernames) + { + this->style_ = FontStyle::ChatMediumBold; + } + else + { + this->style_ = FontStyle::ChatMedium; + } + + TextElement::addToContainer(container, flags); +} + // TIMESTAMP TimestampElement::TimestampElement(QTime time) : MessageElement(MessageElementFlag::Timestamp) diff --git a/src/messages/MessageElement.hpp b/src/messages/MessageElement.hpp index b57bab752c4..2c1e98f4e89 100644 --- a/src/messages/MessageElement.hpp +++ b/src/messages/MessageElement.hpp @@ -133,9 +133,10 @@ enum class MessageElementFlag : int64_t { // needed Collapsed = (1LL << 26), - // used for dynamic bold usernames - BoldUsername = (1LL << 27), - NonBoldUsername = (1LL << 28), + // A mention of a username that isn't the author of the message + Mention = (1LL << 27), + + // Unused = (1LL << 28), // used to check if links should be lowercased LowercaseLinks = (1LL << 29), @@ -236,7 +237,6 @@ class TextElement : public MessageElement protected: QStringList words_; -private: MessageColor color_; FontStyle style_; }; @@ -301,6 +301,42 @@ class LinkElement : public TextElement QStringList original_; }; +/** + * @brief Contains a username mention. + * + * Examples of mentions: + * V + * 13:37 pajlada: hello @forsen + * + * V V + * 13:37 The moderators of this channel are: forsen, nuuls + */ +class MentionElement : public TextElement +{ +public: + MentionElement(const QString &name, MessageColor fallbackColor_, + MessageColor userColor_); + ~MentionElement() override = default; + MentionElement(const MentionElement &) = delete; + MentionElement(MentionElement &&) = delete; + MentionElement &operator=(const MentionElement &) = delete; + MentionElement &operator=(MentionElement &&) = delete; + + void addToContainer(MessageLayoutContainer &container, + MessageElementFlags flags) override; + +private: + /** + * The color of the element in case the "Colorize @usernames" is disabled + **/ + MessageColor fallbackColor; + + /** + * The color of the element in case the "Colorize @usernames" is enabled + **/ + MessageColor userColor; +}; + // contains emote data and will pick the emote based on : // a) are images for the emote type enabled // b) which size it wants diff --git a/src/messages/layouts/MessageLayoutContainer.cpp b/src/messages/layouts/MessageLayoutContainer.cpp index 15a7d71afc3..e5e53f360e0 100644 --- a/src/messages/layouts/MessageLayoutContainer.cpp +++ b/src/messages/layouts/MessageLayoutContainer.cpp @@ -756,9 +756,7 @@ void MessageLayoutContainer::reorderRTL(int firstTextIndex) const auto neutral = isNeutral(element->getText()); const auto neutralOrUsername = - neutral || - element->getFlags().hasAny({MessageElementFlag::BoldUsername, - MessageElementFlag::NonBoldUsername}); + neutral || element->getFlags().has(MessageElementFlag::Mention); if (neutral && ((this->first == FirstWord::RTL && !this->wasPrevReversed_) || diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 524d0375de5..3dfd39720ec 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -51,6 +51,8 @@ using namespace chatterino::literals; namespace { +const QColor AUTOMOD_USER_COLOR{"blue"}; + using namespace std::chrono_literals; const QString regexHelpString("(\\w+)[.,!?;:]*?$"); @@ -756,7 +758,7 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) QString username = match.captured(1); auto originalTextColor = textColor; - if (this->twitchChannel != nullptr && getSettings()->colorUsernames) + if (this->twitchChannel != nullptr) { if (auto userColor = this->twitchChannel->getUserColor(username); @@ -767,21 +769,17 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) } auto prefixedUsername = '@' + username; - this->emplace(prefixedUsername, - MessageElementFlag::BoldUsername, - textColor, FontStyle::ChatMediumBold) - ->setLink({Link::UserInfo, username}) - ->setTrailingSpace(false); - - this->emplace(prefixedUsername, - MessageElementFlag::NonBoldUsername, - textColor) + auto remainder = string.remove(prefixedUsername); + this->emplace(prefixedUsername, originalTextColor, + textColor) ->setLink({Link::UserInfo, username}) - ->setTrailingSpace(false); + ->setTrailingSpace(remainder.isEmpty()); - this->emplace(string.remove(prefixedUsername), - MessageElementFlag::Text, - originalTextColor); + if (!remainder.isEmpty()) + { + this->emplace(remainder, MessageElementFlag::Text, + originalTextColor); + } return; } @@ -797,30 +795,23 @@ void TwitchMessageBuilder::addTextOrEmoji(const QString &string_) { auto originalTextColor = textColor; - if (getSettings()->colorUsernames) + if (auto userColor = this->twitchChannel->getUserColor(username); + userColor.isValid()) { - if (auto userColor = - this->twitchChannel->getUserColor(username); - userColor.isValid()) - { - textColor = userColor; - } + textColor = userColor; } - this->emplace(username, - MessageElementFlag::BoldUsername, - textColor, FontStyle::ChatMediumBold) + auto remainder = string.remove(username); + this->emplace(username, originalTextColor, + textColor) ->setLink({Link::UserInfo, username}) - ->setTrailingSpace(false); + ->setTrailingSpace(remainder.isEmpty()); - this->emplace( - username, MessageElementFlag::NonBoldUsername, textColor) - ->setLink({Link::UserInfo, username}) - ->setTrailingSpace(false); - - this->emplace(string.remove(username), - MessageElementFlag::Text, - originalTextColor); + if (!remainder.isEmpty()) + { + this->emplace(remainder, MessageElementFlag::Text, + originalTextColor); + } return; } @@ -1821,7 +1812,7 @@ void TwitchMessageBuilder::listOfUsersSystemMessage(QString prefix, MessageColor color = MessageColor::System; - if (tc && getSettings()->colorUsernames) + if (tc) { if (auto userColor = tc->getUserColor(username); userColor.isValid()) @@ -1830,14 +1821,7 @@ void TwitchMessageBuilder::listOfUsersSystemMessage(QString prefix, } } - builder - ->emplace(username, MessageElementFlag::BoldUsername, - color, FontStyle::ChatMediumBold) - ->setLink({Link::UserInfo, username}) - ->setTrailingSpace(false); - builder - ->emplace(username, - MessageElementFlag::NonBoldUsername, color) + builder->emplace(username, MessageColor::System, color) ->setLink({Link::UserInfo, username}) ->setTrailingSpace(false); } @@ -1873,7 +1857,7 @@ void TwitchMessageBuilder::listOfUsersSystemMessage( MessageColor color = MessageColor::System; - if (tc && getSettings()->colorUsernames) + if (tc) { if (auto userColor = tc->getUserColor(user.userLogin); userColor.isValid()) @@ -1883,14 +1867,8 @@ void TwitchMessageBuilder::listOfUsersSystemMessage( } builder - ->emplace(user.userName, - MessageElementFlag::BoldUsername, color, - FontStyle::ChatMediumBold) - ->setLink({Link::UserInfo, user.userLogin}) - ->setTrailingSpace(false); - builder - ->emplace(user.userName, - MessageElementFlag::NonBoldUsername, color) + ->emplace(user.userName, MessageColor::System, + color) ->setLink({Link::UserInfo, user.userLogin}) ->setTrailingSpace(false); } @@ -1960,12 +1938,8 @@ MessagePtr TwitchMessageBuilder::makeAutomodInfoMessage( builder.emplace(makeAutoModBadge(), MessageElementFlag::BadgeChannelAuthority); // AutoMod "username" - builder.emplace("AutoMod:", MessageElementFlag::BoldUsername, - MessageColor(QColor("blue")), - FontStyle::ChatMediumBold); - builder.emplace( - "AutoMod:", MessageElementFlag::NonBoldUsername, - MessageColor(QColor("blue"))); + builder.emplace("AutoMod:", AUTOMOD_USER_COLOR, + AUTOMOD_USER_COLOR); switch (action.type) { case AutomodInfoAction::OnHold: { @@ -2019,12 +1993,8 @@ std::pair TwitchMessageBuilder::makeAutomodMessage( builder.emplace(makeAutoModBadge(), MessageElementFlag::BadgeChannelAuthority); // AutoMod "username" - builder.emplace("AutoMod:", MessageElementFlag::BoldUsername, - MessageColor(QColor("blue")), - FontStyle::ChatMediumBold); - builder.emplace( - "AutoMod:", MessageElementFlag::NonBoldUsername, - MessageColor(QColor("blue"))); + builder2.emplace("AutoMod:", AUTOMOD_USER_COLOR, + AUTOMOD_USER_COLOR); // AutoMod header message builder.emplace( ("Held a message for reason: " + action.reason + @@ -2072,14 +2042,8 @@ std::pair TwitchMessageBuilder::makeAutomodMessage( // sender username builder2 - .emplace( - action.target.displayName + ":", MessageElementFlag::BoldUsername, - MessageColor(action.target.color), FontStyle::ChatMediumBold) - ->setLink({Link::UserInfo, action.target.login}); - builder2 - .emplace(action.target.displayName + ":", - MessageElementFlag::NonBoldUsername, - MessageColor(action.target.color)) + .emplace(action.target.displayName + ":", + MessageColor::Text, action.target.color) ->setLink({Link::UserInfo, action.target.login}); // sender's message caught by AutoMod builder2.emplace(action.message, MessageElementFlag::Text, @@ -2275,17 +2239,9 @@ std::pair TwitchMessageBuilder::makeLowTrustUserMessage( appendBadges(&builder2, action.senderBadges, {}, twitchChannel); // sender username - builder2 - .emplace(action.suspiciousUserDisplayName + ":", - MessageElementFlag::BoldUsername, - MessageColor(action.suspiciousUserColor), - FontStyle::ChatMediumBold) - ->setLink({Link::UserInfo, action.suspiciousUserLogin}); - builder2 - .emplace(action.suspiciousUserDisplayName + ":", - MessageElementFlag::NonBoldUsername, - MessageColor(action.suspiciousUserColor)) - ->setLink({Link::UserInfo, action.suspiciousUserLogin}); + builder2.emplace(action.suspiciousUserDisplayName + ":", + MessageColor::Text, + action.suspiciousUserColor); // sender's message caught by AutoMod for (const auto &fragment : action.fragments) diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index 56bea50ae69..63bc63b366b 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -108,7 +108,6 @@ WindowManager::WindowManager(const Paths &paths) this->wordFlagsListener_.addSetting(settings->showBadgesFfz); this->wordFlagsListener_.addSetting(settings->showBadgesSevenTV); this->wordFlagsListener_.addSetting(settings->enableEmoteImages); - this->wordFlagsListener_.addSetting(settings->boldUsernames); this->wordFlagsListener_.addSetting(settings->lowercaseDomains); this->wordFlagsListener_.addSetting(settings->showReplyButton); this->wordFlagsListener_.setCB([this] { @@ -182,8 +181,6 @@ void WindowManager::updateWordTypeMask() // misc flags.set(MEF::AlwaysShow); flags.set(MEF::Collapsed); - flags.set(settings->boldUsernames ? MEF::BoldUsername - : MEF::NonBoldUsername); flags.set(MEF::LowercaseLinks, settings->lowercaseDomains); flags.set(MEF::ChannelPointReward); @@ -422,6 +419,13 @@ void WindowManager::initialize(Settings &settings, const Paths &paths) this->forceLayoutChannelViews(); }); + settings.colorUsernames.connect([this](auto, auto) { + this->forceLayoutChannelViews(); + }); + settings.boldUsernames.connect([this](auto, auto) { + this->forceLayoutChannelViews(); + }); + this->initialized_ = true; }