Formalize zero-width emote implementation (#4314)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -64,6 +64,7 @@
|
||||
#define DRAW_WIDTH (this->width())
|
||||
#define SELECTION_RESUME_SCROLLING_MSG_THRESHOLD 3
|
||||
#define CHAT_HOVER_PAUSE_DURATION 1000
|
||||
#define TOOLTIP_EMOTE_ENTRIES_LIMIT 7
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
@@ -1658,10 +1659,12 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||
auto element = &hoverLayoutElement->getCreator();
|
||||
bool isLinkValid = hoverLayoutElement->getLink().isValid();
|
||||
auto emoteElement = dynamic_cast<const EmoteElement *>(element);
|
||||
auto layeredEmoteElement =
|
||||
dynamic_cast<const LayeredEmoteElement *>(element);
|
||||
bool isNotEmote = emoteElement == nullptr && layeredEmoteElement == nullptr;
|
||||
|
||||
if (element->getTooltip().isEmpty() ||
|
||||
(isLinkValid && emoteElement == nullptr &&
|
||||
!getSettings()->linkInfoTooltip))
|
||||
(isLinkValid && isNotEmote && !getSettings()->linkInfoTooltip))
|
||||
{
|
||||
tooltipWidget->hide();
|
||||
}
|
||||
@@ -1669,7 +1672,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
auto badgeElement = dynamic_cast<const BadgeElement *>(element);
|
||||
|
||||
if ((badgeElement || emoteElement) &&
|
||||
if ((badgeElement || emoteElement || layeredEmoteElement) &&
|
||||
getSettings()->emotesTooltipPreview.getValue())
|
||||
{
|
||||
if (event->modifiers() == Qt::ShiftModifier ||
|
||||
@@ -1677,18 +1680,73 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (emoteElement)
|
||||
{
|
||||
tooltipWidget->setImage(
|
||||
emoteElement->getEmote()->images.getImage(3.0));
|
||||
tooltipWidget->setOne({
|
||||
emoteElement->getEmote()->images.getImage(3.0),
|
||||
element->getTooltip(),
|
||||
});
|
||||
}
|
||||
else if (layeredEmoteElement)
|
||||
{
|
||||
auto &layeredEmotes = layeredEmoteElement->getEmotes();
|
||||
// Should never be empty but ensure it
|
||||
if (!layeredEmotes.empty())
|
||||
{
|
||||
std::vector<TooltipEntry> entries;
|
||||
entries.reserve(layeredEmotes.size());
|
||||
|
||||
auto &emoteTooltips =
|
||||
layeredEmoteElement->getEmoteTooltips();
|
||||
|
||||
// Someone performing some tomfoolery could put an emote with tens,
|
||||
// if not hundreds of zero-width emotes on a single emote. If the
|
||||
// tooltip may take up more than three rows, truncate everything else.
|
||||
bool truncating = false;
|
||||
size_t upperLimit = layeredEmotes.size();
|
||||
if (layeredEmotes.size() > TOOLTIP_EMOTE_ENTRIES_LIMIT)
|
||||
{
|
||||
upperLimit = TOOLTIP_EMOTE_ENTRIES_LIMIT - 1;
|
||||
truncating = true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < upperLimit; ++i)
|
||||
{
|
||||
auto &emote = layeredEmotes[i];
|
||||
if (i == 0)
|
||||
{
|
||||
// First entry gets a large image and full description
|
||||
entries.push_back({emote->images.getImage(3.0),
|
||||
emoteTooltips[i]});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Every other entry gets a small image and just the emote name
|
||||
entries.push_back({emote->images.getImage(1.0),
|
||||
emote->name.string});
|
||||
}
|
||||
}
|
||||
|
||||
if (truncating)
|
||||
{
|
||||
entries.push_back({nullptr, "..."});
|
||||
}
|
||||
|
||||
auto style = layeredEmotes.size() > 2
|
||||
? TooltipStyle::Grid
|
||||
: TooltipStyle::Vertical;
|
||||
tooltipWidget->set(entries, style);
|
||||
}
|
||||
}
|
||||
else if (badgeElement)
|
||||
{
|
||||
tooltipWidget->setImage(
|
||||
badgeElement->getEmote()->images.getImage(3.0));
|
||||
tooltipWidget->setOne({
|
||||
badgeElement->getEmote()->images.getImage(3.0),
|
||||
element->getTooltip(),
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltipWidget->clearImage();
|
||||
tooltipWidget->clearEntries();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1711,7 +1769,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||
auto thumbnailSize = getSettings()->thumbnailSize;
|
||||
if (!thumbnailSize)
|
||||
{
|
||||
tooltipWidget->clearImage();
|
||||
tooltipWidget->clearEntries();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1724,19 +1782,23 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||
shouldHideThumbnail
|
||||
? Image::fromResourcePixmap(getResources().streamerMode)
|
||||
: element->getThumbnail();
|
||||
tooltipWidget->setImage(std::move(thumb));
|
||||
|
||||
if (element->getThumbnailType() ==
|
||||
MessageElement::ThumbnailType::Link_Thumbnail)
|
||||
{
|
||||
tooltipWidget->setImageScale(thumbnailSize, thumbnailSize);
|
||||
tooltipWidget->setOne({std::move(thumb),
|
||||
element->getTooltip(), thumbnailSize,
|
||||
thumbnailSize});
|
||||
}
|
||||
else
|
||||
{
|
||||
tooltipWidget->setOne({std::move(thumb), ""});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tooltipWidget->moveTo(this, event->globalPos());
|
||||
tooltipWidget->setWordWrap(isLinkValid);
|
||||
tooltipWidget->setText(element->getTooltip());
|
||||
tooltipWidget->show();
|
||||
}
|
||||
|
||||
@@ -2134,6 +2196,18 @@ void ChannelView::addImageContextMenuItems(
|
||||
addEmoteContextMenuItems(*emoteElement->getEmote(), creatorFlags,
|
||||
menu);
|
||||
}
|
||||
else if (auto layeredElement =
|
||||
dynamic_cast<const LayeredEmoteElement *>(&creator))
|
||||
{
|
||||
// Give each emote its own submenu
|
||||
for (auto &emote : layeredElement->getUniqueEmotes())
|
||||
{
|
||||
auto emoteAction = menu.addAction(emote->name.string);
|
||||
auto emoteMenu = new QMenu(&menu);
|
||||
emoteAction->setMenu(emoteMenu);
|
||||
addEmoteContextMenuItems(*emote, creatorFlags, *emoteMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add seperator
|
||||
|
||||
Reference in New Issue
Block a user