From a777a227d4dcbbdecabdb5de79f18a00089b07e1 Mon Sep 17 00:00:00 2001 From: nerix Date: Sun, 19 Mar 2023 11:26:30 +0100 Subject: [PATCH] Allow each layered image to retain its own flags (#4460) This fixes an issue where context-menu items for zero-width emotes displayed the wrong provider. --- CHANGELOG.md | 1 + src/common/FlagsEnum.hpp | 12 ++++++ src/messages/MessageElement.cpp | 39 +++++++++++-------- src/messages/MessageElement.hpp | 16 +++++--- src/providers/twitch/TwitchMessageBuilder.cpp | 13 ++++--- src/widgets/helper/ChannelView.cpp | 6 +-- 6 files changed, 58 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e616c300..deec79543 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Minor: Added support for FrankerFaceZ animated emotes. (#4434) - Bugfix: Fixed an issue where animated emotes would render on top of zero-width emotes. (#4314) - Bugfix: Fixed an issue where it was difficult to hover a zero-width emote. (#4314) +- Bugfix: Fixed an issue where context-menu items for zero-width emotes displayed the wrong provider. (#4460) - Dev: Ignore unhandled BTTV user-events. (#4438) - Dev: Only log debug messages when NDEBUG is not defined. (#4442) - Dev: Cleaned up theme related code. (#4450) diff --git a/src/common/FlagsEnum.hpp b/src/common/FlagsEnum.hpp index 5eee93879..07d672751 100644 --- a/src/common/FlagsEnum.hpp +++ b/src/common/FlagsEnum.hpp @@ -42,6 +42,12 @@ public: reinterpret_cast(this->value_) |= static_cast(flag); } + /** Adds the flags from `flags` in this enum. */ + void set(FlagsEnum flags) + { + reinterpret_cast(this->value_) |= static_cast(flags.value_); + } + void unset(T flag) { reinterpret_cast(this->value_) &= ~static_cast(flag); @@ -69,6 +75,12 @@ public: return xd; } + FlagsEnum operator|(FlagsEnum rhs) + { + return static_cast(static_cast(this->value_) | + static_cast(rhs.value_)); + } + bool hasAny(FlagsEnum flags) const { return static_cast(this->value_) & static_cast(flags.value_); diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 29558a8e3..63d274713 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -110,6 +110,11 @@ MessageElementFlags MessageElement::getFlags() const return this->flags_; } +void MessageElement::addFlags(MessageElementFlags flags) +{ + this->flags_.set(flags); +} + MessageElement *MessageElement::updateLink() { this->linkChanged.invoke(); @@ -234,9 +239,9 @@ MessageLayoutElement *EmoteElement::makeImageLayoutElement( return new ImageLayoutElement(*this, image, size); } -LayeredEmoteElement::LayeredEmoteElement(std::vector &&emotes, - MessageElementFlags flags, - const MessageColor &textElementColor) +LayeredEmoteElement::LayeredEmoteElement( + std::vector &&emotes, MessageElementFlags flags, + const MessageColor &textElementColor) : MessageElement(flags) , emotes_(std::move(emotes)) , textElementColor_(textElementColor) @@ -244,7 +249,7 @@ LayeredEmoteElement::LayeredEmoteElement(std::vector &&emotes, this->updateTooltips(); } -void LayeredEmoteElement::addEmoteLayer(const EmotePtr &emote) +void LayeredEmoteElement::addEmoteLayer(const LayeredEmoteElement::Emote &emote) { this->emotes_.push_back(emote); this->updateTooltips(); @@ -295,9 +300,9 @@ std::vector LayeredEmoteElement::getLoadedImages(float scale) std::vector res; res.reserve(this->emotes_.size()); - for (auto emote : this->emotes_) + for (const auto &emote : this->emotes_) { - auto image = emote->images.getImageOrLoaded(scale); + auto image = emote.ptr->images.getImageOrLoaded(scale); if (image->isEmpty()) { continue; @@ -327,9 +332,9 @@ void LayeredEmoteElement::updateTooltips() std::vector result; result.reserve(this->emotes_.size()); - for (auto &emote : this->emotes_) + for (const auto &emote : this->emotes_) { - result.push_back(emote->tooltip.string); + result.push_back(emote.ptr->tooltip.string); } this->emoteTooltips_ = std::move(result); @@ -349,8 +354,8 @@ QString LayeredEmoteElement::getCleanCopyString() const { result += " "; } - result += - TwitchEmotes::cleanUpEmoteCode(this->emotes_[i]->getCopyString()); + result += TwitchEmotes::cleanUpEmoteCode( + this->emotes_[i].ptr->getCopyString()); } return result; } @@ -364,23 +369,25 @@ QString LayeredEmoteElement::getCopyString() const { result += " "; } - result += this->emotes_[i]->getCopyString(); + result += this->emotes_[i].ptr->getCopyString(); } return result; } -const std::vector &LayeredEmoteElement::getEmotes() const +const std::vector &LayeredEmoteElement::getEmotes() + const { return this->emotes_; } -std::vector LayeredEmoteElement::getUniqueEmotes() const +std::vector LayeredEmoteElement::getUniqueEmotes() + const { // Functor for std::copy_if that keeps track of seen elements struct NotDuplicate { - bool operator()(const EmotePtr &element) + bool operator()(const Emote &element) { - return seen.insert(element).second; + return seen.insert(element.ptr).second; } private: @@ -389,7 +396,7 @@ std::vector LayeredEmoteElement::getUniqueEmotes() const // Get unique emotes while maintaining relative layering order NotDuplicate dup; - std::vector unique; + std::vector unique; std::copy_if(this->emotes_.begin(), this->emotes_.end(), std::back_insert_iterator(unique), dup); diff --git a/src/messages/MessageElement.hpp b/src/messages/MessageElement.hpp index 5f6dcca1d..ddff4bf7a 100644 --- a/src/messages/MessageElement.hpp +++ b/src/messages/MessageElement.hpp @@ -187,6 +187,7 @@ public: const Link &getLink() const; bool hasTrailingSpace() const; MessageElementFlags getFlags() const; + void addFlags(MessageElementFlags flags); MessageElement *updateLink(); virtual void addToContainer(MessageLayoutContainer &container, @@ -325,19 +326,24 @@ private: class LayeredEmoteElement : public MessageElement { public: + struct Emote { + EmotePtr ptr; + MessageElementFlags flags; + }; + LayeredEmoteElement( - std::vector &&emotes, MessageElementFlags flags, + std::vector &&emotes, MessageElementFlags flags, const MessageColor &textElementColor = MessageColor::Text); - void addEmoteLayer(const EmotePtr &emote); + void addEmoteLayer(const Emote &emote); void addToContainer(MessageLayoutContainer &container, MessageElementFlags flags) override; // Returns a concatenation of each emote layer's cleaned copy string QString getCleanCopyString() const; - const std::vector &getEmotes() const; - std::vector getUniqueEmotes() const; + const std::vector &getEmotes() const; + std::vector getUniqueEmotes() const; const std::vector &getEmoteTooltips() const; private: @@ -349,7 +355,7 @@ private: void updateTooltips(); std::vector getLoadedImages(float scale); - std::vector emotes_; + std::vector emotes_; std::vector emoteTooltips_; std::unique_ptr textElement_; diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 99895a246..3cf157c54 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -1076,17 +1076,20 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name) // Need to remove EmoteElement and replace with LayeredEmoteElement auto baseEmoteElement = this->releaseBack(); - std::vector layers = {baseEmote, emote.get()}; - this->emplace(std::move(layers), - baseEmoteElement->getFlags(), - this->textColor_); + std::vector layers = { + {baseEmote, baseEmoteElement->getFlags()}, + {emote.get(), flags}}; + this->emplace( + std::move(layers), baseEmoteElement->getFlags() | flags, + this->textColor_); return Success; } auto asLayered = dynamic_cast(&this->back()); if (asLayered) { - asLayered->addEmoteLayer(emote.get()); + asLayered->addEmoteLayer({emote.get(), flags}); + asLayered->addFlags(flags); return Success; } diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 46a0dcfbb..137c45fbc 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1710,7 +1710,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) for (size_t i = 0; i < upperLimit; ++i) { - auto &emote = layeredEmotes[i]; + const auto &emote = layeredEmotes[i].ptr; if (i == 0) { // First entry gets a large image and full description @@ -2202,10 +2202,10 @@ void ChannelView::addImageContextMenuItems( // Give each emote its own submenu for (auto &emote : layeredElement->getUniqueEmotes()) { - auto emoteAction = menu.addAction(emote->name.string); + auto emoteAction = menu.addAction(emote.ptr->name.string); auto emoteMenu = new QMenu(&menu); emoteAction->setMenu(emoteMenu); - addEmoteContextMenuItems(*emote, creatorFlags, *emoteMenu); + addEmoteContextMenuItems(*emote.ptr, emote.flags, *emoteMenu); } } }