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)
|
- 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 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 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: Ignore unhandled BTTV user-events. (#4438)
|
||||||
- Dev: Only log debug messages when NDEBUG is not defined. (#4442)
|
- Dev: Only log debug messages when NDEBUG is not defined. (#4442)
|
||||||
- Dev: Cleaned up theme related code. (#4450)
|
- Dev: Cleaned up theme related code. (#4450)
|
||||||
|
|
|
@ -42,6 +42,12 @@ public:
|
||||||
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flag);
|
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)
|
void unset(T flag)
|
||||||
{
|
{
|
||||||
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
|
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
|
||||||
|
@ -69,6 +75,12 @@ public:
|
||||||
return xd;
|
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
|
bool hasAny(FlagsEnum flags) const
|
||||||
{
|
{
|
||||||
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
|
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
|
||||||
|
|
|
@ -110,6 +110,11 @@ MessageElementFlags MessageElement::getFlags() const
|
||||||
return this->flags_;
|
return this->flags_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageElement::addFlags(MessageElementFlags flags)
|
||||||
|
{
|
||||||
|
this->flags_.set(flags);
|
||||||
|
}
|
||||||
|
|
||||||
MessageElement *MessageElement::updateLink()
|
MessageElement *MessageElement::updateLink()
|
||||||
{
|
{
|
||||||
this->linkChanged.invoke();
|
this->linkChanged.invoke();
|
||||||
|
@ -234,8 +239,8 @@ MessageLayoutElement *EmoteElement::makeImageLayoutElement(
|
||||||
return new ImageLayoutElement(*this, image, size);
|
return new ImageLayoutElement(*this, image, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayeredEmoteElement::LayeredEmoteElement(std::vector<EmotePtr> &&emotes,
|
LayeredEmoteElement::LayeredEmoteElement(
|
||||||
MessageElementFlags flags,
|
std::vector<LayeredEmoteElement::Emote> &&emotes, MessageElementFlags flags,
|
||||||
const MessageColor &textElementColor)
|
const MessageColor &textElementColor)
|
||||||
: MessageElement(flags)
|
: MessageElement(flags)
|
||||||
, emotes_(std::move(emotes))
|
, emotes_(std::move(emotes))
|
||||||
|
@ -244,7 +249,7 @@ LayeredEmoteElement::LayeredEmoteElement(std::vector<EmotePtr> &&emotes,
|
||||||
this->updateTooltips();
|
this->updateTooltips();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayeredEmoteElement::addEmoteLayer(const EmotePtr &emote)
|
void LayeredEmoteElement::addEmoteLayer(const LayeredEmoteElement::Emote &emote)
|
||||||
{
|
{
|
||||||
this->emotes_.push_back(emote);
|
this->emotes_.push_back(emote);
|
||||||
this->updateTooltips();
|
this->updateTooltips();
|
||||||
|
@ -295,9 +300,9 @@ std::vector<ImagePtr> LayeredEmoteElement::getLoadedImages(float scale)
|
||||||
std::vector<ImagePtr> res;
|
std::vector<ImagePtr> res;
|
||||||
res.reserve(this->emotes_.size());
|
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())
|
if (image->isEmpty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -327,9 +332,9 @@ void LayeredEmoteElement::updateTooltips()
|
||||||
std::vector<QString> result;
|
std::vector<QString> result;
|
||||||
result.reserve(this->emotes_.size());
|
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);
|
this->emoteTooltips_ = std::move(result);
|
||||||
|
@ -349,8 +354,8 @@ QString LayeredEmoteElement::getCleanCopyString() const
|
||||||
{
|
{
|
||||||
result += " ";
|
result += " ";
|
||||||
}
|
}
|
||||||
result +=
|
result += TwitchEmotes::cleanUpEmoteCode(
|
||||||
TwitchEmotes::cleanUpEmoteCode(this->emotes_[i]->getCopyString());
|
this->emotes_[i].ptr->getCopyString());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -364,23 +369,25 @@ QString LayeredEmoteElement::getCopyString() const
|
||||||
{
|
{
|
||||||
result += " ";
|
result += " ";
|
||||||
}
|
}
|
||||||
result += this->emotes_[i]->getCopyString();
|
result += this->emotes_[i].ptr->getCopyString();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<EmotePtr> &LayeredEmoteElement::getEmotes() const
|
const std::vector<LayeredEmoteElement::Emote> &LayeredEmoteElement::getEmotes()
|
||||||
|
const
|
||||||
{
|
{
|
||||||
return this->emotes_;
|
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
|
// Functor for std::copy_if that keeps track of seen elements
|
||||||
struct NotDuplicate {
|
struct NotDuplicate {
|
||||||
bool operator()(const EmotePtr &element)
|
bool operator()(const Emote &element)
|
||||||
{
|
{
|
||||||
return seen.insert(element).second;
|
return seen.insert(element.ptr).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -389,7 +396,7 @@ std::vector<EmotePtr> LayeredEmoteElement::getUniqueEmotes() const
|
||||||
|
|
||||||
// Get unique emotes while maintaining relative layering order
|
// Get unique emotes while maintaining relative layering order
|
||||||
NotDuplicate dup;
|
NotDuplicate dup;
|
||||||
std::vector<EmotePtr> unique;
|
std::vector<Emote> unique;
|
||||||
std::copy_if(this->emotes_.begin(), this->emotes_.end(),
|
std::copy_if(this->emotes_.begin(), this->emotes_.end(),
|
||||||
std::back_insert_iterator(unique), dup);
|
std::back_insert_iterator(unique), dup);
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,7 @@ public:
|
||||||
const Link &getLink() const;
|
const Link &getLink() const;
|
||||||
bool hasTrailingSpace() const;
|
bool hasTrailingSpace() const;
|
||||||
MessageElementFlags getFlags() const;
|
MessageElementFlags getFlags() const;
|
||||||
|
void addFlags(MessageElementFlags flags);
|
||||||
MessageElement *updateLink();
|
MessageElement *updateLink();
|
||||||
|
|
||||||
virtual void addToContainer(MessageLayoutContainer &container,
|
virtual void addToContainer(MessageLayoutContainer &container,
|
||||||
|
@ -325,19 +326,24 @@ private:
|
||||||
class LayeredEmoteElement : public MessageElement
|
class LayeredEmoteElement : public MessageElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Emote {
|
||||||
|
EmotePtr ptr;
|
||||||
|
MessageElementFlags flags;
|
||||||
|
};
|
||||||
|
|
||||||
LayeredEmoteElement(
|
LayeredEmoteElement(
|
||||||
std::vector<EmotePtr> &&emotes, MessageElementFlags flags,
|
std::vector<Emote> &&emotes, MessageElementFlags flags,
|
||||||
const MessageColor &textElementColor = MessageColor::Text);
|
const MessageColor &textElementColor = MessageColor::Text);
|
||||||
|
|
||||||
void addEmoteLayer(const EmotePtr &emote);
|
void addEmoteLayer(const Emote &emote);
|
||||||
|
|
||||||
void addToContainer(MessageLayoutContainer &container,
|
void addToContainer(MessageLayoutContainer &container,
|
||||||
MessageElementFlags flags) override;
|
MessageElementFlags flags) override;
|
||||||
|
|
||||||
// Returns a concatenation of each emote layer's cleaned copy string
|
// Returns a concatenation of each emote layer's cleaned copy string
|
||||||
QString getCleanCopyString() const;
|
QString getCleanCopyString() const;
|
||||||
const std::vector<EmotePtr> &getEmotes() const;
|
const std::vector<Emote> &getEmotes() const;
|
||||||
std::vector<EmotePtr> getUniqueEmotes() const;
|
std::vector<Emote> getUniqueEmotes() const;
|
||||||
const std::vector<QString> &getEmoteTooltips() const;
|
const std::vector<QString> &getEmoteTooltips() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -349,7 +355,7 @@ private:
|
||||||
void updateTooltips();
|
void updateTooltips();
|
||||||
std::vector<ImagePtr> getLoadedImages(float scale);
|
std::vector<ImagePtr> getLoadedImages(float scale);
|
||||||
|
|
||||||
std::vector<EmotePtr> emotes_;
|
std::vector<Emote> emotes_;
|
||||||
std::vector<QString> emoteTooltips_;
|
std::vector<QString> emoteTooltips_;
|
||||||
|
|
||||||
std::unique_ptr<TextElement> textElement_;
|
std::unique_ptr<TextElement> textElement_;
|
||||||
|
|
|
@ -1076,9 +1076,11 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
|
||||||
// Need to remove EmoteElement and replace with LayeredEmoteElement
|
// Need to remove EmoteElement and replace with LayeredEmoteElement
|
||||||
auto baseEmoteElement = this->releaseBack();
|
auto baseEmoteElement = this->releaseBack();
|
||||||
|
|
||||||
std::vector<EmotePtr> layers = {baseEmote, emote.get()};
|
std::vector<LayeredEmoteElement::Emote> layers = {
|
||||||
this->emplace<LayeredEmoteElement>(std::move(layers),
|
{baseEmote, baseEmoteElement->getFlags()},
|
||||||
baseEmoteElement->getFlags(),
|
{emote.get(), flags}};
|
||||||
|
this->emplace<LayeredEmoteElement>(
|
||||||
|
std::move(layers), baseEmoteElement->getFlags() | flags,
|
||||||
this->textColor_);
|
this->textColor_);
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -1086,7 +1088,8 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
|
||||||
auto asLayered = dynamic_cast<LayeredEmoteElement *>(&this->back());
|
auto asLayered = dynamic_cast<LayeredEmoteElement *>(&this->back());
|
||||||
if (asLayered)
|
if (asLayered)
|
||||||
{
|
{
|
||||||
asLayered->addEmoteLayer(emote.get());
|
asLayered->addEmoteLayer({emote.get(), flags});
|
||||||
|
asLayered->addFlags(flags);
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1710,7 +1710,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
|
||||||
for (size_t i = 0; i < upperLimit; ++i)
|
for (size_t i = 0; i < upperLimit; ++i)
|
||||||
{
|
{
|
||||||
auto &emote = layeredEmotes[i];
|
const auto &emote = layeredEmotes[i].ptr;
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
// First entry gets a large image and full description
|
// First entry gets a large image and full description
|
||||||
|
@ -2202,10 +2202,10 @@ void ChannelView::addImageContextMenuItems(
|
||||||
// Give each emote its own submenu
|
// Give each emote its own submenu
|
||||||
for (auto &emote : layeredElement->getUniqueEmotes())
|
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);
|
auto emoteMenu = new QMenu(&menu);
|
||||||
emoteAction->setMenu(emoteMenu);
|
emoteAction->setMenu(emoteMenu);
|
||||||
addEmoteContextMenuItems(*emote, creatorFlags, *emoteMenu);
|
addEmoteContextMenuItems(*emote.ptr, emote.flags, *emoteMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue