diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f944fb1221..b83d359ccb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unversioned +- Minor: Added autocompletion in /whispers for Twitch emotes, Global Bttv/Ffz emotes and emojis. (#2999) - Bugfix: Fixed "smiley" emotes being unable to be "Tabbed" with autocompletion, introduced in v2.3.3. (#3010) - Dev: Ubuntu packages are now available (#2936) diff --git a/src/common/CompletionModel.cpp b/src/common/CompletionModel.cpp index f2e590d26af..078ae86a8a3 100644 --- a/src/common/CompletionModel.cpp +++ b/src/common/CompletionModel.cpp @@ -73,124 +73,130 @@ int CompletionModel::rowCount(const QModelIndex &) const void CompletionModel::refresh(const QString &prefix, bool isFirstWord) { - std::function addString; + std::lock_guard guard(this->itemsMutex_); + this->items_.clear(); + + if (prefix.length() < 2 || !this->channel_.isTwitchChannel()) + { + return; + } + + // Twitch channel + auto tc = dynamic_cast(&this->channel_); + + std::function addString; if (getSettings()->prefixOnlyEmoteCompletion) { - addString = [&](const QString &str, TaggedString::Type type) { + addString = [=](const QString &str, TaggedString::Type type) { if (str.startsWith(prefix, Qt::CaseInsensitive)) this->items_.emplace(str + " ", type); }; } else { - addString = [&](const QString &str, TaggedString::Type type) { + addString = [=](const QString &str, TaggedString::Type type) { if (str.contains(prefix, Qt::CaseInsensitive)) this->items_.emplace(str + " ", type); }; } - std::lock_guard guard(this->itemsMutex_); - this->items_.clear(); - - if (prefix.length() < 2) - return; - - if (auto channel = dynamic_cast(&this->channel_)) + if (auto account = getApp()->accounts->twitch.getCurrent()) { - if (auto account = getApp()->accounts->twitch.getCurrent()) + // Twitch Emotes available globally + for (const auto &emote : account->accessEmotes()->emotes) { - // Twitch Emotes available globally - for (const auto &emote : account->accessEmotes()->emotes) - { - addString(emote.first.string, TaggedString::TwitchGlobalEmote); - } + addString(emote.first.string, TaggedString::TwitchGlobalEmote); + } - // Twitch Emotes available locally - auto localEmoteData = account->accessLocalEmotes(); - if (localEmoteData->find(channel->roomId()) != - localEmoteData->end()) + // Twitch Emotes available locally + auto localEmoteData = account->accessLocalEmotes(); + if (tc && localEmoteData->find(tc->roomId()) != localEmoteData->end()) + { + for (const auto &emote : localEmoteData->at(tc->roomId())) { - for (const auto &emote : localEmoteData->at(channel->roomId())) - { - addString(emote.first.string, - TaggedString::Type::TwitchLocalEmote); - } + addString(emote.first.string, + TaggedString::Type::TwitchLocalEmote); } } + } + + // Bttv Global + for (auto &emote : *getApp()->twitch2->getBttvEmotes().emotes()) + { + addString(emote.first.string, TaggedString::Type::BTTVChannelEmote); + } - // Usernames - QString usernamePostfix = - isFirstWord && getSettings()->mentionUsersWithComma ? "," - : QString(); + // Ffz Global + for (auto &emote : *getApp()->twitch2->getFfzEmotes().emotes()) + { + addString(emote.first.string, TaggedString::Type::FFZChannelEmote); + } - if (prefix.startsWith("@")) + // Emojis + if (prefix.startsWith(":")) + { + const auto &emojiShortCodes = getApp()->emotes->emojis.shortCodes; + for (auto &m : emojiShortCodes) { - QString usernamePrefix = prefix; - usernamePrefix.remove(0, 1); + addString(QString(":%1:").arg(m), TaggedString::Type::Emoji); + } + } - auto chatters = - channel->accessChatters()->filterByPrefix(usernamePrefix); + // + // Stuff below is available only in regular Twitch channels + if (!tc) + { + return; + } - for (const auto &name : chatters) - { - addString("@" + name + usernamePostfix, - TaggedString::Type::Username); - } - } - else if (!getSettings()->userCompletionOnlyWithAt) - { - auto chatters = channel->accessChatters()->filterByPrefix(prefix); + // Usernames + QString usernamePostfix = + isFirstWord && getSettings()->mentionUsersWithComma ? "," : QString(); - for (const auto &name : chatters) - { - addString(name + usernamePostfix, TaggedString::Type::Username); - } - } + if (prefix.startsWith("@")) + { + QString usernamePrefix = prefix; + usernamePrefix.remove(0, 1); - // Bttv Global - for (auto &emote : *getApp()->twitch2->getBttvEmotes().emotes()) - { - addString(emote.first.string, TaggedString::Type::BTTVChannelEmote); - } + auto chatters = tc->accessChatters()->filterByPrefix(usernamePrefix); - // Ffz Global - for (auto &emote : *getApp()->twitch2->getFfzEmotes().emotes()) + for (const auto &name : chatters) { - addString(emote.first.string, TaggedString::Type::FFZChannelEmote); + addString("@" + name + usernamePostfix, + TaggedString::Type::Username); } + } + else if (!getSettings()->userCompletionOnlyWithAt) + { + auto chatters = tc->accessChatters()->filterByPrefix(prefix); - // Bttv Channel - for (auto &emote : *channel->bttvEmotes()) + for (const auto &name : chatters) { - addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote); + addString(name + usernamePostfix, TaggedString::Type::Username); } + } - // Ffz Channel - for (auto &emote : *channel->ffzEmotes()) - { - addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote); - } + // Bttv Channel + for (auto &emote : *tc->bttvEmotes()) + { + addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote); + } - // Emojis - if (prefix.startsWith(":")) - { - const auto &emojiShortCodes = getApp()->emotes->emojis.shortCodes; - for (auto &m : emojiShortCodes) - { - addString(":" + m + ":", TaggedString::Type::Emoji); - } - } + // Ffz Channel + for (auto &emote : *tc->ffzEmotes()) + { + addString(emote.first.string, TaggedString::Type::BTTVGlobalEmote); + } - // Commands - for (auto &command : getApp()->commands->items_) - { - addString(command.name, TaggedString::Command); - } + // Commands + for (auto &command : getApp()->commands->items_) + { + addString(command.name, TaggedString::Command); + } - for (auto &command : getApp()->commands->getDefaultTwitchCommandList()) - { - addString(command, TaggedString::Command); - } + for (auto &command : getApp()->commands->getDefaultTwitchCommandList()) + { + addString(command, TaggedString::Command); } } diff --git a/src/common/CompletionModel.hpp b/src/common/CompletionModel.hpp index fee84b6049c..a05c9840762 100644 --- a/src/common/CompletionModel.hpp +++ b/src/common/CompletionModel.hpp @@ -53,8 +53,6 @@ class CompletionModel : public QAbstractListModel static bool compareStrings(const QString &a, const QString &b); private: - TaggedString createUser(const QString &str); - std::set items_; mutable std::mutex itemsMutex_; Channel &channel_;