mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
added some code for collapsing messages
This commit is contained in:
parent
5c6411b50b
commit
c950e9c58a
11 changed files with 109 additions and 21 deletions
BIN
resources/images/collapse.png
Normal file
BIN
resources/images/collapse.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 236 B |
|
@ -33,6 +33,7 @@
|
||||||
<file>images/VSO_Link_blue_16x.png</file>
|
<file>images/VSO_Link_blue_16x.png</file>
|
||||||
<file>sounds/ping2.wav</file>
|
<file>sounds/ping2.wav</file>
|
||||||
<file>images/subscriber.png</file>
|
<file>images/subscriber.png</file>
|
||||||
|
<file>images/collapse.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/qt/etc">
|
<qresource prefix="/qt/etc">
|
||||||
<file>qt.conf</file>
|
<file>qt.conf</file>
|
||||||
|
|
|
@ -61,6 +61,16 @@ const QString &Message::getId() const
|
||||||
return this->id;
|
return this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Message::getCollapsedDefault() const
|
||||||
|
{
|
||||||
|
return this->collapsedDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Message::setCollapsedDefault(bool value)
|
||||||
|
{
|
||||||
|
this->collapsedDefault = value;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void AddCurrentTimestamp(Message *message)
|
void AddCurrentTimestamp(Message *message)
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
std::vector<Word> &getWords();
|
std::vector<Word> &getWords();
|
||||||
bool isDisabled() const;
|
bool isDisabled() const;
|
||||||
const QString &getId() const;
|
const QString &getId() const;
|
||||||
|
bool getCollapsedDefault() const;
|
||||||
|
void setCollapsedDefault(bool value);
|
||||||
|
|
||||||
QString loginName;
|
QString loginName;
|
||||||
QString displayName;
|
QString displayName;
|
||||||
|
@ -57,6 +59,9 @@ private:
|
||||||
QString timeoutUser = "";
|
QString timeoutUser = "";
|
||||||
int timeoutCount = 0;
|
int timeoutCount = 0;
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
|
|
||||||
|
bool collapsedDefault = false;
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::system_clock> parseTime;
|
std::chrono::time_point<std::chrono::system_clock> parseTime;
|
||||||
|
|
||||||
QString content;
|
QString content;
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#define MARGIN_LEFT 8
|
#define MARGIN_LEFT (int)(8 * this->dpiMultiplier)
|
||||||
#define MARGIN_RIGHT 8
|
#define MARGIN_RIGHT (int)(8 * this->dpiMultiplier)
|
||||||
#define MARGIN_TOP 4
|
#define MARGIN_TOP (int)(4 * this->dpiMultiplier)
|
||||||
#define MARGIN_BOTTOM 4
|
#define MARGIN_BOTTOM (int)(4 * this->dpiMultiplier)
|
||||||
|
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ namespace messages {
|
||||||
MessageRef::MessageRef(SharedMessage _message)
|
MessageRef::MessageRef(SharedMessage _message)
|
||||||
: message(_message)
|
: message(_message)
|
||||||
, wordParts()
|
, wordParts()
|
||||||
|
, collapsed(_message->getCollapsedDefault())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +60,9 @@ bool MessageRef::layout(int width, float dpiMultiplyer)
|
||||||
this->currentWordTypes = SettingsManager::getInstance().getWordTypeMask();
|
this->currentWordTypes = SettingsManager::getInstance().getWordTypeMask();
|
||||||
|
|
||||||
// check if dpi changed
|
// check if dpi changed
|
||||||
bool dpiChanged = this->dpiMultiplyer != dpiMultiplyer;
|
bool dpiChanged = this->dpiMultiplier != dpiMultiplyer;
|
||||||
layoutRequired |= dpiChanged;
|
layoutRequired |= dpiChanged;
|
||||||
this->dpiMultiplyer = dpiMultiplyer;
|
this->dpiMultiplier = dpiMultiplyer;
|
||||||
imagesChanged |= dpiChanged;
|
imagesChanged |= dpiChanged;
|
||||||
textChanged |= dpiChanged;
|
textChanged |= dpiChanged;
|
||||||
|
|
||||||
|
@ -105,9 +106,13 @@ void MessageRef::actuallyLayout(int width)
|
||||||
int lineNumber = 0;
|
int lineNumber = 0;
|
||||||
int lineStart = 0;
|
int lineStart = 0;
|
||||||
int lineHeight = 0;
|
int lineHeight = 0;
|
||||||
|
int firstLineHeight = -1;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
uint32_t flags = settings.getWordTypeMask();
|
uint32_t flags = settings.getWordTypeMask();
|
||||||
|
if (this->collapsed) {
|
||||||
|
flags |= Word::Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
// loop throught all the words and add them when a line is full
|
// loop throught all the words and add them when a line is full
|
||||||
for (auto it = this->message->getWords().begin(); it != this->message->getWords().end(); ++it) {
|
for (auto it = this->message->getWords().begin(); it != this->message->getWords().end(); ++it) {
|
||||||
|
@ -132,7 +137,7 @@ void MessageRef::actuallyLayout(int width)
|
||||||
// word wrapping
|
// word wrapping
|
||||||
if (word.isText() && word.getWidth() + MARGIN_LEFT > right) {
|
if (word.isText() && word.getWidth() + MARGIN_LEFT > right) {
|
||||||
// align and end the current line
|
// align and end the current line
|
||||||
alignWordParts(lineStart, lineHeight, width);
|
alignWordParts(lineStart, lineHeight, width, firstLineHeight);
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
int currentPartStart = 0;
|
int currentPartStart = 0;
|
||||||
|
@ -187,7 +192,7 @@ void MessageRef::actuallyLayout(int width)
|
||||||
// doesn't fit in the line
|
// doesn't fit in the line
|
||||||
else {
|
else {
|
||||||
// align and end the current line
|
// align and end the current line
|
||||||
alignWordParts(lineStart, lineHeight, width);
|
alignWordParts(lineStart, lineHeight, width, firstLineHeight);
|
||||||
|
|
||||||
y += lineHeight;
|
y += lineHeight;
|
||||||
|
|
||||||
|
@ -206,11 +211,19 @@ void MessageRef::actuallyLayout(int width)
|
||||||
}
|
}
|
||||||
|
|
||||||
// align and end the current line
|
// align and end the current line
|
||||||
alignWordParts(lineStart, lineHeight, width);
|
alignWordParts(lineStart, lineHeight, width, firstLineHeight);
|
||||||
|
|
||||||
|
this->collapsedHeight = firstLineHeight == -1 ? (int)(24 * dpiMultiplier)
|
||||||
|
: firstLineHeight + MARGIN_TOP + MARGIN_BOTTOM;
|
||||||
|
|
||||||
// update height
|
// update height
|
||||||
int oldHeight = this->height;
|
int oldHeight = this->height;
|
||||||
this->height = y + lineHeight + MARGIN_BOTTOM;
|
|
||||||
|
if (this->isCollapsed()) {
|
||||||
|
this->height = this->collapsedHeight;
|
||||||
|
} else {
|
||||||
|
this->height = y + lineHeight + MARGIN_BOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
// invalidate buffer if height changed
|
// invalidate buffer if height changed
|
||||||
if (oldHeight != this->height) {
|
if (oldHeight != this->height) {
|
||||||
|
@ -227,8 +240,8 @@ void MessageRef::updateTextSizes()
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QFontMetrics &metrics = word.getFontMetrics();
|
QFontMetrics &metrics = word.getFontMetrics();
|
||||||
word.setSize((int)(metrics.width(word.getText()) * this->dpiMultiplyer),
|
word.setSize((int)(metrics.width(word.getText()) * this->dpiMultiplier),
|
||||||
(int)(metrics.height() * this->dpiMultiplyer));
|
(int)(metrics.height() * this->dpiMultiplier));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +249,7 @@ void MessageRef::updateImageSizes()
|
||||||
{
|
{
|
||||||
const int mediumTextLineHeight =
|
const int mediumTextLineHeight =
|
||||||
FontManager::getInstance().getFontMetrics(FontManager::Medium).height();
|
FontManager::getInstance().getFontMetrics(FontManager::Medium).height();
|
||||||
const qreal emoteScale = SettingsManager::getInstance().emoteScale.get() * this->dpiMultiplyer;
|
const qreal emoteScale = SettingsManager::getInstance().emoteScale.get() * this->dpiMultiplier;
|
||||||
const bool scaleEmotesByLineHeight = SettingsManager::getInstance().scaleEmotesByLineHeight;
|
const bool scaleEmotesByLineHeight = SettingsManager::getInstance().scaleEmotesByLineHeight;
|
||||||
|
|
||||||
for (auto &word : this->message->getWords()) {
|
for (auto &word : this->message->getWords()) {
|
||||||
|
@ -262,8 +275,12 @@ const std::vector<WordPart> &MessageRef::getWordParts() const
|
||||||
return this->wordParts;
|
return this->wordParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageRef::alignWordParts(int lineStart, int lineHeight, int width)
|
void MessageRef::alignWordParts(int lineStart, int lineHeight, int width, int &firstLineHeight)
|
||||||
{
|
{
|
||||||
|
if (firstLineHeight == -1) {
|
||||||
|
firstLineHeight = lineHeight;
|
||||||
|
}
|
||||||
|
|
||||||
int xOffset = 0;
|
int xOffset = 0;
|
||||||
|
|
||||||
if (this->message->centered && this->wordParts.size() > 0) {
|
if (this->message->centered && this->wordParts.size() > 0) {
|
||||||
|
@ -399,5 +416,22 @@ int MessageRef::getSelectionIndex(QPoint position)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MessageRef::isCollapsed() const
|
||||||
|
{
|
||||||
|
return this->collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageRef::setCollapsed(bool value)
|
||||||
|
{
|
||||||
|
if (this->collapsed != value) {
|
||||||
|
this->currentLayoutWidth = 0;
|
||||||
|
this->collapsed = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MessageRef::getCollapsedHeight() const
|
||||||
|
{
|
||||||
|
return this->collapsedHeight;
|
||||||
|
}
|
||||||
} // namespace messages
|
} // namespace messages
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
Message *getMessage();
|
Message *getMessage();
|
||||||
int getHeight() const;
|
int getHeight() const;
|
||||||
|
|
||||||
bool layout(int width, float dpiMultiplyer);
|
bool layout(int width, float dpiMultiplier);
|
||||||
|
|
||||||
const std::vector<WordPart> &getWordParts() const;
|
const std::vector<WordPart> &getWordParts() const;
|
||||||
|
|
||||||
|
@ -33,6 +33,10 @@ public:
|
||||||
int getLastCharacterIndex() const;
|
int getLastCharacterIndex() const;
|
||||||
int getSelectionIndex(QPoint position);
|
int getSelectionIndex(QPoint position);
|
||||||
|
|
||||||
|
bool isCollapsed() const;
|
||||||
|
void setCollapsed(bool value);
|
||||||
|
int getCollapsedHeight() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// variables
|
// variables
|
||||||
SharedMessage message;
|
SharedMessage message;
|
||||||
|
@ -43,13 +47,16 @@ private:
|
||||||
int currentLayoutWidth = -1;
|
int currentLayoutWidth = -1;
|
||||||
int fontGeneration = -1;
|
int fontGeneration = -1;
|
||||||
int emoteGeneration = -1;
|
int emoteGeneration = -1;
|
||||||
float dpiMultiplyer = -1;
|
float dpiMultiplier = -1;
|
||||||
|
|
||||||
Word::Type currentWordTypes = Word::None;
|
Word::Type currentWordTypes = Word::None;
|
||||||
|
|
||||||
|
bool collapsed;
|
||||||
|
int collapsedHeight = 32;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void actuallyLayout(int width);
|
void actuallyLayout(int width);
|
||||||
void alignWordParts(int lineStart, int lineHeight, int width);
|
void alignWordParts(int lineStart, int lineHeight, int width, int &firstLineHeight);
|
||||||
void updateTextSizes();
|
void updateTextSizes();
|
||||||
void updateImageSizes();
|
void updateImageSizes();
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,6 +80,9 @@ public:
|
||||||
|
|
||||||
AlwaysShow = (1 << 25),
|
AlwaysShow = (1 << 25),
|
||||||
|
|
||||||
|
// used in the ChannelView class to make the collapse buttons visible if needed
|
||||||
|
Collapsed = (1 << 26),
|
||||||
|
|
||||||
Default = TimestampNoSeconds | Badges | Username | BitsStatic | FfzEmoteImage |
|
Default = TimestampNoSeconds | Badges | Username | BitsStatic | FfzEmoteImage |
|
||||||
BttvEmoteImage | BttvGifEmoteImage | TwitchEmoteImage | BitsAmount | Text |
|
BttvEmoteImage | BttvGifEmoteImage | TwitchEmoteImage | BitsAmount | Text |
|
||||||
ButtonBan | ButtonTimeout | AlwaysShow
|
ButtonBan | ButtonTimeout | AlwaysShow
|
||||||
|
|
|
@ -26,6 +26,7 @@ Resources::Resources()
|
||||||
, badgePremium(lli(":/images/twitchprime_bg.png"))
|
, badgePremium(lli(":/images/twitchprime_bg.png"))
|
||||||
, badgeVerified(lli(":/images/verified.png", 0.25))
|
, badgeVerified(lli(":/images/verified.png", 0.25))
|
||||||
, badgeSubscriber(lli(":/images/subscriber.png", 0.25))
|
, badgeSubscriber(lli(":/images/subscriber.png", 0.25))
|
||||||
|
, badgeCollapsed(lli(":/images/collapse.png"))
|
||||||
, cheerBadge100000(lli(":/images/cheer100000"))
|
, cheerBadge100000(lli(":/images/cheer100000"))
|
||||||
, cheerBadge10000(lli(":/images/cheer10000"))
|
, cheerBadge10000(lli(":/images/cheer10000"))
|
||||||
, cheerBadge5000(lli(":/images/cheer5000"))
|
, cheerBadge5000(lli(":/images/cheer5000"))
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
messages::LazyLoadedImage *badgePremium;
|
messages::LazyLoadedImage *badgePremium;
|
||||||
messages::LazyLoadedImage *badgeVerified;
|
messages::LazyLoadedImage *badgeVerified;
|
||||||
messages::LazyLoadedImage *badgeSubscriber;
|
messages::LazyLoadedImage *badgeSubscriber;
|
||||||
|
messages::LazyLoadedImage *badgeCollapsed;
|
||||||
|
|
||||||
messages::LazyLoadedImage *cheerBadge100000;
|
messages::LazyLoadedImage *cheerBadge100000;
|
||||||
messages::LazyLoadedImage *cheerBadge10000;
|
messages::LazyLoadedImage *cheerBadge10000;
|
||||||
|
|
|
@ -41,6 +41,10 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
|
|
||||||
this->parseUsername();
|
this->parseUsername();
|
||||||
|
|
||||||
|
// this->message->setCollapsedDefault(true);
|
||||||
|
// this->appendWord(Word(this->resources.badgeCollapsed, Word::Collapsed, QString(),
|
||||||
|
// QString()));
|
||||||
|
|
||||||
// The timestamp is always appended to the builder
|
// The timestamp is always appended to the builder
|
||||||
// Whether or not will be rendered is decided/checked later
|
// Whether or not will be rendered is decided/checked later
|
||||||
this->appendTimestamp();
|
this->appendTimestamp();
|
||||||
|
|
|
@ -729,11 +729,19 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||||
QPoint relativePos;
|
QPoint relativePos;
|
||||||
int messageIndex;
|
int messageIndex;
|
||||||
|
|
||||||
|
// no message under cursor
|
||||||
if (!tryGetMessageAt(event->pos(), message, relativePos, messageIndex)) {
|
if (!tryGetMessageAt(event->pos(), message, relativePos, messageIndex)) {
|
||||||
setCursor(Qt::ArrowCursor);
|
this->setCursor(Qt::ArrowCursor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// message under cursor is collapsed
|
||||||
|
if (message->isCollapsed()) {
|
||||||
|
this->setCursor(Qt::PointingHandCursor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is selecting
|
||||||
if (this->selecting) {
|
if (this->selecting) {
|
||||||
int index = message->getSelectionIndex(relativePos);
|
int index = message->getSelectionIndex(relativePos);
|
||||||
|
|
||||||
|
@ -742,16 +750,18 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||||
this->repaint();
|
this->repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if word underneath cursor
|
||||||
const messages::Word *hoverWord;
|
const messages::Word *hoverWord;
|
||||||
if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) {
|
if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) {
|
||||||
setCursor(Qt::ArrowCursor);
|
this->setCursor(Qt::ArrowCursor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if word has a link
|
||||||
if (hoverWord->getLink().isValid()) {
|
if (hoverWord->getLink().isValid()) {
|
||||||
setCursor(Qt::PointingHandCursor);
|
this->setCursor(Qt::PointingHandCursor);
|
||||||
} else {
|
} else {
|
||||||
setCursor(Qt::ArrowCursor);
|
this->setCursor(Qt::ArrowCursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,6 +797,11 @@ void ChannelView::mousePressEvent(QMouseEvent *event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if message is collapsed
|
||||||
|
if (message->isCollapsed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int index = message->getSelectionIndex(relativePos);
|
int index = message->getSelectionIndex(relativePos);
|
||||||
|
|
||||||
auto selectionItem = SelectionItem(messageIndex, index);
|
auto selectionItem = SelectionItem(messageIndex, index);
|
||||||
|
@ -831,6 +846,13 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// message under cursor is collapsed
|
||||||
|
if (message->isCollapsed()) {
|
||||||
|
message->setCollapsed(false);
|
||||||
|
this->layoutMessages();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const messages::Word *hoverWord;
|
const messages::Word *hoverWord;
|
||||||
|
|
||||||
if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) {
|
if ((hoverWord = message->tryGetWordPart(relativePos)) == nullptr) {
|
||||||
|
|
Loading…
Reference in a new issue