mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
fix: Only display spaces between words in reply context (#4977)
This commit is contained in:
parent
1a685d7bd0
commit
854032fce9
6 changed files with 133 additions and 10 deletions
|
@ -26,7 +26,7 @@
|
||||||
- Bugfix: Fixed an issue where the setting `Only search for emote autocompletion at the start of emote names` wouldn't disable if it was enabled when the client started. (#4855)
|
- Bugfix: Fixed an issue where the setting `Only search for emote autocompletion at the start of emote names` wouldn't disable if it was enabled when the client started. (#4855)
|
||||||
- Bugfix: Fixed empty page being added when showing out of bounds dialog. (#4849)
|
- 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 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 an issue where reply context didn't render correctly if an emoji was touching text. (#4875, #4977)
|
||||||
- Bugfix: Fixed the input completion popup from disappearing when clicking on it on Windows and macOS. (#4876)
|
- Bugfix: Fixed the input completion popup from disappearing when clicking on it on Windows and macOS. (#4876)
|
||||||
- Bugfix: Fixed double-click text selection moving its position with each new message. (#4898)
|
- Bugfix: Fixed double-click text selection moving its position with each new message. (#4898)
|
||||||
- Bugfix: Fixed an issue where notifications on Windows would contain no or an old avatar. (#4899)
|
- Bugfix: Fixed an issue where notifications on Windows would contain no or an old avatar. (#4899)
|
||||||
|
|
|
@ -929,7 +929,7 @@ if (CHATTERINO_DEBUG_NATIVE_MESSAGES)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(${LIBRARY_PROJECT} PUBLIC /EHsc /bigobj)
|
target_compile_options(${LIBRARY_PROJECT} PUBLIC /EHsc /bigobj /utf-8)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (APPLE AND BUILD_APP)
|
if (APPLE AND BUILD_APP)
|
||||||
|
|
|
@ -664,16 +664,23 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container,
|
||||||
QString currentText;
|
QString currentText;
|
||||||
|
|
||||||
container.first = FirstWord::Neutral;
|
container.first = FirstWord::Neutral;
|
||||||
|
|
||||||
|
bool firstIteration = true;
|
||||||
for (Word &word : this->words_)
|
for (Word &word : this->words_)
|
||||||
{
|
{
|
||||||
|
if (firstIteration)
|
||||||
|
{
|
||||||
|
firstIteration = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentText += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &parsedWord : app->emotes->emojis.parse(word.text))
|
for (const auto &parsedWord : app->emotes->emojis.parse(word.text))
|
||||||
{
|
{
|
||||||
if (parsedWord.type() == typeid(QString))
|
if (parsedWord.type() == typeid(QString))
|
||||||
{
|
{
|
||||||
if (!currentText.isEmpty())
|
|
||||||
{
|
|
||||||
currentText += ' ';
|
|
||||||
}
|
|
||||||
currentText += boost::get<QString>(parsedWord);
|
currentText += boost::get<QString>(parsedWord);
|
||||||
QString prev =
|
QString prev =
|
||||||
currentText; // only increments the ref-count
|
currentText; // only increments the ref-count
|
||||||
|
@ -714,7 +721,8 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container,
|
||||||
|
|
||||||
container.addElementNoLineBreak(
|
container.addElementNoLineBreak(
|
||||||
(new ImageLayoutElement(*this, image, emoteSize))
|
(new ImageLayoutElement(*this, image, emoteSize))
|
||||||
->setLink(this->getLink()));
|
->setLink(this->getLink())
|
||||||
|
->setTrailingSpace(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -723,9 +731,6 @@ void SingleLineTextElement::addToContainer(MessageLayoutContainer &container,
|
||||||
// Add the last of the pending message text to the container.
|
// Add the last of the pending message text to the container.
|
||||||
if (!currentText.isEmpty())
|
if (!currentText.isEmpty())
|
||||||
{
|
{
|
||||||
// Remove trailing space.
|
|
||||||
currentText = currentText.trimmed();
|
|
||||||
|
|
||||||
int width = metrics.horizontalAdvance(currentText);
|
int width = metrics.horizontalAdvance(currentText);
|
||||||
container.addElementNoLineBreak(
|
container.addElementNoLineBreak(
|
||||||
getTextLayoutElement(currentText, width, false));
|
getTextLayoutElement(currentText, width, false));
|
||||||
|
|
|
@ -152,6 +152,12 @@ namespace chatterino {
|
||||||
|
|
||||||
void Emojis::load()
|
void Emojis::load()
|
||||||
{
|
{
|
||||||
|
if (this->loaded_)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->loaded_ = true;
|
||||||
|
|
||||||
this->loadEmojis();
|
this->loadEmojis();
|
||||||
|
|
||||||
this->sortEmojis();
|
this->sortEmojis();
|
||||||
|
|
|
@ -80,6 +80,8 @@ private:
|
||||||
// Maps the first character of the emoji unicode string to a vector of
|
// Maps the first character of the emoji unicode string to a vector of
|
||||||
// possible emojis
|
// possible emojis
|
||||||
QMap<QChar, QVector<std::shared_ptr<EmojiData>>> emojiFirstByte_;
|
QMap<QChar, QVector<std::shared_ptr<EmojiData>>> emojiFirstByte_;
|
||||||
|
|
||||||
|
bool loaded_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
#include "providers/emoji/Emojis.hpp"
|
#include "providers/emoji/Emojis.hpp"
|
||||||
|
|
||||||
|
#include "common/Literals.hpp"
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
using namespace chatterino;
|
using namespace chatterino;
|
||||||
|
using namespace literals;
|
||||||
|
|
||||||
TEST(Emojis, ShortcodeParsing)
|
TEST(Emojis, ShortcodeParsing)
|
||||||
{
|
{
|
||||||
|
@ -53,3 +56,110 @@ TEST(Emojis, ShortcodeParsing)
|
||||||
<< "Input " << test.input.toStdString() << " failed";
|
<< "Input " << test.input.toStdString() << " failed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Emojis, Parse)
|
||||||
|
{
|
||||||
|
Emojis emojis;
|
||||||
|
|
||||||
|
emojis.load();
|
||||||
|
|
||||||
|
struct TestCase {
|
||||||
|
QString input;
|
||||||
|
std::vector<boost::variant<EmotePtr, QString>> expectedOutput;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto getEmoji = [&](auto code) {
|
||||||
|
std::shared_ptr<EmojiData> emoji;
|
||||||
|
emojis.getEmojis().tryGet(code, emoji);
|
||||||
|
return emoji->emote;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto penguin = getEmoji("1F427");
|
||||||
|
auto cool = getEmoji("1F192");
|
||||||
|
auto skinTone6 = getEmoji("1F3FF");
|
||||||
|
auto england = getEmoji("1F3F4-E0067-E0062-E0065-E006E-E0067-E007F");
|
||||||
|
auto womanRunningtone2 = getEmoji("1F3C3-1F3FC-200D-2640-FE0F");
|
||||||
|
auto kissWomanManTone1 =
|
||||||
|
getEmoji("1F468-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F468-1F3FB");
|
||||||
|
auto heavyEqualsSign = getEmoji("1F7F0");
|
||||||
|
auto coupleKissTone1Tone2 =
|
||||||
|
getEmoji("1F9D1-1F3FB-200D-2764-FE0F-200D-1F48B-200D-1F9D1-1F3FC");
|
||||||
|
auto hearHands = getEmoji("1FAF6");
|
||||||
|
|
||||||
|
const std::vector<TestCase> tests{
|
||||||
|
{
|
||||||
|
"abc",
|
||||||
|
{"abc"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abc def",
|
||||||
|
{"abc def"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abc🐧def",
|
||||||
|
{"abc", penguin, "def"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abc 🐧def",
|
||||||
|
{"abc ", penguin, "def"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
" abc🐧 def ",
|
||||||
|
{" abc", penguin, " def "},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"🐧",
|
||||||
|
{penguin},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"🐧🐧🐧🐧",
|
||||||
|
{penguin, penguin, penguin, penguin},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// england
|
||||||
|
u"\U0001F3F4\U000E0067\U000E0062\U000E0065\U000E006E\U000E0067\U000E007F"_s
|
||||||
|
// cool
|
||||||
|
"\U0001F192"
|
||||||
|
// skin tone 6
|
||||||
|
"\U0001F3FF"
|
||||||
|
// woman running tone2
|
||||||
|
"\U0001F3C3\U0001F3FC\u200D\u2640\uFE0F"
|
||||||
|
// [running] non-qualified
|
||||||
|
"\U0001F3C3\U0001F3FC\u200D\u2640",
|
||||||
|
{england, cool, skinTone6, womanRunningtone2, womanRunningtone2},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// kiss woman tone1 man tone 1
|
||||||
|
u"\U0001F468\U0001F3FB\u200D\u2764\uFE0F\u200D\U0001F48B\u200D\U0001F468\U0001F3FB"_s
|
||||||
|
// [kiss] non-qualified
|
||||||
|
"\U0001F468\U0001F3FB\u200D\u2764\u200D\U0001F48B\u200D"
|
||||||
|
"\U0001F468"
|
||||||
|
"\U0001F3FB"
|
||||||
|
// heavy equals sign
|
||||||
|
"\U0001F7F0",
|
||||||
|
{kissWomanManTone1, kissWomanManTone1, heavyEqualsSign},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// couple kiss tone 1, tone 2
|
||||||
|
u"\U0001F9D1\U0001F3FB\u200D\u2764\uFE0F\u200D\U0001F48B\u200D\U0001F9D1\U0001F3FC"_s
|
||||||
|
// [kiss] non-qualified
|
||||||
|
"\U0001F9D1\U0001F3FB\u200D\u2764\u200D\U0001F48B\u200D\U0001F9D1"
|
||||||
|
"\U0001F3FC"
|
||||||
|
// heart hands
|
||||||
|
"\U0001FAF6",
|
||||||
|
{coupleKissTone1Tone2, coupleKissTone1Tone2, hearHands},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &test : tests)
|
||||||
|
{
|
||||||
|
auto output = emojis.parse(test.input);
|
||||||
|
|
||||||
|
// can't use EXPECT_EQ because EmotePtr can't be printed
|
||||||
|
if (output != test.expectedOutput)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(false)
|
||||||
|
<< "Input " << test.input.toStdString() << " failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue