diff --git a/CHANGELOG.md b/CHANGELOG.md index 4606d64d2..7b4ea7dbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Minor: Updated the flatpakref link included with nightly builds to point to up-to-date flathub-beta builds. (#5008) - Minor: Add a new completion API for experimental plugins feature. (#5000, #5047) - Minor: Re-enabled _Restart on crash_ option on Windows. (#5012) +- Minor: The chatter list button is now hidden if you don't have moderator privileges. (#5245) - Minor: The whisper highlight color can now be configured through the settings. (#5053) - Minor: Added an option to always include the broadcaster in user completions. This is enabled by default. (#5193, #5244) - Minor: Added missing periods at various moderator messages and commands. (#5061) diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index b0eec1f8c..8a9cc9e6c 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -653,23 +653,40 @@ std::vector IrcMessageHandler::parseMessageWithReply( void IrcMessageHandler::handlePrivMessage(Communi::IrcPrivateMessage *message, TwitchIrcServer &server) { - // This is for compatibility with older Chatterino versions. Twitch didn't use - // to allow ZERO WIDTH JOINER unicode character, so Chatterino used ESCAPE_TAG - // instead. - // See https://github.com/Chatterino/chatterino2/issues/3384 and - // https://mm2pl.github.io/emoji_rfc.pdf for more details - - this->addMessage( - message, channelOrEmptyByTarget(message->target(), server), - message->content().replace(COMBINED_FIXER, ZERO_WIDTH_JOINER), server, - false, message->isAction()); - auto chan = channelOrEmptyByTarget(message->target(), server); if (chan->isEmpty()) { return; } + auto *twitchChannel = dynamic_cast(chan.get()); + + if (twitchChannel != nullptr) + { + auto currentUser = getIApp()->getAccounts()->twitch.getCurrent(); + if (message->tag("user-id") == currentUser->getUserId()) + { + auto badgesTag = message->tag("badges"); + if (badgesTag.isValid()) + { + auto parsedBadges = parseBadges(badgesTag.toString()); + twitchChannel->setMod(parsedBadges.contains("moderator")); + twitchChannel->setVIP(parsedBadges.contains("vip")); + twitchChannel->setStaff(parsedBadges.contains("staff")); + } + } + } + + // This is for compatibility with older Chatterino versions. Twitch didn't use + // to allow ZERO WIDTH JOINER unicode character, so Chatterino used ESCAPE_TAG + // instead. + // See https://github.com/Chatterino/chatterino2/issues/3384 and + // https://mm2pl.github.io/emoji_rfc.pdf for more details + this->addMessage( + message, chan, + message->content().replace(COMBINED_FIXER, ZERO_WIDTH_JOINER), server, + false, message->isAction()); + if (message->tags().contains(u"pinned-chat-paid-amount"_s)) { auto ptr = TwitchMessageBuilder::buildHypeChatMessage(message); diff --git a/src/widgets/splits/Split.cpp b/src/widgets/splits/Split.cpp index 780d0998d..9e3126319 100644 --- a/src/widgets/splits/Split.cpp +++ b/src/widgets/splits/Split.cpp @@ -331,7 +331,7 @@ Split::Split(QWidget *parent) }, this->signalHolder_); - this->header_->updateModerationModeIcon(); + this->header_->updateIcons(); this->overlay_->hide(); this->setSizePolicy(QSizePolicy::MinimumExpanding, @@ -813,7 +813,7 @@ void Split::joinChannelInNewTab(ChannelPtr channel) void Split::refreshModerationMode() { - this->header_->updateModerationModeIcon(); + this->header_->updateIcons(); this->view_->queueLayout(); } @@ -865,7 +865,7 @@ void Split::setChannel(IndirectChannel newChannel) if (tc != nullptr) { this->usermodeChangedConnection_ = tc->userStateChanged.connect([this] { - this->header_->updateModerationModeIcon(); + this->header_->updateIcons(); this->header_->updateRoomModes(); }); @@ -881,19 +881,10 @@ void Split::setChannel(IndirectChannel newChannel) }); }); - this->header_->updateModerationModeIcon(); + this->header_->updateIcons(); this->header_->updateChannelText(); this->header_->updateRoomModes(); - if (newChannel.getType() == Channel::Type::Twitch) - { - this->header_->setChattersButtonVisible(true); - } - else - { - this->header_->setChattersButtonVisible(false); - } - this->channelSignalHolder_.managedConnect( this->channel_.get()->displayNameChanged, [this] { this->actionRequested.invoke(Action::RefreshTab); diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index 7e27ad16b..b8b811ca4 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -230,7 +230,7 @@ SplitHeader::SplitHeader(Split *split) this->setMouseTracking(true); this->updateChannelText(); this->handleChannelChanged(); - this->updateModerationModeIcon(); + this->updateIcons(); // The lifetime of these signals are tied to the lifetime of the Split. // Since the SplitHeader is owned by the Split, they will always be destroyed @@ -247,7 +247,7 @@ SplitHeader::SplitHeader(Split *split) this->bSignals_.emplace_back( getIApp()->getAccounts()->twitch.currentUserChanged.connect([this] { - this->updateModerationModeIcon(); + this->updateIcons(); })); auto _ = [this](const auto &, const auto &) { @@ -755,11 +755,6 @@ void SplitHeader::setAddButtonVisible(bool value) this->addButton_->setVisible(value); } -void SplitHeader::setChattersButtonVisible(bool value) -{ - this->chattersButton_->setVisible(value); -} - void SplitHeader::updateChannelText() { auto indirectChannel = this->split_->getIndirectChannel(); @@ -838,26 +833,42 @@ void SplitHeader::updateChannelText() this->titleLabel_->setText(title.isEmpty() ? "" : title); } -void SplitHeader::updateModerationModeIcon() +void SplitHeader::updateIcons() { - auto moderationMode = this->split_->getModerationMode() && - !getSettings()->moderationActions.empty(); - - this->moderationButton_->setPixmap( - moderationMode ? getResources().buttons.modModeEnabled - : getResources().buttons.modModeDisabled); - auto channel = this->split_->getChannel(); auto *twitchChannel = dynamic_cast(channel.get()); - if (twitchChannel != nullptr && - (twitchChannel->hasModRights() || moderationMode)) + if (twitchChannel != nullptr) { - this->moderationButton_->show(); + auto moderationMode = this->split_->getModerationMode() && + !getSettings()->moderationActions.empty(); + + this->moderationButton_->setPixmap( + moderationMode ? getResources().buttons.modModeEnabled + : getResources().buttons.modModeDisabled); + + if (twitchChannel->hasModRights() || moderationMode) + { + this->moderationButton_->show(); + } + else + { + this->moderationButton_->hide(); + } + + if (twitchChannel->hasModRights()) + { + this->chattersButton_->show(); + } + else + { + this->chattersButton_->hide(); + } } else { this->moderationButton_->hide(); + this->chattersButton_->hide(); } } diff --git a/src/widgets/splits/SplitHeader.hpp b/src/widgets/splits/SplitHeader.hpp index 872ba8a8b..efae94849 100644 --- a/src/widgets/splits/SplitHeader.hpp +++ b/src/widgets/splits/SplitHeader.hpp @@ -29,10 +29,9 @@ public: explicit SplitHeader(Split *split); void setAddButtonVisible(bool value); - void setChattersButtonVisible(bool value); void updateChannelText(); - void updateModerationModeIcon(); + void updateIcons(); // Invoked when SplitHeader should update anything refering to a TwitchChannel's mode // has changed (e.g. sub mode toggled) void updateRoomModes();