Add custom image functionality for inline mod buttons. (#5369)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
Mm2PL
2024-05-11 12:54:27 +02:00
committed by GitHub
parent 321d881bfe
commit c3b84cb4b6
15 changed files with 396 additions and 89 deletions
@@ -6,28 +6,11 @@
#include "singletons/Resources.hpp"
#include <QRegularExpression>
#include <QUrl>
namespace chatterino {
// ModerationAction::ModerationAction(Image *_image, const QString &_action)
// : _isImage(true)
// , image(_image)
// , action(_action)
//{
//}
// ModerationAction::ModerationAction(const QString &_line1, const QString
// &_line2,
// const QString &_action)
// : _isImage(false)
// , image(nullptr)
// , line1(_line1)
// , line2(_line2)
// , action(_action)
//{
//}
ModerationAction::ModerationAction(const QString &action)
ModerationAction::ModerationAction(const QString &action, const QUrl &iconPath)
: action_(action)
{
static QRegularExpression replaceRegex("[!/.]");
@@ -37,6 +20,8 @@ ModerationAction::ModerationAction(const QString &action)
if (timeoutMatch.hasMatch())
{
this->type_ = Type::Timeout;
// if (multipleTimeouts > 1) {
// QString line1;
// QString line2;
@@ -99,24 +84,19 @@ ModerationAction::ModerationAction(const QString &action)
}
this->line2_ = "w";
}
// line1 = this->line1_;
// line2 = this->line2_;
// } else {
// this->_moderationActions.emplace_back(getResources().buttonTimeout,
// str);
// }
}
else if (action.startsWith("/ban "))
{
this->imageToLoad_ = 1;
this->type_ = Type::Ban;
}
else if (action.startsWith("/delete "))
{
this->imageToLoad_ = 2;
this->type_ = Type::Delete;
}
else
{
this->type_ = Type::Custom;
QString xD = action;
xD.replace(replaceRegex, "");
@@ -124,6 +104,11 @@ ModerationAction::ModerationAction(const QString &action)
this->line1_ = xD.mid(0, 2);
this->line2_ = xD.mid(2, 2);
}
if (iconPath.isValid())
{
this->iconPath_ = iconPath;
}
}
bool ModerationAction::operator==(const ModerationAction &other) const
@@ -139,19 +124,23 @@ bool ModerationAction::isImage() const
const std::optional<ImagePtr> &ModerationAction::getImage() const
{
assertInGuiThread();
if (this->imageToLoad_ != 0)
if (this->image_.has_value())
{
if (this->imageToLoad_ == 1)
{
this->image_ =
Image::fromResourcePixmap(getResources().buttons.ban);
}
else if (this->imageToLoad_ == 2)
{
this->image_ =
Image::fromResourcePixmap(getResources().buttons.trashCan);
}
return this->image_;
}
if (this->iconPath_.isValid())
{
this->image_ = Image::fromUrl({this->iconPath_.toString()});
}
else if (this->type_ == Type::Ban)
{
this->image_ = Image::fromResourcePixmap(getResources().buttons.ban);
}
else if (this->type_ == Type::Delete)
{
this->image_ =
Image::fromResourcePixmap(getResources().buttons.trashCan);
}
return this->image_;
@@ -172,4 +161,14 @@ const QString &ModerationAction::getAction() const
return this->action_;
}
const QUrl &ModerationAction::iconPath() const
{
return this->iconPath_;
}
ModerationAction::Type ModerationAction::getType() const
{
return this->type_;
}
} // namespace chatterino
@@ -4,6 +4,7 @@
#include <pajlada/serialize.hpp>
#include <QString>
#include <QUrl>
#include <memory>
#include <optional>
@@ -16,7 +17,32 @@ using ImagePtr = std::shared_ptr<Image>;
class ModerationAction
{
public:
ModerationAction(const QString &action);
/**
* Type of the action, parsed from the input `action`
*/
enum class Type {
/**
* /ban <user>
*/
Ban,
/**
* /delete <msg-id>
*/
Delete,
/**
* /timeout <user> <duration>
*/
Timeout,
/**
* Anything not matching the action types above
*/
Custom,
};
ModerationAction(const QString &action, const QUrl &iconPath = {});
bool operator==(const ModerationAction &other) const;
@@ -25,13 +51,18 @@ public:
const QString &getLine1() const;
const QString &getLine2() const;
const QString &getAction() const;
const QUrl &iconPath() const;
Type getType() const;
private:
mutable std::optional<ImagePtr> image_;
QString line1_;
QString line2_;
QString action_;
int imageToLoad_{};
Type type_{};
QUrl iconPath_;
};
} // namespace chatterino
@@ -46,6 +77,7 @@ struct Serialize<chatterino::ModerationAction> {
rapidjson::Value ret(rapidjson::kObjectType);
chatterino::rj::set(ret, "pattern", value.getAction(), a);
chatterino::rj::set(ret, "icon", value.iconPath().toString(), a);
return ret;
}
@@ -63,10 +95,12 @@ struct Deserialize<chatterino::ModerationAction> {
}
QString pattern;
chatterino::rj::getSafe(value, "pattern", pattern);
return chatterino::ModerationAction(pattern);
QString icon;
chatterino::rj::getSafe(value, "icon", icon);
return chatterino::ModerationAction(pattern, QUrl(icon));
}
};
@@ -1,13 +1,19 @@
#include "controllers/moderationactions/ModerationActionModel.hpp"
#include "controllers/moderationactions/ModerationAction.hpp"
#include "messages/Image.hpp"
#include "util/LoadPixmap.hpp"
#include "util/PostToThread.hpp"
#include "util/StandardItemHelper.hpp"
#include <QIcon>
#include <QPixmap>
namespace chatterino {
// commandmodel
ModerationActionModel ::ModerationActionModel(QObject *parent)
: SignalVectorModel<ModerationAction>(1, parent)
: SignalVectorModel<ModerationAction>(2, parent)
{
}
@@ -15,14 +21,31 @@ ModerationActionModel ::ModerationActionModel(QObject *parent)
ModerationAction ModerationActionModel::getItemFromRow(
std::vector<QStandardItem *> &row, const ModerationAction &original)
{
return ModerationAction(row[0]->data(Qt::DisplayRole).toString());
return ModerationAction(
row[Column::Command]->data(Qt::DisplayRole).toString(),
row[Column::Icon]->data(Qt::UserRole).toString());
}
// turns a row in the model into a vector item
void ModerationActionModel::getRowFromItem(const ModerationAction &item,
std::vector<QStandardItem *> &row)
{
setStringItem(row[0], item.getAction());
setStringItem(row[Column::Command], item.getAction());
setFilePathItem(row[Column::Icon], item.iconPath());
if (!item.iconPath().isEmpty())
{
auto oImage = item.getImage();
assert(oImage.has_value());
if (oImage.has_value())
{
auto url = oImage->get()->url();
loadPixmapFromUrl(url, [row](const QPixmap &pixmap) {
postToThread([row, pixmap]() {
row[Column::Icon]->setData(pixmap, Qt::DecorationRole);
});
});
}
}
}
} // namespace chatterino
@@ -13,6 +13,11 @@ class ModerationActionModel : public SignalVectorModel<ModerationAction>
public:
explicit ModerationActionModel(QObject *parent);
enum Column {
Command = 0,
Icon = 1,
};
protected:
// turn a vector item into a model row
ModerationAction getItemFromRow(std::vector<QStandardItem *> &row,