mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Compare commits
30 commits
2d5b6e4c33
...
c9da994af9
Author | SHA1 | Date | |
---|---|---|---|
c9da994af9 | |||
1bdb118391 | |||
0e4897969b | |||
9e8281b75b | |||
374e0c5fa0 | |||
b46a893127 | |||
55a12fa008 | |||
e5e5a79645 | |||
9b31f61de6 | |||
79ee3dc417 | |||
af3d46fe25 | |||
49caab7e7c | |||
ef2647fe05 | |||
b0e3a41312 | |||
fe51ba85e7 | |||
2884c828b0 | |||
e288742360 | |||
1ca5d38ad5 | |||
39e0e00f2d | |||
8745d0740f | |||
5f862c5e5e | |||
a2af8e791b | |||
13d7692a89 | |||
806fa7790d | |||
edaafac010 | |||
7728f01916 | |||
70f497d3bd | |||
3b64f142e6 | |||
e827097c1c | |||
f7dd6de872 |
|
@ -37,6 +37,7 @@
|
||||||
- Minor: Indicate when subscriptions and resubscriptions are for multiple months. (#5642)
|
- Minor: Indicate when subscriptions and resubscriptions are for multiple months. (#5642)
|
||||||
- Minor: Proxy URL information is now included in the `/debug-env` command. (#5648)
|
- Minor: Proxy URL information is now included in the `/debug-env` command. (#5648)
|
||||||
- Minor: Make raid entry message usernames clickable. (#5651)
|
- Minor: Make raid entry message usernames clickable. (#5651)
|
||||||
|
- Minor: Tabs unhighlight when their content is read in other tabs. (#5649)
|
||||||
- Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426, #5612)
|
- Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426, #5612)
|
||||||
- Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378)
|
- Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378)
|
||||||
- Bugfix: Fixed restricted users usernames not being clickable. (#5405)
|
- Bugfix: Fixed restricted users usernames not being clickable. (#5405)
|
||||||
|
@ -104,7 +105,7 @@
|
||||||
- Dev: Added more tests for input completion. (#5604)
|
- Dev: Added more tests for input completion. (#5604)
|
||||||
- Dev: Refactored legacy Unicode zero-width-joiner replacement. (#5594)
|
- Dev: Refactored legacy Unicode zero-width-joiner replacement. (#5594)
|
||||||
- Dev: The JSON output when copying a message (<kbd>SHIFT</kbd> + right-click) is now more extensive. (#5600)
|
- Dev: The JSON output when copying a message (<kbd>SHIFT</kbd> + right-click) is now more extensive. (#5600)
|
||||||
- Dev: Added more tests for message building. (#5598, #5654, #5656)
|
- Dev: Added more tests for message building. (#5598, #5654, #5656, #5671)
|
||||||
- Dev: Twitch messages are now sent using Twitch's Helix API instead of IRC by default. (#5607)
|
- Dev: Twitch messages are now sent using Twitch's Helix API instead of IRC by default. (#5607)
|
||||||
- Dev: `GIFTimer` is no longer initialized in tests. (#5608)
|
- Dev: `GIFTimer` is no longer initialized in tests. (#5608)
|
||||||
- Dev: Emojis now use flags instead of a set of strings for capabilities. (#5616)
|
- Dev: Emojis now use flags instead of a set of strings for capabilities. (#5616)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 88ee08eb3c3f3627ca54b90dafd1d63a6d4da96b
|
Subproject commit 5b5caad7cd57d5ba3ca796bf1521b131d73ca405
|
|
@ -1 +1 @@
|
||||||
Subproject commit c58874c1aa5d0619df2c975bcb87433941b46920
|
Subproject commit 4a0a1e599377cdcdc91b0fbbefc312936b48730c
|
|
@ -204,7 +204,7 @@ void Notebook::duplicatePage(QWidget *page)
|
||||||
{
|
{
|
||||||
newTabPosition = tabPosition + 1;
|
newTabPosition = tabPosition + 1;
|
||||||
}
|
}
|
||||||
auto newTabHighlightState = item->tab->highlightState();
|
|
||||||
QString newTabTitle = "";
|
QString newTabTitle = "";
|
||||||
if (item->tab->hasCustomTitle())
|
if (item->tab->hasCustomTitle())
|
||||||
{
|
{
|
||||||
|
@ -213,7 +213,7 @@ void Notebook::duplicatePage(QWidget *page)
|
||||||
|
|
||||||
auto *tab =
|
auto *tab =
|
||||||
this->addPageAt(newContainer, newTabPosition, newTabTitle, false);
|
this->addPageAt(newContainer, newTabPosition, newTabTitle, false);
|
||||||
tab->setHighlightState(newTabHighlightState);
|
tab->copyHighlightStateAndSourcesFrom(item->tab);
|
||||||
|
|
||||||
newContainer->setTab(tab);
|
newContainer->setTab(tab);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1063,6 +1063,8 @@ void ChannelView::setChannel(const ChannelPtr &underlyingChannel)
|
||||||
|
|
||||||
this->underlyingChannel_ = underlyingChannel;
|
this->underlyingChannel_ = underlyingChannel;
|
||||||
|
|
||||||
|
this->updateID();
|
||||||
|
|
||||||
this->performLayout();
|
this->performLayout();
|
||||||
this->queueUpdate();
|
this->queueUpdate();
|
||||||
|
|
||||||
|
@ -1081,6 +1083,8 @@ void ChannelView::setChannel(const ChannelPtr &underlyingChannel)
|
||||||
void ChannelView::setFilters(const QList<QUuid> &ids)
|
void ChannelView::setFilters(const QList<QUuid> &ids)
|
||||||
{
|
{
|
||||||
this->channelFilters_ = std::make_shared<FilterSet>(ids);
|
this->channelFilters_ = std::make_shared<FilterSet>(ids);
|
||||||
|
|
||||||
|
this->updateID();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QUuid> ChannelView::getFilterIds() const
|
QList<QUuid> ChannelView::getFilterIds() const
|
||||||
|
@ -1190,11 +1194,13 @@ void ChannelView::messageAppended(MessagePtr &message,
|
||||||
(this->channel_->getType() == Channel::Type::TwitchAutomod &&
|
(this->channel_->getType() == Channel::Type::TwitchAutomod &&
|
||||||
getSettings()->enableAutomodHighlight))
|
getSettings()->enableAutomodHighlight))
|
||||||
{
|
{
|
||||||
this->tabHighlightRequested.invoke(HighlightState::Highlighted);
|
this->tabHighlightRequested.invoke(HighlightState::Highlighted,
|
||||||
|
message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->tabHighlightRequested.invoke(HighlightState::NewMessage);
|
this->tabHighlightRequested.invoke(HighlightState::NewMessage,
|
||||||
|
message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3240,4 +3246,27 @@ void ChannelView::pendingLinkInfoStateChanged()
|
||||||
this->tooltipWidget_->applyLastBoundsCheck();
|
this->tooltipWidget_->applyLastBoundsCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelView::updateID()
|
||||||
|
{
|
||||||
|
if (!this->underlyingChannel_)
|
||||||
|
{
|
||||||
|
// cannot update
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t seed = 0;
|
||||||
|
auto first = qHash(this->underlyingChannel_->getName());
|
||||||
|
auto second = qHash(this->getFilterIds());
|
||||||
|
|
||||||
|
boost::hash_combine(seed, first);
|
||||||
|
boost::hash_combine(seed, second);
|
||||||
|
|
||||||
|
this->id_ = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChannelView::ChannelViewID ChannelView::getID() const
|
||||||
|
{
|
||||||
|
return this->id_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -179,6 +179,9 @@ public:
|
||||||
|
|
||||||
LimitedQueueSnapshot<MessageLayoutPtr> &getMessagesSnapshot();
|
LimitedQueueSnapshot<MessageLayoutPtr> &getMessagesSnapshot();
|
||||||
|
|
||||||
|
// Returns true if message should be included
|
||||||
|
bool shouldIncludeMessage(const MessagePtr &m) const;
|
||||||
|
|
||||||
void queueLayout();
|
void queueLayout();
|
||||||
void invalidateBuffers();
|
void invalidateBuffers();
|
||||||
|
|
||||||
|
@ -212,9 +215,13 @@ public:
|
||||||
|
|
||||||
Scrollbar *scrollbar();
|
Scrollbar *scrollbar();
|
||||||
|
|
||||||
|
using ChannelViewID = std::size_t;
|
||||||
|
ChannelViewID getID() const;
|
||||||
|
|
||||||
pajlada::Signals::Signal<QMouseEvent *> mouseDown;
|
pajlada::Signals::Signal<QMouseEvent *> mouseDown;
|
||||||
pajlada::Signals::NoArgSignal selectionChanged;
|
pajlada::Signals::NoArgSignal selectionChanged;
|
||||||
pajlada::Signals::Signal<HighlightState> tabHighlightRequested;
|
pajlada::Signals::Signal<HighlightState, const MessagePtr &>
|
||||||
|
tabHighlightRequested;
|
||||||
pajlada::Signals::NoArgSignal liveStatusChanged;
|
pajlada::Signals::NoArgSignal liveStatusChanged;
|
||||||
pajlada::Signals::Signal<const Link &> linkClicked;
|
pajlada::Signals::Signal<const Link &> linkClicked;
|
||||||
pajlada::Signals::Signal<QString, FromTwitchLinkOpenChannelIn>
|
pajlada::Signals::Signal<QString, FromTwitchLinkOpenChannelIn>
|
||||||
|
@ -314,6 +321,9 @@ private:
|
||||||
void showReplyThreadPopup(const MessagePtr &message);
|
void showReplyThreadPopup(const MessagePtr &message);
|
||||||
bool canReplyToMessages() const;
|
bool canReplyToMessages() const;
|
||||||
|
|
||||||
|
void updateID();
|
||||||
|
ChannelViewID id_{};
|
||||||
|
|
||||||
bool layoutQueued_ = false;
|
bool layoutQueued_ = false;
|
||||||
bool bufferInvalidationQueued_ = false;
|
bool bufferInvalidationQueued_ = false;
|
||||||
|
|
||||||
|
@ -374,9 +384,6 @@ private:
|
||||||
|
|
||||||
FilterSetPtr channelFilters_;
|
FilterSetPtr channelFilters_;
|
||||||
|
|
||||||
// Returns true if message should be included
|
|
||||||
bool shouldIncludeMessage(const MessagePtr &m) const;
|
|
||||||
|
|
||||||
// Returns whether the scrollbar should have highlights
|
// Returns whether the scrollbar should have highlights
|
||||||
bool showScrollbarHighlights() const;
|
bool showScrollbarHighlights() const;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "widgets/helper/NotebookTab.hpp"
|
#include "widgets/helper/NotebookTab.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
|
#include "common/Channel.hpp"
|
||||||
#include "common/Common.hpp"
|
#include "common/Common.hpp"
|
||||||
#include "controllers/hotkeys/HotkeyCategory.hpp"
|
#include "controllers/hotkeys/HotkeyCategory.hpp"
|
||||||
#include "controllers/hotkeys/HotkeyController.hpp"
|
#include "controllers/hotkeys/HotkeyController.hpp"
|
||||||
|
@ -12,9 +13,11 @@
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
#include "widgets/splits/DraggedSplit.hpp"
|
#include "widgets/splits/DraggedSplit.hpp"
|
||||||
|
#include "widgets/splits/Split.hpp"
|
||||||
#include "widgets/splits/SplitContainer.hpp"
|
#include "widgets/splits/SplitContainer.hpp"
|
||||||
|
|
||||||
#include <boost/bind/bind.hpp>
|
#include <boost/bind/bind.hpp>
|
||||||
|
#include <boost/container_hash/hash.hpp>
|
||||||
#include <QAbstractAnimation>
|
#include <QAbstractAnimation>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -302,10 +305,144 @@ bool NotebookTab::isSelected() const
|
||||||
return this->selected_;
|
return this->selected_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NotebookTab::removeNewMessageSource(
|
||||||
|
const ChannelView::ChannelViewID &source)
|
||||||
|
{
|
||||||
|
this->highlightSources_.newMessageSource.erase(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotebookTab::removeHighlightedSource(
|
||||||
|
const ChannelView::ChannelViewID &source)
|
||||||
|
{
|
||||||
|
this->highlightSources_.highlightedSource.erase(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotebookTab::removeHighlightStateChangeSources(
|
||||||
|
const HighlightSources &toRemove)
|
||||||
|
{
|
||||||
|
for (const auto &source : toRemove.newMessageSource)
|
||||||
|
{
|
||||||
|
this->removeNewMessageSource(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &source : toRemove.highlightedSource)
|
||||||
|
{
|
||||||
|
this->removeHighlightedSource(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotebookTab::newHighlightSourceAdded(const ChannelView &channelViewSource)
|
||||||
|
{
|
||||||
|
auto channelViewId = channelViewSource.getID();
|
||||||
|
this->removeHighlightedSource(channelViewId);
|
||||||
|
this->removeNewMessageSource(channelViewId);
|
||||||
|
this->updateHighlightStateDueSourcesChange();
|
||||||
|
|
||||||
|
auto *splitNotebook = dynamic_cast<SplitNotebook *>(this->notebook_);
|
||||||
|
if (splitNotebook)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < splitNotebook->getPageCount(); ++i)
|
||||||
|
{
|
||||||
|
auto *splitContainer =
|
||||||
|
dynamic_cast<SplitContainer *>(splitNotebook->getPageAt(i));
|
||||||
|
if (splitContainer)
|
||||||
|
{
|
||||||
|
auto *tab = splitContainer->getTab();
|
||||||
|
if (tab && tab != this)
|
||||||
|
{
|
||||||
|
tab->removeHighlightedSource(channelViewId);
|
||||||
|
tab->removeNewMessageSource(channelViewId);
|
||||||
|
tab->updateHighlightStateDueSourcesChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotebookTab::updateHighlightStateDueSourcesChange()
|
||||||
|
{
|
||||||
|
if (!this->highlightSources_.highlightedSource.empty())
|
||||||
|
{
|
||||||
|
assert(this->highlightState_ == HighlightState::Highlighted);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->highlightSources_.newMessageSource.empty())
|
||||||
|
{
|
||||||
|
if (this->highlightState_ != HighlightState::NewMessage)
|
||||||
|
{
|
||||||
|
this->highlightState_ = HighlightState::NewMessage;
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this->highlightState_ != HighlightState::None)
|
||||||
|
{
|
||||||
|
this->highlightState_ = HighlightState::None;
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(this->highlightState_ != HighlightState::Highlighted);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotebookTab::copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab)
|
||||||
|
{
|
||||||
|
if (this->isSelected())
|
||||||
|
{
|
||||||
|
assert(this->highlightSources_.highlightedSource.empty());
|
||||||
|
assert(this->highlightSources_.newMessageSource.empty());
|
||||||
|
assert(this->highlightState_ == HighlightState::None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->highlightSources_ = sourceTab->highlightSources_;
|
||||||
|
|
||||||
|
if (!this->highlightEnabled_ &&
|
||||||
|
sourceTab->highlightState_ == HighlightState::NewMessage)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->highlightState_ == sourceTab->highlightState_ ||
|
||||||
|
this->highlightState_ == HighlightState::Highlighted)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->highlightState_ = sourceTab->highlightState_;
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
void NotebookTab::setSelected(bool value)
|
void NotebookTab::setSelected(bool value)
|
||||||
{
|
{
|
||||||
this->selected_ = value;
|
this->selected_ = value;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
auto *splitNotebook = dynamic_cast<SplitNotebook *>(this->notebook_);
|
||||||
|
if (splitNotebook)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < splitNotebook->getPageCount(); ++i)
|
||||||
|
{
|
||||||
|
auto *splitContainer =
|
||||||
|
dynamic_cast<SplitContainer *>(splitNotebook->getPageAt(i));
|
||||||
|
if (splitContainer)
|
||||||
|
{
|
||||||
|
auto *tab = splitContainer->getTab();
|
||||||
|
if (tab && tab != this)
|
||||||
|
{
|
||||||
|
tab->removeHighlightStateChangeSources(
|
||||||
|
this->highlightSources_);
|
||||||
|
tab->updateHighlightStateDueSourcesChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->highlightSources_.clear();
|
||||||
this->highlightState_ = HighlightState::None;
|
this->highlightState_ = HighlightState::None;
|
||||||
|
|
||||||
this->update();
|
this->update();
|
||||||
|
@ -358,13 +495,23 @@ bool NotebookTab::isLive() const
|
||||||
return this->isLive_;
|
return this->isLive_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HighlightState NotebookTab::highlightState() const
|
||||||
|
{
|
||||||
|
return this->highlightState_;
|
||||||
|
}
|
||||||
|
|
||||||
void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
|
void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
|
||||||
{
|
{
|
||||||
if (this->isSelected())
|
if (this->isSelected())
|
||||||
{
|
{
|
||||||
|
assert(this->highlightSources_.highlightedSource.empty());
|
||||||
|
assert(this->highlightSources_.newMessageSource.empty());
|
||||||
|
assert(this->highlightState_ == HighlightState::None);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->highlightSources_.clear();
|
||||||
|
|
||||||
if (!this->highlightEnabled_ &&
|
if (!this->highlightEnabled_ &&
|
||||||
newHighlightStyle == HighlightState::NewMessage)
|
newHighlightStyle == HighlightState::NewMessage)
|
||||||
{
|
{
|
||||||
|
@ -381,9 +528,87 @@ void NotebookTab::setHighlightState(HighlightState newHighlightStyle)
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
HighlightState NotebookTab::highlightState() const
|
void NotebookTab::updateHighlightState(HighlightState newHighlightStyle,
|
||||||
|
const ChannelView &channelViewSource,
|
||||||
|
const MessagePtr &message)
|
||||||
{
|
{
|
||||||
return this->highlightState_;
|
if (this->isSelected())
|
||||||
|
{
|
||||||
|
assert(this->highlightSources_.highlightedSource.empty());
|
||||||
|
assert(this->highlightSources_.newMessageSource.empty());
|
||||||
|
assert(this->highlightState_ == HighlightState::None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->shouldMessageHighlight(channelViewSource, message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->highlightEnabled_ &&
|
||||||
|
newHighlightStyle == HighlightState::NewMessage)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// message is highlighting unvisible tab
|
||||||
|
|
||||||
|
auto channelViewId = channelViewSource.getID();
|
||||||
|
|
||||||
|
switch (newHighlightStyle)
|
||||||
|
{
|
||||||
|
case HighlightState::Highlighted: {
|
||||||
|
if (!this->highlightSources_.highlightedSource.contains(
|
||||||
|
channelViewId))
|
||||||
|
{
|
||||||
|
this->highlightSources_.highlightedSource.insert(channelViewId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HighlightState::NewMessage: {
|
||||||
|
if (!this->highlightSources_.newMessageSource.contains(
|
||||||
|
channelViewId))
|
||||||
|
{
|
||||||
|
this->highlightSources_.newMessageSource.insert(channelViewId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HighlightState::None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->highlightState_ == newHighlightStyle ||
|
||||||
|
this->highlightState_ == HighlightState::Highlighted)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->highlightState_ = newHighlightStyle;
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NotebookTab::shouldMessageHighlight(const ChannelView &channelViewSource,
|
||||||
|
const MessagePtr &message) const
|
||||||
|
{
|
||||||
|
auto *visibleSplitContainer =
|
||||||
|
dynamic_cast<SplitContainer *>(this->notebook_->getSelectedPage());
|
||||||
|
if (visibleSplitContainer != nullptr)
|
||||||
|
{
|
||||||
|
const auto &visibleSplits = visibleSplitContainer->getSplits();
|
||||||
|
for (const auto &visibleSplit : visibleSplits)
|
||||||
|
{
|
||||||
|
if (channelViewSource.underlyingChannel() ==
|
||||||
|
visibleSplit->getChannel() &&
|
||||||
|
visibleSplit->getChannelView().shouldIncludeMessage(message) &&
|
||||||
|
channelViewSource.shouldIncludeMessage(message) &&
|
||||||
|
channelViewSource.getFilterIds().empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotebookTab::setHighlightsEnabled(const bool &newVal)
|
void NotebookTab::setHighlightsEnabled(const bool &newVal)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "common/Common.hpp"
|
#include "common/Common.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/helper/Button.hpp"
|
||||||
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
|
|
||||||
#include <pajlada/settings/setting.hpp>
|
#include <pajlada/settings/setting.hpp>
|
||||||
|
@ -59,11 +60,25 @@ public:
|
||||||
**/
|
**/
|
||||||
bool isLive() const;
|
bool isLive() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the highlight state of this tab clearing highlight sources
|
||||||
|
*
|
||||||
|
* Obeys the HighlightsEnabled setting and highlight states hierarchy
|
||||||
|
*/
|
||||||
void setHighlightState(HighlightState style);
|
void setHighlightState(HighlightState style);
|
||||||
HighlightState highlightState() const;
|
/**
|
||||||
|
* @brief Updates the highlight state and highlight sources of this tab
|
||||||
|
*
|
||||||
|
* Obeys the HighlightsEnabled setting and the highlight state hierarchy and tracks the highlight state update sources
|
||||||
|
*/
|
||||||
|
void updateHighlightState(HighlightState style,
|
||||||
|
const ChannelView &channelViewSource,
|
||||||
|
const MessagePtr &message);
|
||||||
|
void copyHighlightStateAndSourcesFrom(const NotebookTab *sourceTab);
|
||||||
void setHighlightsEnabled(const bool &newVal);
|
void setHighlightsEnabled(const bool &newVal);
|
||||||
|
void newHighlightSourceAdded(const ChannelView &channelViewSource);
|
||||||
bool hasHighlightsEnabled() const;
|
bool hasHighlightsEnabled() const;
|
||||||
|
HighlightState highlightState() const;
|
||||||
|
|
||||||
void moveAnimated(QPoint targetPos, bool animated = true);
|
void moveAnimated(QPoint targetPos, bool animated = true);
|
||||||
|
|
||||||
|
@ -107,6 +122,25 @@ private:
|
||||||
|
|
||||||
int normalTabWidthForHeight(int height) const;
|
int normalTabWidthForHeight(int height) const;
|
||||||
|
|
||||||
|
bool shouldMessageHighlight(const ChannelView &channelViewSource,
|
||||||
|
const MessagePtr &message) const;
|
||||||
|
|
||||||
|
struct HighlightSources {
|
||||||
|
std::unordered_set<ChannelView::ChannelViewID> newMessageSource;
|
||||||
|
std::unordered_set<ChannelView::ChannelViewID> highlightedSource;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
this->newMessageSource.clear();
|
||||||
|
this->highlightedSource.clear();
|
||||||
|
}
|
||||||
|
} highlightSources_;
|
||||||
|
|
||||||
|
void removeHighlightStateChangeSources(const HighlightSources &toRemove);
|
||||||
|
void removeNewMessageSource(const ChannelView::ChannelViewID &source);
|
||||||
|
void removeHighlightedSource(const ChannelView::ChannelViewID &source);
|
||||||
|
void updateHighlightStateDueSourcesChange();
|
||||||
|
|
||||||
QPropertyAnimation positionChangedAnimation_;
|
QPropertyAnimation positionChangedAnimation_;
|
||||||
QPoint positionAnimationDesiredPoint_;
|
QPoint positionAnimationDesiredPoint_;
|
||||||
|
|
||||||
|
|
|
@ -213,13 +213,22 @@ void SplitContainer::addSplit(Split *split)
|
||||||
|
|
||||||
auto &&conns = this->connectionsPerSplit_[split];
|
auto &&conns = this->connectionsPerSplit_[split];
|
||||||
|
|
||||||
conns.managedConnect(split->getChannelView().tabHighlightRequested,
|
conns.managedConnect(
|
||||||
[this](HighlightState state) {
|
split->getChannelView().tabHighlightRequested,
|
||||||
if (this->tab_ != nullptr)
|
[this, split](HighlightState state, const MessagePtr &message) {
|
||||||
{
|
if (this->tab_ != nullptr)
|
||||||
this->tab_->setHighlightState(state);
|
{
|
||||||
}
|
this->tab_->updateHighlightState(state, split->getChannelView(),
|
||||||
});
|
message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
conns.managedConnect(split->channelChanged, [this, split] {
|
||||||
|
if (this->tab_ != nullptr)
|
||||||
|
{
|
||||||
|
this->tab_->newHighlightSourceAdded(split->getChannelView());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
conns.managedConnect(split->getChannelView().liveStatusChanged, [this]() {
|
conns.managedConnect(split->getChannelView().liveStatusChanged, [this]() {
|
||||||
this->refreshTabLiveStatus();
|
this->refreshTabLiveStatus();
|
||||||
|
|
157
tests/snapshots/IrcMessageHandler/clearchat.json
Normal file
157
tests/snapshots/IrcMessageHandler/clearchat.json
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
{
|
||||||
|
"input": "@room-id=11148817;rm-received-ts=1729627607652;tmi-sent-ts=1729627607545;historical=1 :tmi.twitch.tv CLEARCHAT #pajlada",
|
||||||
|
"output": [
|
||||||
|
{
|
||||||
|
"badgeInfos": {
|
||||||
|
},
|
||||||
|
"badges": [
|
||||||
|
],
|
||||||
|
"channelName": "",
|
||||||
|
"count": 1,
|
||||||
|
"displayName": "",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"element": {
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"20:06"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"format": "",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"time": "20:06:47",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TimestampElement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"Chat"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"has"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"been"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"cleared"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"by"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"moderator."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flags": "System|DoNotTriggerNotification",
|
||||||
|
"id": "",
|
||||||
|
"localizedName": "",
|
||||||
|
"loginName": "",
|
||||||
|
"messageText": "Chat has been cleared by a moderator.",
|
||||||
|
"searchText": "Chat has been cleared by a moderator.",
|
||||||
|
"serverReceivedTime": "",
|
||||||
|
"timeoutUser": "",
|
||||||
|
"usernameColor": "#ff000000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
157
tests/snapshots/IrcMessageHandler/emoteonly-on.json
Normal file
157
tests/snapshots/IrcMessageHandler/emoteonly-on.json
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
{
|
||||||
|
"input": "@historical=1;rm-received-ts=1729627965650;msg-id=emote_only_on :tmi.twitch.tv NOTICE #pajlada :This room is now in emote-only mode.",
|
||||||
|
"output": [
|
||||||
|
{
|
||||||
|
"badgeInfos": {
|
||||||
|
},
|
||||||
|
"badges": [
|
||||||
|
],
|
||||||
|
"channelName": "",
|
||||||
|
"count": 1,
|
||||||
|
"displayName": "",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"element": {
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"20:12"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"format": "",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"time": "20:12:45",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TimestampElement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"This"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"room"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"is"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"now"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"in"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"emote-only"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"mode."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flags": "System|DoNotTriggerNotification",
|
||||||
|
"id": "",
|
||||||
|
"localizedName": "",
|
||||||
|
"loginName": "",
|
||||||
|
"messageText": "This room is now in emote-only mode.",
|
||||||
|
"searchText": "This room is now in emote-only mode.",
|
||||||
|
"serverReceivedTime": "",
|
||||||
|
"timeoutUser": "",
|
||||||
|
"usernameColor": "#ff000000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
145
tests/snapshots/IrcMessageHandler/raid.json
Normal file
145
tests/snapshots/IrcMessageHandler/raid.json
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
{
|
||||||
|
"input": "@badges=subscriber/24;login=nerixyz;msg-param-displayName=nerixyz;user-type=;tmi-sent-ts=1729626466361;system-msg=2\\sraiders\\sfrom\\snerixyz\\shave\\sjoined!;room-id=11148817;user-id=129546453;display-name=nerixyz;subscriber=1;historical=1;rm-received-ts=1729626466492;msg-id=raid;vip=0;id=7299b7bc-61ce-423c-85ce-8d651b56cce4;msg-param-login=nerixyz;color=#FF0000;mod=0;msg-param-viewerCount=2;flags=;msg-param-profileImageURL=https://static-cdn.jtvnw.net/jtv_user_pictures/e065218b-49df-459d-afd3-c6557870f551-profile_image-%s.png;emotes=;badge-info=subscriber/28 :tmi.twitch.tv USERNOTICE #pajlada",
|
||||||
|
"output": [
|
||||||
|
{
|
||||||
|
"badgeInfos": {
|
||||||
|
},
|
||||||
|
"badges": [
|
||||||
|
],
|
||||||
|
"channelName": "",
|
||||||
|
"count": 1,
|
||||||
|
"displayName": "",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"element": {
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"19:47"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"format": "",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"time": "19:47:46",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TimestampElement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"raiders"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"from"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "Text",
|
||||||
|
"fallbackColor": "System",
|
||||||
|
"flags": "Text|Mention",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "MentionElement",
|
||||||
|
"userColor": "#ffff0000",
|
||||||
|
"userLoginName": "nerixyz",
|
||||||
|
"words": [
|
||||||
|
"nerixyz"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"have"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"joined!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flags": "System|DoNotTriggerNotification|Subscription",
|
||||||
|
"id": "",
|
||||||
|
"localizedName": "",
|
||||||
|
"loginName": "",
|
||||||
|
"messageText": "2 raiders from nerixyz have joined!",
|
||||||
|
"searchText": "2 raiders from nerixyz have joined!",
|
||||||
|
"serverReceivedTime": "",
|
||||||
|
"timeoutUser": "",
|
||||||
|
"usernameColor": "#ff000000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
5
tests/snapshots/IrcMessageHandler/shared-chat-raid.json
Normal file
5
tests/snapshots/IrcMessageHandler/shared-chat-raid.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"input": "@color=#FF0000;emotes=;subscriber=0;msg-id=sharedchatnotice;historical=1;msg-param-profileImageURL=https://static-cdn.jtvnw.net/jtv_user_pictures/e065218b-49df-459d-afd3-c6557870f551-profile_image-%s.png;tmi-sent-ts=1729627237027;rm-received-ts=1729627237138;msg-param-displayName=nerixyz;id=c585cb3e-cb4f-4a48-a251-b568d217587e;display-name=nerixyz;badges=;user-id=129546453;source-id=d86cdfb2-e138-48e2-985f-5b8efb765ba4;source-room-id=955766119;room-id=11148817;user-type=;msg-param-login=nerixyz;flags=;source-badge-info=;mod=0;vip=0;system-msg=2\\sraiders\\sfrom\\snerixyz\\shave\\sjoined!;login=nerixyz;msg-param-viewerCount=2;source-badges=;source-msg-id=raid;badge-info= :tmi.twitch.tv USERNOTICE #pajlada",
|
||||||
|
"output": [
|
||||||
|
]
|
||||||
|
}
|
87
tests/snapshots/IrcMessageHandler/timeout.json
Normal file
87
tests/snapshots/IrcMessageHandler/timeout.json
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"input": "@tmi-sent-ts=1729628658012;rm-received-ts=1729628658106;historical=1;ban-duration=1;room-id=11148817;target-user-id=129546453 :tmi.twitch.tv CLEARCHAT #pajlada nerixyz",
|
||||||
|
"output": [
|
||||||
|
{
|
||||||
|
"badgeInfos": {
|
||||||
|
},
|
||||||
|
"badges": [
|
||||||
|
],
|
||||||
|
"channelName": "",
|
||||||
|
"count": 1,
|
||||||
|
"displayName": "",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"element": {
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"20:24"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"flags": "Timestamp",
|
||||||
|
"format": "",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"time": "20:24:18",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TimestampElement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "UserInfo",
|
||||||
|
"value": "nerixyz"
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"nerixyz"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "System",
|
||||||
|
"flags": "Text",
|
||||||
|
"link": {
|
||||||
|
"type": "None",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"style": "ChatMedium",
|
||||||
|
"tooltip": "",
|
||||||
|
"trailingSpace": true,
|
||||||
|
"type": "TextElement",
|
||||||
|
"words": [
|
||||||
|
"has",
|
||||||
|
"been",
|
||||||
|
"timed",
|
||||||
|
"out",
|
||||||
|
"for",
|
||||||
|
"1s."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"flags": "System|Timeout|DoNotTriggerNotification",
|
||||||
|
"id": "",
|
||||||
|
"localizedName": "",
|
||||||
|
"loginName": "",
|
||||||
|
"messageText": "nerixyz has been timed out for 1s. ",
|
||||||
|
"searchText": "nerixyz has been timed out for 1s. ",
|
||||||
|
"serverReceivedTime": "",
|
||||||
|
"timeoutUser": "nerixyz",
|
||||||
|
"usernameColor": "#ff000000"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue