diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 7443abe4c..3d9da28ab 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -22,146 +22,190 @@ #include #include -namespace chatterino { +#include + namespace { - auto makeTitleMessage(const QString &title) + +using namespace chatterino; + +auto makeTitleMessage(const QString &title) +{ + MessageBuilder builder; + builder.emplace(title, MessageElementFlag::Text); + builder->flags.set(MessageFlag::Centered); + return builder.release(); +} + +auto makeEmoteMessage(const EmoteMap &map, const MessageElementFlag &emoteFlag) +{ + MessageBuilder builder; + builder->flags.set(MessageFlag::Centered); + builder->flags.set(MessageFlag::DisableCompactEmotes); + + if (map.empty()) { - MessageBuilder builder; - builder.emplace(title, MessageElementFlag::Text); - builder->flags.set(MessageFlag::Centered); + builder.emplace("no emotes available", + MessageElementFlag::Text, + MessageColor::System); return builder.release(); } - auto makeEmoteMessage(const EmoteMap &map, - const MessageElementFlag &emoteFlag) + + std::vector> vec(map.begin(), map.end()); + std::sort(vec.begin(), vec.end(), + [](const std::pair &l, + const std::pair &r) { + return CompletionModel::compareStrings(l.first.string, + r.first.string); + }); + for (const auto &emote : vec) { + builder + .emplace( + emote.second, + MessageElementFlags{MessageElementFlag::AlwaysShow, emoteFlag}) + ->setLink(Link(Link::InsertText, emote.first.string)); + } + + return builder.release(); +} + +auto makeEmojiMessage(EmojiMap &emojiMap) +{ + MessageBuilder builder; + builder->flags.set(MessageFlag::Centered); + builder->flags.set(MessageFlag::DisableCompactEmotes); + + emojiMap.each([&builder](const auto &key, const auto &value) { + (void)key; // unused + + builder + .emplace( + value->emote, + MessageElementFlags{MessageElementFlag::AlwaysShow, + MessageElementFlag::EmojiAll}) + ->setLink( + Link(Link::Type::InsertText, ":" + value->shortCodes[0] + ":")); + }); + + return builder.release(); +} + +void addTwitchEmoteSets( + std::vector> sets, + Channel &globalChannel, Channel &subChannel, QString currentChannelName) +{ + QMap>> mapOfSets; + + for (const auto &set : sets) + { + // Some emotes (e.g. follower ones) are only available in their origin channel + if (set->local && currentChannelName != set->channelName) + { + continue; + } + + // TITLE + auto channelName = set->channelName; + auto text = set->text.isEmpty() ? "Twitch" : set->text; + + // EMOTES MessageBuilder builder; builder->flags.set(MessageFlag::Centered); builder->flags.set(MessageFlag::DisableCompactEmotes); - if (map.empty()) + // If value of map is empty, create init pair and add title. + if (mapOfSets.find(channelName) == mapOfSets.end()) { - builder.emplace("no emotes available", - MessageElementFlag::Text, - MessageColor::System); - return builder.release(); + std::vector b; + b.push_back(makeTitleMessage(text)); + mapOfSets[channelName] = qMakePair(set->key == "0", b); } - std::vector> vec(map.begin(), map.end()); - std::sort(vec.begin(), vec.end(), - [](const std::pair &l, - const std::pair &r) { - return CompletionModel::compareStrings(l.first.string, - r.first.string); - }); - for (const auto &emote : vec) + for (const auto &emote : set->emotes) { builder .emplace( - emote.second, + getApp()->emotes->twitch.getOrCreateEmote(emote.id, + emote.name), MessageElementFlags{MessageElementFlag::AlwaysShow, - emoteFlag}) - ->setLink(Link(Link::InsertText, emote.first.string)); + MessageElementFlag::TwitchEmote}) + ->setLink(Link(Link::InsertText, emote.name.string)); } - return builder.release(); + mapOfSets[channelName].second.push_back(builder.release()); } - auto makeEmojiMessage(EmojiMap &emojiMap) + + // Output to channel all created messages, + // That contain title or emotes. + // Put current channel emotes at the top + auto currentChannelPair = mapOfSets[currentChannelName]; + for (const auto &message : currentChannelPair.second) { - MessageBuilder builder; - builder->flags.set(MessageFlag::Centered); - builder->flags.set(MessageFlag::DisableCompactEmotes); - - emojiMap.each([&builder](const auto &key, const auto &value) { - builder - .emplace( - value->emote, - MessageElementFlags{MessageElementFlag::AlwaysShow, - MessageElementFlag::EmojiAll}) - ->setLink(Link(Link::Type::InsertText, - ":" + value->shortCodes[0] + ":")); - }); - - return builder.release(); + subChannel.addMessage(message); } - void addEmoteSets( - std::vector> sets, - Channel &globalChannel, Channel &subChannel, QString currentChannelName) + mapOfSets.remove(currentChannelName); + + for (const auto &pair : mapOfSets) { - QMap>> mapOfSets; - - for (const auto &set : sets) + auto &channel = pair.first ? globalChannel : subChannel; + for (const auto &message : pair.second) { - // Some emotes (e.g. follower ones) are only available in their origin channel - if (set->local && currentChannelName != set->channelName) - { - continue; - } - - // TITLE - auto channelName = set->channelName; - auto text = set->text.isEmpty() ? "Twitch" : set->text; - - // EMOTES - MessageBuilder builder; - builder->flags.set(MessageFlag::Centered); - builder->flags.set(MessageFlag::DisableCompactEmotes); - - // If value of map is empty, create init pair and add title. - if (mapOfSets.find(channelName) == mapOfSets.end()) - { - std::vector b; - b.push_back(makeTitleMessage(text)); - mapOfSets[channelName] = qMakePair(set->key == "0", b); - } - - for (const auto &emote : set->emotes) - { - builder - .emplace( - getApp()->emotes->twitch.getOrCreateEmote(emote.id, - emote.name), - MessageElementFlags{MessageElementFlag::AlwaysShow, - MessageElementFlag::TwitchEmote}) - ->setLink(Link(Link::InsertText, emote.name.string)); - } - - mapOfSets[channelName].second.push_back(builder.release()); - } - - // Output to channel all created messages, - // That contain title or emotes. - // Put current channel emotes at the top - auto currentChannelPair = mapOfSets[currentChannelName]; - for (auto message : currentChannelPair.second) - { - subChannel.addMessage(message); - } - mapOfSets.remove(currentChannelName); - - foreach (auto pair, mapOfSets) - { - auto &channel = pair.first ? globalChannel : subChannel; - for (auto message : pair.second) - { - channel.addMessage(message); - } + channel.addMessage(message); } } - void addEmotes(Channel &channel, const EmoteMap &map, const QString &title, - const MessageElementFlag &emoteFlag) +} + +void addEmotes(Channel &channel, const EmoteMap &map, const QString &title, + const MessageElementFlag &emoteFlag) +{ + channel.addMessage(makeTitleMessage(title)); + channel.addMessage(makeEmoteMessage(map, emoteFlag)); +} + +void loadEmojis(ChannelView &view, EmojiMap &emojiMap) +{ + ChannelPtr emojiChannel(new Channel("", Channel::Type::None)); + emojiChannel->addMessage(makeEmojiMessage(emojiMap)); + + view.setChannel(emojiChannel); +} + +void loadEmojis(Channel &channel, EmojiMap &emojiMap, const QString &title) +{ + channel.addMessage(makeTitleMessage(title)); + channel.addMessage(makeEmojiMessage(emojiMap)); +} + +// Create an emote +EmoteMap filterEmoteMap(const QString &text, + std::shared_ptr emotes) +{ + EmoteMap filteredMap; + + for (const auto &emote : *emotes) { - channel.addMessage(makeTitleMessage(title)); - channel.addMessage(makeEmoteMessage(map, emoteFlag)); - }; + if (emote.first.string.contains(text, Qt::CaseInsensitive)) + { + filteredMap.insert(emote); + } + } + + return filteredMap; +} + } // namespace +namespace chatterino { + EmotePopup::EmotePopup(QWidget *parent) : BasePopup(BaseWindow::EnableCustomFrame, parent) + , search_(new QLineEdit()) + , notebook_(new Notebook(this)) { this->setStayInScreenRect(true); this->moveTo(this, getApp()->windows->emotePopupPos(), false); - auto layout = new QVBoxLayout(this); + auto *layout = new QVBoxLayout(this); this->getLayoutContainer()->setLayout(layout); QRegularExpression searchRegex("\\S*"); @@ -170,11 +214,10 @@ EmotePopup::EmotePopup(QWidget *parent) layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); - QHBoxLayout *layout2 = new QHBoxLayout(this); + auto *layout2 = new QHBoxLayout(this); layout2->setContentsMargins(8, 8, 8, 8); layout2->setSpacing(8); - this->search_ = new QLineEdit(); this->search_->setPlaceholderText("Search all emotes..."); this->search_->setValidator(new TrimRegExpValidator(searchRegex)); this->search_->setClearButtonEnabled(true); @@ -192,7 +235,7 @@ EmotePopup::EmotePopup(QWidget *parent) }; auto makeView = [&](QString tabTitle, bool addToNotebook = true) { - auto view = new ChannelView(); + auto *view = new ChannelView(); view->setOverrideFlags(MessageElementFlags{ MessageElementFlag::Default, MessageElementFlag::AlwaysShow, @@ -202,7 +245,7 @@ EmotePopup::EmotePopup(QWidget *parent) if (addToNotebook) { - this->notebook_->addPage(view, tabTitle); + this->notebook_->addPage(view, std::move(tabTitle)); } return view; @@ -212,7 +255,6 @@ EmotePopup::EmotePopup(QWidget *parent) this->searchView_->hide(); layout->addWidget(this->searchView_); - this->notebook_ = new Notebook(this); layout->addWidget(this->notebook_); layout->setContentsMargins(0, 0, 0, 0); @@ -221,7 +263,7 @@ EmotePopup::EmotePopup(QWidget *parent) this->globalEmotesView_ = makeView("Global"); this->viewEmojis_ = makeView("Emojis"); - this->loadEmojis(*this->viewEmojis_, getApp()->emotes->emojis.emojis); + loadEmojis(*this->viewEmojis_, getApp()->emotes->emojis.emojis); this->addShortcuts(); this->signalHolder_.managedConnect(getApp()->hotkeys->onItemsUpdated, [this]() { @@ -237,7 +279,7 @@ void EmotePopup::addShortcuts() HotkeyController::HotkeyMap actions{ {"openTab", // CTRL + 1-8 to open corresponding tab. [this](std::vector arguments) -> QString { - if (arguments.size() == 0) + if (arguments.empty()) { qCWarning(chatterinoHotkeys) << "openTab shortcut called without arguments. Takes " @@ -260,7 +302,7 @@ void EmotePopup::addShortcuts() } else { - bool ok; + bool ok{false}; int result = target.toInt(&ok); if (ok) { @@ -279,20 +321,20 @@ void EmotePopup::addShortcuts() return ""; }}, {"delete", - [this](std::vector) -> QString { + [this](const std::vector &) -> QString { this->close(); return ""; }}, {"scrollPage", [this](std::vector arguments) -> QString { - if (arguments.size() == 0) + if (arguments.empty()) { qCWarning(chatterinoHotkeys) << "scrollPage hotkey called without arguments!"; return "scrollPage hotkey called without arguments!"; } auto direction = arguments.at(0); - auto channelView = dynamic_cast( + auto *channelView = dynamic_cast( this->notebook_->getSelectedPage()); auto &scrollbar = channelView->getScrollBar(); @@ -314,7 +356,7 @@ void EmotePopup::addShortcuts() {"reject", nullptr}, {"accept", nullptr}, {"search", - [this](std::vector) -> QString { + [this](const std::vector &) -> QString { this->search_->setFocus(); this->search_->selectAll(); return ""; @@ -329,7 +371,7 @@ void EmotePopup::loadChannel(ChannelPtr channel) { BenchmarkGuard guard("loadChannel"); - this->channel_ = channel; + this->channel_ = std::move(channel); this->twitchChannel_ = dynamic_cast(this->channel_.get()); this->setWindowTitle("Emotes in #" + this->channel_->getName()); @@ -344,7 +386,7 @@ void EmotePopup::loadChannel(ChannelPtr channel) auto channelChannel = std::make_shared("", Channel::Type::None); // twitch - addEmoteSets( + addTwitchEmoteSets( getApp()->accounts->twitch.getCurrent()->accessEmotes()->emoteSets, *globalChannel, *subChannel, this->channel_->getName()); @@ -399,21 +441,6 @@ void EmotePopup::loadChannel(ChannelPtr channel) } } -void EmotePopup::loadEmojis(ChannelView &view, EmojiMap &emojiMap) -{ - ChannelPtr emojiChannel(new Channel("", Channel::Type::None)); - emojiChannel->addMessage(makeEmojiMessage(emojiMap)); - - view.setChannel(emojiChannel); -} - -void EmotePopup::loadEmojis(Channel &channel, EmojiMap &emojiMap, - const QString &title) -{ - channel.addMessage(makeTitleMessage(title)); - channel.addMessage(makeEmojiMessage(emojiMap)); -} - void EmotePopup::filterTwitchEmotes(std::shared_ptr searchChannel, const QString &searchText) { @@ -432,56 +459,66 @@ void EmotePopup::filterTwitchEmotes(std::shared_ptr searchChannel, }); setCopy->emotes.resize(std::distance(setCopy->emotes.begin(), setIt)); - if (setCopy->emotes.size() > 0) + if (!setCopy->emotes.empty()) + { twitchGlobalEmotes.push_back(setCopy); + } } - auto bttvGlobalEmotes = this->filterEmoteMap( - searchText, getApp()->twitch->getBttvEmotes().emotes()); - auto ffzGlobalEmotes = this->filterEmoteMap( - searchText, getApp()->twitch->getFfzEmotes().emotes()); - auto *seventvGlobalEmotes = this->filterEmoteMap( + auto bttvGlobalEmotes = + filterEmoteMap(searchText, getApp()->twitch->getBttvEmotes().emotes()); + auto ffzGlobalEmotes = + filterEmoteMap(searchText, getApp()->twitch->getFfzEmotes().emotes()); + auto seventvGlobalEmotes = filterEmoteMap( searchText, getApp()->twitch->getSeventvEmotes().globalEmotes()); // twitch - addEmoteSets(twitchGlobalEmotes, *searchChannel, *searchChannel, - this->channel_->getName()); + addTwitchEmoteSets(twitchGlobalEmotes, *searchChannel, *searchChannel, + this->channel_->getName()); // global - if (bttvGlobalEmotes->size() > 0) - addEmotes(*searchChannel, *bttvGlobalEmotes, "BetterTTV (Global)", - MessageElementFlag::BttvEmote); - if (ffzGlobalEmotes->size() > 0) - addEmotes(*searchChannel, *ffzGlobalEmotes, "FrankerFaceZ (Global)", - MessageElementFlag::FfzEmote); - if (!seventvGlobalEmotes->empty()) + if (!bttvGlobalEmotes.empty()) { - addEmotes(*searchChannel, *seventvGlobalEmotes, "SevenTV (Global)", + addEmotes(*searchChannel, bttvGlobalEmotes, "BetterTTV (Global)", + MessageElementFlag::BttvEmote); + } + if (!ffzGlobalEmotes.empty()) + { + addEmotes(*searchChannel, ffzGlobalEmotes, "FrankerFaceZ (Global)", + MessageElementFlag::FfzEmote); + } + if (!seventvGlobalEmotes.empty()) + { + addEmotes(*searchChannel, seventvGlobalEmotes, "SevenTV (Global)", MessageElementFlag::SevenTVEmote); } - if (!this->twitchChannel_) + if (this->twitchChannel_ == nullptr) { return; } auto bttvChannelEmotes = - this->filterEmoteMap(searchText, this->twitchChannel_->bttvEmotes()); + filterEmoteMap(searchText, this->twitchChannel_->bttvEmotes()); auto ffzChannelEmotes = - this->filterEmoteMap(searchText, this->twitchChannel_->ffzEmotes()); - auto *seventvChannelEmotes = - this->filterEmoteMap(searchText, this->twitchChannel_->seventvEmotes()); + filterEmoteMap(searchText, this->twitchChannel_->ffzEmotes()); + auto seventvChannelEmotes = + filterEmoteMap(searchText, this->twitchChannel_->seventvEmotes()); // channel - if (bttvChannelEmotes->size() > 0) - addEmotes(*searchChannel, *bttvChannelEmotes, "BetterTTV (Channel)", - MessageElementFlag::BttvEmote); - if (ffzChannelEmotes->size() > 0) - addEmotes(*searchChannel, *ffzChannelEmotes, "FrankerFaceZ (Channel)", - MessageElementFlag::FfzEmote); - if (!seventvChannelEmotes->empty()) + if (!bttvChannelEmotes.empty()) { - addEmotes(*searchChannel, *seventvChannelEmotes, "SevenTV (Channel)", + addEmotes(*searchChannel, bttvChannelEmotes, "BetterTTV (Channel)", + MessageElementFlag::BttvEmote); + } + if (!ffzChannelEmotes.empty()) + { + addEmotes(*searchChannel, ffzChannelEmotes, "FrankerFaceZ (Channel)", + MessageElementFlag::FfzEmote); + } + if (!seventvChannelEmotes.empty()) + { + addEmotes(*searchChannel, seventvChannelEmotes, "SevenTV (Channel)", MessageElementFlag::SevenTVEmote); } } @@ -516,7 +553,9 @@ void EmotePopup::filterEmotes(const QString &searchText) }); // emojis if (emojiCount > 0) - this->loadEmojis(*searchChannel, filteredEmojis, "Emojis"); + { + loadEmojis(*searchChannel, filteredEmojis, "Emojis"); + } this->searchView_->setChannel(searchChannel); @@ -524,25 +563,10 @@ void EmotePopup::filterEmotes(const QString &searchText) this->searchView_->show(); } -EmoteMap *EmotePopup::filterEmoteMap(const QString &text, - std::shared_ptr emotes) -{ - auto filteredMap = new EmoteMap(); - - for (const auto &emote : *emotes) - { - if (emote.first.string.contains(text, Qt::CaseInsensitive)) - { - filteredMap->insert(emote); - } - } - - return filteredMap; -} - void EmotePopup::closeEvent(QCloseEvent *event) { getApp()->windows->setEmotePopupPos(this->pos()); - QWidget::closeEvent(event); + BaseWindow::closeEvent(event); } + } // namespace chatterino diff --git a/src/widgets/dialogs/EmotePopup.hpp b/src/widgets/dialogs/EmotePopup.hpp index 5b4e11b01..0c4a4f3dd 100644 --- a/src/widgets/dialogs/EmotePopup.hpp +++ b/src/widgets/dialogs/EmotePopup.hpp @@ -1,6 +1,5 @@ #pragma once -#include "providers/emoji/Emojis.hpp" #include "providers/twitch/TwitchChannel.hpp" #include "widgets/BasePopup.hpp" #include "widgets/Notebook.hpp" @@ -22,7 +21,7 @@ public: void loadChannel(ChannelPtr channel); - virtual void closeEvent(QCloseEvent *event) override; + void closeEvent(QCloseEvent *event) override; pajlada::Signals::Signal linkClicked; @@ -43,13 +42,9 @@ private: QLineEdit *search_; Notebook *notebook_; - void loadEmojis(ChannelView &view, EmojiMap &emojiMap); - void loadEmojis(Channel &channel, EmojiMap &emojiMap, const QString &title); void filterTwitchEmotes(std::shared_ptr searchChannel, const QString &searchText); void filterEmotes(const QString &text); - EmoteMap *filterEmoteMap(const QString &text, - std::shared_ptr emotes); void addShortcuts() override; };