refactored MessageBuilder

This commit is contained in:
fourtf
2018-08-07 01:35:24 +02:00
parent f71ff08e68
commit c26422aec1
29 changed files with 964 additions and 970 deletions
+1
View File
@@ -6,6 +6,7 @@
#include "debug/Log.hpp"
#include "singletons/Emotes.hpp"
#include "singletons/WindowManager.hpp"
#include "util/DebugCount.hpp"
#include "util/PostToThread.hpp"
#include <QBuffer>
+6 -191
View File
@@ -1,20 +1,22 @@
#include "messages/Message.hpp"
#include "MessageElement.hpp"
#include "providers/twitch/PubsubActions.hpp"
#include "util/DebugCount.hpp"
#include "util/IrcHelpers.hpp"
using SBHighlight = chatterino::ScrollbarHighlight;
namespace chatterino {
void Message::addElement(MessageElement *element)
Message::Message()
: parseTime(QTime::currentTime())
{
this->elements_.push_back(std::unique_ptr<MessageElement>(element));
DebugCount::increase("messages");
}
const std::vector<std::unique_ptr<MessageElement>> &Message::getElements() const
Message::~Message()
{
return this->elements_;
DebugCount::decrease("messages");
}
SBHighlight Message::getScrollBarHighlight() const
@@ -28,195 +30,8 @@ SBHighlight Message::getScrollBarHighlight() const
}
// Static
MessagePtr Message::createSystemMessage(const QString &text)
{
MessagePtr message(new Message);
message->addElement(new TimestampElement(QTime::currentTime()));
message->addElement(
new TextElement(text, MessageElement::Text, MessageColor::System));
message->flags |= MessageFlags::System;
message->flags |= MessageFlags::DoNotTriggerNotification;
message->searchText = text;
return message;
}
MessagePtr Message::createMessage(const QString &text)
{
MessagePtr message(new Message);
message->addElement(new TimestampElement(QTime::currentTime()));
message->addElement(
new TextElement(text, MessageElement::Text, MessageColor::Text));
message->searchText = text;
return message;
}
namespace {
void appendDuration(int count, QChar &&order, QString &outString)
{
outString.append(QString::number(count));
outString.append(order);
}
QString makeDuration(int timeoutSeconds)
{
QString res;
int seconds = timeoutSeconds % 60;
int timeoutMinutes = timeoutSeconds / 60;
int minutes = timeoutMinutes % 60;
int timeoutHours = timeoutMinutes / 60;
int hours = timeoutHours % 24;
int days = timeoutHours / 24;
if (days > 0) {
appendDuration(days, 'd', res);
}
if (hours > 0) {
if (!res.isEmpty()) {
res.append(" ");
}
appendDuration(hours, 'h', res);
}
if (minutes > 0) {
if (!res.isEmpty()) {
res.append(" ");
}
appendDuration(minutes, 'm', res);
}
if (seconds > 0) {
if (!res.isEmpty()) {
res.append(" ");
}
appendDuration(seconds, 's', res);
}
return res;
}
} // namespace
MessagePtr Message::createTimeoutMessage(const QString &username,
const QString &durationInSeconds,
const QString &reason,
bool multipleTimes)
{
QString text;
text.append(username);
if (!durationInSeconds.isEmpty()) {
text.append(" has been timed out");
// TODO: Implement who timed the user out
text.append(" for ");
bool ok = true;
int timeoutSeconds = durationInSeconds.toInt(&ok);
if (ok) {
text.append(makeDuration(timeoutSeconds));
}
} else {
text.append(" has been permanently banned");
}
if (reason.length() > 0) {
text.append(": \"");
text.append(parseTagString(reason));
text.append("\"");
}
text.append(".");
if (multipleTimes) {
text.append(" (multiple times)");
}
MessagePtr message = Message::createSystemMessage(text);
message->flags.EnableFlag(MessageFlags::System);
message->flags.EnableFlag(MessageFlags::Timeout);
message->timeoutUser = username;
return message;
}
MessagePtr Message::createTimeoutMessage(const BanAction &action,
uint32_t count)
{
MessagePtr msg(new Message);
msg->addElement(new TimestampElement(QTime::currentTime()));
msg->flags.EnableFlag(MessageFlags::System);
msg->flags.EnableFlag(MessageFlags::Timeout);
msg->timeoutUser = action.target.name;
msg->count = count;
QString text;
if (action.isBan()) {
if (action.reason.isEmpty()) {
text = QString("%1 banned %2.") //
.arg(action.source.name)
.arg(action.target.name);
} else {
text = QString("%1 banned %2: \"%3\".") //
.arg(action.source.name)
.arg(action.target.name)
.arg(action.reason);
}
} else {
if (action.reason.isEmpty()) {
text = QString("%1 timed out %2 for %3.") //
.arg(action.source.name)
.arg(action.target.name)
.arg(makeDuration(action.duration));
} else {
text = QString("%1 timed out %2 for %3: \"%4\".") //
.arg(action.source.name)
.arg(action.target.name)
.arg(makeDuration(action.duration))
.arg(action.reason);
}
if (count > 1) {
text.append(QString(" (%1 times)").arg(count));
}
}
msg->addElement(
new TextElement(text, MessageElement::Text, MessageColor::System));
msg->searchText = text;
return msg;
}
MessagePtr Message::createUntimeoutMessage(const UnbanAction &action)
{
MessagePtr msg(new Message);
msg->addElement(new TimestampElement(QTime::currentTime()));
msg->flags.EnableFlag(MessageFlags::System);
msg->flags.EnableFlag(MessageFlags::Untimeout);
msg->timeoutUser = action.target.name;
QString text;
if (action.wasBan()) {
text = QString("%1 unbanned %2.") //
.arg(action.source.name)
.arg(action.target.name);
} else {
text = QString("%1 untimedout %2.") //
.arg(action.source.name)
.arg(action.target.name);
}
msg->addElement(
new TextElement(text, MessageElement::Text, MessageColor::System));
msg->searchText = text;
return msg;
}
} // namespace chatterino
+6 -38
View File
@@ -6,27 +6,13 @@
#include "widgets/helper/ScrollbarHighlight.hpp"
#include <QTime>
#include <cinttypes>
#include <memory>
#include <vector>
#include "util/DebugCount.hpp"
namespace chatterino {
struct Message {
Message()
: parseTime(QTime::currentTime())
{
DebugCount::increase("messages");
}
~Message()
{
DebugCount::decrease("messages");
}
struct Message : boost::noncopyable {
enum MessageFlags : uint16_t {
None = 0,
System = (1 << 0),
@@ -43,6 +29,9 @@ struct Message {
Subscription = (1 << 11),
};
Message();
~Message();
FlagsEnum<MessageFlags> flags;
QTime parseTime;
QString id;
@@ -51,33 +40,12 @@ struct Message {
QString displayName;
QString localizedName;
QString timeoutUser;
uint32_t count = 1;
std::vector<std::unique_ptr<MessageElement>> elements;
// Messages should not be added after the message is done initializing.
void addElement(MessageElement *element);
const std::vector<std::unique_ptr<MessageElement>> &getElements() const;
// Scrollbar
ScrollbarHighlight getScrollBarHighlight() const;
private:
std::vector<std::unique_ptr<MessageElement>> elements_;
public:
static std::shared_ptr<Message> createSystemMessage(const QString &text);
static std::shared_ptr<Message> createMessage(const QString &text);
static std::shared_ptr<Message> createTimeoutMessage(
const QString &username, const QString &durationInSeconds,
const QString &reason, bool multipleTimes);
static std::shared_ptr<Message> createTimeoutMessage(
const BanAction &action, uint32_t count = 1);
static std::shared_ptr<Message> createUntimeoutMessage(
const UnbanAction &action);
};
using MessagePtr = std::shared_ptr<Message>;
using MessagePtr = std::shared_ptr<const Message>;
} // namespace chatterino
+143 -15
View File
@@ -4,43 +4,171 @@
#include "singletons/Emotes.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Theme.hpp"
#include "util/FormatTime.hpp"
#include "util/IrcHelpers.hpp"
#include <QDateTime>
namespace chatterino {
MessagePtr makeSystemMessage(const QString &text)
{
return MessageBuilder(systemMessage, text).release();
}
MessageBuilder::MessageBuilder()
: message_(new Message)
: message_(std::make_unique<Message>())
{
}
MessagePtr MessageBuilder::getMessage()
MessageBuilder::MessageBuilder(const QString &text)
: MessageBuilder()
{
return this->message_;
this->emplace<TimestampElement>();
this->emplace<TextElement>(text, MessageElement::Text,
MessageColor::System);
this->message().searchText = text;
}
void MessageBuilder::append(MessageElement *element)
MessageBuilder::MessageBuilder(SystemMessageTag, const QString &text)
: MessageBuilder()
{
this->message_->addElement(element);
this->emplace<TimestampElement>();
this->emplace<TextElement>(text, MessageElement::Text,
MessageColor::System);
this->message().flags |= Message::System;
this->message().flags |= Message::DoNotTriggerNotification;
this->message().searchText = text;
}
void MessageBuilder::appendTimestamp()
MessageBuilder::MessageBuilder(TimeoutMessageTag, const QString &username,
const QString &durationInSeconds,
const QString &reason, bool multipleTimes)
: MessageBuilder()
{
this->appendTimestamp(QTime::currentTime());
}
QString text;
void MessageBuilder::setHighlight(bool value)
{
if (value) {
this->message_->flags |= Message::Highlighted;
text.append(username);
if (!durationInSeconds.isEmpty()) {
text.append(" has been timed out");
// TODO: Implement who timed the user out
text.append(" for ");
bool ok = true;
int timeoutSeconds = durationInSeconds.toInt(&ok);
if (ok) {
text.append(formatTime(timeoutSeconds));
}
} else {
this->message_->flags &= ~Message::Highlighted;
text.append(" has been permanently banned");
}
if (reason.length() > 0) {
text.append(": \"");
text.append(parseTagString(reason));
text.append("\"");
}
text.append(".");
if (multipleTimes) {
text.append(" (multiple times)");
}
this->message().flags.EnableFlag(Message::System);
this->message().flags.EnableFlag(Message::Timeout);
this->message().flags.EnableFlag(Message::DoNotTriggerNotification);
this->message().timeoutUser = username;
}
void MessageBuilder::appendTimestamp(const QTime &time)
MessageBuilder::MessageBuilder(const BanAction &action, uint32_t count)
{
this->append(new TimestampElement(time));
this->emplace<TimestampElement>();
this->message().flags.EnableFlag(Message::System);
this->message().flags.EnableFlag(Message::Timeout);
this->message().timeoutUser = action.target.name;
this->message().count = count;
QString text;
if (action.isBan()) {
if (action.reason.isEmpty()) {
text = QString("%1 banned %2.") //
.arg(action.source.name)
.arg(action.target.name);
} else {
text = QString("%1 banned %2: \"%3\".") //
.arg(action.source.name)
.arg(action.target.name)
.arg(action.reason);
}
} else {
if (action.reason.isEmpty()) {
text = QString("%1 timed out %2 for %3.") //
.arg(action.source.name)
.arg(action.target.name)
.arg(formatTime(action.duration));
} else {
text = QString("%1 timed out %2 for %3: \"%4\".") //
.arg(action.source.name)
.arg(action.target.name)
.arg(formatTime(action.duration))
.arg(action.reason);
}
if (count > 1) {
text.append(QString(" (%1 times)").arg(count));
}
}
this->emplace<TextElement>(text, MessageElement::Text,
MessageColor::System);
this->message().searchText = text;
}
MessageBuilder::MessageBuilder(const UnbanAction &action)
{
this->emplace<TimestampElement>();
this->message().flags.EnableFlag(Message::System);
this->message().flags.EnableFlag(Message::Untimeout);
this->message().timeoutUser = action.target.name;
QString text;
if (action.wasBan()) {
text = QString("%1 unbanned %2.") //
.arg(action.source.name)
.arg(action.target.name);
} else {
text = QString("%1 untimedout %2.") //
.arg(action.source.name)
.arg(action.target.name);
}
this->emplace<TextElement>(text, MessageElement::Text,
MessageColor::System);
this->message().searchText = text;
}
Message *MessageBuilder::operator->()
{
return this->message_.get();
}
Message &MessageBuilder::message()
{
return *this->message_;
}
MessagePtr MessageBuilder::release()
{
return MessagePtr(this->message_.release());
}
void MessageBuilder::append(std::unique_ptr<MessageElement> element)
{
this->message().elements.push_back(std::move(element));
}
QString MessageBuilder::matchLink(const QString &string)
+28 -12
View File
@@ -3,21 +3,36 @@
#include "messages/Message.hpp"
#include <QRegularExpression>
#include <ctime>
namespace chatterino {
struct MessageBuilder {
struct SystemMessageTag {
};
struct TimeoutMessageTag {
};
const SystemMessageTag systemMessage{};
const TimeoutMessageTag timeoutMessage{};
MessagePtr makeSystemMessage(const QString &text);
class MessageBuilder
{
public:
MessageBuilder();
MessageBuilder(const QString &text);
MessageBuilder(SystemMessageTag, const QString &text);
MessageBuilder(TimeoutMessageTag, const QString &username,
const QString &durationInSeconds, const QString &reason,
bool multipleTimes);
MessageBuilder(const BanAction &action, uint32_t count = 1);
MessageBuilder(const UnbanAction &action);
MessagePtr getMessage();
Message *operator->();
Message &message();
MessagePtr release();
void setHighlight(bool value);
void append(MessageElement *element);
void appendTimestamp();
void appendTimestamp(const QTime &time);
void append(std::unique_ptr<MessageElement> element);
QString matchLink(const QString &string);
template <typename T, typename... Args>
@@ -26,13 +41,14 @@ public:
static_assert(std::is_base_of<MessageElement, T>::value,
"T must extend MessageElement");
T *element = new T(std::forward<Args>(args)...);
this->append(element);
return element;
auto unique = std::make_unique<T>(std::forward<Args>(args)...);
auto pointer = unique.get();
this->append(std::move(unique));
return pointer;
}
protected:
MessagePtr message_;
private:
std::unique_ptr<Message> message_;
};
} // namespace chatterino
+1
View File
@@ -7,6 +7,7 @@
#include "messages/layouts/MessageLayoutContainer.hpp"
#include "messages/layouts/MessageLayoutElement.hpp"
#include "singletons/Settings.hpp"
#include "util/DebugCount.hpp"
namespace chatterino {
+3 -3
View File
@@ -5,6 +5,7 @@
#include "singletons/Emotes.hpp"
#include "singletons/Settings.hpp"
#include "singletons/WindowManager.hpp"
#include "util/DebugCount.hpp"
#include <QApplication>
#include <QDebug>
@@ -32,7 +33,7 @@ MessageLayout::~MessageLayout()
DebugCount::decrease("message layout");
}
Message *MessageLayout::getMessage()
const Message *MessageLayout::getMessage()
{
return this->message_.get();
}
@@ -104,8 +105,7 @@ void MessageLayout::actuallyLayout(int width, MessageElement::Flags _flags)
this->container_.begin(width, this->scale_, messageFlags);
for (const std::unique_ptr<MessageElement> &element :
this->message_->getElements()) {
for (const auto &element : this->message_->elements) {
element->addToContainer(this->container_, _flags);
}
+1 -1
View File
@@ -28,7 +28,7 @@ public:
MessageLayout(MessagePtr message_);
~MessageLayout();
Message *getMessage();
const Message *getMessage();
// Height
int getHeight() const;