From 0bba2299b33df238adca93e1e624a1ebf9119955 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Sat, 16 Nov 2024 15:41:48 -0500 Subject: [PATCH] Set the size of custom emoticons to the font height, and fix alignment Currently custom emojis render weirdly in NeoChat. Not only are they large, they're also in charge and like to mess up the layout of the text. Now that's fixed and they'll take up the same height as the surrounding text. It's now centered in the text too. --- src/texthandler.cpp | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/texthandler.cpp b/src/texthandler.cpp index dcfbfc02f..33be763a5 100644 --- a/src/texthandler.cpp +++ b/src/texthandler.cpp @@ -4,6 +4,7 @@ #include "texthandler.h" #include +#include #include #include #include @@ -34,7 +35,8 @@ static const QHash allowedAttributes = { {QStringLiteral("font"), {QStringLiteral("data-mx-bg-color"), QStringLiteral("data-mx-color"), QStringLiteral("color")}}, {QStringLiteral("span"), {QStringLiteral("data-mx-bg-color"), QStringLiteral("data-mx-color"), QStringLiteral("data-mx-spoiler")}}, {QStringLiteral("a"), {QStringLiteral("name"), QStringLiteral("target"), QStringLiteral("href")}}, - {QStringLiteral("img"), {QStringLiteral("width"), QStringLiteral("height"), QStringLiteral("alt"), QStringLiteral("title"), QStringLiteral("src")}}, + {QStringLiteral("img"), + {QStringLiteral("style"), QStringLiteral("width"), QStringLiteral("height"), QStringLiteral("alt"), QStringLiteral("title"), QStringLiteral("src")}}, {QStringLiteral("ol"), {QStringLiteral("start")}}, {QStringLiteral("code"), {QStringLiteral("class")}}}; static const QStringList allowedLinkSchemes = {QStringLiteral("https"), @@ -50,6 +52,8 @@ static const QStringList blockTags = {QStringLiteral("blockquote"), QStringLiteral("table"), QStringLiteral("pre")}; +static const QString customEmojiStyle = QStringLiteral("vertical-align:bottom"); + QString TextHandler::data() const { return m_data; @@ -131,9 +135,29 @@ TextHandler::handleRecieveRichText(Qt::TextFormat inputFormat, const NeoChatRoom while (i.hasNext()) { const QRegularExpressionMatch match = i.next(); const QUrl mediaUrl = room->makeMediaUrl(event->id(), QUrl(QStringLiteral("mxc://") + match.captured(2) + u'/' + match.captured(3))); + + QStringList extraAttributes = match.captured(4).split(QChar::Space); + const bool isEmoticon = match.captured(1).contains(QStringLiteral("data-mx-emoticon")); + + // If the image does not have an explicit width, but has a vertical-align it's most likely an emoticon. + // We must do some pre-processing for it to show up nicely in and around text. + if (isEmoticon) { + // Remove any pre-existing height + extraAttributes.removeIf([](const QString &s) { + return s.contains(QStringLiteral("height=")); + }); + + // Make sure it's the same height as the rest of the text + const QFontMetrics metrics(QGuiApplication::font()); + extraAttributes.append(QStringLiteral("height=\"%1\"").arg(metrics.height())); + + // Align it properly + extraAttributes.append(QStringLiteral("style=\"%1\"").arg(customEmojiStyle)); + } + m_dataBuffer.replace(match.captured(0), - QStringLiteral("'); + QStringLiteral("'); } } @@ -493,6 +517,12 @@ QString TextHandler::cleanAttributes(const QString &tag, const QString &tagStrin if (getAttributeData(nextAttribute).remove(u'"').startsWith(QStringLiteral("language-"))) { outputString.append(u' ' + nextAttribute); } + } else if (tag == QStringLiteral("img") && getAttributeType(nextAttribute) == QStringLiteral("style")) { + const QString attributeData = TextRegex::attributeData.match(getAttributeData(nextAttribute)).captured(1); + // Ignore every other style attribute except for our own, which we use to align custom emoticons + if (attributeData == customEmojiStyle) { + outputString.append(u' ' + nextAttribute); + } } else { outputString.append(u' ' + nextAttribute); }