diff --git a/src/controllers/commands/commandcontroller.cpp b/src/controllers/commands/commandcontroller.cpp index 9b897f902..4265a35e0 100644 --- a/src/controllers/commands/commandcontroller.cpp +++ b/src/controllers/commands/commandcontroller.cpp @@ -110,7 +110,7 @@ QString CommandController::execCommand(const QString &text, ChannelPtr channel, return ""; } else if (commandName == "/uptime") { - const auto &streamStatus = twitchChannel->GetStreamStatus(); + const auto &streamStatus = twitchChannel->getStreamStatus(); QString messageText = streamStatus.live ? streamStatus.uptime : "Channel is not live."; diff --git a/src/providers/twitch/ircmessagehandler.cpp b/src/providers/twitch/ircmessagehandler.cpp index 3d199e979..a8b226499 100644 --- a/src/providers/twitch/ircmessagehandler.cpp +++ b/src/providers/twitch/ircmessagehandler.cpp @@ -27,34 +27,48 @@ IrcMessageHandler &IrcMessageHandler::getInstance() void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message) { const auto &tags = message->tags(); - auto iterator = tags.find("room-id"); + auto app = getApp(); - if (iterator != tags.end()) { - auto roomID = iterator.value().toString(); + // get twitch channel + QString chanName; + if (!trimChannelName(message->parameter(0), chanName)) { + return; + } + auto chan = app->twitch.server->getChannelOrEmpty(chanName); + TwitchChannel *twitchChannel = dynamic_cast(chan.get()); - QStringList words = QString(message->toData()).split("#"); + if (twitchChannel) { + // room-id + decltype(tags.find("xD")) it; - // ensure the format is valid - if (words.length() < 2) { - return; - } + if ((it = tags.find("room-id")) != tags.end()) { + auto roomID = it.value().toString(); - auto app = getApp(); - - QString channelName = words.at(1); - - auto channel = app->twitch.server->getChannelOrEmpty(channelName); - - if (channel->isEmpty()) { - return; - } - - if (auto twitchChannel = dynamic_cast(channel.get())) { - // set the room id of the channel twitchChannel->setRoomID(roomID); + + app->resources->loadChannelData(roomID); } - app->resources->loadChannelData(roomID); + // Room modes + TwitchChannel::RoomModes roomModes = twitchChannel->getRoomModes(); + + if ((it = tags.find("emote-only")) != tags.end()) { + roomModes.emoteOnly = it.value() == "1"; + } + if ((it = tags.find("subs-only")) != tags.end()) { + roomModes.submode = it.value() == "1"; + } + if ((it = tags.find("slow")) != tags.end()) { + roomModes.slowMode = it.value().toInt(); + } + if ((it = tags.find("r9k")) != tags.end()) { + roomModes.r9k = it.value() == "1"; + } + if ((it = tags.find("broadcaster-lang")) != tags.end()) { + roomModes.broadcasterLang = it.value().toString(); + } + + twitchChannel->setRoomModes(roomModes); } } @@ -66,7 +80,7 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) } QString chanName; - if (!TrimChannelName(message->parameter(0), chanName)) { + if (!trimChannelName(message->parameter(0), chanName)) { return; } @@ -116,7 +130,7 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) auto app = getApp(); QString channelName; - if (!TrimChannelName(message->parameter(0), channelName)) { + if (!trimChannelName(message->parameter(0), channelName)) { return; } @@ -203,7 +217,8 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) // auto channel = app->twitch.server->getChannelOrEmpty(channelName); // if (channel->isEmpty()) { - // debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager", + // debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel + // manager", // channelName); // return; // } diff --git a/src/providers/twitch/twitchchannel.cpp b/src/providers/twitch/twitchchannel.cpp index 2b7300d21..ab663ad36 100644 --- a/src/providers/twitch/twitchchannel.cpp +++ b/src/providers/twitch/twitchchannel.cpp @@ -86,7 +86,7 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection }; auto doRefreshChatters = [=]() { - const auto streamStatus = this->GetStreamStatus(); + const auto streamStatus = this->getStreamStatus(); if (app->settings->onlyFetchChattersForSmallerStreamers) { if (streamStatus.live && streamStatus.viewerCount > app->settings->smallStreamerLimit) { @@ -213,6 +213,35 @@ void TwitchChannel::addRecentChatter(const std::shared_ptr &m this->completionModel.addUser(message->displayName); } +TwitchChannel::RoomModes TwitchChannel::getRoomModes() +{ + std::lock_guard lock(this->roomModeMutex); + + return this->roomModes; +} + +void TwitchChannel::setRoomModes(const RoomModes &_roomModes) +{ + { + std::lock_guard lock(this->roomModeMutex); + this->roomModes = _roomModes; + } + + this->roomModesChanged.invoke(); +} + +bool TwitchChannel::isLive() const +{ + std::lock_guard lock(this->streamStatusMutex); + return this->streamStatus.live; +} + +TwitchChannel::StreamStatus TwitchChannel::getStreamStatus() const +{ + std::lock_guard lock(this->streamStatusMutex); + return this->streamStatus; +} + void TwitchChannel::setLive(bool newLiveStatus) { bool gotNewLiveStatus = false; diff --git a/src/providers/twitch/twitchchannel.hpp b/src/providers/twitch/twitchchannel.hpp index 4e5531d77..a594bdf72 100644 --- a/src/providers/twitch/twitchchannel.hpp +++ b/src/providers/twitch/twitchchannel.hpp @@ -38,6 +38,15 @@ public: bool broadcaster; }; + struct RoomModes { + bool submode = false; + bool r9k = false; + bool emoteOnly = false; + // int folowerOnly = 0; + int slowMode = 0; + QString broadcasterLang; + }; + ~TwitchChannel() final; void reloadChannelEmotes(); @@ -66,25 +75,20 @@ public: pajlada::Signals::NoArgBoltSignal fetchMessages; pajlada::Signals::NoArgSignal userStateChanged; + pajlada::Signals::NoArgSignal roomModesChanged; QString roomID; + RoomModes getRoomModes(); + void setRoomModes(const RoomModes &roomModes); - StreamStatus GetStreamStatus() const - { - std::lock_guard lock(this->streamStatusMutex); - return this->streamStatus; - } + StreamStatus getStreamStatus() const; struct NameOptions { QString displayName; QString localizedName; }; - bool IsLive() const - { - std::lock_guard lock(this->streamStatusMutex); - return this->streamStatus.live; - } + bool isLive() const; private: explicit TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection); @@ -103,6 +107,8 @@ private: bool mod; QByteArray messageSuffix; QString lastSentMessage; + RoomModes roomModes; + std::mutex roomModeMutex; Communi::IrcConnection *readConnection; diff --git a/src/providers/twitch/twitchhelpers.cpp b/src/providers/twitch/twitchhelpers.cpp index 4f6f663ac..98140c6c2 100644 --- a/src/providers/twitch/twitchhelpers.cpp +++ b/src/providers/twitch/twitchhelpers.cpp @@ -5,7 +5,7 @@ namespace chatterino { namespace providers { namespace twitch { -bool TrimChannelName(const QString &channelName, QString &outChannelName) +bool trimChannelName(const QString &channelName, QString &outChannelName) { if (channelName.length() < 3) { debug::Log("channel name length below 3"); diff --git a/src/providers/twitch/twitchhelpers.hpp b/src/providers/twitch/twitchhelpers.hpp index 997821d66..56f0bb94c 100644 --- a/src/providers/twitch/twitchhelpers.hpp +++ b/src/providers/twitch/twitchhelpers.hpp @@ -6,7 +6,7 @@ namespace chatterino { namespace providers { namespace twitch { -bool TrimChannelName(const QString &channelName, QString &outChannelName); +bool trimChannelName(const QString &channelName, QString &outChannelName); } // namespace twitch } // namespace providers diff --git a/src/providers/twitch/twitchserver.cpp b/src/providers/twitch/twitchserver.cpp index 41d42cb7b..ab1845353 100644 --- a/src/providers/twitch/twitchserver.cpp +++ b/src/providers/twitch/twitchserver.cpp @@ -78,7 +78,7 @@ std::shared_ptr TwitchServer::createChannel(const QString &channelName) void TwitchServer::privateMessageReceived(IrcPrivateMessage *message) { QString channelName; - if (!TrimChannelName(message->target(), channelName)) { + if (!trimChannelName(message->target(), channelName)) { return; } diff --git a/src/singletons/fontmanager.cpp b/src/singletons/fontmanager.cpp index b25bc8b28..49d00c1ec 100644 --- a/src/singletons/fontmanager.cpp +++ b/src/singletons/fontmanager.cpp @@ -83,7 +83,6 @@ FontManager::FontData &FontManager::getOrCreateFontData(Type type, float scale) if (it != map.end()) { // return if found - qDebug() << it->second.font; return it->second; } diff --git a/src/widgets/helper/splitheader.cpp b/src/widgets/helper/splitheader.cpp index 7264f81ab..617b22650 100644 --- a/src/widgets/helper/splitheader.cpp +++ b/src/widgets/helper/splitheader.cpp @@ -63,6 +63,16 @@ SplitHeader::SplitHeader(Split *_split) layout->addStretch(1); + // mode button + auto mode = layout.emplace(this).assign(&this->modeButton); + + mode->getLabel().setText("dank\nmemes"); + + // QObject::connect(mode.getElement(), &RippleEffectButton::clicked, this, [this] + // { + // // + // }); + // moderation mode auto moderator = layout.emplace(this).assign(&this->moderationButton); @@ -167,7 +177,7 @@ void SplitHeader::updateChannelText() TwitchChannel *twitchChannel = dynamic_cast(channel.get()); if (twitchChannel != nullptr) { - const auto &streamStatus = twitchChannel->GetStreamStatus(); + const auto &streamStatus = twitchChannel->getStreamStatus(); if (streamStatus.live) { this->isLive = true; @@ -216,6 +226,45 @@ void SplitHeader::updateModerationModeIcon() this->moderationButton->setVisible(modButtonVisible); } +void SplitHeader::updateModes() +{ + TwitchChannel *tc = dynamic_cast(this->split->getChannel().get()); + if (tc == nullptr) { + return; + } + + TwitchChannel::RoomModes roomModes = tc->getRoomModes(); + + QString text; + + if (roomModes.r9k) { + text += "r9k, "; + } + if (roomModes.slowMode) { + text += QString("slow(%1), ").arg(QString::number(roomModes.slowMode)); + } + if (roomModes.emoteOnly) { + text += "emote, "; + } + if (roomModes.submode) { + text += "sub, "; + } + + if (text.length() > 2) { + text = text.mid(0, text.size() - 2); + } + + qDebug() << text; + + static QRegularExpression commaReplacement("^.+?, .+?,( ).+$"); + QRegularExpressionMatch match = commaReplacement.match(text); + if (match.hasMatch()) { + text = text.mid(0, match.capturedStart(1)) + '\n' + text.mid(match.capturedEnd(1)); + } + + this->modeButton->getLabel().setText(text); +} + void SplitHeader::paintEvent(QPaintEvent *) { QPainter painter(this); diff --git a/src/widgets/helper/splitheader.hpp b/src/widgets/helper/splitheader.hpp index 167d5e7f4..ff6e0047a 100644 --- a/src/widgets/helper/splitheader.hpp +++ b/src/widgets/helper/splitheader.hpp @@ -34,6 +34,7 @@ public: // Update channel text from chat widget void updateChannelText(); void updateModerationModeIcon(); + void updateModes(); protected: virtual void scaleChangedEvent(float) override; @@ -59,6 +60,7 @@ private: RippleEffectButton *dropdownButton; // Label *titleLabel; SignalLabel *titleLabel; + RippleEffectLabel *modeButton; RippleEffectButton *moderationButton; QMenu dropdownMenu; diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp index 2f30d4e78..c3f9f1e9e 100644 --- a/src/widgets/split.cpp +++ b/src/widgets/split.cpp @@ -129,15 +129,10 @@ Split::Split(QWidget *parent) this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); this->managedConnect(modifierStatusChanged, [this](Qt::KeyboardModifiers status) { - - qDebug() << "xD" << status; - if ((status == Qt::AltModifier || status == (Qt::AltModifier | Qt::ControlModifier)) && this->isMouseOver) { - qDebug() << "show"; this->overlay->show(); } else { - qDebug() << "hide"; this->overlay->hide(); } }); @@ -187,6 +182,7 @@ void Split::setChannel(IndirectChannel newChannel) this->view.setChannel(newChannel.get()); this->usermodeChangedConnection.disconnect(); + this->roomModeChangedConnection.disconnect(); this->indirectChannelChangedConnection.disconnect(); TwitchChannel *tc = dynamic_cast(newChannel.get().get()); @@ -194,6 +190,9 @@ void Split::setChannel(IndirectChannel newChannel) if (tc != nullptr) { this->usermodeChangedConnection = tc->userStateChanged.connect([this] { this->header.updateModerationModeIcon(); }); + + this->roomModeChangedConnection = + tc->roomModesChanged.connect([this] { this->header.updateModes(); }); } this->indirectChannelChangedConnection = newChannel.getChannelChanged().connect([this] { // @@ -202,6 +201,7 @@ void Split::setChannel(IndirectChannel newChannel) this->header.updateModerationModeIcon(); this->header.updateChannelText(); + this->header.updateModes(); this->channelChanged.invoke(); } diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp index 45a09d887..41257550d 100644 --- a/src/widgets/split.hpp +++ b/src/widgets/split.hpp @@ -100,6 +100,8 @@ private: pajlada::Signals::Connection channelIDChangedConnection; pajlada::Signals::Connection usermodeChangedConnection; + pajlada::Signals::Connection roomModeChangedConnection; + pajlada::Signals::Connection indirectChannelChangedConnection; std::vector managedConnections;