Display all parsed elements when parsing emojis in replies (#4875)

This commit is contained in:
nerix 2023-10-08 12:09:42 +02:00 committed by GitHub
parent 4db93bf1da
commit fe4d6121a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 42 deletions

View file

@ -19,6 +19,7 @@
- Bugfix: Fixed too much text being copied when copying chat messages. (#4812, #4830, #4839)
- Bugfix: Fixed empty page being added when showing out of bounds dialog. (#4849)
- Bugfix: Fixed issue on Windows preventing the title bar from being dragged in the top left corner. (#4873)
- Bugfix: Fixed an issue where reply context didn't render correctly if an emoji was touching text. (#4875)
- Bugfix: Fixed the input completion popup from disappearing when clicking on it on Windows and macOS. (#4876)
- Dev: Fixed UTF16 encoding of `modes` file for the installer. (#4791)
- Dev: Temporarily disable High DPI scaling on Qt6 builds on Windows. (#4767)

View file

@ -458,6 +458,7 @@ set(SOURCE_FILES
util/Twitch.cpp
util/Twitch.hpp
util/TypeName.hpp
util/Variant.hpp
util/WidgetHelpers.cpp
util/WidgetHelpers.hpp
util/WindowsHelper.cpp

View file

@ -12,6 +12,7 @@
#include "singletons/Settings.hpp"
#include "singletons/Theme.hpp"
#include "util/DebugCount.hpp"
#include "util/Variant.hpp"
namespace chatterino {
@ -665,55 +666,56 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container,
container.first = FirstWord::Neutral;
for (Word &word : this->words_)
{
auto parsedWords = app->emotes->emojis.parse(word.text);
if (parsedWords.size() == 0)
for (const auto &parsedWord : app->emotes->emojis.parse(word.text))
{
continue; // sanity check
}
auto &parsedWord = parsedWords[0];
if (parsedWord.type() == typeid(QString))
{
if (!currentText.isEmpty())
if (parsedWord.type() == typeid(QString))
{
currentText += ' ';
}
currentText += word.text;
QString prev = currentText; // only increments the ref-count
currentText = metrics.elidedText(currentText, Qt::ElideRight,
container.remainingWidth());
if (currentText != prev)
{
break;
}
}
else if (parsedWord.type() == typeid(EmotePtr))
{
auto emote = boost::get<EmotePtr>(parsedWord);
auto image =
emote->images.getImageOrLoaded(container.getScale());
if (!image->isEmpty())
{
auto emoteScale = getSettings()->emoteScale.getValue();
int currentWidth = metrics.horizontalAdvance(currentText);
auto emoteSize = QSize(image->width(), image->height()) *
(emoteScale * container.getScale());
if (!container.fitsInLine(currentWidth + emoteSize.width()))
if (!currentText.isEmpty())
{
currentText += ' ';
}
currentText += boost::get<QString>(parsedWord);
QString prev =
currentText; // only increments the ref-count
currentText =
metrics.elidedText(currentText, Qt::ElideRight,
container.remainingWidth());
if (currentText != prev)
{
currentText += ellipsis;
break;
}
}
else if (parsedWord.type() == typeid(EmotePtr))
{
auto emote = boost::get<EmotePtr>(parsedWord);
auto image =
emote->images.getImageOrLoaded(container.getScale());
if (!image->isEmpty())
{
auto emoteScale = getSettings()->emoteScale.getValue();
// Add currently pending text to container, then add the emote after.
container.addElementNoLineBreak(
getTextLayoutElement(currentText, currentWidth, false));
currentText.clear();
int currentWidth =
metrics.horizontalAdvance(currentText);
auto emoteSize =
QSize(image->width(), image->height()) *
(emoteScale * container.getScale());
container.addElementNoLineBreak(
(new ImageLayoutElement(*this, image, emoteSize))
->setLink(this->getLink()));
if (!container.fitsInLine(currentWidth +
emoteSize.width()))
{
currentText += ellipsis;
break;
}
// Add currently pending text to container, then add the emote after.
container.addElementNoLineBreak(getTextLayoutElement(
currentText, currentWidth, false));
currentText.clear();
container.addElementNoLineBreak(
(new ImageLayoutElement(*this, image, emoteSize))
->setLink(this->getLink()));
}
}
}
}

28
src/util/Variant.hpp Normal file
View file

@ -0,0 +1,28 @@
#pragma once
namespace chatterino::variant {
/// Compile-time safe visitor for std and boost variants.
///
/// From https://en.cppreference.com/w/cpp/utility/variant/visit
///
/// Usage:
///
/// ```
/// std::variant<int, double> v;
/// std::visit(variant::Overloaded{
/// [](double) { qDebug() << "double"; },
/// [](int) { qDebug() << "int"; }
/// }, v);
/// ```
template <class... Ts>
struct Overloaded : Ts... {
using Ts::operator()...;
};
// Technically, we shouldn't need this, as we're on C++ 20,
// but not all of our compilers support CTAD for aggregates yet.
template <class... Ts>
Overloaded(Ts...) -> Overloaded<Ts...>;
} // namespace chatterino::variant