bundling timeouts from same user

This commit is contained in:
fourtf 2018-01-05 23:14:55 +01:00
parent 47a813d5d6
commit 315cfd8605
10 changed files with 124 additions and 14 deletions

View file

@ -188,7 +188,6 @@ HEADERS += \
src/const.hpp \ src/const.hpp \
src/widgets/tooltipwidget.hpp \ src/widgets/tooltipwidget.hpp \
src/precompiled_headers.hpp \ src/precompiled_headers.hpp \
src/messages/wordflags.hpp \
src/singletons/thememanager.hpp \ src/singletons/thememanager.hpp \
src/twitch/twitchaccountmanager.hpp \ src/twitch/twitchaccountmanager.hpp \
src/singletons/helper/completionmodel.hpp \ src/singletons/helper/completionmodel.hpp \

View file

@ -56,15 +56,24 @@ void Channel::addMessage(std::shared_ptr<Message> message)
this->messageAppended(message); this->messageAppended(message);
} }
void Channel::addMessagesAtStart(std::vector<messages::SharedMessage> &messages) void Channel::addMessagesAtStart(std::vector<messages::SharedMessage> &_messages)
{ {
std::vector<messages::SharedMessage> addedMessages = this->messages.pushFront(messages); std::vector<messages::SharedMessage> addedMessages = this->messages.pushFront(_messages);
if (addedMessages.size() != 0) { if (addedMessages.size() != 0) {
this->messagesAddedAtStart(addedMessages); this->messagesAddedAtStart(addedMessages);
} }
} }
void Channel::replaceMessage(messages::SharedMessage message, messages::SharedMessage replacement)
{
int index = this->messages.replaceItem(message, replacement);
if (index >= 0) {
this->messageReplaced((size_t)index, replacement);
}
}
void Channel::addRecentChatter(const std::shared_ptr<messages::Message> &message) void Channel::addRecentChatter(const std::shared_ptr<messages::Message> &message)
{ {
assert(!message->loginName.isEmpty()); assert(!message->loginName.isEmpty());

View file

@ -27,12 +27,14 @@ public:
boost::signals2::signal<void(messages::SharedMessage &)> messageRemovedFromStart; boost::signals2::signal<void(messages::SharedMessage &)> messageRemovedFromStart;
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended; boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
boost::signals2::signal<void(std::vector<messages::SharedMessage> &)> messagesAddedAtStart; boost::signals2::signal<void(std::vector<messages::SharedMessage> &)> messagesAddedAtStart;
boost::signals2::signal<void(size_t index, messages::SharedMessage &)> messageReplaced;
virtual bool isEmpty() const; virtual bool isEmpty() const;
messages::LimitedQueueSnapshot<messages::SharedMessage> getMessageSnapshot(); messages::LimitedQueueSnapshot<messages::SharedMessage> getMessageSnapshot();
void addMessage(messages::SharedMessage message); void addMessage(messages::SharedMessage message);
void addMessagesAtStart(std::vector<messages::SharedMessage> &messages); void addMessagesAtStart(std::vector<messages::SharedMessage> &messages);
void replaceMessage(messages::SharedMessage message, messages::SharedMessage replacement);
void addRecentChatter(const std::shared_ptr<messages::Message> &message); void addRecentChatter(const std::shared_ptr<messages::Message> &message);
struct NameOptions { struct NameOptions {

View file

@ -132,6 +132,40 @@ public:
return acceptedItems; return acceptedItems;
} }
// replaces a single item, return true if successful
int replaceItem(const T &item, const T &replacement)
{
std::lock_guard<std::mutex> lock(this->mutex);
int x = 0;
for (size_t i = 0; i < this->chunks->size(); i++) {
Chunk &chunk = this->chunks->at(i);
size_t start = i == 0 ? this->firstChunkOffset : 0;
size_t end = i == chunk->size() - 1 ? this->lastChunkEnd : chunk->size();
for (size_t j = start; j < end; j++) {
if (chunk->at(j) == item) {
Chunk newChunk = std::make_shared<std::vector<T>>();
newChunk->resize(chunk->size());
for (size_t k = 0; k < chunk->size(); k++) {
newChunk->at(k) = chunk->at(k);
}
newChunk->at(j) = replacement;
this->chunks->at(i) = newChunk;
return x;
}
x++;
}
}
return -1;
}
// void insertAfter(const std::vector<T> &items, const T &index) // void insertAfter(const std::vector<T> &items, const T &index)
messages::LimitedQueueSnapshot<T> getSnapshot() messages::LimitedQueueSnapshot<T> getSnapshot()

View file

@ -55,6 +55,26 @@ std::vector<Word> &Message::getWords()
return this->words; return this->words;
} }
Message::MessageFlags Message::getFlags() const
{
return this->flags;
}
void Message::setFlags(MessageFlags _flags)
{
this->flags = flags;
}
void Message::addFlags(MessageFlags _flags)
{
this->flags = (MessageFlags)((MessageFlagsType)this->flags | (MessageFlagsType)_flags);
}
void Message::removeFlags(MessageFlags _flags)
{
this->flags = (MessageFlags)((MessageFlagsType)this->flags & ~((MessageFlagsType)_flags));
}
bool Message::isDisabled() const bool Message::isDisabled() const
{ {
return this->disabled; return this->disabled;
@ -147,12 +167,13 @@ Message *Message::createSystemMessage(const QString &text)
MessageColor(MessageColor::Type::System), MessageColor(MessageColor::Type::System),
singletons::FontManager::Medium, word, QString())); singletons::FontManager::Medium, word, QString()));
} }
message->addFlags(Message::System);
return message; return message;
} }
Message *Message::createTimeoutMessage(const QString &username, const QString &durationInSeconds, Message *Message::createTimeoutMessage(const QString &username, const QString &durationInSeconds,
const QString &reason) const QString &reason, bool multipleTimes)
{ {
QString text; QString text;
@ -181,7 +202,14 @@ Message *Message::createTimeoutMessage(const QString &username, const QString &d
} }
text.append("."); text.append(".");
return Message::createSystemMessage(text); if (multipleTimes) {
text.append(" (multiple times)");
}
Message *message = Message::createSystemMessage(text);
message->addFlags(Message::Timeout);
message->timeoutUser = username;
return message;
} }
} // namespace messages } // namespace messages

View file

@ -14,10 +14,17 @@ namespace messages {
class Message; class Message;
typedef std::shared_ptr<Message> SharedMessage; typedef std::shared_ptr<Message> SharedMessage;
typedef uint32_t MessageFlagsType;
class Message class Message
{ {
public: public:
enum MessageFlags : uint32_t {
None = 0,
System = (1 << 1),
Timeout = (1 << 2),
};
bool containsHighlightedPhrase() const; bool containsHighlightedPhrase() const;
void setHighlight(bool value); void setHighlight(bool value);
const QString &getTimeoutUser() const; const QString &getTimeoutUser() const;
@ -25,6 +32,10 @@ public:
const QString &getContent() const; const QString &getContent() const;
const std::chrono::time_point<std::chrono::system_clock> &getParseTime() const; const std::chrono::time_point<std::chrono::system_clock> &getParseTime() const;
std::vector<Word> &getWords(); std::vector<Word> &getWords();
MessageFlags getFlags() const;
void setFlags(MessageFlags flags);
void addFlags(MessageFlags flags);
void removeFlags(MessageFlags flags);
bool isDisabled() const; bool isDisabled() const;
void setDisabled(bool value); void setDisabled(bool value);
const QString &getId() const; const QString &getId() const;
@ -45,7 +56,7 @@ public:
static Message *createSystemMessage(const QString &text); static Message *createSystemMessage(const QString &text);
static Message *createTimeoutMessage(const QString &username, const QString &durationInSeconds, static Message *createTimeoutMessage(const QString &username, const QString &durationInSeconds,
const QString &reason); const QString &reason, bool multipleTimes);
private: private:
static LazyLoadedImage *badgeStaff; static LazyLoadedImage *badgeStaff;
@ -58,6 +69,8 @@ private:
static QRegularExpression *cheerRegex; static QRegularExpression *cheerRegex;
MessageFlags flags = MessageFlags::None;
// what is highlightTab? // what is highlightTab?
bool highlightTab = false; bool highlightTab = false;

View file

@ -1 +0,0 @@
#pragma once

View file

@ -71,8 +71,7 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
// check if the chat has been cleared by a moderator // check if the chat has been cleared by a moderator
if (message->parameters().length() == 1) { if (message->parameters().length() == 1) {
std::shared_ptr<Message> msg( SharedMessage msg(Message::createSystemMessage("Chat has been cleared by a moderator."));
Message::createSystemMessage("Chat has been cleared by a moderator."));
c->addMessage(msg); c->addMessage(msg);
@ -95,20 +94,35 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
} }
// add the notice that the user has been timed out // add the notice that the user has been timed out
SharedMessage msg(Message::createTimeoutMessage(username, durationInSeconds, reason)); LimitedQueueSnapshot<SharedMessage> snapshot = c->getMessageSnapshot();
bool addMessage = true;
for (int i = std::max(0, (int)snapshot.getLength() - 20); i < snapshot.getLength(); i++) {
if (snapshot[i]->getFlags() & Message::Timeout && snapshot[i]->timeoutUser == username) {
SharedMessage replacement(
Message::createTimeoutMessage(username, durationInSeconds, reason, true));
c->replaceMessage(snapshot[i], replacement);
addMessage = false;
break;
}
}
if (addMessage) {
SharedMessage msg(
Message::createTimeoutMessage(username, durationInSeconds, reason, false));
c->addMessage(msg); c->addMessage(msg);
}
// disable the messages from the user // disable the messages from the user
LimitedQueueSnapshot<SharedMessage> snapshot = c->getMessageSnapshot();
for (int i = 0; i < snapshot.getLength(); i++) { for (int i = 0; i < snapshot.getLength(); i++) {
if (snapshot[i]->getTimeoutUser() == username) { if (!(snapshot[i]->getFlags() & Message::Timeout) &&
snapshot[i]->getTimeoutUser() == username) {
snapshot[i]->setDisabled(true); snapshot[i]->setDisabled(true);
} }
} }
// refresh all // refresh all
WindowManager::getInstance().layoutVisibleChatWidgets(c.get()); WindowManager::getInstance().repaintVisibleChatWidgets(c.get());
} }
void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message) void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message)

View file

@ -104,6 +104,8 @@ ChannelView::~ChannelView()
this->messageRemovedConnection.disconnect(); this->messageRemovedConnection.disconnect();
this->repaintGifsConnection.disconnect(); this->repaintGifsConnection.disconnect();
this->layoutConnection.disconnect(); this->layoutConnection.disconnect();
this->messageAddedAtStartConnection.disconnect();
this->messageReplacedConnection.disconnect();
} }
void ChannelView::queueUpdate() void ChannelView::queueUpdate()
@ -429,6 +431,15 @@ void ChannelView::setChannel(std::shared_ptr<Channel> newChannel)
this->layoutMessages(); this->layoutMessages();
}); });
// on message replaced
this->messageReplacedConnection =
newChannel->messageReplaced.connect([this](size_t index, SharedMessage replacement) {
SharedMessageRef newItem(new MessageRef(replacement));
this->messages.replaceItem(this->messages.getSnapshot()[index], newItem);
this->layoutMessages();
});
auto snapshot = newChannel->getMessageSnapshot(); auto snapshot = newChannel->getMessageSnapshot();
for (size_t i = 0; i < snapshot.getLength(); i++) { for (size_t i = 0; i < snapshot.getLength(); i++) {

View file

@ -117,6 +117,7 @@ private:
boost::signals2::connection messageAppendedConnection; boost::signals2::connection messageAppendedConnection;
boost::signals2::connection messageAddedAtStartConnection; boost::signals2::connection messageAddedAtStartConnection;
boost::signals2::connection messageRemovedConnection; boost::signals2::connection messageRemovedConnection;
boost::signals2::connection messageReplacedConnection;
boost::signals2::connection repaintGifsConnection; boost::signals2::connection repaintGifsConnection;
boost::signals2::connection layoutConnection; boost::signals2::connection layoutConnection;