feat: stack /clear messages (#5806)

This commit is contained in:
nerix
2025-01-12 12:54:14 +01:00
committed by GitHub
parent 7b33560fd9
commit 7dbb27e22e
17 changed files with 640 additions and 111 deletions
+77
View File
@@ -118,4 +118,81 @@ void addOrReplaceChannelTimeout(const Buf &buffer, MessagePtr message,
}
}
/// Adds a clear message or replaces a previous one sent in the last 20 messages and in the last 5s.
/// This function accepts any buffer to store the messsages in.
/// @param replaceMessage A function of type `void (int index, MessagePtr toReplace, MessagePtr replacement)`
/// - replace `buffer[i]` (=toReplace) with `replacement`
/// @param addMessage A function of type `void (MessagePtr message)`
/// - adds the `message`.
template <typename Buffer, typename Replace, typename Add>
void addOrReplaceChannelClear(const Buffer &buffer, MessagePtr message,
QTime now, Replace replaceMessage, Add addMessage)
{
// NOTE: This function uses the messages PARSE time to figure out whether they should be replaced
// This works as expected for incoming messages, but not for historic messages.
// This has never worked before, but would be nice in the future.
// For this to work, we need to make sure *all* messages have a "server received time".
auto snapshotLength = static_cast<qsizetype>(buffer.size());
auto end = std::max<qsizetype>(0, snapshotLength - 20);
bool shouldAddMessage = true;
QTime minimumTime = now.addSecs(-5);
auto timeoutStackStyle = static_cast<TimeoutStackStyle>(
getSettings()->timeoutStackStyle.getValue());
if (timeoutStackStyle == TimeoutStackStyle::DontStack)
{
addMessage(message);
return;
}
for (auto i = snapshotLength - 1; i >= end; --i)
{
const MessagePtr &s = buffer[i];
if (s->parseTime < minimumTime)
{
break;
}
bool isClearChat = s->flags.has(MessageFlag::ClearChat);
if (timeoutStackStyle ==
TimeoutStackStyle::DontStackBeyondUserMessage &&
!isClearChat)
{
break;
}
if (!isClearChat || message->flags.has(MessageFlag::PubSub) !=
s->flags.has(MessageFlag::PubSub))
{
continue;
}
if (timeoutStackStyle ==
TimeoutStackStyle::DontStackBeyondUserMessage &&
s->flags.has(MessageFlag::PubSub) &&
s->timeoutUser != message->timeoutUser)
{
break;
}
uint32_t count = s->count + 1;
auto replacement = MessageBuilder::makeClearChatMessage(
message->parseTime, message->timeoutUser, count);
replacement->flags = message->flags;
replaceMessage(i, s, replacement);
shouldAddMessage = false;
break;
}
if (shouldAddMessage)
{
addMessage(message);
}
}
} // namespace chatterino
+14
View File
@@ -38,6 +38,20 @@ void VectorMessageSink::addOrReplaceTimeout(MessagePtr clearchatMessage,
false);
}
void VectorMessageSink::addOrReplaceClearChat(MessagePtr clearchatMessage,
QTime now)
{
addOrReplaceChannelClear(
this->messages_, std::move(clearchatMessage), now,
[&](auto idx, auto /*msg*/, auto &&replacement) {
replacement->flags.set(this->additionalFlags);
this->messages_[idx] = replacement;
},
[&](auto &&msg) {
this->messages_.emplace_back(msg);
});
}
void VectorMessageSink::disableAllMessages()
{
if (this->additionalFlags.has(MessageFlag::RecentMessage))
+1
View File
@@ -15,6 +15,7 @@ public:
MessagePtr message, MessageContext ctx,
std::optional<MessageFlags> overridingFlags = std::nullopt) override;
void addOrReplaceTimeout(MessagePtr clearchatMessage, QTime now) override;
void addOrReplaceClearChat(MessagePtr clearchatMessage, QTime now) override;
void disableAllMessages() override;