Added support for Twitch's Chat Replies (#3722)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
Daniel Sage
2022-07-31 06:45:25 -04:00
committed by GitHub
parent a280089693
commit 20c974fdab
53 changed files with 2022 additions and 310 deletions
+33
View File
@@ -55,6 +55,11 @@ const Message *MessageLayout::getMessage()
return this->message_.get();
}
const MessagePtr &MessageLayout::getMessagePtr() const
{
return this->message_;
}
// Height
int MessageLayout::getHeight() const
{
@@ -147,6 +152,12 @@ void MessageLayout::actuallyLayout(int width, MessageElementFlags flags)
continue;
}
if (!this->renderReplies_ &&
element->getFlags().has(MessageElementFlag::RepliedMessage))
{
continue;
}
element->addToContainer(*this->container_, flags);
}
@@ -414,4 +425,26 @@ void MessageLayout::addSelectionText(QString &str, int from, int to,
this->container_->addSelectionText(str, from, to, copymode);
}
bool MessageLayout::isReplyable() const
{
if (this->message_->loginName.isEmpty())
{
return false;
}
if (this->message_->flags.hasAny(
{MessageFlag::System, MessageFlag::Subscription,
MessageFlag::Timeout, MessageFlag::Whisper}))
{
return false;
}
return true;
}
void MessageLayout::setRenderReplies(bool render)
{
this->renderReplies_ = render;
}
} // namespace chatterino
+4
View File
@@ -37,6 +37,7 @@ public:
~MessageLayout();
const Message *getMessage();
const MessagePtr &getMessagePtr() const;
int getHeight() const;
@@ -62,6 +63,8 @@ public:
// Misc
bool isDisabled() const;
bool isReplyable() const;
void setRenderReplies(bool render);
private:
// variables
@@ -69,6 +72,7 @@ private:
std::shared_ptr<MessageLayoutContainer> container_;
std::shared_ptr<QPixmap> buffer_{};
bool bufferValid_ = false;
bool renderReplies_ = true;
int height_ = 0;
@@ -661,6 +661,14 @@ void MessageLayoutContainer::addSelectionText(QString &str, int from, int to,
for (auto &element : this->elements_)
{
if (copymode != CopyMode::Everything &&
element->getCreator().getFlags().has(
MessageElementFlag::RepliedMessage))
{
// Don't include the message being replied to
continue;
}
if (copymode == CopyMode::OnlyTextAndEmotes)
{
if (element->getCreator().getFlags().hasAny(
@@ -10,6 +10,7 @@
#include <QDebug>
#include <QPainter>
#include <QPainterPath>
namespace chatterino {
@@ -205,6 +206,44 @@ void ImageWithBackgroundLayoutElement::paint(QPainter &painter)
}
}
//
// IMAGE WITH CIRCLE BACKGROUND
//
ImageWithCircleBackgroundLayoutElement::ImageWithCircleBackgroundLayoutElement(
MessageElement &creator, ImagePtr image, const QSize &imageSize,
QColor color, int padding)
: ImageLayoutElement(creator, image,
imageSize + QSize(padding, padding) * 2)
, color_(color)
, imageSize_(imageSize)
, padding_(padding)
{
}
void ImageWithCircleBackgroundLayoutElement::paint(QPainter &painter)
{
if (this->image_ == nullptr)
{
return;
}
auto pixmap = this->image_->pixmapOrLoad();
if (pixmap && !this->image_->animated())
{
QRectF boxRect(this->getRect());
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(this->color_, Qt::SolidPattern));
painter.drawEllipse(boxRect);
QRectF imgRect;
imgRect.setTopLeft(boxRect.topLeft());
imgRect.setSize(this->imageSize_);
imgRect.translate(this->padding_, this->padding_);
painter.drawPixmap(imgRect, *pixmap, QRectF());
}
}
//
// TEXT
//
@@ -402,4 +441,67 @@ int TextIconLayoutElement::getXFromIndex(int index)
}
}
ReplyCurveLayoutElement::ReplyCurveLayoutElement(MessageElement &creator,
const QSize &size,
float thickness,
float neededMargin)
: MessageLayoutElement(creator, size)
, pen_(QColor("#888"), thickness, Qt::SolidLine, Qt::RoundCap)
, neededMargin_(neededMargin)
{
}
void ReplyCurveLayoutElement::paint(QPainter &painter)
{
QRectF paintRect(this->getRect());
QPainterPath bezierPath;
qreal top = paintRect.top() + paintRect.height() * 0.25; // 25% from top
qreal left = paintRect.left() + this->neededMargin_;
qreal bottom = paintRect.bottom() - this->neededMargin_;
QPointF startPoint(left, bottom);
QPointF controlPoint(left, top);
QPointF endPoint(paintRect.right(), top);
// Create curve path
bezierPath.moveTo(startPoint);
bezierPath.quadTo(controlPoint, endPoint);
// Render curve
painter.setPen(this->pen_);
painter.setRenderHint(QPainter::Antialiasing);
painter.drawPath(bezierPath);
}
void ReplyCurveLayoutElement::paintAnimated(QPainter &painter, int yOffset)
{
}
int ReplyCurveLayoutElement::getMouseOverIndex(const QPoint &abs) const
{
return 0;
}
int ReplyCurveLayoutElement::getXFromIndex(int index)
{
if (index <= 0)
{
return this->getRect().left();
}
else
{
return this->getRect().right();
}
}
void ReplyCurveLayoutElement::addCopyTextToString(QString &str, int from,
int to) const
{
}
int ReplyCurveLayoutElement::getSelectionIndexCount() const
{
return 1;
}
} // namespace chatterino
@@ -1,5 +1,6 @@
#pragma once
#include <QPen>
#include <QPoint>
#include <QRect>
#include <QString>
@@ -93,6 +94,23 @@ private:
QColor color_;
};
class ImageWithCircleBackgroundLayoutElement : public ImageLayoutElement
{
public:
ImageWithCircleBackgroundLayoutElement(MessageElement &creator,
ImagePtr image,
const QSize &imageSize, QColor color,
int padding);
protected:
void paint(QPainter &painter) override;
private:
const QColor color_;
const QSize imageSize_;
const int padding_;
};
// TEXT
class TextLayoutElement : public MessageLayoutElement
{
@@ -142,4 +160,24 @@ private:
QString line2;
};
class ReplyCurveLayoutElement : public MessageLayoutElement
{
public:
ReplyCurveLayoutElement(MessageElement &creator, const QSize &size,
float thickness, float lMargin);
protected:
void paint(QPainter &painter) override;
void paintAnimated(QPainter &painter, int yOffset) override;
int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(int index) override;
void addCopyTextToString(QString &str, int from = 0,
int to = INT_MAX) const override;
int getSelectionIndexCount() const override;
private:
const QPen pen_;
const float neededMargin_;
};
} // namespace chatterino