Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into chatterino7
Browse files Browse the repository at this point in the history
Now we're on commit 14d11b6; Changes from upstream we've pulled

- Minor: Add search to emote popup. (Chatterino#3404)
- Minor: Messages can now be highlighted by subscriber or founder badges. (Chatterino#3445)
- Bugfix: Fixed crash that could occur if the user opens/closes ChannelViews (e.g. EmotePopup, or Splits) then modifies the showLastMessageIndicator setting. (Chatterino#3444)
- Dev: Batch checking live status for channels with live notifications that aren't connected. (Chatterino#3442)
- Dev: Added /fakemsg command for debugging (Chatterino#3448)
- Dev: Notebook::select\* functions now take an optional `focusPage` parameter (true by default) which keeps the default behaviour of selecting the page after it has been selected. If set to false, the page is _not_ focused after being selected. (Chatterino#3446)
  • Loading branch information
zneix committed Jan 2, 2022
2 parents fe20b94 + ac925d2 commit 6a2ea95
Show file tree
Hide file tree
Showing 12 changed files with 360 additions and 128 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
- Minor: Added autocompletion for default Twitch commands starting with the dot (e.g. `.mods` which does the same as `/mods`). (#3144)
- Minor: Sorted usernames in `Users joined/parted` messages alphabetically. (#3421)
- Minor: Mod list, VIP list, and Users joined/parted messages are now searchable. (#3426)
- Minor: Add search to emote popup. (#3404)
- Minor: Messages can now be highlighted by subscriber or founder badges. (#3445)
- Bugfix: Fix Split Input hotkeys not being available when input is hidden (#3362)
- Bugfix: Fixed colored usernames sometimes not working. (#3170)
- Bugfix: Restored ability to send duplicate `/me` messages. (#3166)
Expand Down Expand Up @@ -75,10 +77,14 @@
- Bugfix: Fixed zero-width emotes sometimes wrapping lines incorrectly. (#3389)
- Bugfix: Fixed using special chars in Windows username breaking the storage of custom commands (#3397)
- Bugfix: Fixed character counter changing fonts after going over the limit. (#3422)
- Bugfix: Fixed crash that could occur if the user opens/closes ChannelViews (e.g. EmotePopup, or Splits) then modifies the showLastMessageIndicator setting. (#3444)
- Dev: Batch checking live status for channels with live notifications that aren't connected. (#3442)
- Dev: Add GitHub action to test builds without precompiled headers enabled. (#3327)
- Dev: Renamed CMake's build option `USE_SYSTEM_QT5KEYCHAIN` to `USE_SYSTEM_QTKEYCHAIN`. (#3103)
- Dev: Add benchmarks that can be compiled with the `BUILD_BENCHMARKS` CMake flag. Off by default. (#3038)
- Dev: Added CMake build option `BUILD_WITH_QTKEYCHAIN` to build with or without Qt5Keychain support (On by default). (#3318)
- Dev: Added /fakemsg command for debugging (#3448)
- Dev: Notebook::select\* functions now take an optional `focusPage` parameter (true by default) which keeps the default behaviour of selecting the page after it has been selected. If set to false, the page is _not_ focused after being selected. (#3446)

## 2.3.4

Expand Down
16 changes: 16 additions & 0 deletions src/controllers/commands/CommandController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,22 @@ void CommandController::initialize(Settings &, Paths &paths)
getApp()->twitch2->sendRawMessage(words.mid(1).join(" "));
return "";
});
#ifndef NDEBUG
this->registerCommand(
"/fakemsg",
[](const QStringList &words, ChannelPtr channel) -> QString {
if (words.size() < 2)
{
channel->addMessage(makeSystemMessage(
"Usage: /fakemsg (raw irc text) - injects raw irc text as "
"if it was a message received from TMI"));
return "";
}
auto ircText = words.mid(1).join(" ");
getApp()->twitch2->addFakeMessage(ircText);
return "";
});
#endif
}

void CommandController::save()
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/hotkeys/ActionNames.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ inline const std::map<HotkeyCategory, ActionDefinitionMap> actionNames{
}},
{HotkeyCategory::Window,
{
#ifdef C_DEBUG
#ifndef NDEBUG
{"addCheerMessage", ActionDefinition{"Debug: Add cheer test message"}},
{"addEmoteMessage", ActionDefinition{"Debug: Add emote test message"}},
{"addLinkMessage",
Expand Down
151 changes: 96 additions & 55 deletions src/controllers/notifications/NotificationController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <QDir>
#include <QMediaPlayer>
#include <QUrl>
#include <unordered_set>

namespace chatterino {

Expand Down Expand Up @@ -127,78 +128,118 @@ NotificationModel *NotificationController::createModel(QObject *parent,
return model;
}

namespace {
// TODO: combine this with getEmoteSetBatches in TwitchAccount.cpp, maybe some templated thing
std::vector<QStringList> getChannelsInBatches(QStringList channels)
{
constexpr int batchSize = 100;

int batchCount = (channels.size() / batchSize) + 1;

std::vector<QStringList> batches;
batches.reserve(batchCount);

for (int i = 0; i < batchCount; i++)
{
QStringList batch;

// I hate you, msvc
int last = (std::min)(batchSize, channels.size() - batchSize * i);
for (int j = 0; j < last; j++)
{
batch.push_back(channels.at(j + (batchSize * i)));
}
batches.emplace_back(batch);
}

return batches;
}
} // namespace

void NotificationController::fetchFakeChannels()
{
qCDebug(chatterinoNotification) << "fetching fake channels";
QStringList channels;
for (std::vector<int>::size_type i = 0;
i != channelMap[Platform::Twitch].raw().size(); i++)
{
auto chan = getApp()->twitch.server->getChannelOrEmpty(
channelMap[Platform::Twitch].raw()[i]);
if (chan->isEmpty())
{
getFakeTwitchChannelLiveStatus(
channelMap[Platform::Twitch].raw()[i]);
channels.push_back(channelMap[Platform::Twitch].raw()[i]);
}
}
for (const auto &batch : getChannelsInBatches(channels))
{
getHelix()->fetchStreams(
QStringList(), batch,
[batch, this](std::vector<HelixStream> streams) {
std::unordered_set<QString> liveStreams;
for (const auto &stream : streams)
{
liveStreams.insert(stream.userName);
}

for (const auto &name : batch)
{
auto it = liveStreams.find(name);
this->checkStream(it != liveStreams.end(), name);
}
},
[batch]() {
// we done fucked up.
qCWarning(chatterinoNotification)
<< "Failed to fetch live status for " << batch;
});
}
}

void NotificationController::getFakeTwitchChannelLiveStatus(
const QString &channelName)
void NotificationController::checkStream(bool live, QString channelName)
{
getHelix()->getStreamByName(
channelName,
[channelName, this](bool live, const auto &stream) {
qCDebug(chatterinoNotification) << "[TwitchChannel" << channelName
<< "] Refreshing live status";
qCDebug(chatterinoNotification)
<< "[TwitchChannel" << channelName << "] Refreshing live status";

if (!live)
{
// Stream is offline
this->removeFakeChannel(channelName);
return;
}
if (!live)
{
// Stream is offline
this->removeFakeChannel(channelName);
return;
}

// Stream is online
auto i = std::find(fakeTwitchChannels.begin(),
fakeTwitchChannels.end(), channelName);
// Stream is online
auto i = std::find(fakeTwitchChannels.begin(), fakeTwitchChannels.end(),
channelName);

if (i != fakeTwitchChannels.end())
{
// We have already pushed the live state of this stream
// Could not find stream in fake Twitch channels!
return;
}
if (i != fakeTwitchChannels.end())
{
// We have already pushed the live state of this stream
// Could not find stream in fake Twitch channels!
return;
}

if (Toasts::isEnabled())
{
getApp()->toasts->sendChannelNotification(channelName,
Platform::Twitch);
}
if (getSettings()->notificationPlaySound &&
!(isInStreamerMode() &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getApp()->notifications->playSound();
}
if (getSettings()->notificationFlashTaskbar &&
!(isInStreamerMode() &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getApp()->windows->sendAlert();
}
MessageBuilder builder;
TwitchMessageBuilder::liveMessage(channelName, &builder);
getApp()->twitch2->liveChannel->addMessage(builder.release());

// Indicate that we have pushed notifications for this stream
fakeTwitchChannels.push_back(channelName);
},
[channelName, this] {
qCDebug(chatterinoNotification)
<< "[TwitchChannel" << channelName
<< "] Refreshing live status (Missing ID)";
this->removeFakeChannel(channelName);
});
if (Toasts::isEnabled())
{
getApp()->toasts->sendChannelNotification(channelName,
Platform::Twitch);
}
if (getSettings()->notificationPlaySound &&
!(isInStreamerMode() &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getApp()->notifications->playSound();
}
if (getSettings()->notificationFlashTaskbar &&
!(isInStreamerMode() &&
getSettings()->streamerModeSuppressLiveNotifications))
{
getApp()->windows->sendAlert();
}
MessageBuilder builder;
TwitchMessageBuilder::liveMessage(channelName, &builder);
getApp()->twitch2->liveChannel->addMessage(builder.release());

// Indicate that we have pushed notifications for this stream
fakeTwitchChannels.push_back(channelName);
}

void NotificationController::removeFakeChannel(const QString channelName)
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/notifications/NotificationController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class NotificationController final : public Singleton, private QObject

void fetchFakeChannels();
void removeFakeChannel(const QString channelName);
void getFakeTwitchChannelLiveStatus(const QString &channelName);
void checkStream(bool live, QString channelName);

// fakeTwitchChannels is a list of streams who are live that we have already sent out a notification for
std::vector<QString> fakeTwitchChannels;
Expand Down
43 changes: 23 additions & 20 deletions src/widgets/Notebook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ int Notebook::indexOf(QWidget *page) const
return -1;
}

void Notebook::select(QWidget *page)
void Notebook::select(QWidget *page, bool focusPage)
{
if (page == this->selectedPage_)
{
Expand All @@ -148,20 +148,23 @@ void Notebook::select(QWidget *page)
item.tab->setSelected(true);
item.tab->raise();

if (item.selectedWidget == nullptr)
if (focusPage)
{
item.page->setFocus();
}
else
{
if (containsChild(page, item.selectedWidget))
if (item.selectedWidget == nullptr)
{
item.selectedWidget->setFocus(Qt::MouseFocusReason);
item.page->setFocus();
}
else
{
qCDebug(chatterinoWidget)
<< "Notebook: selected child of page doesn't exist anymore";
if (containsChild(page, item.selectedWidget))
{
item.selectedWidget->setFocus(Qt::MouseFocusReason);
}
else
{
qCDebug(chatterinoWidget) << "Notebook: selected child of "
"page doesn't exist anymore";
}
}
}
}
Expand Down Expand Up @@ -216,17 +219,17 @@ bool Notebook::containsChild(const QObject *obj, const QObject *child)
});
}

void Notebook::selectIndex(int index)
void Notebook::selectIndex(int index, bool focusPage)
{
if (index < 0 || this->items_.count() <= index)
{
return;
}

this->select(this->items_[index].page);
this->select(this->items_[index].page, focusPage);
}

void Notebook::selectNextTab()
void Notebook::selectNextTab(bool focusPage)
{
if (this->items_.size() <= 1)
{
Expand All @@ -236,10 +239,10 @@ void Notebook::selectNextTab()
auto index =
(this->indexOf(this->selectedPage_) + 1) % this->items_.count();

this->select(this->items_[index].page);
this->select(this->items_[index].page, focusPage);
}

void Notebook::selectPreviousTab()
void Notebook::selectPreviousTab(bool focusPage)
{
if (this->items_.size() <= 1)
{
Expand All @@ -253,18 +256,18 @@ void Notebook::selectPreviousTab()
index += this->items_.count();
}

this->select(this->items_[index].page);
this->select(this->items_[index].page, focusPage);
}

void Notebook::selectLastTab()
void Notebook::selectLastTab(bool focusPage)
{
const auto size = this->items_.size();
if (size <= 1)
{
return;
}

this->select(this->items_[size - 1].page);
this->select(this->items_[size - 1].page, focusPage);
}

int Notebook::getPageCount() const
Expand Down Expand Up @@ -806,7 +809,7 @@ SplitContainer *SplitNotebook::getOrAddSelectedPage()
: this->addPage();
}

void SplitNotebook::select(QWidget *page)
void SplitNotebook::select(QWidget *page, bool focusPage)
{
if (auto selectedPage = this->getSelectedPage())
{
Expand All @@ -818,7 +821,7 @@ void SplitNotebook::select(QWidget *page)
}
}
}
this->Notebook::select(page);
this->Notebook::select(page, focusPage);
}

} // namespace chatterino
12 changes: 6 additions & 6 deletions src/widgets/Notebook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ class Notebook : public BaseWidget
void removeCurrentPage();

int indexOf(QWidget *page) const;
virtual void select(QWidget *page);
void selectIndex(int index);
void selectNextTab();
void selectPreviousTab();
void selectLastTab();
virtual void select(QWidget *page, bool focusPage = true);
void selectIndex(int index, bool focusPage = true);
void selectNextTab(bool focusPage = true);
void selectPreviousTab(bool focusPage = true);
void selectLastTab(bool focusPage = true);

int getPageCount() const;
QWidget *getPageAt(int index) const;
Expand Down Expand Up @@ -108,7 +108,7 @@ class SplitNotebook : public Notebook

SplitContainer *addPage(bool select = false);
SplitContainer *getOrAddSelectedPage();
void select(QWidget *page) override;
void select(QWidget *page, bool focusPage = true) override;

protected:
void showEvent(QShowEvent *event) override;
Expand Down
3 changes: 3 additions & 0 deletions src/widgets/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ void Window::addDebugStuff(HotkeyController::HotkeyMap &actions)
// "first time chat" message
miscMessages.emplace_back(R"(@badge-info=;badges=glhf-pledge/1;client-nonce=5d2627b0cbe56fa05faf5420def4807d;color=#1E90FF;display-name=oldcoeur;emote-only=1;emotes=84608:0-7;first-msg=1;flags=;id=7412fea4-8683-4cc9-a506-4228127a5c2d;mod=0;room-id=11148817;subscriber=0;tmi-sent-ts=1623429859222;turbo=0;user-id=139147886;user-type= :oldcoeur!oldcoeur@oldcoeur.tmi.twitch.tv PRIVMSG #pajlada :cmonBruh)");

// Message with founder badge
miscMessages.emplace_back(R"(@badge-info=founder/72;badges=founder/0,bits/5000;color=#FF0000;display-name=TranRed;emotes=;first-msg=0;flags=;id=7482163f-493d-41d9-b36f-fba50e0701b7;mod=0;room-id=11148817;subscriber=0;tmi-sent-ts=1641123773885;turbo=0;user-id=57019243;user-type= :tranred!tranred@tranred.tmi.twitch.tv PRIVMSG #pajlada :GFMP pajaE)");

// various link tests
linkMessages.emplace_back(R"(@badge-info=subscriber/48;badges=broadcaster/1,subscriber/36,partner/1;color=#CC44FF;display-name=pajlada;emotes=;flags=;id=3c23cf3c-0864-4699-a76b-089350141147;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1577628844607;turbo=0;user-id=11148817;user-type= :pajlada!pajlada@pajlada.tmi.twitch.tv PRIVMSG #pajlada : Links that should pass: )" + getValidLinks().join(' '));
linkMessages.emplace_back(R"(@badge-info=subscriber/48;badges=broadcaster/1,subscriber/36,partner/1;color=#CC44FF;display-name=pajlada;emotes=;flags=;id=3c23cf3c-0864-4699-a76b-089350141147;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1577628844607;turbo=0;user-id=11148817;user-type= :pajlada!pajlada@pajlada.tmi.twitch.tv PRIVMSG #pajlada : Links that should NOT pass: )" + getInvalidLinks().join(' '));
Expand Down
Loading

0 comments on commit 6a2ea95

Please sign in to comment.