diff --git a/CHANGELOG.md b/CHANGELOG.md index 0009ff0c5..daeabfe38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - Minor: Bold usernames enabled by default - Minor: Improve UX of the "Login expired!" message (#2029) - Minor: PageUp and PageDown now scroll in the selected split (#2070, #2081) +- Minor: Allow highlights to be excluded from `/mentions`. Excluded highlights will not trigger tab highlights either. (#1793, #2036) - Bugfix: Fix bug preventing users from setting the highlight color of the second entry in the "User" highlights tab (#1898) - Bugfix: Fix bug where the "check user follow state" event could trigger a network request requesting the user to follow or unfollow a user. By itself its quite harmless as it just repeats to Twitch the same follow state we had, so no follows should have been lost by this but it meant there was a rogue network request that was fired that could cause a crash (#1906) - Bugfix: /usercard command will now respect the "Automatically close user popup" setting (#1918) diff --git a/src/controllers/highlights/HighlightModel.cpp b/src/controllers/highlights/HighlightModel.cpp index 12135e3be..31556ed9b 100644 --- a/src/controllers/highlights/HighlightModel.cpp +++ b/src/controllers/highlights/HighlightModel.cpp @@ -9,7 +9,7 @@ namespace chatterino { // commandmodel HighlightModel::HighlightModel(QObject *parent) - : SignalVectorModel(7, parent) + : SignalVectorModel(Column::COUNT, parent) { } @@ -25,6 +25,7 @@ HighlightPhrase HighlightModel::getItemFromRow( return HighlightPhrase{ row[Column::Pattern]->data(Qt::DisplayRole).toString(), + row[Column::ShowInMentions]->data(Qt::DisplayRole).toBool(), row[Column::FlashTaskbar]->data(Qt::CheckStateRole).toBool(), row[Column::PlaySound]->data(Qt::CheckStateRole).toBool(), row[Column::UseRegex]->data(Qt::CheckStateRole).toBool(), @@ -38,6 +39,7 @@ void HighlightModel::getRowFromItem(const HighlightPhrase &item, std::vector &row) { setStringItem(row[Column::Pattern], item.getPattern()); + setBoolItem(row[Column::ShowInMentions], item.showInMentions()); setBoolItem(row[Column::FlashTaskbar], item.hasAlert()); setBoolItem(row[Column::PlaySound], item.hasSound()); setBoolItem(row[Column::UseRegex], item.isRegex()); @@ -54,6 +56,9 @@ void HighlightModel::afterInit() getSettings()->enableSelfHighlight.getValue(), true, false); usernameRow[Column::Pattern]->setData("Your username (automatic)", Qt::DisplayRole); + setBoolItem(usernameRow[Column::ShowInMentions], + getSettings()->showSelfHighlightInMentions.getValue(), true, + false); setBoolItem(usernameRow[Column::FlashTaskbar], getSettings()->enableSelfHighlightTaskbar.getValue(), true, false); @@ -76,6 +81,7 @@ void HighlightModel::afterInit() setBoolItem(whisperRow[Column::Pattern], getSettings()->enableWhisperHighlight.getValue(), true, false); whisperRow[Column::Pattern]->setData("Whispers", Qt::DisplayRole); + whisperRow[Column::ShowInMentions]->setFlags(0); // We have /whispers setBoolItem(whisperRow[Column::FlashTaskbar], getSettings()->enableWhisperHighlightTaskbar.getValue(), true, false); @@ -100,6 +106,7 @@ void HighlightModel::afterInit() setBoolItem(subRow[Column::Pattern], getSettings()->enableSubHighlight.getValue(), true, false); subRow[Column::Pattern]->setData("Subscriptions", Qt::DisplayRole); + subRow[Column::ShowInMentions]->setFlags(0); setBoolItem(subRow[Column::FlashTaskbar], getSettings()->enableSubHighlightTaskbar.getValue(), true, false); @@ -122,6 +129,7 @@ void HighlightModel::afterInit() getSettings()->enableRedeemedHighlight.getValue(), true, false); redeemedRow[Column::Pattern]->setData( "Highlights redeemed with Channel Points", Qt::DisplayRole); + redeemedRow[Column::ShowInMentions]->setFlags(0); // setBoolItem(redeemedRow[Column::FlashTaskbar], // getSettings()->enableRedeemedHighlightTaskbar.getValue(), true, // false); @@ -174,6 +182,17 @@ void HighlightModel::customRowSetData(const std::vector &row, } } break; + case Column::ShowInMentions: { + if (role == Qt::CheckStateRole) + { + if (rowIndex == 0) + { + getSettings()->showSelfHighlightInMentions.setValue( + value.toBool()); + } + } + } + break; case Column::FlashTaskbar: { if (role == Qt::CheckStateRole) { diff --git a/src/controllers/highlights/HighlightModel.hpp b/src/controllers/highlights/HighlightModel.hpp index 92acd2e0a..e57a4bdd7 100644 --- a/src/controllers/highlights/HighlightModel.hpp +++ b/src/controllers/highlights/HighlightModel.hpp @@ -15,12 +15,14 @@ public: // Used here, in HighlightingPage and in UserHighlightModel enum Column { Pattern = 0, - FlashTaskbar = 1, - PlaySound = 2, - UseRegex = 3, - CaseSensitive = 4, - SoundPath = 5, - Color = 6 + ShowInMentions = 1, + FlashTaskbar = 2, + PlaySound = 3, + UseRegex = 4, + CaseSensitive = 5, + SoundPath = 6, + Color = 7, + COUNT // keep this as last member of enum }; constexpr static int WHISPER_ROW = 1; diff --git a/src/controllers/highlights/HighlightPhrase.cpp b/src/controllers/highlights/HighlightPhrase.cpp index 9cfa4fe0f..0284fb89f 100644 --- a/src/controllers/highlights/HighlightPhrase.cpp +++ b/src/controllers/highlights/HighlightPhrase.cpp @@ -16,19 +16,20 @@ QColor HighlightPhrase::FALLBACK_SUB_COLOR = QColor(196, 102, 255, 100); bool HighlightPhrase::operator==(const HighlightPhrase &other) const { - return std::tie(this->pattern_, this->hasSound_, this->hasAlert_, - this->isRegex_, this->isCaseSensitive_, this->soundUrl_, - this->color_) == std::tie(other.pattern_, other.hasSound_, - other.hasAlert_, other.isRegex_, - other.isCaseSensitive_, - other.soundUrl_, other.color_); + return std::tie(this->pattern_, this->showInMentions_, this->hasSound_, + this->hasAlert_, this->isRegex_, this->isCaseSensitive_, + this->soundUrl_, this->color_) == + std::tie(other.pattern_, other.showInMentions_, other.hasSound_, + other.hasAlert_, other.isRegex_, other.isCaseSensitive_, + other.soundUrl_, other.color_); } -HighlightPhrase::HighlightPhrase(const QString &pattern, bool hasAlert, - bool hasSound, bool isRegex, +HighlightPhrase::HighlightPhrase(const QString &pattern, bool showInMentions, + bool hasAlert, bool hasSound, bool isRegex, bool isCaseSensitive, const QString &soundUrl, QColor color) : pattern_(pattern) + , showInMentions_(showInMentions) , hasAlert_(hasAlert) , hasSound_(hasSound) , isRegex_(isRegex) @@ -45,11 +46,12 @@ HighlightPhrase::HighlightPhrase(const QString &pattern, bool hasAlert, this->color_ = std::make_shared(color); } -HighlightPhrase::HighlightPhrase(const QString &pattern, bool hasAlert, - bool hasSound, bool isRegex, +HighlightPhrase::HighlightPhrase(const QString &pattern, bool showInMentions, + bool hasAlert, bool hasSound, bool isRegex, bool isCaseSensitive, const QString &soundUrl, std::shared_ptr color) : pattern_(pattern) + , showInMentions_(showInMentions) , hasAlert_(hasAlert) , hasSound_(hasSound) , isRegex_(isRegex) @@ -71,6 +73,11 @@ const QString &HighlightPhrase::getPattern() const return this->pattern_; } +bool HighlightPhrase::showInMentions() const +{ + return this->showInMentions_; +} + bool HighlightPhrase::hasAlert() const { return this->hasAlert_; diff --git a/src/controllers/highlights/HighlightPhrase.hpp b/src/controllers/highlights/HighlightPhrase.hpp index 205cfb9a0..ace959f7c 100644 --- a/src/controllers/highlights/HighlightPhrase.hpp +++ b/src/controllers/highlights/HighlightPhrase.hpp @@ -24,20 +24,21 @@ public: * * Use this constructor when creating a new HighlightPhrase. */ - HighlightPhrase(const QString &pattern, bool hasAlert, bool hasSound, - bool isRegex, bool isCaseSensitive, const QString &soundUrl, - QColor color); + HighlightPhrase(const QString &pattern, bool showInMentions, bool hasAlert, + bool hasSound, bool isRegex, bool isCaseSensitive, + const QString &soundUrl, QColor color); /** * @brief Create a new HighlightPhrase. * * Use this constructor when updating an existing HighlightPhrase's color. */ - HighlightPhrase(const QString &pattern, bool hasAlert, bool hasSound, - bool isRegex, bool isCaseSensitive, const QString &soundUrl, - std::shared_ptr color); + HighlightPhrase(const QString &pattern, bool showInMentions, bool hasAlert, + bool hasSound, bool isRegex, bool isCaseSensitive, + const QString &soundUrl, std::shared_ptr color); const QString &getPattern() const; + bool showInMentions() const; bool hasAlert() const; /** @@ -84,6 +85,7 @@ public: private: QString pattern_; + bool showInMentions_; bool hasAlert_; bool hasSound_; bool isRegex_; @@ -97,6 +99,14 @@ private: namespace pajlada { +namespace { + chatterino::HighlightPhrase constructError() + { + return chatterino::HighlightPhrase(QString(), false, false, false, + false, false, QString(), QColor()); + } +} // namespace + template <> struct Serialize { static rapidjson::Value get(const chatterino::HighlightPhrase &value, @@ -105,6 +115,7 @@ struct Serialize { rapidjson::Value ret(rapidjson::kObjectType); chatterino::rj::set(ret, "pattern", value.getPattern(), a); + chatterino::rj::set(ret, "showInMentions", value.showInMentions(), a); chatterino::rj::set(ret, "alert", value.hasAlert(), a); chatterino::rj::set(ret, "sound", value.hasSound(), a); chatterino::rj::set(ret, "regex", value.isRegex(), a); @@ -123,11 +134,11 @@ struct Deserialize { { if (!value.IsObject()) { - return chatterino::HighlightPhrase(QString(), true, false, false, - false, "", QColor()); + return constructError(); } QString _pattern; + bool _showInMentions = true; bool _hasAlert = true; bool _hasSound = false; bool _isRegex = false; @@ -136,6 +147,7 @@ struct Deserialize { QString encodedColor; chatterino::rj::getSafe(value, "pattern", _pattern); + chatterino::rj::getSafe(value, "showInMentions", _showInMentions); chatterino::rj::getSafe(value, "alert", _hasAlert); chatterino::rj::getSafe(value, "sound", _hasSound); chatterino::rj::getSafe(value, "regex", _isRegex); @@ -147,9 +159,9 @@ struct Deserialize { if (!_color.isValid()) _color = chatterino::HighlightPhrase::FALLBACK_HIGHLIGHT_COLOR; - return chatterino::HighlightPhrase(_pattern, _hasAlert, _hasSound, - _isRegex, _isCaseSensitive, - _soundUrl, _color); + return chatterino::HighlightPhrase(_pattern, _showInMentions, _hasAlert, + _hasSound, _isRegex, + _isCaseSensitive, _soundUrl, _color); } }; diff --git a/src/controllers/highlights/UserHighlightModel.cpp b/src/controllers/highlights/UserHighlightModel.cpp index e12d7e052..cde9c4965 100644 --- a/src/controllers/highlights/UserHighlightModel.cpp +++ b/src/controllers/highlights/UserHighlightModel.cpp @@ -7,9 +7,11 @@ namespace chatterino { +using Column = HighlightModel::Column; + // commandmodel UserHighlightModel::UserHighlightModel(QObject *parent) - : SignalVectorModel(7, parent) + : SignalVectorModel(Column::COUNT, parent) { } @@ -17,8 +19,6 @@ UserHighlightModel::UserHighlightModel(QObject *parent) HighlightPhrase UserHighlightModel::getItemFromRow( std::vector &row, const HighlightPhrase &original) { - using Column = HighlightModel::Column; - // In order for old messages to update their highlight color, we need to // update the highlight color here. auto highlightColor = original.getColor(); @@ -27,6 +27,7 @@ HighlightPhrase UserHighlightModel::getItemFromRow( return HighlightPhrase{ row[Column::Pattern]->data(Qt::DisplayRole).toString(), + row[Column::ShowInMentions]->data(Qt::CheckStateRole).toBool(), row[Column::FlashTaskbar]->data(Qt::CheckStateRole).toBool(), row[Column::PlaySound]->data(Qt::CheckStateRole).toBool(), row[Column::UseRegex]->data(Qt::CheckStateRole).toBool(), @@ -39,9 +40,8 @@ HighlightPhrase UserHighlightModel::getItemFromRow( void UserHighlightModel::getRowFromItem(const HighlightPhrase &item, std::vector &row) { - using Column = HighlightModel::Column; - setStringItem(row[Column::Pattern], item.getPattern()); + setBoolItem(row[Column::ShowInMentions], item.showInMentions()); setBoolItem(row[Column::FlashTaskbar], item.hasAlert()); setBoolItem(row[Column::PlaySound], item.hasSound()); setBoolItem(row[Column::UseRegex], item.isRegex()); diff --git a/src/messages/Message.hpp b/src/messages/Message.hpp index 9e780ee2f..b91313545 100644 --- a/src/messages/Message.hpp +++ b/src/messages/Message.hpp @@ -37,6 +37,7 @@ enum class MessageFlag : uint32_t { Similar = (1 << 19), RedeemedHighlight = (1 << 20), RedeemedChannelPointReward = (1 << 21), + ShowInMentions = (1 << 22), }; using MessageFlags = FlagsEnum; diff --git a/src/messages/SharedMessageBuilder.cpp b/src/messages/SharedMessageBuilder.cpp index 73d435eb4..10ac74e21 100644 --- a/src/messages/SharedMessageBuilder.cpp +++ b/src/messages/SharedMessageBuilder.cpp @@ -208,6 +208,11 @@ void SharedMessageBuilder::parseHighlights() this->message().flags.set(MessageFlag::Highlighted); this->message().highlightColor = userHighlight.getColor(); + if (userHighlight.showInMentions()) + { + this->message().flags.set(MessageFlag::ShowInMentions); + } + if (userHighlight.hasAlert()) { this->highlightAlert_ = true; @@ -252,7 +257,8 @@ void SharedMessageBuilder::parseHighlights() if (getSettings()->enableSelfHighlight && currentUsername.size() > 0) { HighlightPhrase selfHighlight( - currentUsername, getSettings()->enableSelfHighlightTaskbar, + currentUsername, getSettings()->showSelfHighlightInMentions, + getSettings()->enableSelfHighlightTaskbar, getSettings()->enableSelfHighlightSound, false, false, getSettings()->selfHighlightSoundUrl.getValue(), ColorProvider::instance().color(ColorType::SelfHighlight)); @@ -270,6 +276,11 @@ void SharedMessageBuilder::parseHighlights() this->message().flags.set(MessageFlag::Highlighted); this->message().highlightColor = highlight.getColor(); + if (highlight.showInMentions()) + { + this->message().flags.set(MessageFlag::ShowInMentions); + } + if (highlight.hasAlert()) { this->highlightAlert_ = true; diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 4f6a2695a..bb16005c6 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -261,11 +261,12 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message, builder.triggerHighlights(); } - auto highlighted = msg->flags.has(MessageFlag::Highlighted); + const auto highlighted = msg->flags.has(MessageFlag::Highlighted); + const auto showInMentions = msg->flags.has(MessageFlag::ShowInMentions); if (!isSub) { - if (highlighted) + if (highlighted && showInMentions) { server.mentionsChannel->addMessage(msg); } diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index 9469ed199..60c30fd24 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -213,6 +213,8 @@ public: BoolSetting enableSelfHighlight = { "/highlighting/selfHighlight/nameIsHighlightKeyword", true}; + BoolSetting showSelfHighlightInMentions = { + "/highlighting/selfHighlight/showSelfHighlightInMentions", true}; BoolSetting enableSelfHighlightSound = { "/highlighting/selfHighlight/enableSound", true}; BoolSetting enableSelfHighlightTaskbar = { diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 7e4049df3..e751432b2 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -788,6 +788,7 @@ void ChannelView::messageAppended(MessagePtr &message, if (!messageFlags->has(MessageFlag::DoNotTriggerNotification)) { if (messageFlags->has(MessageFlag::Highlighted) && + messageFlags->has(MessageFlag::ShowInMentions) && !messageFlags->has(MessageFlag::Subscription)) { this->tabHighlightRequested.invoke(HighlightState::Highlighted); diff --git a/src/widgets/settingspages/HighlightingPage.cpp b/src/widgets/settingspages/HighlightingPage.cpp index f1364de7a..bc21a39f7 100644 --- a/src/widgets/settingspages/HighlightingPage.cpp +++ b/src/widgets/settingspages/HighlightingPage.cpp @@ -55,7 +55,8 @@ HighlightingPage::HighlightingPage() &getSettings()->highlightedMessages)) .getElement(); view->addRegexHelpLink(); - view->setTitles({"Pattern", "Flash\ntaskbar", "Play\nsound", + view->setTitles({"Pattern", "Show in\nMentions", + "Flash\ntaskbar", "Play\nsound", "Enable\nregex", "Case-\nsensitive", "Custom\nsound", "Color"}); view->getTableView()->horizontalHeader()->setSectionResizeMode( @@ -72,7 +73,7 @@ HighlightingPage::HighlightingPage() view->addButtonPressed.connect([] { getSettings()->highlightedMessages.append(HighlightPhrase{ - "my phrase", true, false, false, false, "", + "my phrase", true, true, false, false, false, "", *ColorProvider::instance().color( ColorType::SelfHighlight)}); }); @@ -102,7 +103,8 @@ HighlightingPage::HighlightingPage() // Case-sensitivity doesn't make sense for user names so it is // set to "false" by default & the column is hidden - view->setTitles({"Username", "Flash\ntaskbar", "Play\nsound", + view->setTitles({"Username", "Show in\nMentions", + "Flash\ntaskbar", "Play\nsound", "Enable\nregex", "Case-\nsensitive", "Custom\nsound", "Color"}); view->getTableView()->horizontalHeader()->setSectionResizeMode( @@ -119,7 +121,7 @@ HighlightingPage::HighlightingPage() view->addButtonPressed.connect([] { getSettings()->highlightedUsers.append(HighlightPhrase{ - "highlighted user", true, false, false, false, "", + "highlighted user", true, true, false, false, false, "", *ColorProvider::instance().color( ColorType::SelfHighlight)}); });