Remove "custom on success" logic from Image.

Create a new message element and message layout element type for mod badges.
This commit is contained in:
Rasmus Karlsson 2019-09-08 11:30:06 +02:00 committed by fourtf
parent 256a65a12e
commit dbce128cc3
8 changed files with 84 additions and 53 deletions

View file

@ -349,9 +349,6 @@ void Image::actuallyLoad()
if (!shared)
return Failure;
if (shared->customOnSuccess_)
return shared->customOnSuccess_(shared, result);
auto data = result.getData();
// const cast since we are only reading from it
@ -396,11 +393,4 @@ bool Image::operator!=(const Image &other) const
return !this->operator==(other);
}
ImagePtr Image::setCustomOnSuccess(
std::function<Outcome(ImagePtr, NetworkResult)> customOnSuccess)
{
this->customOnSuccess_ = customOnSuccess;
return shared_from_this();
}
} // namespace chatterino

View file

@ -68,18 +68,13 @@ public:
bool operator==(const Image &image) const;
bool operator!=(const Image &image) const;
ImagePtr setCustomOnSuccess(
std::function<Outcome(ImagePtr, NetworkResult)> onSuccess);
private:
Image();
Image(const Url &url, qreal scale);
Image(qreal scale);
public:
void setPixmap(const QPixmap &pixmap);
private:
void actuallyLoad();
Url url_{};
@ -88,6 +83,5 @@ private:
bool shouldLoad_{false};
std::unique_ptr<detail::Frames> frames_{};
QObject object_{};
std::function<Outcome(ImagePtr, NetworkResult)> customOnSuccess_{};
};
} // namespace chatterino

View file

@ -145,7 +145,7 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container,
QSize(int(container.getScale() * image->width() * emoteScale),
int(container.getScale() * image->height() * emoteScale));
container.addElement((new ImageLayoutElement(*this, image, size))
container.addElement(this->makeImageLayoutElement(image, size)
->setLink(this->getLink()));
}
else
@ -159,6 +159,27 @@ void EmoteElement::addToContainer(MessageLayoutContainer &container,
}
}
MessageLayoutElement *EmoteElement::makeImageLayoutElement(
const ImagePtr &image, const QSize &size)
{
return new ImageLayoutElement(*this, image, size);
}
// MOD BADGE
ModBadgeElement::ModBadgeElement(const EmotePtr &data,
MessageElementFlags flags_)
: EmoteElement(data, flags_)
{
}
MessageLayoutElement *ModBadgeElement::makeImageLayoutElement(
const ImagePtr &image, const QSize &size)
{
static const QColor modBadgeBackgroundColor("#34AE0A");
return new ImageWithBackgroundLayoutElement(*this, image, size,
modBadgeBackgroundColor);
}
// BADGE
BadgeElement::BadgeElement(const EmotePtr &emote, MessageElementFlags flags)
: MessageElement(flags)

View file

@ -17,6 +17,7 @@
namespace chatterino {
class Channel;
struct MessageLayoutContainer;
class MessageLayoutElement;
class Image;
using ImagePtr = std::shared_ptr<Image>;
@ -209,11 +210,26 @@ public:
MessageElementFlags flags_) override;
EmotePtr getEmote() const;
protected:
virtual MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size);
private:
std::unique_ptr<TextElement> textElement_;
EmotePtr emote_;
};
// Behaves like an emote element, except it creates a different image layout element that draws the mod badge background
class ModBadgeElement : public EmoteElement
{
public:
ModBadgeElement(const EmotePtr &data, MessageElementFlags flags_);
protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size) override;
};
class BadgeElement : public MessageElement
{
public:

View file

@ -168,6 +168,33 @@ int ImageLayoutElement::getXFromIndex(int index)
}
}
//
// IMAGE WITH BACKGROUND
//
ImageWithBackgroundLayoutElement::ImageWithBackgroundLayoutElement(
MessageElement &creator, ImagePtr image, const QSize &size, QColor color)
: ImageLayoutElement(creator, image, size)
, color_(color)
{
}
void ImageWithBackgroundLayoutElement::paint(QPainter &painter)
{
if (this->image_ == nullptr)
{
return;
}
auto pixmap = this->image_->pixmapOrLoad();
if (pixmap && !this->image_->animated())
{
painter.fillRect(QRectF(this->getRect()), this->color_);
// fourtf: make it use qreal values
painter.drawPixmap(QRectF(this->getRect()), *pixmap, QRectF());
}
}
//
// TEXT
//

View file

@ -72,10 +72,22 @@ protected:
int getMouseOverIndex(const QPoint &abs) const override;
int getXFromIndex(int index) override;
private:
ImagePtr image_;
};
class ImageWithBackgroundLayoutElement : public ImageLayoutElement
{
public:
ImageWithBackgroundLayoutElement(MessageElement &creator, ImagePtr image,
const QSize &size, QColor color);
protected:
void paint(QPainter &painter) override;
private:
QColor color_;
};
// TEXT
class TextLayoutElement : public MessageLayoutElement
{

View file

@ -15,30 +15,6 @@
namespace chatterino {
namespace {
Outcome addModBadgeBackground(ImagePtr image, NetworkResult result)
{
auto data = result.getData();
QBuffer buffer(const_cast<QByteArray *>(&data));
buffer.open(QIODevice::ReadOnly);
QImageReader reader(&buffer);
if (reader.imageCount() == 0)
return Failure;
QPixmap badgeOverlay = QPixmap::fromImageReader(&reader);
QPixmap badgePixmap(badgeOverlay.width(), badgeOverlay.height());
// the default mod badge green color
badgePixmap.fill(QColor("#34AE0A"));
QPainter painter(&badgePixmap);
QRectF rect(0, 0, badgeOverlay.width(), badgeOverlay.height());
painter.drawPixmap(rect, badgeOverlay, rect);
image->setPixmap(badgePixmap);
return Success;
}
Url getEmoteLink(const QJsonObject &urls, const QString &emoteScale)
{
auto emote = urls.value(emoteScale);
@ -123,16 +99,11 @@ namespace {
auto modBadge3x = getEmoteLink(modUrls, "4");
auto modBadgeImageSet = ImageSet{
Image::fromUrl(modBadge1x, 1)
->setCustomOnSuccess(addModBadgeBackground),
modBadge2x.string.isEmpty()
? Image::getEmpty()
: Image::fromUrl(modBadge2x, 0.5)
->setCustomOnSuccess(addModBadgeBackground),
modBadge3x.string.isEmpty()
? Image::getEmpty()
: Image::fromUrl(modBadge3x, 0.25)
->setCustomOnSuccess(addModBadgeBackground),
Image::fromUrl(modBadge1x, 1),
modBadge2x.string.isEmpty() ? Image::getEmpty()
: Image::fromUrl(modBadge2x, 0.5),
modBadge3x.string.isEmpty() ? Image::getEmpty()
: Image::fromUrl(modBadge3x, 0.25),
};
modBadge = std::make_shared<Emote>(Emote{

View file

@ -1171,7 +1171,7 @@ void TwitchMessageBuilder::appendTwitchBadges()
{
if (auto customModBadge = this->twitchChannel->ffzCustomModBadge())
{
this->emplace<BadgeElement>(
this->emplace<ModBadgeElement>(
customModBadge.get(),
MessageElementFlag::BadgeChannelAuthority)
->setTooltip((*customModBadge)->tooltip.string);