mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
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.
This commit is contained in:
parent
0acbc0d2c3
commit
a777a227d4
|
@ -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)
|
||||
|
|
|
@ -42,6 +42,12 @@ public:
|
|||
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flag);
|
||||
}
|
||||
|
||||
/** Adds the flags from `flags` in this enum. */
|
||||
void set(FlagsEnum flags)
|
||||
{
|
||||
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flags.value_);
|
||||
}
|
||||
|
||||
void unset(T flag)
|
||||
{
|
||||
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
|
||||
|
@ -69,6 +75,12 @@ public:
|
|||
return xd;
|
||||
}
|
||||
|
||||
FlagsEnum operator|(FlagsEnum rhs)
|
||||
{
|
||||
return static_cast<T>(static_cast<Q>(this->value_) |
|
||||
static_cast<Q>(rhs.value_));
|
||||
}
|
||||
|
||||
bool hasAny(FlagsEnum flags) const
|
||||
{
|
||||
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
|
||||
|
|
|
@ -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,8 +239,8 @@ MessageLayoutElement *EmoteElement::makeImageLayoutElement(
|
|||
return new ImageLayoutElement(*this, image, size);
|
||||
}
|
||||
|
||||
LayeredEmoteElement::LayeredEmoteElement(std::vector<EmotePtr> &&emotes,
|
||||
MessageElementFlags flags,
|
||||
LayeredEmoteElement::LayeredEmoteElement(
|
||||
std::vector<LayeredEmoteElement::Emote> &&emotes, MessageElementFlags flags,
|
||||
const MessageColor &textElementColor)
|
||||
: MessageElement(flags)
|
||||
, emotes_(std::move(emotes))
|
||||
|
@ -244,7 +249,7 @@ LayeredEmoteElement::LayeredEmoteElement(std::vector<EmotePtr> &&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<ImagePtr> LayeredEmoteElement::getLoadedImages(float scale)
|
|||
std::vector<ImagePtr> 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<QString> 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<EmotePtr> &LayeredEmoteElement::getEmotes() const
|
||||
const std::vector<LayeredEmoteElement::Emote> &LayeredEmoteElement::getEmotes()
|
||||
const
|
||||
{
|
||||
return this->emotes_;
|
||||
}
|
||||
|
||||
std::vector<EmotePtr> LayeredEmoteElement::getUniqueEmotes() const
|
||||
std::vector<LayeredEmoteElement::Emote> 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<EmotePtr> LayeredEmoteElement::getUniqueEmotes() const
|
|||
|
||||
// Get unique emotes while maintaining relative layering order
|
||||
NotDuplicate dup;
|
||||
std::vector<EmotePtr> unique;
|
||||
std::vector<Emote> unique;
|
||||
std::copy_if(this->emotes_.begin(), this->emotes_.end(),
|
||||
std::back_insert_iterator(unique), dup);
|
||||
|
||||
|
|
|
@ -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<EmotePtr> &&emotes, MessageElementFlags flags,
|
||||
std::vector<Emote> &&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<EmotePtr> &getEmotes() const;
|
||||
std::vector<EmotePtr> getUniqueEmotes() const;
|
||||
const std::vector<Emote> &getEmotes() const;
|
||||
std::vector<Emote> getUniqueEmotes() const;
|
||||
const std::vector<QString> &getEmoteTooltips() const;
|
||||
|
||||
private:
|
||||
|
@ -349,7 +355,7 @@ private:
|
|||
void updateTooltips();
|
||||
std::vector<ImagePtr> getLoadedImages(float scale);
|
||||
|
||||
std::vector<EmotePtr> emotes_;
|
||||
std::vector<Emote> emotes_;
|
||||
std::vector<QString> emoteTooltips_;
|
||||
|
||||
std::unique_ptr<TextElement> textElement_;
|
||||
|
|
|
@ -1076,9 +1076,11 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
|
|||
// Need to remove EmoteElement and replace with LayeredEmoteElement
|
||||
auto baseEmoteElement = this->releaseBack();
|
||||
|
||||
std::vector<EmotePtr> layers = {baseEmote, emote.get()};
|
||||
this->emplace<LayeredEmoteElement>(std::move(layers),
|
||||
baseEmoteElement->getFlags(),
|
||||
std::vector<LayeredEmoteElement::Emote> layers = {
|
||||
{baseEmote, baseEmoteElement->getFlags()},
|
||||
{emote.get(), flags}};
|
||||
this->emplace<LayeredEmoteElement>(
|
||||
std::move(layers), baseEmoteElement->getFlags() | flags,
|
||||
this->textColor_);
|
||||
return Success;
|
||||
}
|
||||
|
@ -1086,7 +1088,8 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
|
|||
auto asLayered = dynamic_cast<LayeredEmoteElement *>(&this->back());
|
||||
if (asLayered)
|
||||
{
|
||||
asLayered->addEmoteLayer(emote.get());
|
||||
asLayered->addEmoteLayer({emote.get(), flags});
|
||||
asLayered->addFlags(flags);
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue