mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
refactor: Remove Leading Mention in Replies and Highlight Participated Threads (#4047)
This commit is contained in:
parent
29272e130a
commit
4e2da540d2
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Unversioned
|
||||
|
||||
- Major: Added support for Twitch's Chat Replies. [Wiki Page](https://wiki.chatterino.com/Features/#message-replies) (#3722, #3989, #4041)
|
||||
- Major: Added support for Twitch's Chat Replies. [Wiki Page](https://wiki.chatterino.com/Features/#message-replies) (#3722, #3989, #4041, #4047)
|
||||
- Major: Added multi-channel searching to search dialog via keyboard shortcut. (Ctrl+Shift+F by default) (#3694, #3875)
|
||||
- Minor: Added highlights for `Elevated Messages`. (#4016)
|
||||
- Minor: Removed total views from the usercard, as Twitch no longer updates the number. (#3792)
|
||||
|
|
|
@ -11,10 +11,12 @@ auto highlightPhraseCheck(const HighlightPhrase &highlight) -> HighlightCheck
|
|||
return HighlightCheck{
|
||||
[highlight](const auto &args, const auto &badges,
|
||||
const auto &senderName, const auto &originalMessage,
|
||||
const auto &flags,
|
||||
const auto self) -> boost::optional<HighlightResult> {
|
||||
(void)args; // unused
|
||||
(void)badges; // unused
|
||||
(void)senderName; // unused
|
||||
(void)flags; // unused
|
||||
|
||||
if (self)
|
||||
{
|
||||
|
@ -60,11 +62,12 @@ void rebuildSubscriptionHighlights(Settings &settings,
|
|||
|
||||
checks.emplace_back(HighlightCheck{
|
||||
[=](const auto &args, const auto &badges, const auto &senderName,
|
||||
const auto &originalMessage,
|
||||
const auto &originalMessage, const auto &flags,
|
||||
const auto self) -> boost::optional<HighlightResult> {
|
||||
(void)badges; // unused
|
||||
(void)senderName; // unused
|
||||
(void)originalMessage; // unused
|
||||
(void)flags; // unused
|
||||
(void)self; // unused
|
||||
|
||||
if (!args.isSubscriptionMessage)
|
||||
|
@ -105,11 +108,12 @@ void rebuildWhisperHighlights(Settings &settings,
|
|||
|
||||
checks.emplace_back(HighlightCheck{
|
||||
[=](const auto &args, const auto &badges, const auto &senderName,
|
||||
const auto &originalMessage,
|
||||
const auto &originalMessage, const auto &flags,
|
||||
const auto self) -> boost::optional<HighlightResult> {
|
||||
(void)badges; // unused
|
||||
(void)senderName; // unused
|
||||
(void)originalMessage; // unused
|
||||
(void)flags; // unused
|
||||
(void)self; // unused
|
||||
|
||||
if (!args.isReceivedWhisper)
|
||||
|
@ -128,6 +132,44 @@ void rebuildWhisperHighlights(Settings &settings,
|
|||
}
|
||||
}
|
||||
|
||||
void rebuildReplyThreadHighlight(Settings &settings,
|
||||
std::vector<HighlightCheck> &checks)
|
||||
{
|
||||
if (settings.enableThreadHighlight)
|
||||
{
|
||||
auto highlightSound = settings.enableThreadHighlightSound.getValue();
|
||||
auto highlightAlert = settings.enableThreadHighlightTaskbar.getValue();
|
||||
auto highlightSoundUrlValue =
|
||||
settings.threadHighlightSoundUrl.getValue();
|
||||
boost::optional<QUrl> highlightSoundUrl;
|
||||
if (!highlightSoundUrlValue.isEmpty())
|
||||
{
|
||||
highlightSoundUrl = highlightSoundUrlValue;
|
||||
}
|
||||
auto highlightInMentions =
|
||||
settings.showThreadHighlightInMentions.getValue();
|
||||
checks.emplace_back(HighlightCheck{
|
||||
[=](const auto & /*args*/, const auto & /*badges*/,
|
||||
const auto & /*senderName*/, const auto & /*originalMessage*/,
|
||||
const auto &flags,
|
||||
const auto self) -> boost::optional<HighlightResult> {
|
||||
if (flags.has(MessageFlag::ParticipatedThread) && !self)
|
||||
{
|
||||
return HighlightResult{
|
||||
highlightAlert,
|
||||
highlightSound,
|
||||
highlightSoundUrl,
|
||||
ColorProvider::instance().color(
|
||||
ColorType::ThreadMessageHighlight),
|
||||
highlightInMentions,
|
||||
};
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
void rebuildMessageHighlights(Settings &settings,
|
||||
std::vector<HighlightCheck> &checks)
|
||||
{
|
||||
|
@ -163,10 +205,12 @@ void rebuildUserHighlights(Settings &settings,
|
|||
checks.emplace_back(HighlightCheck{
|
||||
[highlight](const auto &args, const auto &badges,
|
||||
const auto &senderName, const auto &originalMessage,
|
||||
const auto &flags,
|
||||
const auto self) -> boost::optional<HighlightResult> {
|
||||
(void)args; // unused
|
||||
(void)badges; // unused
|
||||
(void)originalMessage; // unused
|
||||
(void)flags; // unused
|
||||
(void)self; // unused
|
||||
|
||||
if (!highlight.isMatch(senderName))
|
||||
|
@ -201,10 +245,12 @@ void rebuildBadgeHighlights(Settings &settings,
|
|||
checks.emplace_back(HighlightCheck{
|
||||
[highlight](const auto &args, const auto &badges,
|
||||
const auto &senderName, const auto &originalMessage,
|
||||
const auto &flags,
|
||||
const auto self) -> boost::optional<HighlightResult> {
|
||||
(void)args; // unused
|
||||
(void)senderName; // unused
|
||||
(void)originalMessage; // unused
|
||||
(void)flags; // unused
|
||||
(void)self; // unused
|
||||
|
||||
for (const Badge &badge : badges)
|
||||
|
@ -247,6 +293,11 @@ void HighlightController::initialize(Settings &settings, Paths & /*paths*/)
|
|||
this->rebuildListener_.addSetting(settings.enableSubHighlight);
|
||||
this->rebuildListener_.addSetting(settings.enableSubHighlightSound);
|
||||
this->rebuildListener_.addSetting(settings.enableSubHighlightTaskbar);
|
||||
this->rebuildListener_.addSetting(settings.enableThreadHighlight);
|
||||
this->rebuildListener_.addSetting(settings.enableThreadHighlightSound);
|
||||
this->rebuildListener_.addSetting(settings.enableThreadHighlightTaskbar);
|
||||
this->rebuildListener_.addSetting(settings.threadHighlightSoundUrl);
|
||||
this->rebuildListener_.addSetting(settings.showThreadHighlightInMentions);
|
||||
|
||||
this->rebuildListener_.setCB([this, &settings] {
|
||||
qCDebug(chatterinoHighlights)
|
||||
|
@ -294,7 +345,7 @@ void HighlightController::rebuildChecks(Settings &settings)
|
|||
checks->clear();
|
||||
|
||||
// CURRENT ORDER:
|
||||
// Subscription -> Whisper -> User -> Message -> Badge
|
||||
// Subscription -> Whisper -> User -> Message -> Reply Threads -> Badge
|
||||
|
||||
rebuildSubscriptionHighlights(settings, *checks);
|
||||
|
||||
|
@ -304,12 +355,15 @@ void HighlightController::rebuildChecks(Settings &settings)
|
|||
|
||||
rebuildMessageHighlights(settings, *checks);
|
||||
|
||||
rebuildReplyThreadHighlight(settings, *checks);
|
||||
|
||||
rebuildBadgeHighlights(settings, *checks);
|
||||
}
|
||||
|
||||
std::pair<bool, HighlightResult> HighlightController::check(
|
||||
const MessageParseArgs &args, const std::vector<Badge> &badges,
|
||||
const QString &senderName, const QString &originalMessage) const
|
||||
const QString &senderName, const QString &originalMessage,
|
||||
const MessageFlags &messageFlags) const
|
||||
{
|
||||
bool highlighted = false;
|
||||
auto result = HighlightResult::emptyResult();
|
||||
|
@ -322,8 +376,8 @@ std::pair<bool, HighlightResult> HighlightController::check(
|
|||
|
||||
for (const auto &check : *checks)
|
||||
{
|
||||
if (auto checkResult =
|
||||
check.cb(args, badges, senderName, originalMessage, self);
|
||||
if (auto checkResult = check.cb(args, badges, senderName,
|
||||
originalMessage, messageFlags, self);
|
||||
checkResult)
|
||||
{
|
||||
highlighted = true;
|
||||
|
|
|
@ -142,7 +142,8 @@ struct HighlightResult {
|
|||
struct HighlightCheck {
|
||||
using Checker = std::function<boost::optional<HighlightResult>(
|
||||
const MessageParseArgs &args, const std::vector<Badge> &badges,
|
||||
const QString &senderName, const QString &originalMessage, bool self)>;
|
||||
const QString &senderName, const QString &originalMessage,
|
||||
const MessageFlags &messageFlags, bool self)>;
|
||||
Checker cb;
|
||||
};
|
||||
|
||||
|
@ -156,7 +157,8 @@ public:
|
|||
**/
|
||||
[[nodiscard]] std::pair<bool, HighlightResult> check(
|
||||
const MessageParseArgs &args, const std::vector<Badge> &badges,
|
||||
const QString &senderName, const QString &originalMessage) const;
|
||||
const QString &senderName, const QString &originalMessage,
|
||||
const MessageFlags &messageFlags) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -213,6 +213,36 @@ void HighlightModel::afterInit()
|
|||
|
||||
this->insertCustomRow(elevatedMessageRow,
|
||||
HighlightRowIndexes::ElevatedMessageRow);
|
||||
|
||||
// Highlight settings for reply threads
|
||||
std::vector<QStandardItem *> threadMessageRow = this->createRow();
|
||||
setBoolItem(threadMessageRow[Column::Pattern],
|
||||
getSettings()->enableThreadHighlight.getValue(), true, false);
|
||||
threadMessageRow[Column::Pattern]->setData("Participated Reply Threads",
|
||||
Qt::DisplayRole);
|
||||
setBoolItem(threadMessageRow[Column::ShowInMentions],
|
||||
getSettings()->showThreadHighlightInMentions.getValue(), true,
|
||||
false);
|
||||
setBoolItem(threadMessageRow[Column::FlashTaskbar],
|
||||
getSettings()->enableThreadHighlightTaskbar.getValue(), true,
|
||||
false);
|
||||
setBoolItem(threadMessageRow[Column::PlaySound],
|
||||
getSettings()->enableThreadHighlightSound.getValue(), true,
|
||||
false);
|
||||
threadMessageRow[Column::UseRegex]->setFlags({});
|
||||
threadMessageRow[Column::CaseSensitive]->setFlags({});
|
||||
|
||||
QUrl threadMessageSound =
|
||||
QUrl(getSettings()->threadHighlightSoundUrl.getValue());
|
||||
setFilePathItem(threadMessageRow[Column::SoundPath], threadMessageSound,
|
||||
false);
|
||||
|
||||
auto threadMessageColor =
|
||||
ColorProvider::instance().color(ColorType::ThreadMessageHighlight);
|
||||
setColorItem(threadMessageRow[Column::Color], *threadMessageColor, false);
|
||||
|
||||
this->insertCustomRow(threadMessageRow,
|
||||
HighlightRowIndexes::ThreadMessageRow);
|
||||
}
|
||||
|
||||
void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
||||
|
@ -252,6 +282,11 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
|||
getSettings()->enableElevatedMessageHighlight.setValue(
|
||||
value.toBool());
|
||||
}
|
||||
else if (rowIndex == HighlightRowIndexes::ThreadMessageRow)
|
||||
{
|
||||
getSettings()->enableThreadHighlight.setValue(
|
||||
value.toBool());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -263,6 +298,11 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
|||
getSettings()->showSelfHighlightInMentions.setValue(
|
||||
value.toBool());
|
||||
}
|
||||
else if (rowIndex == HighlightRowIndexes::ThreadMessageRow)
|
||||
{
|
||||
getSettings()->showThreadHighlightInMentions.setValue(
|
||||
value.toBool());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -300,6 +340,11 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
|||
// ->enableElevatedMessageHighlightTaskbar.setvalue(
|
||||
// value.toBool());
|
||||
}
|
||||
else if (rowIndex == HighlightRowIndexes::ThreadMessageRow)
|
||||
{
|
||||
getSettings()->enableThreadHighlightTaskbar.setValue(
|
||||
value.toBool());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -336,6 +381,11 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
|||
// getSettings()->enableElevatedMessageHighlightSound.setValue(
|
||||
// value.toBool());
|
||||
}
|
||||
else if (rowIndex == HighlightRowIndexes::ThreadMessageRow)
|
||||
{
|
||||
getSettings()->enableThreadHighlightSound.setValue(
|
||||
value.toBool());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -381,6 +431,11 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
|||
getSettings()->elevatedMessageHighlightSoundUrl.setValue(
|
||||
value.toString());
|
||||
}
|
||||
else if (rowIndex == HighlightRowIndexes::ThreadMessageRow)
|
||||
{
|
||||
getSettings()->threadHighlightSoundUrl.setValue(
|
||||
value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -424,6 +479,13 @@ void HighlightModel::customRowSetData(const std::vector<QStandardItem *> &row,
|
|||
.updateColor(ColorType::ElevatedMessageHighlight,
|
||||
QColor(colorName));
|
||||
}
|
||||
else if (rowIndex == HighlightRowIndexes::ThreadMessageRow)
|
||||
{
|
||||
getSettings()->threadHighlightColor.setValue(colorName);
|
||||
const_cast<ColorProvider &>(ColorProvider::instance())
|
||||
.updateColor(ColorType::ThreadMessageHighlight,
|
||||
QColor(colorName));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
RedeemedRow = 3,
|
||||
FirstMessageRow = 4,
|
||||
ElevatedMessageRow = 5,
|
||||
ThreadMessageRow = 6,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -16,6 +16,8 @@ QColor HighlightPhrase::FALLBACK_FIRST_MESSAGE_HIGHLIGHT_COLOR =
|
|||
QColor(72, 127, 63, 60);
|
||||
QColor HighlightPhrase::FALLBACK_ELEVATED_MESSAGE_HIGHLIGHT_COLOR =
|
||||
QColor(255, 174, 66, 60);
|
||||
QColor HighlightPhrase::FALLBACK_THREAD_HIGHLIGHT_COLOR =
|
||||
QColor(143, 48, 24, 60);
|
||||
QColor HighlightPhrase::FALLBACK_SUB_COLOR = QColor(196, 102, 255, 100);
|
||||
|
||||
bool HighlightPhrase::operator==(const HighlightPhrase &other) const
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
static QColor FALLBACK_SUB_COLOR;
|
||||
static QColor FALLBACK_FIRST_MESSAGE_HIGHLIGHT_COLOR;
|
||||
static QColor FALLBACK_ELEVATED_MESSAGE_HIGHLIGHT_COLOR;
|
||||
static QColor FALLBACK_THREAD_HIGHLIGHT_COLOR;
|
||||
|
||||
private:
|
||||
QString pattern_;
|
||||
|
|
|
@ -43,6 +43,7 @@ enum class MessageFlag : int64_t {
|
|||
FirstMessage = (1LL << 23),
|
||||
ReplyMessage = (1LL << 24),
|
||||
ElevatedMessage = (1LL << 25),
|
||||
ParticipatedThread = (1LL << 26),
|
||||
};
|
||||
using MessageFlags = FlagsEnum<MessageFlag>;
|
||||
|
||||
|
|
|
@ -58,4 +58,14 @@ size_t MessageThread::liveCount(
|
|||
return count;
|
||||
}
|
||||
|
||||
bool MessageThread::participated() const
|
||||
{
|
||||
return this->participated_;
|
||||
}
|
||||
|
||||
void MessageThread::markParticipated()
|
||||
{
|
||||
this->participated_ = true;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -23,6 +23,10 @@ public:
|
|||
/// Returns the number of live reply references
|
||||
size_t liveCount(const std::shared_ptr<const Message> &exclude) const;
|
||||
|
||||
bool participated() const;
|
||||
|
||||
void markParticipated();
|
||||
|
||||
const QString &rootId() const
|
||||
{
|
||||
return rootMessageId_;
|
||||
|
@ -42,6 +46,7 @@ private:
|
|||
const QString rootMessageId_;
|
||||
const std::shared_ptr<const Message> rootMessage_;
|
||||
std::vector<std::weak_ptr<const Message>> replies_;
|
||||
bool participated_ = false;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -149,7 +149,8 @@ void SharedMessageBuilder::parseHighlights()
|
|||
|
||||
auto badges = SharedMessageBuilder::parseBadgeTag(this->tags);
|
||||
auto [highlighted, highlightResult] = getIApp()->getHighlights()->check(
|
||||
this->args, badges, this->ircMessage->nick(), this->originalMessage_);
|
||||
this->args, badges, this->ircMessage->nick(), this->originalMessage_,
|
||||
this->message().flags);
|
||||
|
||||
if (!highlighted)
|
||||
{
|
||||
|
|
|
@ -147,6 +147,20 @@ void ColorProvider::initTypeColorMap()
|
|||
std::make_shared<QColor>(
|
||||
HighlightPhrase::FALLBACK_ELEVATED_MESSAGE_HIGHLIGHT_COLOR)});
|
||||
}
|
||||
|
||||
customColor = getSettings()->threadHighlightColor;
|
||||
if (QColor(customColor).isValid())
|
||||
{
|
||||
this->typeColorMap_.insert({ColorType::ThreadMessageHighlight,
|
||||
std::make_shared<QColor>(customColor)});
|
||||
}
|
||||
else
|
||||
{
|
||||
this->typeColorMap_.insert(
|
||||
{ColorType::ThreadMessageHighlight,
|
||||
std::make_shared<QColor>(
|
||||
HighlightPhrase::FALLBACK_THREAD_HIGHLIGHT_COLOR)});
|
||||
}
|
||||
}
|
||||
|
||||
void ColorProvider::initDefaultColors()
|
||||
|
|
|
@ -14,6 +14,7 @@ enum class ColorType {
|
|||
RedeemedHighlight,
|
||||
FirstMessageHighlight,
|
||||
ElevatedMessageHighlight,
|
||||
ThreadMessageHighlight,
|
||||
};
|
||||
|
||||
class ColorProvider
|
||||
|
|
|
@ -67,6 +67,65 @@ MessagePtr generateBannedMessage(bool confirmedBan)
|
|||
return builder.release();
|
||||
}
|
||||
|
||||
int stripLeadingReplyMention(const QVariantMap &tags, QString &content)
|
||||
{
|
||||
if (!getSettings()->stripReplyMention)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (const auto it = tags.find("reply-parent-display-name");
|
||||
it != tags.end())
|
||||
{
|
||||
auto displayName = it.value().toString();
|
||||
if (content.startsWith('@') &&
|
||||
content.at(1 + displayName.length()) == ' ' &&
|
||||
content.indexOf(displayName, 1) == 1)
|
||||
{
|
||||
int messageOffset = 1 + displayName.length() + 1;
|
||||
content.remove(0, messageOffset);
|
||||
return messageOffset;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateReplyParticipatedStatus(const QVariantMap &tags,
|
||||
const QString &senderLogin,
|
||||
TwitchMessageBuilder &builder,
|
||||
std::shared_ptr<MessageThread> &thread,
|
||||
bool isNew)
|
||||
{
|
||||
const auto ¤tLogin =
|
||||
getApp()->accounts->twitch.getCurrent()->getUserName();
|
||||
if (thread->participated())
|
||||
{
|
||||
builder.message().flags.set(MessageFlag::ParticipatedThread);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
if (const auto it = tags.find("reply-parent-user-login");
|
||||
it != tags.end())
|
||||
{
|
||||
auto name = it.value().toString();
|
||||
if (name == currentLogin)
|
||||
{
|
||||
thread->markParticipated();
|
||||
builder.message().flags.set(MessageFlag::ParticipatedThread);
|
||||
return; // already marked as participated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (senderLogin == currentLogin)
|
||||
{
|
||||
thread->markParticipated();
|
||||
// don't set the highlight here
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
namespace chatterino {
|
||||
|
||||
|
@ -259,9 +318,12 @@ std::vector<MessagePtr> IrcMessageHandler::parseMessageWithReply(
|
|||
return this->parsePrivMessage(channel, privMsg);
|
||||
}
|
||||
|
||||
QString content = privMsg->content();
|
||||
int messageOffset = stripLeadingReplyMention(privMsg->tags(), content);
|
||||
MessageParseArgs args;
|
||||
TwitchMessageBuilder builder(channel, message, args, privMsg->content(),
|
||||
TwitchMessageBuilder builder(channel, message, args, content,
|
||||
privMsg->isAction());
|
||||
builder.setMessageOffset(messageOffset);
|
||||
|
||||
this->populateReply(tc, message, otherLoaded, builder);
|
||||
|
||||
|
@ -295,10 +357,12 @@ void IrcMessageHandler::populateReply(
|
|||
auto threadIt = channel->threads_.find(replyID);
|
||||
if (threadIt != channel->threads_.end())
|
||||
{
|
||||
const auto owned = threadIt->second.lock();
|
||||
auto owned = threadIt->second.lock();
|
||||
if (owned)
|
||||
{
|
||||
// Thread already exists (has a reply)
|
||||
updateReplyParticipatedStatus(tags, message->nick(), builder,
|
||||
owned, false);
|
||||
builder.setThread(owned);
|
||||
return;
|
||||
}
|
||||
|
@ -331,6 +395,8 @@ void IrcMessageHandler::populateReply(
|
|||
{
|
||||
std::shared_ptr<MessageThread> newThread =
|
||||
std::make_shared<MessageThread>(foundMessage);
|
||||
updateReplyParticipatedStatus(tags, message->nick(), builder,
|
||||
newThread, true);
|
||||
|
||||
builder.setThread(newThread);
|
||||
// Store weak reference to thread in channel
|
||||
|
@ -341,7 +407,7 @@ void IrcMessageHandler::populateReply(
|
|||
|
||||
void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
|
||||
const QString &target,
|
||||
const QString &content,
|
||||
const QString &content_,
|
||||
TwitchIrcServer &server, bool isSub,
|
||||
bool isAction)
|
||||
{
|
||||
|
@ -384,7 +450,7 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
|
|||
[=, &server](ChannelPointReward reward) {
|
||||
if (reward.id == rewardId)
|
||||
{
|
||||
this->addMessage(clone, target, content, server, isSub,
|
||||
this->addMessage(clone, target, content_, server, isSub,
|
||||
isAction);
|
||||
clone->deleteLater();
|
||||
return true;
|
||||
|
@ -396,7 +462,11 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
|
|||
args.channelPointRewardId = rewardId;
|
||||
}
|
||||
|
||||
QString content = content_;
|
||||
int messageOffset = stripLeadingReplyMention(tags, content);
|
||||
|
||||
TwitchMessageBuilder builder(chan.get(), _message, args, content, isAction);
|
||||
builder.setMessageOffset(messageOffset);
|
||||
|
||||
if (const auto it = tags.find("reply-parent-msg-id"); it != tags.end())
|
||||
{
|
||||
|
@ -405,7 +475,10 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
|
|||
if (threadIt != channel->threads_.end() && !threadIt->second.expired())
|
||||
{
|
||||
// Thread already exists (has a reply)
|
||||
builder.setThread(threadIt->second.lock());
|
||||
auto thread = threadIt->second.lock();
|
||||
updateReplyParticipatedStatus(tags, _message->nick(), builder,
|
||||
thread, false);
|
||||
builder.setThread(thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -414,7 +487,9 @@ void IrcMessageHandler::addMessage(Communi::IrcMessage *_message,
|
|||
if (root)
|
||||
{
|
||||
// Found root reply message
|
||||
const auto newThread = std::make_shared<MessageThread>(root);
|
||||
auto newThread = std::make_shared<MessageThread>(root);
|
||||
updateReplyParticipatedStatus(tags, _message->nick(), builder,
|
||||
newThread, true);
|
||||
|
||||
builder.setThread(newThread);
|
||||
// Store weak reference to thread in channel
|
||||
|
|
|
@ -999,8 +999,10 @@ void TwitchMessageBuilder::appendTwitchEmote(
|
|||
return;
|
||||
}
|
||||
|
||||
auto start = correctPositions[coords.at(0).toUInt()];
|
||||
auto end = correctPositions[coords.at(1).toUInt()];
|
||||
auto start =
|
||||
correctPositions[coords.at(0).toUInt() - this->messageOffset_];
|
||||
auto end =
|
||||
correctPositions[coords.at(1).toUInt() - this->messageOffset_];
|
||||
|
||||
if (start >= end || start < 0 || end > this->originalMessage_.length())
|
||||
{
|
||||
|
@ -1589,4 +1591,9 @@ void TwitchMessageBuilder::setThread(std::shared_ptr<MessageThread> thread)
|
|||
this->thread_ = std::move(thread);
|
||||
}
|
||||
|
||||
void TwitchMessageBuilder::setMessageOffset(int offset)
|
||||
{
|
||||
this->messageOffset_ = offset;
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -47,6 +47,7 @@ public:
|
|||
MessagePtr build() override;
|
||||
|
||||
void setThread(std::shared_ptr<MessageThread> thread);
|
||||
void setMessageOffset(int offset);
|
||||
|
||||
static void appendChannelPointRewardMessage(
|
||||
const ChannelPointReward &reward, MessageBuilder *builder, bool isMod,
|
||||
|
@ -110,6 +111,18 @@ private:
|
|||
bool historicalMessage_ = false;
|
||||
std::shared_ptr<MessageThread> thread_;
|
||||
|
||||
/**
|
||||
* Starting offset to be used on index-based operations on `originalMessage_`.
|
||||
*
|
||||
* For example:
|
||||
* originalMessage_ = "there"
|
||||
* messageOffset_ = 4
|
||||
* (the irc message is "hey there")
|
||||
*
|
||||
* then the index 6 would resolve to 6 - 4 = 2 => 'e'
|
||||
*/
|
||||
int messageOffset_ = 0;
|
||||
|
||||
QString userId_;
|
||||
bool senderIsBroadcaster{};
|
||||
};
|
||||
|
|
|
@ -118,6 +118,7 @@ public:
|
|||
// BoolSetting collapseLongMessages =
|
||||
// {"/appearance/messages/collapseLongMessages", false};
|
||||
BoolSetting showReplyButton = {"/appearance/showReplyButton", false};
|
||||
BoolSetting stripReplyMention = {"/appearance/stripReplyMention", true};
|
||||
IntSetting collpseMessagesMinLines = {
|
||||
"/appearance/messages/collapseMessagesMinLines", 0};
|
||||
BoolSetting alternateMessages = {
|
||||
|
@ -327,6 +328,19 @@ public:
|
|||
""};
|
||||
QStringSetting subHighlightColor = {"/highlighting/subHighlightColor", ""};
|
||||
|
||||
BoolSetting enableThreadHighlight = {
|
||||
"/highlighting/thread/nameIsHighlightKeyword", true};
|
||||
BoolSetting showThreadHighlightInMentions = {
|
||||
"/highlighting/thread/showSelfHighlightInMentions", true};
|
||||
BoolSetting enableThreadHighlightSound = {
|
||||
"/highlighting/thread/enableSound", true};
|
||||
BoolSetting enableThreadHighlightTaskbar = {
|
||||
"/highlighting/thread/enableTaskbarFlashing", true};
|
||||
QStringSetting threadHighlightSoundUrl = {
|
||||
"/highlighting/threadHighlightSoundUrl", ""};
|
||||
QStringSetting threadHighlightColor = {"/highlighting/threadHighlightColor",
|
||||
""};
|
||||
|
||||
QStringSetting highlightColor = {"/highlighting/color", ""};
|
||||
|
||||
BoolSetting longAlerts = {"/highlighting/alerts", false};
|
||||
|
|
|
@ -719,6 +719,7 @@ void GeneralPage::initLayout(GeneralPageView &layout)
|
|||
layout.addCheckbox("Combine multiple bit tips into one", s.stackBits);
|
||||
layout.addCheckbox("Messages in /mentions highlights tab",
|
||||
s.highlightMentions);
|
||||
layout.addCheckbox("Strip leading mention in replies", s.stripReplyMention);
|
||||
|
||||
// Helix timegate settings
|
||||
auto helixTimegateGetValue = [](auto val) {
|
||||
|
|
|
@ -485,6 +485,7 @@ struct TestCase {
|
|||
std::vector<Badge> badges;
|
||||
QString senderName;
|
||||
QString originalMessage;
|
||||
MessageFlags flags;
|
||||
} input;
|
||||
|
||||
struct {
|
||||
|
@ -727,8 +728,9 @@ TEST_F(HighlightControllerTest, A)
|
|||
|
||||
for (const auto &[input, expected] : tests)
|
||||
{
|
||||
auto [isMatch, matchResult] = this->controller->check(
|
||||
input.args, input.badges, input.senderName, input.originalMessage);
|
||||
auto [isMatch, matchResult] =
|
||||
this->controller->check(input.args, input.badges, input.senderName,
|
||||
input.originalMessage, input.flags);
|
||||
|
||||
EXPECT_EQ(isMatch, expected.state)
|
||||
<< qUtf8Printable(input.senderName) << ": "
|
||||
|
|
Loading…
Reference in a new issue