Files
chatterino2/src/messages/MessageElement.hpp
Daniel Pasch 8532c6d3bc Add thumbnails to link tooltips if available (#1664)
This feature is off by default and can be enabled in the settings with the "Show link thumbnail" setting. This feature also requires the "Show link info when hovering" setting to be enabled.

thumbnails support is only there for direct image links, twitch clips, and youtube links. can be expanded in the future in the /api repo

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
2020-05-10 12:11:10 +02:00

295 lines
7.6 KiB
C++

#pragma once
#include "common/FlagsEnum.hpp"
#include "messages/Link.hpp"
#include "messages/MessageColor.hpp"
#include "singletons/Fonts.hpp"
#include <QRect>
#include <QString>
#include <QTime>
#include <boost/noncopyable.hpp>
#include <cstdint>
#include <memory>
#include <pajlada/signals/signalholder.hpp>
#include <vector>
namespace chatterino {
class Channel;
struct MessageLayoutContainer;
class MessageLayoutElement;
class Image;
using ImagePtr = std::shared_ptr<Image>;
struct Emote;
using EmotePtr = std::shared_ptr<const Emote>;
enum class MessageElementFlag {
None = 0,
Misc = (1 << 0),
Text = (1 << 1),
Username = (1 << 2),
Timestamp = (1 << 3),
TwitchEmoteImage = (1 << 4),
TwitchEmoteText = (1 << 5),
TwitchEmote = TwitchEmoteImage | TwitchEmoteText,
BttvEmoteImage = (1 << 6),
BttvEmoteText = (1 << 7),
BttvEmote = BttvEmoteImage | BttvEmoteText,
FfzEmoteImage = (1 << 10),
FfzEmoteText = (1 << 11),
FfzEmote = FfzEmoteImage | FfzEmoteText,
EmoteImages = TwitchEmoteImage | BttvEmoteImage | FfzEmoteImage,
EmoteText = TwitchEmoteText | BttvEmoteText | FfzEmoteText,
BitsStatic = (1 << 12),
BitsAnimated = (1 << 13),
// Slot 1: Twitch
// - Staff badge
// - Admin badge
// - Global Moderator badge
BadgeGlobalAuthority = (1 << 14),
// Slot 2: Twitch
// - Moderator badge
// - Broadcaster badge
BadgeChannelAuthority = (1 << 15),
// Slot 3: Twitch
// - Subscription badges
BadgeSubscription = (1 << 16),
// Slot 4: Twitch
// - Turbo badge
// - Prime badge
// - Bit badges
// - Game badges
BadgeVanity = (1 << 17),
// Slot 5: Chatterino
// - Chatterino developer badge
// - Chatterino donator badge
// - Chatterino top donator badge
BadgeChatterino = (1 << 18),
Badges = BadgeGlobalAuthority | BadgeChannelAuthority | BadgeSubscription |
BadgeVanity | BadgeChatterino,
ChannelName = (1 << 19),
BitsAmount = (1 << 20),
ModeratorTools = (1 << 21),
EmojiImage = (1 << 23),
EmojiText = (1 << 24),
EmojiAll = EmojiImage | EmojiText,
AlwaysShow = (1 << 25),
// used in the ChannelView class to make the collapse buttons visible if
// needed
Collapsed = (1 << 26),
// used for dynamic bold usernames
BoldUsername = (1 << 27),
NonBoldUsername = (1 << 28),
// for links
LowercaseLink = (1 << 29),
OriginalLink = (1 << 30),
// ZeroWidthEmotes are emotes that are supposed to overlay over any pre-existing emotes
// e.g. BTTV's SoSnowy during christmas season
ZeroWidthEmote = (1 << 31),
Default = Timestamp | Badges | Username | BitsStatic | FfzEmoteImage |
BttvEmoteImage | TwitchEmoteImage | BitsAmount | Text |
AlwaysShow,
};
using MessageElementFlags = FlagsEnum<MessageElementFlag>;
class MessageElement : boost::noncopyable
{
public:
enum UpdateFlags : char {
Update_Text = 1,
Update_Emotes = 2,
Update_Images = 4,
Update_All = Update_Text | Update_Emotes | Update_Images
};
enum ThumbnailType : char {
Link_Thumbnail = 1,
};
virtual ~MessageElement();
MessageElement *setLink(const Link &link);
MessageElement *setText(const QString &text);
MessageElement *setTooltip(const QString &tooltip);
MessageElement *setThumbnailType(const ThumbnailType type);
MessageElement *setThumbnail(const ImagePtr &thumbnail);
MessageElement *setTrailingSpace(bool value);
const QString &getTooltip() const;
const ImagePtr &getThumbnail() const;
const ThumbnailType &getThumbnailType() const;
const Link &getLink() const;
bool hasTrailingSpace() const;
MessageElementFlags getFlags() const;
MessageElement *updateLink();
virtual void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags) = 0;
pajlada::Signals::NoArgSignal linkChanged;
protected:
MessageElement(MessageElementFlags flags);
bool trailingSpace = true;
private:
QString text_;
Link link_;
QString tooltip_;
ImagePtr thumbnail_;
ThumbnailType thumbnailType_;
MessageElementFlags flags_;
};
// used when layout element doesn't have a creator
class EmptyElement : public MessageElement
{
public:
EmptyElement();
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags) override;
static EmptyElement &instance();
private:
ImagePtr image_;
};
// contains a simple image
class ImageElement : public MessageElement
{
public:
ImageElement(ImagePtr image, MessageElementFlags flags);
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags) override;
private:
ImagePtr image_;
};
// contains a text, it will split it into words
class TextElement : public MessageElement
{
public:
TextElement(const QString &text, MessageElementFlags flags,
const MessageColor &color = MessageColor::Text,
FontStyle style = FontStyle::ChatMedium);
~TextElement() override = default;
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags) override;
private:
MessageColor color_;
FontStyle style_;
struct Word {
QString text;
int width = -1;
};
std::vector<Word> words_;
};
// contains emote data and will pick the emote based on :
// a) are images for the emote type enabled
// b) which size it wants
class EmoteElement : public MessageElement
{
public:
EmoteElement(const EmotePtr &data, MessageElementFlags flags_);
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags_) override;
EmotePtr getEmote() const;
protected:
virtual MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size);
private:
std::unique_ptr<TextElement> textElement_;
EmotePtr emote_;
};
class BadgeElement : public MessageElement
{
public:
BadgeElement(const EmotePtr &data, MessageElementFlags flags_);
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags_) override;
EmotePtr getEmote() const;
protected:
virtual MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size);
private:
EmotePtr emote_;
};
class ModBadgeElement : public BadgeElement
{
public:
ModBadgeElement(const EmotePtr &data, MessageElementFlags flags_);
protected:
MessageLayoutElement *makeImageLayoutElement(const ImagePtr &image,
const QSize &size) override;
};
// contains a text, formated depending on the preferences
class TimestampElement : public MessageElement
{
public:
TimestampElement(QTime time_ = QTime::currentTime());
~TimestampElement() override = default;
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags) override;
TextElement *formatTime(const QTime &time);
private:
QTime time_;
std::unique_ptr<TextElement> element_;
QString format_;
};
// adds all the custom moderation buttons, adds a variable amount of items
// depending on settings fourtf: implement
class TwitchModerationElement : public MessageElement
{
public:
TwitchModerationElement();
void addToContainer(MessageLayoutContainer &container,
MessageElementFlags flags) override;
};
} // namespace chatterino